AudioPlayer.cpp revision 5295c0c55d41a2906ea7f65a3f22e6278cb17d4b
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      mReachedEOS(false),
41      mFinalStatus(OK),
42      mStarted(false),
43      mAudioSink(audioSink) {
44}
45
46AudioPlayer::~AudioPlayer() {
47    if (mStarted) {
48        stop();
49    }
50}
51
52void AudioPlayer::setSource(const sp<MediaSource> &source) {
53    CHECK_EQ(mSource, NULL);
54    mSource = source;
55}
56
57status_t AudioPlayer::start() {
58    CHECK(!mStarted);
59    CHECK(mSource != NULL);
60
61    status_t err = mSource->start();
62
63    if (err != OK) {
64        return err;
65    }
66
67    sp<MetaData> format = mSource->getFormat();
68    const char *mime;
69    bool success = format->findCString(kKeyMIMEType, &mime);
70    CHECK(success);
71    CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
72
73    success = format->findInt32(kKeySampleRate, &mSampleRate);
74    CHECK(success);
75
76    int32_t numChannels;
77    success = format->findInt32(kKeyChannelCount, &numChannels);
78    CHECK(success);
79
80    if (mAudioSink.get() != NULL) {
81        status_t err = mAudioSink->open(
82                mSampleRate, numChannels, AudioSystem::PCM_16_BIT,
83                DEFAULT_AUDIOSINK_BUFFERCOUNT,
84                &AudioPlayer::AudioSinkCallback, this);
85        if (err != OK) {
86            mSource->stop();
87
88            return err;
89        }
90
91        mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
92        mFrameSize = mAudioSink->frameSize();
93
94        mAudioSink->start();
95    } else {
96        mAudioTrack = new AudioTrack(
97                AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT,
98                (numChannels == 2)
99                    ? AudioSystem::CHANNEL_OUT_STEREO
100                    : AudioSystem::CHANNEL_OUT_MONO,
101                8192, 0, &AudioCallback, this, 0);
102
103        if ((err = mAudioTrack->initCheck()) != OK) {
104            delete mAudioTrack;
105            mAudioTrack = NULL;
106
107            mSource->stop();
108
109            return err;
110        }
111
112        mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
113        mFrameSize = mAudioTrack->frameSize();
114
115        mAudioTrack->start();
116    }
117
118    mStarted = true;
119
120    return OK;
121}
122
123void AudioPlayer::pause() {
124    CHECK(mStarted);
125
126    if (mAudioSink.get() != NULL) {
127        mAudioSink->pause();
128    } else {
129        mAudioTrack->stop();
130    }
131}
132
133void AudioPlayer::resume() {
134    CHECK(mStarted);
135
136    if (mAudioSink.get() != NULL) {
137        mAudioSink->start();
138    } else {
139        mAudioTrack->start();
140    }
141}
142
143void AudioPlayer::stop() {
144    CHECK(mStarted);
145
146    if (mAudioSink.get() != NULL) {
147        mAudioSink->stop();
148        mAudioSink->close();
149    } else {
150        mAudioTrack->stop();
151
152        delete mAudioTrack;
153        mAudioTrack = NULL;
154    }
155
156    // Make sure to release any buffer we hold onto so that the
157    // source is able to stop().
158    if (mInputBuffer != NULL) {
159        LOGV("AudioPlayer releasing input buffer.");
160
161        mInputBuffer->release();
162        mInputBuffer = NULL;
163    }
164
165    mSource->stop();
166
167    mNumFramesPlayed = 0;
168    mPositionTimeMediaUs = -1;
169    mPositionTimeRealUs = -1;
170    mSeeking = false;
171    mReachedEOS = false;
172    mFinalStatus = OK;
173    mStarted = false;
174}
175
176// static
177void AudioPlayer::AudioCallback(int event, void *user, void *info) {
178    static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
179}
180
181bool AudioPlayer::isSeeking() {
182    Mutex::Autolock autoLock(mLock);
183    return mSeeking;
184}
185
186bool AudioPlayer::reachedEOS(status_t *finalStatus) {
187    *finalStatus = OK;
188
189    Mutex::Autolock autoLock(mLock);
190    *finalStatus = mFinalStatus;
191    return mReachedEOS;
192}
193
194// static
195size_t AudioPlayer::AudioSinkCallback(
196        MediaPlayerBase::AudioSink *audioSink,
197        void *buffer, size_t size, void *cookie) {
198    AudioPlayer *me = (AudioPlayer *)cookie;
199
200    return me->fillBuffer(buffer, size);
201}
202
203void AudioPlayer::AudioCallback(int event, void *info) {
204    if (event != AudioTrack::EVENT_MORE_DATA) {
205        return;
206    }
207
208    AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
209    size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
210
211    buffer->size = numBytesWritten;
212}
213
214size_t AudioPlayer::fillBuffer(void *data, size_t size) {
215    if (mNumFramesPlayed == 0) {
216        LOGV("AudioCallback");
217    }
218
219    if (mReachedEOS) {
220        return 0;
221    }
222
223    size_t size_done = 0;
224    size_t size_remaining = size;
225    while (size_remaining > 0) {
226        MediaSource::ReadOptions options;
227
228        {
229            Mutex::Autolock autoLock(mLock);
230
231            if (mSeeking) {
232                options.setSeekTo(mSeekTimeUs);
233
234                if (mInputBuffer != NULL) {
235                    mInputBuffer->release();
236                    mInputBuffer = NULL;
237                }
238
239                mSeeking = false;
240            }
241        }
242
243        if (mInputBuffer == NULL) {
244            status_t err = mSource->read(&mInputBuffer, &options);
245
246            CHECK((err == OK && mInputBuffer != NULL)
247                   || (err != OK && mInputBuffer == NULL));
248
249            Mutex::Autolock autoLock(mLock);
250
251            if (err != OK) {
252                mReachedEOS = true;
253                mFinalStatus = err;
254                break;
255            }
256
257            CHECK(mInputBuffer->meta_data()->findInt64(
258                        kKeyTime, &mPositionTimeMediaUs));
259
260            mPositionTimeRealUs =
261                ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
262                    / mSampleRate;
263
264            LOGV("buffer->size() = %d, "
265                 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
266                 mInputBuffer->range_length(),
267                 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
268        }
269
270        if (mInputBuffer->range_length() == 0) {
271            mInputBuffer->release();
272            mInputBuffer = NULL;
273
274            continue;
275        }
276
277        size_t copy = size_remaining;
278        if (copy > mInputBuffer->range_length()) {
279            copy = mInputBuffer->range_length();
280        }
281
282        memcpy((char *)data + size_done,
283               (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
284               copy);
285
286        mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
287                                mInputBuffer->range_length() - copy);
288
289        size_done += copy;
290        size_remaining -= copy;
291    }
292
293    Mutex::Autolock autoLock(mLock);
294    mNumFramesPlayed += size_done / mFrameSize;
295
296    return size_done;
297}
298
299int64_t AudioPlayer::getRealTimeUs() {
300    Mutex::Autolock autoLock(mLock);
301    return getRealTimeUsLocked();
302}
303
304int64_t AudioPlayer::getRealTimeUsLocked() const {
305    return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
306}
307
308int64_t AudioPlayer::getMediaTimeUs() {
309    Mutex::Autolock autoLock(mLock);
310
311    if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
312        return 0;
313    }
314
315    int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
316    if (realTimeOffset < 0) {
317        realTimeOffset = 0;
318    }
319
320    return mPositionTimeMediaUs + realTimeOffset;
321}
322
323bool AudioPlayer::getMediaTimeMapping(
324        int64_t *realtime_us, int64_t *mediatime_us) {
325    Mutex::Autolock autoLock(mLock);
326
327    *realtime_us = mPositionTimeRealUs;
328    *mediatime_us = mPositionTimeMediaUs;
329
330    return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
331}
332
333status_t AudioPlayer::seekTo(int64_t time_us) {
334    Mutex::Autolock autoLock(mLock);
335
336    mSeeking = true;
337    mReachedEOS = false;
338    mSeekTimeUs = time_us;
339
340    return OK;
341}
342
343}
344