AudioPlayer.cpp revision 84ec55b736ae2278d6abdc1c7a0312de46ef5f3d
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      mStarted(false),
41      mAudioSink(audioSink) {
42}
43
44AudioPlayer::~AudioPlayer() {
45    if (mStarted) {
46        stop();
47    }
48}
49
50void AudioPlayer::setSource(const sp<MediaSource> &source) {
51    CHECK_EQ(mSource, NULL);
52    mSource = source;
53}
54
55void AudioPlayer::start() {
56    CHECK(!mStarted);
57    CHECK(mSource != NULL);
58
59    status_t err = mSource->start();
60    CHECK_EQ(err, OK);
61
62    sp<MetaData> format = mSource->getFormat();
63    const char *mime;
64    bool success = format->findCString(kKeyMIMEType, &mime);
65    CHECK(success);
66    CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
67
68    success = format->findInt32(kKeySampleRate, &mSampleRate);
69    CHECK(success);
70
71    int32_t numChannels;
72    success = format->findInt32(kKeyChannelCount, &numChannels);
73    CHECK(success);
74
75    if (mAudioSink.get() != NULL) {
76        status_t err = mAudioSink->open(
77                mSampleRate, numChannels, AudioSystem::PCM_16_BIT,
78                DEFAULT_AUDIOSINK_BUFFERCOUNT,
79                &AudioPlayer::AudioSinkCallback, this);
80        CHECK_EQ(err, OK);
81
82        mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
83        mFrameSize = mAudioSink->frameSize();
84
85        mAudioSink->start();
86    } else {
87        mAudioTrack = new AudioTrack(
88                AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT,
89                (numChannels == 2)
90                    ? AudioSystem::CHANNEL_OUT_STEREO
91                    : AudioSystem::CHANNEL_OUT_MONO,
92                8192, 0, &AudioCallback, this, 0);
93
94        CHECK_EQ(mAudioTrack->initCheck(), OK);
95
96        mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
97        mFrameSize = mAudioTrack->frameSize();
98
99        mAudioTrack->start();
100    }
101
102    mStarted = true;
103}
104
105void AudioPlayer::pause() {
106    CHECK(mStarted);
107
108    if (mAudioSink.get() != NULL) {
109        mAudioSink->pause();
110    } else {
111        mAudioTrack->stop();
112    }
113}
114
115void AudioPlayer::resume() {
116    CHECK(mStarted);
117
118    if (mAudioSink.get() != NULL) {
119        mAudioSink->start();
120    } else {
121        mAudioTrack->start();
122    }
123}
124
125void AudioPlayer::stop() {
126    CHECK(mStarted);
127
128    if (mAudioSink.get() != NULL) {
129        mAudioSink->stop();
130    } else {
131        mAudioTrack->stop();
132
133        delete mAudioTrack;
134        mAudioTrack = NULL;
135    }
136
137    // Make sure to release any buffer we hold onto so that the
138    // source is able to stop().
139    if (mInputBuffer != NULL) {
140        LOGV("AudioPlayer releasing input buffer.");
141
142        mInputBuffer->release();
143        mInputBuffer = NULL;
144    }
145
146    mSource->stop();
147
148    mNumFramesPlayed = 0;
149    mPositionTimeMediaUs = -1;
150    mPositionTimeRealUs = -1;
151    mSeeking = false;
152    mStarted = false;
153}
154
155// static
156void AudioPlayer::AudioCallback(int event, void *user, void *info) {
157    static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
158}
159
160// static
161void AudioPlayer::AudioSinkCallback(
162        MediaPlayerBase::AudioSink *audioSink,
163        void *buffer, size_t size, void *cookie) {
164    AudioPlayer *me = (AudioPlayer *)cookie;
165
166    me->fillBuffer(buffer, size);
167}
168
169void AudioPlayer::AudioCallback(int event, void *info) {
170    if (event != AudioTrack::EVENT_MORE_DATA) {
171        return;
172    }
173
174    AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
175    fillBuffer(buffer->raw, buffer->size);
176}
177
178void AudioPlayer::fillBuffer(void *data, size_t size) {
179    if (mNumFramesPlayed == 0) {
180        LOGV("AudioCallback");
181    }
182
183    size_t size_done = 0;
184    size_t size_remaining = size;
185    while (size_remaining > 0) {
186        MediaSource::ReadOptions options;
187
188        {
189            Mutex::Autolock autoLock(mLock);
190
191            if (mSeeking) {
192                options.setSeekTo(mSeekTimeUs);
193
194                if (mInputBuffer != NULL) {
195                    mInputBuffer->release();
196                    mInputBuffer = NULL;
197                }
198                mSeeking = false;
199            }
200        }
201
202        if (mInputBuffer == NULL) {
203            status_t err = mSource->read(&mInputBuffer, &options);
204
205            CHECK((err == OK && mInputBuffer != NULL)
206                   || (err != OK && mInputBuffer == NULL));
207
208            if (err != OK) {
209                memset((char *)data + size_done, 0, size_remaining);
210                break;
211            }
212
213            Mutex::Autolock autoLock(mLock);
214            CHECK(mInputBuffer->meta_data()->findInt64(
215                        kKeyTime, &mPositionTimeMediaUs));
216
217            mPositionTimeRealUs =
218                ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
219                    / mSampleRate;
220
221            LOGV("buffer->size() = %d, "
222                 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
223                 mInputBuffer->range_length(),
224                 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
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