AudioPlayer.cpp revision 3cc219dfc67b866e10828f0c17641668d47c1cd8
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 <binder/IPCThreadState.h>
22#include <media/AudioTrack.h>
23#include <media/stagefright/AudioPlayer.h>
24#include <media/stagefright/MediaDebug.h>
25#include <media/stagefright/MediaDefs.h>
26#include <media/stagefright/MediaErrors.h>
27#include <media/stagefright/MediaSource.h>
28#include <media/stagefright/MetaData.h>
29
30namespace android {
31
32AudioPlayer::AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink)
33    : mAudioTrack(NULL),
34      mInputBuffer(NULL),
35      mSampleRate(0),
36      mLatencyUs(0),
37      mFrameSize(0),
38      mNumFramesPlayed(0),
39      mPositionTimeMediaUs(-1),
40      mPositionTimeRealUs(-1),
41      mSeeking(false),
42      mReachedEOS(false),
43      mFinalStatus(OK),
44      mStarted(false),
45      mIsFirstBuffer(false),
46      mFirstBufferResult(OK),
47      mFirstBuffer(NULL),
48      mAudioSink(audioSink) {
49}
50
51AudioPlayer::~AudioPlayer() {
52    if (mStarted) {
53        stop();
54    }
55}
56
57void AudioPlayer::setSource(const sp<MediaSource> &source) {
58    CHECK_EQ(mSource, NULL);
59    mSource = source;
60}
61
62status_t AudioPlayer::start(bool sourceAlreadyStarted) {
63    CHECK(!mStarted);
64    CHECK(mSource != NULL);
65
66    status_t err;
67    if (!sourceAlreadyStarted) {
68        err = mSource->start();
69
70        if (err != OK) {
71            return err;
72        }
73    }
74
75    // We allow an optional INFO_FORMAT_CHANGED at the very beginning
76    // of playback, if there is one, getFormat below will retrieve the
77    // updated format, if there isn't, we'll stash away the valid buffer
78    // of data to be used on the first audio callback.
79
80    CHECK(mFirstBuffer == NULL);
81
82    mFirstBufferResult = mSource->read(&mFirstBuffer);
83    if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
84        LOGV("INFO_FORMAT_CHANGED!!!");
85
86        CHECK(mFirstBuffer == NULL);
87        mFirstBufferResult = OK;
88        mIsFirstBuffer = false;
89    } else {
90        mIsFirstBuffer = true;
91    }
92
93    sp<MetaData> format = mSource->getFormat();
94    const char *mime;
95    bool success = format->findCString(kKeyMIMEType, &mime);
96    CHECK(success);
97    CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
98
99    success = format->findInt32(kKeySampleRate, &mSampleRate);
100    CHECK(success);
101
102    int32_t numChannels;
103    success = format->findInt32(kKeyChannelCount, &numChannels);
104    CHECK(success);
105
106    if (mAudioSink.get() != NULL) {
107        status_t err = mAudioSink->open(
108                mSampleRate, numChannels, AudioSystem::PCM_16_BIT,
109                DEFAULT_AUDIOSINK_BUFFERCOUNT,
110                &AudioPlayer::AudioSinkCallback, this);
111        if (err != OK) {
112            if (mFirstBuffer != NULL) {
113                mFirstBuffer->release();
114                mFirstBuffer = NULL;
115            }
116
117            if (!sourceAlreadyStarted) {
118                mSource->stop();
119            }
120
121            return err;
122        }
123
124        mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
125        mFrameSize = mAudioSink->frameSize();
126
127        mAudioSink->start();
128    } else {
129        mAudioTrack = new AudioTrack(
130                AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT,
131                (numChannels == 2)
132                    ? AudioSystem::CHANNEL_OUT_STEREO
133                    : AudioSystem::CHANNEL_OUT_MONO,
134                0, 0, &AudioCallback, this, 0);
135
136        if ((err = mAudioTrack->initCheck()) != OK) {
137            delete mAudioTrack;
138            mAudioTrack = NULL;
139
140            if (mFirstBuffer != NULL) {
141                mFirstBuffer->release();
142                mFirstBuffer = NULL;
143            }
144
145            if (!sourceAlreadyStarted) {
146                mSource->stop();
147            }
148
149            return err;
150        }
151
152        mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
153        mFrameSize = mAudioTrack->frameSize();
154
155        mAudioTrack->start();
156    }
157
158    mStarted = true;
159
160    return OK;
161}
162
163void AudioPlayer::pause() {
164    CHECK(mStarted);
165
166    if (mAudioSink.get() != NULL) {
167        mAudioSink->pause();
168    } else {
169        mAudioTrack->stop();
170    }
171}
172
173void AudioPlayer::resume() {
174    CHECK(mStarted);
175
176    if (mAudioSink.get() != NULL) {
177        mAudioSink->start();
178    } else {
179        mAudioTrack->start();
180    }
181}
182
183void AudioPlayer::stop() {
184    CHECK(mStarted);
185
186    if (mAudioSink.get() != NULL) {
187        mAudioSink->stop();
188        mAudioSink->close();
189    } else {
190        mAudioTrack->stop();
191
192        delete mAudioTrack;
193        mAudioTrack = NULL;
194    }
195
196    // Make sure to release any buffer we hold onto so that the
197    // source is able to stop().
198
199    if (mFirstBuffer != NULL) {
200        mFirstBuffer->release();
201        mFirstBuffer = NULL;
202    }
203
204    if (mInputBuffer != NULL) {
205        LOGV("AudioPlayer releasing input buffer.");
206
207        mInputBuffer->release();
208        mInputBuffer = NULL;
209    }
210
211    mSource->stop();
212
213    // The following hack is necessary to ensure that the OMX
214    // component is completely released by the time we may try
215    // to instantiate it again.
216    wp<MediaSource> tmp = mSource;
217    mSource.clear();
218    while (tmp.promote() != NULL) {
219        usleep(1000);
220    }
221    IPCThreadState::self()->flushCommands();
222
223    mNumFramesPlayed = 0;
224    mPositionTimeMediaUs = -1;
225    mPositionTimeRealUs = -1;
226    mSeeking = false;
227    mReachedEOS = false;
228    mFinalStatus = OK;
229    mStarted = false;
230}
231
232// static
233void AudioPlayer::AudioCallback(int event, void *user, void *info) {
234    static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
235}
236
237bool AudioPlayer::isSeeking() {
238    Mutex::Autolock autoLock(mLock);
239    return mSeeking;
240}
241
242bool AudioPlayer::reachedEOS(status_t *finalStatus) {
243    *finalStatus = OK;
244
245    Mutex::Autolock autoLock(mLock);
246    *finalStatus = mFinalStatus;
247    return mReachedEOS;
248}
249
250// static
251size_t AudioPlayer::AudioSinkCallback(
252        MediaPlayerBase::AudioSink *audioSink,
253        void *buffer, size_t size, void *cookie) {
254    AudioPlayer *me = (AudioPlayer *)cookie;
255
256    return me->fillBuffer(buffer, size);
257}
258
259void AudioPlayer::AudioCallback(int event, void *info) {
260    if (event != AudioTrack::EVENT_MORE_DATA) {
261        return;
262    }
263
264    AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
265    size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
266
267    buffer->size = numBytesWritten;
268}
269
270size_t AudioPlayer::fillBuffer(void *data, size_t size) {
271    if (mNumFramesPlayed == 0) {
272        LOGV("AudioCallback");
273    }
274
275    if (mReachedEOS) {
276        return 0;
277    }
278
279    size_t size_done = 0;
280    size_t size_remaining = size;
281    while (size_remaining > 0) {
282        MediaSource::ReadOptions options;
283
284        {
285            Mutex::Autolock autoLock(mLock);
286
287            if (mSeeking) {
288                if (mIsFirstBuffer) {
289                    if (mFirstBuffer != NULL) {
290                        mFirstBuffer->release();
291                        mFirstBuffer = NULL;
292                    }
293                    mIsFirstBuffer = false;
294                }
295
296                options.setSeekTo(mSeekTimeUs);
297
298                if (mInputBuffer != NULL) {
299                    mInputBuffer->release();
300                    mInputBuffer = NULL;
301                }
302
303                mSeeking = false;
304            }
305        }
306
307        if (mInputBuffer == NULL) {
308            status_t err;
309
310            if (mIsFirstBuffer) {
311                mInputBuffer = mFirstBuffer;
312                mFirstBuffer = NULL;
313                err = mFirstBufferResult;
314
315                mIsFirstBuffer = false;
316            } else {
317                err = mSource->read(&mInputBuffer, &options);
318            }
319
320            CHECK((err == OK && mInputBuffer != NULL)
321                   || (err != OK && mInputBuffer == NULL));
322
323            Mutex::Autolock autoLock(mLock);
324
325            if (err != OK) {
326                mReachedEOS = true;
327                mFinalStatus = err;
328                break;
329            }
330
331            CHECK(mInputBuffer->meta_data()->findInt64(
332                        kKeyTime, &mPositionTimeMediaUs));
333
334            mPositionTimeRealUs =
335                ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
336                    / mSampleRate;
337
338            LOGV("buffer->size() = %d, "
339                 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
340                 mInputBuffer->range_length(),
341                 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
342        }
343
344        if (mInputBuffer->range_length() == 0) {
345            mInputBuffer->release();
346            mInputBuffer = NULL;
347
348            continue;
349        }
350
351        size_t copy = size_remaining;
352        if (copy > mInputBuffer->range_length()) {
353            copy = mInputBuffer->range_length();
354        }
355
356        memcpy((char *)data + size_done,
357               (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
358               copy);
359
360        mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
361                                mInputBuffer->range_length() - copy);
362
363        size_done += copy;
364        size_remaining -= copy;
365    }
366
367    Mutex::Autolock autoLock(mLock);
368    mNumFramesPlayed += size_done / mFrameSize;
369
370    return size_done;
371}
372
373int64_t AudioPlayer::getRealTimeUs() {
374    Mutex::Autolock autoLock(mLock);
375    return getRealTimeUsLocked();
376}
377
378int64_t AudioPlayer::getRealTimeUsLocked() const {
379    return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
380}
381
382int64_t AudioPlayer::getMediaTimeUs() {
383    Mutex::Autolock autoLock(mLock);
384
385    if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
386        return 0;
387    }
388
389    int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
390    if (realTimeOffset < 0) {
391        realTimeOffset = 0;
392    }
393
394    return mPositionTimeMediaUs + realTimeOffset;
395}
396
397bool AudioPlayer::getMediaTimeMapping(
398        int64_t *realtime_us, int64_t *mediatime_us) {
399    Mutex::Autolock autoLock(mLock);
400
401    *realtime_us = mPositionTimeRealUs;
402    *mediatime_us = mPositionTimeMediaUs;
403
404    return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
405}
406
407status_t AudioPlayer::seekTo(int64_t time_us) {
408    Mutex::Autolock autoLock(mLock);
409
410    mSeeking = true;
411    mReachedEOS = false;
412    mSeekTimeUs = time_us;
413
414    return OK;
415}
416
417}
418