AudioPlayer.cpp revision b2e3954c94717e43b3dc9b880564f166cfbbc0a2
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 <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> 29 30#include "include/AwesomePlayer.h" 31 32namespace android { 33 34AudioPlayer::AudioPlayer( 35 const sp<MediaPlayerBase::AudioSink> &audioSink, 36 AwesomePlayer *observer) 37 : mAudioTrack(NULL), 38 mInputBuffer(NULL), 39 mSampleRate(0), 40 mLatencyUs(0), 41 mFrameSize(0), 42 mNumFramesPlayed(0), 43 mPositionTimeMediaUs(-1), 44 mPositionTimeRealUs(-1), 45 mSeeking(false), 46 mReachedEOS(false), 47 mFinalStatus(OK), 48 mStarted(false), 49 mIsFirstBuffer(false), 50 mFirstBufferResult(OK), 51 mFirstBuffer(NULL), 52 mAudioSink(audioSink), 53 mObserver(observer) { 54} 55 56AudioPlayer::~AudioPlayer() { 57 if (mStarted) { 58 reset(); 59 } 60} 61 62void AudioPlayer::setSource(const sp<MediaSource> &source) { 63 CHECK_EQ(mSource, NULL); 64 mSource = source; 65} 66 67status_t AudioPlayer::start(bool sourceAlreadyStarted) { 68 CHECK(!mStarted); 69 CHECK(mSource != NULL); 70 71 status_t err; 72 if (!sourceAlreadyStarted) { 73 err = mSource->start(); 74 75 if (err != OK) { 76 return err; 77 } 78 } 79 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. 84 85 CHECK(mFirstBuffer == NULL); 86 87 mFirstBufferResult = mSource->read(&mFirstBuffer); 88 if (mFirstBufferResult == INFO_FORMAT_CHANGED) { 89 LOGV("INFO_FORMAT_CHANGED!!!"); 90 91 CHECK(mFirstBuffer == NULL); 92 mFirstBufferResult = OK; 93 mIsFirstBuffer = false; 94 } else { 95 mIsFirstBuffer = true; 96 } 97 98 sp<MetaData> format = mSource->getFormat(); 99 const char *mime; 100 bool success = format->findCString(kKeyMIMEType, &mime); 101 CHECK(success); 102 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)); 103 104 success = format->findInt32(kKeySampleRate, &mSampleRate); 105 CHECK(success); 106 107 int32_t numChannels; 108 success = format->findInt32(kKeyChannelCount, &numChannels); 109 CHECK(success); 110 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); 116 if (err != OK) { 117 if (mFirstBuffer != NULL) { 118 mFirstBuffer->release(); 119 mFirstBuffer = NULL; 120 } 121 122 if (!sourceAlreadyStarted) { 123 mSource->stop(); 124 } 125 126 return err; 127 } 128 129 mLatencyUs = (int64_t)mAudioSink->latency() * 1000; 130 mFrameSize = mAudioSink->frameSize(); 131 132 mAudioSink->start(); 133 } else { 134 mAudioTrack = new AudioTrack( 135 AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT, 136 (numChannels == 2) 137 ? AudioSystem::CHANNEL_OUT_STEREO 138 : AudioSystem::CHANNEL_OUT_MONO, 139 0, 0, &AudioCallback, this, 0); 140 141 if ((err = mAudioTrack->initCheck()) != OK) { 142 delete mAudioTrack; 143 mAudioTrack = NULL; 144 145 if (mFirstBuffer != NULL) { 146 mFirstBuffer->release(); 147 mFirstBuffer = NULL; 148 } 149 150 if (!sourceAlreadyStarted) { 151 mSource->stop(); 152 } 153 154 return err; 155 } 156 157 mLatencyUs = (int64_t)mAudioTrack->latency() * 1000; 158 mFrameSize = mAudioTrack->frameSize(); 159 160 mAudioTrack->start(); 161 } 162 163 mStarted = true; 164 165 return OK; 166} 167 168void AudioPlayer::pause(bool playPendingSamples) { 169 CHECK(mStarted); 170 171 if (playPendingSamples) { 172 if (mAudioSink.get() != NULL) { 173 mAudioSink->stop(); 174 } else { 175 mAudioTrack->stop(); 176 } 177 } else { 178 if (mAudioSink.get() != NULL) { 179 mAudioSink->pause(); 180 } else { 181 mAudioTrack->pause(); 182 } 183 } 184} 185 186void AudioPlayer::resume() { 187 CHECK(mStarted); 188 189 if (mAudioSink.get() != NULL) { 190 mAudioSink->start(); 191 } else { 192 mAudioTrack->start(); 193 } 194} 195 196void AudioPlayer::reset() { 197 CHECK(mStarted); 198 199 if (mAudioSink.get() != NULL) { 200 mAudioSink->stop(); 201 mAudioSink->close(); 202 } else { 203 mAudioTrack->stop(); 204 205 delete mAudioTrack; 206 mAudioTrack = NULL; 207 } 208 209 // Make sure to release any buffer we hold onto so that the 210 // source is able to stop(). 211 212 if (mFirstBuffer != NULL) { 213 mFirstBuffer->release(); 214 mFirstBuffer = NULL; 215 } 216 217 if (mInputBuffer != NULL) { 218 LOGV("AudioPlayer releasing input buffer."); 219 220 mInputBuffer->release(); 221 mInputBuffer = NULL; 222 } 223 224 mSource->stop(); 225 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; 230 mSource.clear(); 231 while (tmp.promote() != NULL) { 232 usleep(1000); 233 } 234 IPCThreadState::self()->flushCommands(); 235 236 mNumFramesPlayed = 0; 237 mPositionTimeMediaUs = -1; 238 mPositionTimeRealUs = -1; 239 mSeeking = false; 240 mReachedEOS = false; 241 mFinalStatus = OK; 242 mStarted = false; 243} 244 245// static 246void AudioPlayer::AudioCallback(int event, void *user, void *info) { 247 static_cast<AudioPlayer *>(user)->AudioCallback(event, info); 248} 249 250bool AudioPlayer::isSeeking() { 251 Mutex::Autolock autoLock(mLock); 252 return mSeeking; 253} 254 255bool AudioPlayer::reachedEOS(status_t *finalStatus) { 256 *finalStatus = OK; 257 258 Mutex::Autolock autoLock(mLock); 259 *finalStatus = mFinalStatus; 260 return mReachedEOS; 261} 262 263// static 264size_t AudioPlayer::AudioSinkCallback( 265 MediaPlayerBase::AudioSink *audioSink, 266 void *buffer, size_t size, void *cookie) { 267 AudioPlayer *me = (AudioPlayer *)cookie; 268 269 return me->fillBuffer(buffer, size); 270} 271 272void AudioPlayer::AudioCallback(int event, void *info) { 273 if (event != AudioTrack::EVENT_MORE_DATA) { 274 return; 275 } 276 277 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info; 278 size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size); 279 280 buffer->size = numBytesWritten; 281} 282 283size_t AudioPlayer::fillBuffer(void *data, size_t size) { 284 if (mNumFramesPlayed == 0) { 285 LOGV("AudioCallback"); 286 } 287 288 if (mReachedEOS) { 289 return 0; 290 } 291 292 size_t size_done = 0; 293 size_t size_remaining = size; 294 while (size_remaining > 0) { 295 MediaSource::ReadOptions options; 296 297 { 298 Mutex::Autolock autoLock(mLock); 299 300 if (mSeeking) { 301 if (mIsFirstBuffer) { 302 if (mFirstBuffer != NULL) { 303 mFirstBuffer->release(); 304 mFirstBuffer = NULL; 305 } 306 mIsFirstBuffer = false; 307 } 308 309 options.setSeekTo(mSeekTimeUs); 310 311 if (mInputBuffer != NULL) { 312 mInputBuffer->release(); 313 mInputBuffer = NULL; 314 } 315 316 mSeeking = false; 317 if (mObserver) { 318 mObserver->postAudioSeekComplete(); 319 } 320 } 321 } 322 323 if (mInputBuffer == NULL) { 324 status_t err; 325 326 if (mIsFirstBuffer) { 327 mInputBuffer = mFirstBuffer; 328 mFirstBuffer = NULL; 329 err = mFirstBufferResult; 330 331 mIsFirstBuffer = false; 332 } else { 333 err = mSource->read(&mInputBuffer, &options); 334 } 335 336 CHECK((err == OK && mInputBuffer != NULL) 337 || (err != OK && mInputBuffer == NULL)); 338 339 Mutex::Autolock autoLock(mLock); 340 341 if (err != OK) { 342 if (mObserver && !mReachedEOS) { 343 mObserver->postAudioEOS(); 344 } 345 346 mReachedEOS = true; 347 mFinalStatus = err; 348 break; 349 } 350 351 CHECK(mInputBuffer->meta_data()->findInt64( 352 kKeyTime, &mPositionTimeMediaUs)); 353 354 mPositionTimeRealUs = 355 ((mNumFramesPlayed + size_done / mFrameSize) * 1000000) 356 / mSampleRate; 357 358 LOGV("buffer->size() = %d, " 359 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f", 360 mInputBuffer->range_length(), 361 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6); 362 } 363 364 if (mInputBuffer->range_length() == 0) { 365 mInputBuffer->release(); 366 mInputBuffer = NULL; 367 368 continue; 369 } 370 371 size_t copy = size_remaining; 372 if (copy > mInputBuffer->range_length()) { 373 copy = mInputBuffer->range_length(); 374 } 375 376 memcpy((char *)data + size_done, 377 (const char *)mInputBuffer->data() + mInputBuffer->range_offset(), 378 copy); 379 380 mInputBuffer->set_range(mInputBuffer->range_offset() + copy, 381 mInputBuffer->range_length() - copy); 382 383 size_done += copy; 384 size_remaining -= copy; 385 } 386 387 Mutex::Autolock autoLock(mLock); 388 mNumFramesPlayed += size_done / mFrameSize; 389 390 return size_done; 391} 392 393int64_t AudioPlayer::getRealTimeUs() { 394 Mutex::Autolock autoLock(mLock); 395 return getRealTimeUsLocked(); 396} 397 398int64_t AudioPlayer::getRealTimeUsLocked() const { 399 return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate; 400} 401 402int64_t AudioPlayer::getMediaTimeUs() { 403 Mutex::Autolock autoLock(mLock); 404 405 if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) { 406 return 0; 407 } 408 409 int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs; 410 if (realTimeOffset < 0) { 411 realTimeOffset = 0; 412 } 413 414 return mPositionTimeMediaUs + realTimeOffset; 415} 416 417bool AudioPlayer::getMediaTimeMapping( 418 int64_t *realtime_us, int64_t *mediatime_us) { 419 Mutex::Autolock autoLock(mLock); 420 421 *realtime_us = mPositionTimeRealUs; 422 *mediatime_us = mPositionTimeMediaUs; 423 424 return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1; 425} 426 427status_t AudioPlayer::seekTo(int64_t time_us) { 428 Mutex::Autolock autoLock(mLock); 429 430 mSeeking = true; 431 mReachedEOS = false; 432 mSeekTimeUs = time_us; 433 434 if (mAudioSink != NULL) { 435 mAudioSink->flush(); 436 } else { 437 mAudioTrack->flush(); 438 } 439 440 return OK; 441} 442 443} 444