2 * Copyright (C) 2009 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "AudioPlayer"
19 #include <utils/Log.h>
21 #include <binder/IPCThreadState.h>
22 #include <media/AudioTrack.h>
23 #include <media/stagefright/AudioPlayer.h>
24 #include <media/stagefright/MediaDebug.h>
25 #include <media/stagefright/MediaDefs.h>
26 #include <media/stagefright/MediaErrors.h>
27 #include <media/stagefright/MediaSource.h>
28 #include <media/stagefright/MetaData.h>
30 #include "include/AwesomePlayer.h"
34 AudioPlayer::AudioPlayer(
35 const sp<MediaPlayerBase::AudioSink> &audioSink,
36 AwesomePlayer *observer)
43 mPositionTimeMediaUs(-1),
44 mPositionTimeRealUs(-1),
49 mIsFirstBuffer(false),
50 mFirstBufferResult(OK),
52 mAudioSink(audioSink),
56 AudioPlayer::~AudioPlayer() {
62 void AudioPlayer::setSource(const sp<MediaSource> &source) {
63 CHECK_EQ(mSource, NULL);
67 status_t AudioPlayer::start(bool sourceAlreadyStarted) {
69 CHECK(mSource != NULL);
72 if (!sourceAlreadyStarted) {
73 err = mSource->start();
80 // We allow an optional INFO_FORMAT_CHANGED at the very beginning
81 // of playback, if there is one, getFormat below will retrieve the
82 // updated format, if there isn't, we'll stash away the valid buffer
83 // of data to be used on the first audio callback.
85 CHECK(mFirstBuffer == NULL);
87 mFirstBufferResult = mSource->read(&mFirstBuffer);
88 if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
89 LOGV("INFO_FORMAT_CHANGED!!!");
91 CHECK(mFirstBuffer == NULL);
92 mFirstBufferResult = OK;
93 mIsFirstBuffer = false;
95 mIsFirstBuffer = true;
98 sp<MetaData> format = mSource->getFormat();
100 bool success = format->findCString(kKeyMIMEType, &mime);
102 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
104 success = format->findInt32(kKeySampleRate, &mSampleRate);
108 success = format->findInt32(kKeyChannelCount, &numChannels);
111 if (mAudioSink.get() != NULL) {
112 status_t err = mAudioSink->open(
113 mSampleRate, numChannels, AudioSystem::PCM_16_BIT,
114 DEFAULT_AUDIOSINK_BUFFERCOUNT,
115 &AudioPlayer::AudioSinkCallback, this);
117 if (mFirstBuffer != NULL) {
118 mFirstBuffer->release();
122 if (!sourceAlreadyStarted) {
129 mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
130 mFrameSize = mAudioSink->frameSize();
134 mAudioTrack = new AudioTrack(
135 AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT,
137 ? AudioSystem::CHANNEL_OUT_STEREO
138 : AudioSystem::CHANNEL_OUT_MONO,
139 0, 0, &AudioCallback, this, 0);
141 if ((err = mAudioTrack->initCheck()) != OK) {
145 if (mFirstBuffer != NULL) {
146 mFirstBuffer->release();
150 if (!sourceAlreadyStarted) {
157 mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
158 mFrameSize = mAudioTrack->frameSize();
160 mAudioTrack->start();
168 void AudioPlayer::pause(bool playPendingSamples) {
171 if (playPendingSamples) {
172 if (mAudioSink.get() != NULL) {
178 if (mAudioSink.get() != NULL) {
181 mAudioTrack->pause();
186 void AudioPlayer::resume() {
189 if (mAudioSink.get() != NULL) {
192 mAudioTrack->start();
196 void AudioPlayer::reset() {
199 if (mAudioSink.get() != NULL) {
209 // Make sure to release any buffer we hold onto so that the
210 // source is able to stop().
212 if (mFirstBuffer != NULL) {
213 mFirstBuffer->release();
217 if (mInputBuffer != NULL) {
218 LOGV("AudioPlayer releasing input buffer.");
220 mInputBuffer->release();
226 // The following hack is necessary to ensure that the OMX
227 // component is completely released by the time we may try
228 // to instantiate it again.
229 wp<MediaSource> tmp = mSource;
231 while (tmp.promote() != NULL) {
234 IPCThreadState::self()->flushCommands();
236 mNumFramesPlayed = 0;
237 mPositionTimeMediaUs = -1;
238 mPositionTimeRealUs = -1;
246 void AudioPlayer::AudioCallback(int event, void *user, void *info) {
247 static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
250 bool AudioPlayer::isSeeking() {
251 Mutex::Autolock autoLock(mLock);
255 bool AudioPlayer::reachedEOS(status_t *finalStatus) {
258 Mutex::Autolock autoLock(mLock);
259 *finalStatus = mFinalStatus;
264 size_t AudioPlayer::AudioSinkCallback(
265 MediaPlayerBase::AudioSink *audioSink,
266 void *buffer, size_t size, void *cookie) {
267 AudioPlayer *me = (AudioPlayer *)cookie;
269 return me->fillBuffer(buffer, size);
272 void AudioPlayer::AudioCallback(int event, void *info) {
273 if (event != AudioTrack::EVENT_MORE_DATA) {
277 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
278 size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
280 buffer->size = numBytesWritten;
283 size_t AudioPlayer::fillBuffer(void *data, size_t size) {
284 if (mNumFramesPlayed == 0) {
285 LOGV("AudioCallback");
292 size_t size_done = 0;
293 size_t size_remaining = size;
294 while (size_remaining > 0) {
295 MediaSource::ReadOptions options;
298 Mutex::Autolock autoLock(mLock);
301 if (mIsFirstBuffer) {
302 if (mFirstBuffer != NULL) {
303 mFirstBuffer->release();
306 mIsFirstBuffer = false;
309 options.setSeekTo(mSeekTimeUs);
311 if (mInputBuffer != NULL) {
312 mInputBuffer->release();
318 mObserver->postAudioSeekComplete();
323 if (mInputBuffer == NULL) {
326 if (mIsFirstBuffer) {
327 mInputBuffer = mFirstBuffer;
329 err = mFirstBufferResult;
331 mIsFirstBuffer = false;
333 err = mSource->read(&mInputBuffer, &options);
336 CHECK((err == OK && mInputBuffer != NULL)
337 || (err != OK && mInputBuffer == NULL));
339 Mutex::Autolock autoLock(mLock);
342 if (mObserver && !mReachedEOS) {
343 mObserver->postAudioEOS();
351 CHECK(mInputBuffer->meta_data()->findInt64(
352 kKeyTime, &mPositionTimeMediaUs));
354 mPositionTimeRealUs =
355 ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
358 LOGV("buffer->size() = %d, "
359 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
360 mInputBuffer->range_length(),
361 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
364 if (mInputBuffer->range_length() == 0) {
365 mInputBuffer->release();
371 size_t copy = size_remaining;
372 if (copy > mInputBuffer->range_length()) {
373 copy = mInputBuffer->range_length();
376 memcpy((char *)data + size_done,
377 (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
380 mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
381 mInputBuffer->range_length() - copy);
384 size_remaining -= copy;
387 Mutex::Autolock autoLock(mLock);
388 mNumFramesPlayed += size_done / mFrameSize;
393 int64_t AudioPlayer::getRealTimeUs() {
394 Mutex::Autolock autoLock(mLock);
395 return getRealTimeUsLocked();
398 int64_t AudioPlayer::getRealTimeUsLocked() const {
399 return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
402 int64_t AudioPlayer::getMediaTimeUs() {
403 Mutex::Autolock autoLock(mLock);
405 if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
409 int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
410 if (realTimeOffset < 0) {
414 return mPositionTimeMediaUs + realTimeOffset;
417 bool AudioPlayer::getMediaTimeMapping(
418 int64_t *realtime_us, int64_t *mediatime_us) {
419 Mutex::Autolock autoLock(mLock);
421 *realtime_us = mPositionTimeRealUs;
422 *mediatime_us = mPositionTimeMediaUs;
424 return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
427 status_t AudioPlayer::seekTo(int64_t time_us) {
428 Mutex::Autolock autoLock(mLock);
432 mSeekTimeUs = time_us;
434 if (mAudioSink != NULL) {
437 mAudioTrack->flush();