AudioPlayer.cpp revision a98420e863c374d1f15309467f2a1fc58d979d3b
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/MediaSource.h>
27#include <media/stagefright/MetaData.h>
28
29namespace android {
30
31AudioPlayer::AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink)
32    : mAudioTrack(NULL),
33      mInputBuffer(NULL),
34      mSampleRate(0),
35      mLatencyUs(0),
36      mFrameSize(0),
37      mNumFramesPlayed(0),
38      mPositionTimeMediaUs(-1),
39      mPositionTimeRealUs(-1),
40      mSeeking(false),
41      mReachedEOS(false),
42      mFinalStatus(OK),
43      mStarted(false),
44      mAudioSink(audioSink) {
45}
46
47AudioPlayer::~AudioPlayer() {
48    if (mStarted) {
49        stop();
50    }
51}
52
53void AudioPlayer::setSource(const sp<MediaSource> &source) {
54    CHECK_EQ(mSource, NULL);
55    mSource = source;
56}
57
58status_t AudioPlayer::start(bool sourceAlreadyStarted) {
59    CHECK(!mStarted);
60    CHECK(mSource != NULL);
61
62    status_t err;
63    if (!sourceAlreadyStarted) {
64        err = mSource->start();
65
66        if (err != OK) {
67            return err;
68        }
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                0, 0, &AudioCallback, this, 0);
106
107        if ((err = mAudioTrack->initCheck()) != OK) {
108            delete mAudioTrack;
109            mAudioTrack = NULL;
110
111            mSource->stop();
112
113            return err;
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    // The following hack is necessary to ensure that the OMX
172    // component is completely released by the time we may try
173    // to instantiate it again.
174    wp<MediaSource> tmp = mSource;
175    mSource.clear();
176    while (tmp.promote() != NULL) {
177        usleep(1000);
178    }
179    IPCThreadState::self()->flushCommands();
180
181    mNumFramesPlayed = 0;
182    mPositionTimeMediaUs = -1;
183    mPositionTimeRealUs = -1;
184    mSeeking = false;
185    mReachedEOS = false;
186    mFinalStatus = OK;
187    mStarted = false;
188}
189
190// static
191void AudioPlayer::AudioCallback(int event, void *user, void *info) {
192    static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
193}
194
195bool AudioPlayer::isSeeking() {
196    Mutex::Autolock autoLock(mLock);
197    return mSeeking;
198}
199
200bool AudioPlayer::reachedEOS(status_t *finalStatus) {
201    *finalStatus = OK;
202
203    Mutex::Autolock autoLock(mLock);
204    *finalStatus = mFinalStatus;
205    return mReachedEOS;
206}
207
208// static
209size_t AudioPlayer::AudioSinkCallback(
210        MediaPlayerBase::AudioSink *audioSink,
211        void *buffer, size_t size, void *cookie) {
212    AudioPlayer *me = (AudioPlayer *)cookie;
213
214    return me->fillBuffer(buffer, size);
215}
216
217void AudioPlayer::AudioCallback(int event, void *info) {
218    if (event != AudioTrack::EVENT_MORE_DATA) {
219        return;
220    }
221
222    AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
223    size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
224
225    buffer->size = numBytesWritten;
226}
227
228size_t AudioPlayer::fillBuffer(void *data, size_t size) {
229    if (mNumFramesPlayed == 0) {
230        LOGV("AudioCallback");
231    }
232
233    if (mReachedEOS) {
234        return 0;
235    }
236
237    size_t size_done = 0;
238    size_t size_remaining = size;
239    while (size_remaining > 0) {
240        MediaSource::ReadOptions options;
241
242        {
243            Mutex::Autolock autoLock(mLock);
244
245            if (mSeeking) {
246                options.setSeekTo(mSeekTimeUs);
247
248                if (mInputBuffer != NULL) {
249                    mInputBuffer->release();
250                    mInputBuffer = NULL;
251                }
252
253                mSeeking = false;
254            }
255        }
256
257        if (mInputBuffer == NULL) {
258            status_t err = mSource->read(&mInputBuffer, &options);
259
260            CHECK((err == OK && mInputBuffer != NULL)
261                   || (err != OK && mInputBuffer == NULL));
262
263            Mutex::Autolock autoLock(mLock);
264
265            if (err != OK) {
266                mReachedEOS = true;
267                mFinalStatus = err;
268                break;
269            }
270
271            CHECK(mInputBuffer->meta_data()->findInt64(
272                        kKeyTime, &mPositionTimeMediaUs));
273
274            mPositionTimeRealUs =
275                ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
276                    / mSampleRate;
277
278            LOGV("buffer->size() = %d, "
279                 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
280                 mInputBuffer->range_length(),
281                 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
282        }
283
284        if (mInputBuffer->range_length() == 0) {
285            mInputBuffer->release();
286            mInputBuffer = NULL;
287
288            continue;
289        }
290
291        size_t copy = size_remaining;
292        if (copy > mInputBuffer->range_length()) {
293            copy = mInputBuffer->range_length();
294        }
295
296        memcpy((char *)data + size_done,
297               (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
298               copy);
299
300        mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
301                                mInputBuffer->range_length() - copy);
302
303        size_done += copy;
304        size_remaining -= copy;
305    }
306
307    Mutex::Autolock autoLock(mLock);
308    mNumFramesPlayed += size_done / mFrameSize;
309
310    return size_done;
311}
312
313int64_t AudioPlayer::getRealTimeUs() {
314    Mutex::Autolock autoLock(mLock);
315    return getRealTimeUsLocked();
316}
317
318int64_t AudioPlayer::getRealTimeUsLocked() const {
319    return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
320}
321
322int64_t AudioPlayer::getMediaTimeUs() {
323    Mutex::Autolock autoLock(mLock);
324
325    if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
326        return 0;
327    }
328
329    int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
330    if (realTimeOffset < 0) {
331        realTimeOffset = 0;
332    }
333
334    return mPositionTimeMediaUs + realTimeOffset;
335}
336
337bool AudioPlayer::getMediaTimeMapping(
338        int64_t *realtime_us, int64_t *mediatime_us) {
339    Mutex::Autolock autoLock(mLock);
340
341    *realtime_us = mPositionTimeRealUs;
342    *mediatime_us = mPositionTimeMediaUs;
343
344    return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
345}
346
347status_t AudioPlayer::seekTo(int64_t time_us) {
348    Mutex::Autolock autoLock(mLock);
349
350    mSeeking = true;
351    mReachedEOS = false;
352    mSeekTimeUs = time_us;
353
354    return OK;
355}
356
357}
358