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