AudioPlayer.cpp revision ad6516d9247bd0a76a393810b041c3e4094f0e36
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "AudioPlayer"
19#include <utils/Log.h>
20
21#include <media/AudioTrack.h>
22#include <media/stagefright/AudioPlayer.h>
23#include <media/stagefright/MediaDebug.h>
24#include <media/stagefright/MediaDefs.h>
25#include <media/stagefright/MediaSource.h>
26#include <media/stagefright/MetaData.h>
27
28namespace android {
29
30AudioPlayer::AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink)
31    : mAudioTrack(NULL),
32      mInputBuffer(NULL),
33      mSampleRate(0),
34      mLatencyUs(0),
35      mFrameSize(0),
36      mNumFramesPlayed(0),
37      mPositionTimeMediaUs(-1),
38      mPositionTimeRealUs(-1),
39      mSeeking(false),
40      mStarted(false),
41      mAudioSink(audioSink) {
42}
43
44AudioPlayer::~AudioPlayer() {
45    if (mStarted) {
46        stop();
47    }
48}
49
50void AudioPlayer::setListenerCallback(
51        void (*notify)(void *cookie, int what), void *cookie) {
52    mListenerCallback = notify;
53    mListenerCookie = cookie;
54}
55
56void AudioPlayer::setSource(const sp<MediaSource> &source) {
57    CHECK_EQ(mSource, NULL);
58    mSource = source;
59}
60
61status_t AudioPlayer::start() {
62    CHECK(!mStarted);
63    CHECK(mSource != NULL);
64
65    status_t err = mSource->start();
66
67    if (err != OK) {
68        return err;
69    }
70
71    sp<MetaData> format = mSource->getFormat();
72    const char *mime;
73    bool success = format->findCString(kKeyMIMEType, &mime);
74    CHECK(success);
75    CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
76
77    success = format->findInt32(kKeySampleRate, &mSampleRate);
78    CHECK(success);
79
80    int32_t numChannels;
81    success = format->findInt32(kKeyChannelCount, &numChannels);
82    CHECK(success);
83
84    if (mAudioSink.get() != NULL) {
85        status_t err = mAudioSink->open(
86                mSampleRate, numChannels, AudioSystem::PCM_16_BIT,
87                DEFAULT_AUDIOSINK_BUFFERCOUNT,
88                &AudioPlayer::AudioSinkCallback, this);
89        if (err != OK) {
90            mSource->stop();
91
92            return err;
93        }
94
95        mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
96        mFrameSize = mAudioSink->frameSize();
97
98        mAudioSink->start();
99    } else {
100        mAudioTrack = new AudioTrack(
101                AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT,
102                (numChannels == 2)
103                    ? AudioSystem::CHANNEL_OUT_STEREO
104                    : AudioSystem::CHANNEL_OUT_MONO,
105                8192, 0, &AudioCallback, this, 0);
106
107        if (mAudioTrack->initCheck() != OK) {
108            delete mAudioTrack;
109            mAudioTrack = NULL;
110
111            mSource->stop();
112
113            return mAudioTrack->initCheck();
114        }
115
116        mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
117        mFrameSize = mAudioTrack->frameSize();
118
119        mAudioTrack->start();
120    }
121
122    mStarted = true;
123
124    return OK;
125}
126
127void AudioPlayer::pause() {
128    CHECK(mStarted);
129
130    if (mAudioSink.get() != NULL) {
131        mAudioSink->pause();
132    } else {
133        mAudioTrack->stop();
134    }
135}
136
137void AudioPlayer::resume() {
138    CHECK(mStarted);
139
140    if (mAudioSink.get() != NULL) {
141        mAudioSink->start();
142    } else {
143        mAudioTrack->start();
144    }
145}
146
147void AudioPlayer::stop() {
148    CHECK(mStarted);
149
150    if (mAudioSink.get() != NULL) {
151        mAudioSink->stop();
152        mAudioSink->close();
153    } else {
154        mAudioTrack->stop();
155
156        delete mAudioTrack;
157        mAudioTrack = NULL;
158    }
159
160    // Make sure to release any buffer we hold onto so that the
161    // source is able to stop().
162    if (mInputBuffer != NULL) {
163        LOGV("AudioPlayer releasing input buffer.");
164
165        mInputBuffer->release();
166        mInputBuffer = NULL;
167    }
168
169    mSource->stop();
170
171    mNumFramesPlayed = 0;
172    mPositionTimeMediaUs = -1;
173    mPositionTimeRealUs = -1;
174    mSeeking = false;
175    mStarted = false;
176}
177
178// static
179void AudioPlayer::AudioCallback(int event, void *user, void *info) {
180    static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
181}
182
183// static
184void AudioPlayer::AudioSinkCallback(
185        MediaPlayerBase::AudioSink *audioSink,
186        void *buffer, size_t size, void *cookie) {
187    AudioPlayer *me = (AudioPlayer *)cookie;
188
189    me->fillBuffer(buffer, size);
190}
191
192void AudioPlayer::AudioCallback(int event, void *info) {
193    if (event != AudioTrack::EVENT_MORE_DATA) {
194        return;
195    }
196
197    AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
198    fillBuffer(buffer->raw, buffer->size);
199}
200
201void AudioPlayer::fillBuffer(void *data, size_t size) {
202    if (mNumFramesPlayed == 0) {
203        LOGV("AudioCallback");
204    }
205
206    size_t size_done = 0;
207    size_t size_remaining = size;
208    while (size_remaining > 0) {
209        MediaSource::ReadOptions options;
210
211        {
212            Mutex::Autolock autoLock(mLock);
213
214            if (mSeeking) {
215                options.setSeekTo(mSeekTimeUs);
216
217                if (mInputBuffer != NULL) {
218                    mInputBuffer->release();
219                    mInputBuffer = NULL;
220                }
221            }
222        }
223
224        if (mInputBuffer == NULL) {
225            status_t err = mSource->read(&mInputBuffer, &options);
226
227            CHECK((err == OK && mInputBuffer != NULL)
228                   || (err != OK && mInputBuffer == NULL));
229
230            if (mSeeking) {
231                mSeeking = false;
232
233                if (mListenerCallback) {
234                    (*mListenerCallback)(mListenerCookie, SEEK_COMPLETE);
235                }
236            }
237
238            if (err != OK) {
239                if (mListenerCallback) {
240                    (*mListenerCallback)(mListenerCookie, REACHED_EOS);
241                }
242
243                memset((char *)data + size_done, 0, size_remaining);
244                break;
245            }
246
247            Mutex::Autolock autoLock(mLock);
248            CHECK(mInputBuffer->meta_data()->findInt64(
249                        kKeyTime, &mPositionTimeMediaUs));
250
251            mPositionTimeRealUs =
252                -mLatencyUs
253                + ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
254                    / mSampleRate;
255
256            LOGV("buffer->size() = %d, "
257                 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
258                 mInputBuffer->range_length(),
259                 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
260        }
261
262        if (mInputBuffer->range_length() == 0) {
263            mInputBuffer->release();
264            mInputBuffer = NULL;
265
266            continue;
267        }
268
269        size_t copy = size_remaining;
270        if (copy > mInputBuffer->range_length()) {
271            copy = mInputBuffer->range_length();
272        }
273
274        memcpy((char *)data + size_done,
275               (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
276               copy);
277
278        mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
279                                mInputBuffer->range_length() - copy);
280
281        size_done += copy;
282        size_remaining -= copy;
283    }
284
285    Mutex::Autolock autoLock(mLock);
286    mNumFramesPlayed += size / mFrameSize;
287}
288
289int64_t AudioPlayer::getRealTimeUs() {
290    Mutex::Autolock autoLock(mLock);
291    return getRealTimeUsLocked();
292}
293
294int64_t AudioPlayer::getRealTimeUsLocked() const {
295    return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
296}
297
298int64_t AudioPlayer::getMediaTimeUs() {
299    Mutex::Autolock autoLock(mLock);
300
301    if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
302        return 0;
303    }
304
305    return mPositionTimeMediaUs + (getRealTimeUsLocked() - mPositionTimeRealUs);
306}
307
308bool AudioPlayer::getMediaTimeMapping(
309        int64_t *realtime_us, int64_t *mediatime_us) {
310    Mutex::Autolock autoLock(mLock);
311
312    *realtime_us = mPositionTimeRealUs;
313    *mediatime_us = mPositionTimeMediaUs;
314
315    return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
316}
317
318status_t AudioPlayer::seekTo(int64_t time_us) {
319    Mutex::Autolock autoLock(mLock);
320
321    mSeeking = true;
322    mSeekTimeUs = time_us;
323
324    return OK;
325}
326
327}
328