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