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