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