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