AudioPlayer.cpp revision fe9b71919cdddf898a516169db840751878098ca
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 memset(data, 0, size); 290 291 return size; 292 } 293 294 size_t size_done = 0; 295 size_t size_remaining = size; 296 while (size_remaining > 0) { 297 MediaSource::ReadOptions options; 298 299 { 300 Mutex::Autolock autoLock(mLock); 301 302 if (mSeeking) { 303 if (mIsFirstBuffer) { 304 if (mFirstBuffer != NULL) { 305 mFirstBuffer->release(); 306 mFirstBuffer = NULL; 307 } 308 mIsFirstBuffer = false; 309 } 310 311 options.setSeekTo(mSeekTimeUs); 312 313 if (mInputBuffer != NULL) { 314 mInputBuffer->release(); 315 mInputBuffer = NULL; 316 } 317 318 mSeeking = false; 319 if (mObserver) { 320 mObserver->postAudioSeekComplete(); 321 } 322 } 323 } 324 325 if (mInputBuffer == NULL) { 326 status_t err; 327 328 if (mIsFirstBuffer) { 329 mInputBuffer = mFirstBuffer; 330 mFirstBuffer = NULL; 331 err = mFirstBufferResult; 332 333 mIsFirstBuffer = false; 334 } else { 335 err = mSource->read(&mInputBuffer, &options); 336 } 337 338 CHECK((err == OK && mInputBuffer != NULL) 339 || (err != OK && mInputBuffer == NULL)); 340 341 Mutex::Autolock autoLock(mLock); 342 343 if (err != OK) { 344 if (mObserver && !mReachedEOS) { 345 mObserver->postAudioEOS(); 346 } 347 348 mReachedEOS = true; 349 mFinalStatus = err; 350 break; 351 } 352 353 CHECK(mInputBuffer->meta_data()->findInt64( 354 kKeyTime, &mPositionTimeMediaUs)); 355 356 mPositionTimeRealUs = 357 ((mNumFramesPlayed + size_done / mFrameSize) * 1000000) 358 / mSampleRate; 359 360 LOGV("buffer->size() = %d, " 361 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f", 362 mInputBuffer->range_length(), 363 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6); 364 } 365 366 if (mInputBuffer->range_length() == 0) { 367 mInputBuffer->release(); 368 mInputBuffer = NULL; 369 370 continue; 371 } 372 373 size_t copy = size_remaining; 374 if (copy > mInputBuffer->range_length()) { 375 copy = mInputBuffer->range_length(); 376 } 377 378 memcpy((char *)data + size_done, 379 (const char *)mInputBuffer->data() + mInputBuffer->range_offset(), 380 copy); 381 382 mInputBuffer->set_range(mInputBuffer->range_offset() + copy, 383 mInputBuffer->range_length() - copy); 384 385 size_done += copy; 386 size_remaining -= copy; 387 } 388 389 Mutex::Autolock autoLock(mLock); 390 mNumFramesPlayed += size_done / mFrameSize; 391 392 return size_done; 393} 394 395int64_t AudioPlayer::getRealTimeUs() { 396 Mutex::Autolock autoLock(mLock); 397 return getRealTimeUsLocked(); 398} 399 400int64_t AudioPlayer::getRealTimeUsLocked() const { 401 return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate; 402} 403 404int64_t AudioPlayer::getMediaTimeUs() { 405 Mutex::Autolock autoLock(mLock); 406 407 if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) { 408 if (mSeeking) { 409 return mSeekTimeUs; 410 } 411 412 return 0; 413 } 414 415 int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs; 416 if (realTimeOffset < 0) { 417 realTimeOffset = 0; 418 } 419 420 return mPositionTimeMediaUs + realTimeOffset; 421} 422 423bool AudioPlayer::getMediaTimeMapping( 424 int64_t *realtime_us, int64_t *mediatime_us) { 425 Mutex::Autolock autoLock(mLock); 426 427 *realtime_us = mPositionTimeRealUs; 428 *mediatime_us = mPositionTimeMediaUs; 429 430 return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1; 431} 432 433status_t AudioPlayer::seekTo(int64_t time_us) { 434 Mutex::Autolock autoLock(mLock); 435 436 mSeeking = true; 437 mPositionTimeRealUs = mPositionTimeMediaUs = -1; 438 mReachedEOS = false; 439 mSeekTimeUs = time_us; 440 441 if (mAudioSink != NULL) { 442 mAudioSink->flush(); 443 } else { 444 mAudioTrack->flush(); 445 } 446 447 return OK; 448} 449 450} 451