AwesomePlayer.cpp revision d6119356f45c9c57cac812357d969ecc3001087e
122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/* 222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * Copyright (C) 2009 The Android Open Source Project 322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * 422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * Licensed under the Apache License, Version 2.0 (the "License"); 522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * you may not use this file except in compliance with the License. 622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * You may obtain a copy of the License at 722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * 822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * http://www.apache.org/licenses/LICENSE-2.0 987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * 1087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * Unless required by applicable law or agreed to in writing, software 1122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * distributed under the License is distributed on an "AS IS" BASIS, 1222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * See the License for the specific language governing permissions and 1422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * limitations under the License. 15d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao */ 1622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//#define LOG_NDEBUG 0 1822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#define LOG_TAG "AwesomePlayer" 1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <utils/Log.h> 206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <dlfcn.h> 2222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 2322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "include/ARTSPController.h" 2422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "include/AwesomePlayer.h" 2522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "include/LiveSource.h" 2622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "include/SoftwareRenderer.h" 2722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "include/NuCachedSource2.h" 2822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "include/ThrottledSource.h" 2922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "include/MPEG2TSExtractor.h" 3022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 3122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "ARTPSession.h" 3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "APacketSource.h" 3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "ASessionDescription.h" 3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "UDPPusher.h" 3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <binder/IPCThreadState.h> 376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <media/stagefright/AudioPlayer.h> 3822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/DataSource.h> 3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/FileSource.h> 4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/MediaBuffer.h> 4122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/MediaDefs.h> 4222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/MediaExtractor.h> 4322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/MediaDebug.h> 4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/MediaSource.h> 4522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/MetaData.h> 4622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/OMXCodec.h> 4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <surfaceflinger/Surface.h> 4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/foundation/ALooper.h> 5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaonamespace android { 5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaostatic int64_t kLowWaterMarkUs = 2000000ll; // 2secs 5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaostatic int64_t kHighWaterMarkUs = 10000000ll; // 10secs 5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 57struct AwesomeEvent : public TimedEventQueue::Event { 58 AwesomeEvent( 59 AwesomePlayer *player, 60 void (AwesomePlayer::*method)()) 61 : mPlayer(player), 62 mMethod(method) { 63 } 64 65protected: 66 virtual ~AwesomeEvent() {} 67 68 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { 69 (mPlayer->*mMethod)(); 70 } 71 72private: 73 AwesomePlayer *mPlayer; 74 void (AwesomePlayer::*mMethod)(); 75 76 AwesomeEvent(const AwesomeEvent &); 77 AwesomeEvent &operator=(const AwesomeEvent &); 78}; 79 80struct AwesomeRemoteRenderer : public AwesomeRenderer { 81 AwesomeRemoteRenderer(const sp<IOMXRenderer> &target) 82 : mTarget(target) { 83 } 84 85 virtual void render(MediaBuffer *buffer) { 86 void *id; 87 if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) { 88 mTarget->render((IOMX::buffer_id)id); 89 } 90 } 91 92private: 93 sp<IOMXRenderer> mTarget; 94 95 AwesomeRemoteRenderer(const AwesomeRemoteRenderer &); 96 AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &); 97}; 98 99struct AwesomeLocalRenderer : public AwesomeRenderer { 100 AwesomeLocalRenderer( 101 bool previewOnly, 102 const char *componentName, 103 OMX_COLOR_FORMATTYPE colorFormat, 104 const sp<ISurface> &isurface, 105 const sp<Surface> &surface, 106 size_t displayWidth, size_t displayHeight, 107 size_t decodedWidth, size_t decodedHeight) 108 : mTarget(NULL), 109 mLibHandle(NULL) { 110 init(previewOnly, componentName, 111 colorFormat, isurface, surface, displayWidth, 112 displayHeight, decodedWidth, decodedHeight); 113 } 114 115 virtual void render(MediaBuffer *buffer) { 116 render((const uint8_t *)buffer->data() + buffer->range_offset(), 117 buffer->range_length()); 118 } 119 120 void render(const void *data, size_t size) { 121 mTarget->render(data, size, NULL); 122 } 123 124protected: 125 virtual ~AwesomeLocalRenderer() { 126 delete mTarget; 127 mTarget = NULL; 128 129 if (mLibHandle) { 130 dlclose(mLibHandle); 131 mLibHandle = NULL; 132 } 133 } 134 135private: 136 VideoRenderer *mTarget; 137 void *mLibHandle; 138 139 void init( 140 bool previewOnly, 141 const char *componentName, 142 OMX_COLOR_FORMATTYPE colorFormat, 143 const sp<ISurface> &isurface, 144 const sp<Surface> &surface, 145 size_t displayWidth, size_t displayHeight, 146 size_t decodedWidth, size_t decodedHeight); 147 148 AwesomeLocalRenderer(const AwesomeLocalRenderer &); 149 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);; 150}; 151 152void AwesomeLocalRenderer::init( 153 bool previewOnly, 154 const char *componentName, 155 OMX_COLOR_FORMATTYPE colorFormat, 156 const sp<ISurface> &isurface, 157 const sp<Surface> &surface, 158 size_t displayWidth, size_t displayHeight, 159 size_t decodedWidth, size_t decodedHeight) { 160 if (!previewOnly) { 161 // We will stick to the vanilla software-color-converting renderer 162 // for "previewOnly" mode, to avoid unneccessarily switching overlays 163 // more often than necessary. 164 165 mLibHandle = dlopen("libstagefrighthw.so", RTLD_NOW); 166 167 if (mLibHandle) { 168 typedef VideoRenderer *(*CreateRendererFunc)( 169 const sp<ISurface> &surface, 170 const char *componentName, 171 OMX_COLOR_FORMATTYPE colorFormat, 172 size_t displayWidth, size_t displayHeight, 173 size_t decodedWidth, size_t decodedHeight); 174 175 CreateRendererFunc func = 176 (CreateRendererFunc)dlsym( 177 mLibHandle, 178 "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20" 179 "OMX_COLOR_FORMATTYPEjjjj"); 180 181 if (func) { 182 mTarget = 183 (*func)(isurface, componentName, colorFormat, 184 displayWidth, displayHeight, 185 decodedWidth, decodedHeight); 186 } 187 } 188 } 189 190 if (mTarget == NULL) { 191 mTarget = new SoftwareRenderer( 192 colorFormat, surface, displayWidth, displayHeight, 193 decodedWidth, decodedHeight); 194 } 195} 196 197AwesomePlayer::AwesomePlayer() 198 : mQueueStarted(false), 199 mTimeSource(NULL), 200 mVideoRendererIsPreview(false), 201 mAudioPlayer(NULL), 202 mFlags(0), 203 mExtractorFlags(0), 204 mLastVideoBuffer(NULL), 205 mVideoBuffer(NULL), 206 mSuspensionState(NULL) { 207 CHECK_EQ(mClient.connect(), OK); 208 209 DataSource::RegisterDefaultSniffers(); 210 211 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent); 212 mVideoEventPending = false; 213 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone); 214 mStreamDoneEventPending = false; 215 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate); 216 mBufferingEventPending = false; 217 218 mCheckAudioStatusEvent = new AwesomeEvent( 219 this, &AwesomePlayer::onCheckAudioStatus); 220 221 mAudioStatusEventPending = false; 222 223 reset(); 224} 225 226AwesomePlayer::~AwesomePlayer() { 227 if (mQueueStarted) { 228 mQueue.stop(); 229 } 230 231 reset(); 232 233 mClient.disconnect(); 234} 235 236void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) { 237 mQueue.cancelEvent(mVideoEvent->eventID()); 238 mVideoEventPending = false; 239 mQueue.cancelEvent(mStreamDoneEvent->eventID()); 240 mStreamDoneEventPending = false; 241 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID()); 242 mAudioStatusEventPending = false; 243 244 if (!keepBufferingGoing) { 245 mQueue.cancelEvent(mBufferingEvent->eventID()); 246 mBufferingEventPending = false; 247 } 248} 249 250void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) { 251 Mutex::Autolock autoLock(mLock); 252 mListener = listener; 253} 254 255status_t AwesomePlayer::setDataSource( 256 const char *uri, const KeyedVector<String8, String8> *headers) { 257 Mutex::Autolock autoLock(mLock); 258 return setDataSource_l(uri, headers); 259} 260 261status_t AwesomePlayer::setDataSource_l( 262 const char *uri, const KeyedVector<String8, String8> *headers) { 263 reset_l(); 264 265 mUri = uri; 266 267 if (headers) { 268 mUriHeaders = *headers; 269 } 270 271 // The actual work will be done during preparation in the call to 272 // ::finishSetDataSource_l to avoid blocking the calling thread in 273 // setDataSource for any significant time. 274 275 return OK; 276} 277 278status_t AwesomePlayer::setDataSource( 279 int fd, int64_t offset, int64_t length) { 280 Mutex::Autolock autoLock(mLock); 281 282 reset_l(); 283 284 sp<DataSource> dataSource = new FileSource(fd, offset, length); 285 286 status_t err = dataSource->initCheck(); 287 288 if (err != OK) { 289 return err; 290 } 291 292 mFileSource = dataSource; 293 294 return setDataSource_l(dataSource); 295} 296 297status_t AwesomePlayer::setDataSource_l( 298 const sp<DataSource> &dataSource) { 299 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 300 301 if (extractor == NULL) { 302 return UNKNOWN_ERROR; 303 } 304 305 return setDataSource_l(extractor); 306} 307 308status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { 309 bool haveAudio = false; 310 bool haveVideo = false; 311 for (size_t i = 0; i < extractor->countTracks(); ++i) { 312 sp<MetaData> meta = extractor->getTrackMetaData(i); 313 314 const char *mime; 315 CHECK(meta->findCString(kKeyMIMEType, &mime)); 316 317 if (!haveVideo && !strncasecmp(mime, "video/", 6)) { 318 setVideoSource(extractor->getTrack(i)); 319 haveVideo = true; 320 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) { 321 setAudioSource(extractor->getTrack(i)); 322 haveAudio = true; 323 324 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { 325 // Only do this for vorbis audio, none of the other audio 326 // formats even support this ringtone specific hack and 327 // retrieving the metadata on some extractors may turn out 328 // to be very expensive. 329 sp<MetaData> fileMeta = extractor->getMetaData(); 330 int32_t loop; 331 if (fileMeta != NULL 332 && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) { 333 mFlags |= AUTO_LOOPING; 334 } 335 } 336 } 337 338 if (haveAudio && haveVideo) { 339 break; 340 } 341 } 342 343 if (!haveAudio && !haveVideo) { 344 return UNKNOWN_ERROR; 345 } 346 347 mExtractorFlags = extractor->flags(); 348 349 return OK; 350} 351 352void AwesomePlayer::reset() { 353 Mutex::Autolock autoLock(mLock); 354 reset_l(); 355} 356 357void AwesomePlayer::reset_l() { 358 if (mFlags & PREPARING) { 359 mFlags |= PREPARE_CANCELLED; 360 if (mConnectingDataSource != NULL) { 361 LOGI("interrupting the connection process"); 362 mConnectingDataSource->disconnect(); 363 } 364 } 365 366 while (mFlags & PREPARING) { 367 mPreparedCondition.wait(mLock); 368 } 369 370 cancelPlayerEvents(); 371 372 mCachedSource.clear(); 373 mAudioTrack.clear(); 374 mVideoTrack.clear(); 375 376 // Shutdown audio first, so that the respone to the reset request 377 // appears to happen instantaneously as far as the user is concerned 378 // If we did this later, audio would continue playing while we 379 // shutdown the video-related resources and the player appear to 380 // not be as responsive to a reset request. 381 if (mAudioPlayer == NULL && mAudioSource != NULL) { 382 // If we had an audio player, it would have effectively 383 // taken possession of the audio source and stopped it when 384 // _it_ is stopped. Otherwise this is still our responsibility. 385 mAudioSource->stop(); 386 } 387 mAudioSource.clear(); 388 389 mTimeSource = NULL; 390 391 delete mAudioPlayer; 392 mAudioPlayer = NULL; 393 394 mVideoRenderer.clear(); 395 396 if (mLastVideoBuffer) { 397 mLastVideoBuffer->release(); 398 mLastVideoBuffer = NULL; 399 } 400 401 if (mVideoBuffer) { 402 mVideoBuffer->release(); 403 mVideoBuffer = NULL; 404 } 405 406 if (mRTSPController != NULL) { 407 mRTSPController->disconnect(); 408 mRTSPController.clear(); 409 } 410 411 mRTPPusher.clear(); 412 mRTCPPusher.clear(); 413 mRTPSession.clear(); 414 415 if (mVideoSource != NULL) { 416 mVideoSource->stop(); 417 418 // The following hack is necessary to ensure that the OMX 419 // component is completely released by the time we may try 420 // to instantiate it again. 421 wp<MediaSource> tmp = mVideoSource; 422 mVideoSource.clear(); 423 while (tmp.promote() != NULL) { 424 usleep(1000); 425 } 426 IPCThreadState::self()->flushCommands(); 427 } 428 429 mDurationUs = -1; 430 mFlags = 0; 431 mExtractorFlags = 0; 432 mVideoWidth = mVideoHeight = -1; 433 mTimeSourceDeltaUs = 0; 434 mVideoTimeUs = 0; 435 436 mSeeking = false; 437 mSeekNotificationSent = false; 438 mSeekTimeUs = 0; 439 440 mUri.setTo(""); 441 mUriHeaders.clear(); 442 443 mFileSource.clear(); 444 445 delete mSuspensionState; 446 mSuspensionState = NULL; 447} 448 449void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) { 450 if (mListener != NULL) { 451 sp<MediaPlayerBase> listener = mListener.promote(); 452 453 if (listener != NULL) { 454 listener->sendEvent(msg, ext1, ext2); 455 } 456 } 457} 458 459// Returns true iff cached duration is available/applicable. 460bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) { 461 off_t totalSize; 462 463 if (mRTSPController != NULL) { 464 *durationUs = mRTSPController->getQueueDurationUs(eos); 465 return true; 466 } else if (mCachedSource != NULL && mDurationUs >= 0 467 && mCachedSource->getSize(&totalSize) == OK) { 468 int64_t bitrate = totalSize * 8000000ll / mDurationUs; // in bits/sec 469 470 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(eos); 471 *durationUs = cachedDataRemaining * 8000000ll / bitrate; 472 return true; 473 } 474 475 return false; 476} 477 478void AwesomePlayer::onBufferingUpdate() { 479 Mutex::Autolock autoLock(mLock); 480 if (!mBufferingEventPending) { 481 return; 482 } 483 mBufferingEventPending = false; 484 485 if (mCachedSource != NULL) { 486 bool eos; 487 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos); 488 489 if (eos) { 490 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100); 491 if (mFlags & PREPARING) { 492 LOGV("cache has reached EOS, prepare is done."); 493 finishAsyncPrepare_l(); 494 } 495 } else { 496 off_t size; 497 if (mDurationUs >= 0 && mCachedSource->getSize(&size) == OK) { 498 int64_t bitrate = size * 8000000ll / mDurationUs; // in bits/sec 499 500 size_t cachedSize = mCachedSource->cachedSize(); 501 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate; 502 503 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs; 504 if (percentage > 100) { 505 percentage = 100; 506 } 507 508 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage); 509 } else { 510 // We don't know the bitrate of the stream, use absolute size 511 // limits to maintain the cache. 512 513 const size_t kLowWaterMarkBytes = 40000; 514 const size_t kHighWaterMarkBytes = 200000; 515 516 if ((mFlags & PLAYING) && !eos 517 && (cachedDataRemaining < kLowWaterMarkBytes)) { 518 LOGI("cache is running low (< %d) , pausing.", 519 kLowWaterMarkBytes); 520 mFlags |= CACHE_UNDERRUN; 521 pause_l(); 522 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 523 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) { 524 if (mFlags & CACHE_UNDERRUN) { 525 LOGI("cache has filled up (> %d), resuming.", 526 kHighWaterMarkBytes); 527 mFlags &= ~CACHE_UNDERRUN; 528 play_l(); 529 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END); 530 } else if (mFlags & PREPARING) { 531 LOGV("cache has filled up (> %d), prepare is done", 532 kHighWaterMarkBytes); 533 finishAsyncPrepare_l(); 534 } 535 } 536 } 537 } 538 } 539 540 int64_t cachedDurationUs; 541 bool eos; 542 if (getCachedDuration_l(&cachedDurationUs, &eos)) { 543 if ((mFlags & PLAYING) && !eos 544 && (cachedDurationUs < kLowWaterMarkUs)) { 545 LOGI("cache is running low (%.2f secs) , pausing.", 546 cachedDurationUs / 1E6); 547 mFlags |= CACHE_UNDERRUN; 548 pause_l(); 549 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START); 550 } else if (eos || cachedDurationUs > kHighWaterMarkUs) { 551 if (mFlags & CACHE_UNDERRUN) { 552 LOGI("cache has filled up (%.2f secs), resuming.", 553 cachedDurationUs / 1E6); 554 mFlags &= ~CACHE_UNDERRUN; 555 play_l(); 556 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END); 557 } else if (mFlags & PREPARING) { 558 LOGV("cache has filled up (%.2f secs), prepare is done", 559 cachedDurationUs / 1E6); 560 finishAsyncPrepare_l(); 561 } 562 } 563 } 564 565 postBufferingEvent_l(); 566} 567 568void AwesomePlayer::partial_reset_l() { 569 // Only reset the video renderer and shut down the video decoder. 570 // Then instantiate a new video decoder and resume video playback. 571 572 mVideoRenderer.clear(); 573 574 if (mLastVideoBuffer) { 575 mLastVideoBuffer->release(); 576 mLastVideoBuffer = NULL; 577 } 578 579 if (mVideoBuffer) { 580 mVideoBuffer->release(); 581 mVideoBuffer = NULL; 582 } 583 584 { 585 mVideoSource->stop(); 586 587 // The following hack is necessary to ensure that the OMX 588 // component is completely released by the time we may try 589 // to instantiate it again. 590 wp<MediaSource> tmp = mVideoSource; 591 mVideoSource.clear(); 592 while (tmp.promote() != NULL) { 593 usleep(1000); 594 } 595 IPCThreadState::self()->flushCommands(); 596 } 597 598 CHECK_EQ(OK, initVideoDecoder(OMXCodec::kIgnoreCodecSpecificData)); 599} 600 601void AwesomePlayer::onStreamDone() { 602 // Posted whenever any stream finishes playing. 603 604 Mutex::Autolock autoLock(mLock); 605 if (!mStreamDoneEventPending) { 606 return; 607 } 608 mStreamDoneEventPending = false; 609 610 if (mStreamDoneStatus == INFO_DISCONTINUITY) { 611 // This special status is returned because an http live stream's 612 // video stream switched to a different bandwidth at this point 613 // and future data may have been encoded using different parameters. 614 // This requires us to shutdown the video decoder and reinstantiate 615 // a fresh one. 616 617 LOGV("INFO_DISCONTINUITY"); 618 619 CHECK(mVideoSource != NULL); 620 621 partial_reset_l(); 622 postVideoEvent_l(); 623 return; 624 } else if (mStreamDoneStatus != ERROR_END_OF_STREAM) { 625 LOGV("MEDIA_ERROR %d", mStreamDoneStatus); 626 627 notifyListener_l( 628 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus); 629 630 pause_l(true /* at eos */); 631 632 mFlags |= AT_EOS; 633 return; 634 } 635 636 const bool allDone = 637 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS)) 638 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS)); 639 640 if (!allDone) { 641 return; 642 } 643 644 if (mFlags & (LOOPING | AUTO_LOOPING)) { 645 seekTo_l(0); 646 647 if (mVideoSource != NULL) { 648 postVideoEvent_l(); 649 } 650 } else { 651 LOGV("MEDIA_PLAYBACK_COMPLETE"); 652 notifyListener_l(MEDIA_PLAYBACK_COMPLETE); 653 654 pause_l(true /* at eos */); 655 656 mFlags |= AT_EOS; 657 } 658} 659 660status_t AwesomePlayer::play() { 661 Mutex::Autolock autoLock(mLock); 662 663 mFlags &= ~CACHE_UNDERRUN; 664 665 return play_l(); 666} 667 668status_t AwesomePlayer::play_l() { 669 if (mFlags & PLAYING) { 670 return OK; 671 } 672 673 if (!(mFlags & PREPARED)) { 674 status_t err = prepare_l(); 675 676 if (err != OK) { 677 return err; 678 } 679 } 680 681 mFlags |= PLAYING; 682 mFlags |= FIRST_FRAME; 683 684 bool deferredAudioSeek = false; 685 686 if (mAudioSource != NULL) { 687 if (mAudioPlayer == NULL) { 688 if (mAudioSink != NULL) { 689 mAudioPlayer = new AudioPlayer(mAudioSink, this); 690 mAudioPlayer->setSource(mAudioSource); 691 692 // We've already started the MediaSource in order to enable 693 // the prefetcher to read its data. 694 status_t err = mAudioPlayer->start( 695 true /* sourceAlreadyStarted */); 696 697 if (err != OK) { 698 delete mAudioPlayer; 699 mAudioPlayer = NULL; 700 701 mFlags &= ~(PLAYING | FIRST_FRAME); 702 703 return err; 704 } 705 706 mTimeSource = mAudioPlayer; 707 708 deferredAudioSeek = true; 709 710 mWatchForAudioSeekComplete = false; 711 mWatchForAudioEOS = true; 712 } 713 } else { 714 mAudioPlayer->resume(); 715 } 716 } 717 718 if (mTimeSource == NULL && mAudioPlayer == NULL) { 719 mTimeSource = &mSystemTimeSource; 720 } 721 722 if (mVideoSource != NULL) { 723 // Kick off video playback 724 postVideoEvent_l(); 725 } 726 727 if (deferredAudioSeek) { 728 // If there was a seek request while we were paused 729 // and we're just starting up again, honor the request now. 730 seekAudioIfNecessary_l(); 731 } 732 733 if (mFlags & AT_EOS) { 734 // Legacy behaviour, if a stream finishes playing and then 735 // is started again, we play from the start... 736 seekTo_l(0); 737 } 738 739 return OK; 740} 741 742void AwesomePlayer::notifyVideoSize_l() { 743 sp<MetaData> meta = mVideoSource->getFormat(); 744 745 int32_t decodedWidth, decodedHeight; 746 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 747 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 748 749 notifyListener_l(MEDIA_SET_VIDEO_SIZE, decodedWidth, decodedHeight); 750} 751 752void AwesomePlayer::initRenderer_l() { 753 if (mSurface != NULL || mISurface != NULL) { 754 sp<MetaData> meta = mVideoSource->getFormat(); 755 756 int32_t format; 757 const char *component; 758 int32_t decodedWidth, decodedHeight; 759 CHECK(meta->findInt32(kKeyColorFormat, &format)); 760 CHECK(meta->findCString(kKeyDecoderComponent, &component)); 761 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 762 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 763 764 mVideoRenderer.clear(); 765 766 // Must ensure that mVideoRenderer's destructor is actually executed 767 // before creating a new one. 768 IPCThreadState::self()->flushCommands(); 769 770 if (mSurface != NULL) { 771 // Other decoders are instantiated locally and as a consequence 772 // allocate their buffers in local address space. 773 mVideoRenderer = new AwesomeLocalRenderer( 774 false, // previewOnly 775 component, 776 (OMX_COLOR_FORMATTYPE)format, 777 mISurface, 778 mSurface, 779 mVideoWidth, mVideoHeight, 780 decodedWidth, decodedHeight); 781 } else { 782 // Our OMX codecs allocate buffers on the media_server side 783 // therefore they require a remote IOMXRenderer that knows how 784 // to display them. 785 mVideoRenderer = new AwesomeRemoteRenderer( 786 mClient.interface()->createRenderer( 787 mISurface, component, 788 (OMX_COLOR_FORMATTYPE)format, 789 decodedWidth, decodedHeight, 790 mVideoWidth, mVideoHeight)); 791 } 792 } 793} 794 795status_t AwesomePlayer::pause() { 796 Mutex::Autolock autoLock(mLock); 797 798 mFlags &= ~CACHE_UNDERRUN; 799 800 return pause_l(); 801} 802 803status_t AwesomePlayer::pause_l(bool at_eos) { 804 if (!(mFlags & PLAYING)) { 805 return OK; 806 } 807 808 cancelPlayerEvents(true /* keepBufferingGoing */); 809 810 if (mAudioPlayer != NULL) { 811 if (at_eos) { 812 // If we played the audio stream to completion we 813 // want to make sure that all samples remaining in the audio 814 // track's queue are played out. 815 mAudioPlayer->pause(true /* playPendingSamples */); 816 } else { 817 mAudioPlayer->pause(); 818 } 819 } 820 821 mFlags &= ~PLAYING; 822 823 return OK; 824} 825 826bool AwesomePlayer::isPlaying() const { 827 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN); 828} 829 830void AwesomePlayer::setISurface(const sp<ISurface> &isurface) { 831 Mutex::Autolock autoLock(mLock); 832 833 mISurface = isurface; 834} 835 836void AwesomePlayer::setSurface(const sp<Surface> &surface) { 837 Mutex::Autolock autoLock(mLock); 838 839 mSurface = surface; 840} 841 842void AwesomePlayer::setAudioSink( 843 const sp<MediaPlayerBase::AudioSink> &audioSink) { 844 Mutex::Autolock autoLock(mLock); 845 846 mAudioSink = audioSink; 847} 848 849status_t AwesomePlayer::setLooping(bool shouldLoop) { 850 Mutex::Autolock autoLock(mLock); 851 852 mFlags = mFlags & ~LOOPING; 853 854 if (shouldLoop) { 855 mFlags |= LOOPING; 856 } 857 858 return OK; 859} 860 861status_t AwesomePlayer::getDuration(int64_t *durationUs) { 862 Mutex::Autolock autoLock(mMiscStateLock); 863 864 if (mDurationUs < 0) { 865 return UNKNOWN_ERROR; 866 } 867 868 *durationUs = mDurationUs; 869 870 return OK; 871} 872 873status_t AwesomePlayer::getPosition(int64_t *positionUs) { 874 if (mRTSPController != NULL) { 875 *positionUs = mRTSPController->getNormalPlayTimeUs(); 876 } 877 else if (mSeeking) { 878 *positionUs = mSeekTimeUs; 879 } else if (mVideoSource != NULL) { 880 Mutex::Autolock autoLock(mMiscStateLock); 881 *positionUs = mVideoTimeUs; 882 } else if (mAudioPlayer != NULL) { 883 *positionUs = mAudioPlayer->getMediaTimeUs(); 884 } else { 885 *positionUs = 0; 886 } 887 888 return OK; 889} 890 891status_t AwesomePlayer::seekTo(int64_t timeUs) { 892 if (mExtractorFlags & MediaExtractor::CAN_SEEK) { 893 Mutex::Autolock autoLock(mLock); 894 return seekTo_l(timeUs); 895 } 896 897 return OK; 898} 899 900// static 901void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) { 902 static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone(); 903} 904 905void AwesomePlayer::onRTSPSeekDone() { 906 notifyListener_l(MEDIA_SEEK_COMPLETE); 907 mSeekNotificationSent = true; 908} 909 910status_t AwesomePlayer::seekTo_l(int64_t timeUs) { 911 if (mRTSPController != NULL) { 912 mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this); 913 return OK; 914 } 915 916 if (mFlags & CACHE_UNDERRUN) { 917 mFlags &= ~CACHE_UNDERRUN; 918 play_l(); 919 } 920 921 mSeeking = true; 922 mSeekNotificationSent = false; 923 mSeekTimeUs = timeUs; 924 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS); 925 926 seekAudioIfNecessary_l(); 927 928 if (!(mFlags & PLAYING)) { 929 LOGV("seeking while paused, sending SEEK_COMPLETE notification" 930 " immediately."); 931 932 notifyListener_l(MEDIA_SEEK_COMPLETE); 933 mSeekNotificationSent = true; 934 } 935 936 return OK; 937} 938 939void AwesomePlayer::seekAudioIfNecessary_l() { 940 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) { 941 mAudioPlayer->seekTo(mSeekTimeUs); 942 943 mWatchForAudioSeekComplete = true; 944 mWatchForAudioEOS = true; 945 mSeekNotificationSent = false; 946 } 947} 948 949status_t AwesomePlayer::getVideoDimensions( 950 int32_t *width, int32_t *height) const { 951 Mutex::Autolock autoLock(mLock); 952 953 if (mVideoWidth < 0 || mVideoHeight < 0) { 954 return UNKNOWN_ERROR; 955 } 956 957 *width = mVideoWidth; 958 *height = mVideoHeight; 959 960 return OK; 961} 962 963void AwesomePlayer::setAudioSource(sp<MediaSource> source) { 964 CHECK(source != NULL); 965 966 mAudioTrack = source; 967} 968 969status_t AwesomePlayer::initAudioDecoder() { 970 sp<MetaData> meta = mAudioTrack->getFormat(); 971 972 const char *mime; 973 CHECK(meta->findCString(kKeyMIMEType, &mime)); 974 975 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 976 mAudioSource = mAudioTrack; 977 } else { 978 mAudioSource = OMXCodec::Create( 979 mClient.interface(), mAudioTrack->getFormat(), 980 false, // createEncoder 981 mAudioTrack); 982 } 983 984 if (mAudioSource != NULL) { 985 int64_t durationUs; 986 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 987 Mutex::Autolock autoLock(mMiscStateLock); 988 if (mDurationUs < 0 || durationUs > mDurationUs) { 989 mDurationUs = durationUs; 990 } 991 } 992 993 status_t err = mAudioSource->start(); 994 995 if (err != OK) { 996 mAudioSource.clear(); 997 return err; 998 } 999 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) { 1000 // For legacy reasons we're simply going to ignore the absence 1001 // of an audio decoder for QCELP instead of aborting playback 1002 // altogether. 1003 return OK; 1004 } 1005 1006 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 1007} 1008 1009void AwesomePlayer::setVideoSource(sp<MediaSource> source) { 1010 CHECK(source != NULL); 1011 1012 mVideoTrack = source; 1013} 1014 1015status_t AwesomePlayer::initVideoDecoder(uint32_t flags) { 1016 mVideoSource = OMXCodec::Create( 1017 mClient.interface(), mVideoTrack->getFormat(), 1018 false, // createEncoder 1019 mVideoTrack, 1020 NULL, flags); 1021 1022 if (mVideoSource != NULL) { 1023 int64_t durationUs; 1024 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 1025 Mutex::Autolock autoLock(mMiscStateLock); 1026 if (mDurationUs < 0 || durationUs > mDurationUs) { 1027 mDurationUs = durationUs; 1028 } 1029 } 1030 1031 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth)); 1032 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight)); 1033 1034 status_t err = mVideoSource->start(); 1035 1036 if (err != OK) { 1037 mVideoSource.clear(); 1038 return err; 1039 } 1040 } 1041 1042 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 1043} 1044 1045void AwesomePlayer::onVideoEvent() { 1046 Mutex::Autolock autoLock(mLock); 1047 if (!mVideoEventPending) { 1048 // The event has been cancelled in reset_l() but had already 1049 // been scheduled for execution at that time. 1050 return; 1051 } 1052 mVideoEventPending = false; 1053 1054 if (mSeeking) { 1055 if (mLastVideoBuffer) { 1056 mLastVideoBuffer->release(); 1057 mLastVideoBuffer = NULL; 1058 } 1059 1060 if (mVideoBuffer) { 1061 mVideoBuffer->release(); 1062 mVideoBuffer = NULL; 1063 } 1064 1065 if (mCachedSource != NULL && mAudioSource != NULL) { 1066 // We're going to seek the video source first, followed by 1067 // the audio source. 1068 // In order to avoid jumps in the DataSource offset caused by 1069 // the audio codec prefetching data from the old locations 1070 // while the video codec is already reading data from the new 1071 // locations, we'll "pause" the audio source, causing it to 1072 // stop reading input data until a subsequent seek. 1073 1074 if (mAudioPlayer != NULL) { 1075 mAudioPlayer->pause(); 1076 } 1077 mAudioSource->pause(); 1078 } 1079 } 1080 1081 if (!mVideoBuffer) { 1082 MediaSource::ReadOptions options; 1083 if (mSeeking) { 1084 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); 1085 1086 options.setSeekTo( 1087 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST_SYNC); 1088 } 1089 for (;;) { 1090 status_t err = mVideoSource->read(&mVideoBuffer, &options); 1091 options.clearSeekTo(); 1092 1093 if (err != OK) { 1094 CHECK_EQ(mVideoBuffer, NULL); 1095 1096 if (err == INFO_FORMAT_CHANGED) { 1097 LOGV("VideoSource signalled format change."); 1098 1099 notifyVideoSize_l(); 1100 1101 if (mVideoRenderer != NULL) { 1102 mVideoRendererIsPreview = false; 1103 initRenderer_l(); 1104 } 1105 continue; 1106 } 1107 1108 mFlags |= VIDEO_AT_EOS; 1109 postStreamDoneEvent_l(err); 1110 return; 1111 } 1112 1113 if (mVideoBuffer->range_length() == 0) { 1114 // Some decoders, notably the PV AVC software decoder 1115 // return spurious empty buffers that we just want to ignore. 1116 1117 mVideoBuffer->release(); 1118 mVideoBuffer = NULL; 1119 continue; 1120 } 1121 1122 break; 1123 } 1124 } 1125 1126 int64_t timeUs; 1127 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 1128 1129 { 1130 Mutex::Autolock autoLock(mMiscStateLock); 1131 mVideoTimeUs = timeUs; 1132 } 1133 1134 if (mSeeking) { 1135 if (mAudioPlayer != NULL) { 1136 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6); 1137 1138 mAudioPlayer->seekTo(timeUs); 1139 mAudioPlayer->resume(); 1140 mWatchForAudioSeekComplete = true; 1141 mWatchForAudioEOS = true; 1142 } else if (!mSeekNotificationSent) { 1143 // If we're playing video only, report seek complete now, 1144 // otherwise audio player will notify us later. 1145 notifyListener_l(MEDIA_SEEK_COMPLETE); 1146 } 1147 1148 mFlags |= FIRST_FRAME; 1149 mSeeking = false; 1150 mSeekNotificationSent = false; 1151 } 1152 1153 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource; 1154 1155 if (mFlags & FIRST_FRAME) { 1156 mFlags &= ~FIRST_FRAME; 1157 1158 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs; 1159 } 1160 1161 int64_t realTimeUs, mediaTimeUs; 1162 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL 1163 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 1164 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 1165 } 1166 1167 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs; 1168 1169 int64_t latenessUs = nowUs - timeUs; 1170 1171 if (mRTPSession != NULL) { 1172 // We'll completely ignore timestamps for gtalk videochat 1173 // and we'll play incoming video as fast as we get it. 1174 latenessUs = 0; 1175 } 1176 1177 if (latenessUs > 40000) { 1178 // We're more than 40ms late. 1179 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6); 1180 1181 mVideoBuffer->release(); 1182 mVideoBuffer = NULL; 1183 1184 postVideoEvent_l(); 1185 return; 1186 } 1187 1188 if (latenessUs < -10000) { 1189 // We're more than 10ms early. 1190 1191 postVideoEvent_l(10000); 1192 return; 1193 } 1194 1195 if (mVideoRendererIsPreview || mVideoRenderer == NULL) { 1196 mVideoRendererIsPreview = false; 1197 1198 initRenderer_l(); 1199 } 1200 1201 if (mVideoRenderer != NULL) { 1202 mVideoRenderer->render(mVideoBuffer); 1203 } 1204 1205 if (mLastVideoBuffer) { 1206 mLastVideoBuffer->release(); 1207 mLastVideoBuffer = NULL; 1208 } 1209 mLastVideoBuffer = mVideoBuffer; 1210 mVideoBuffer = NULL; 1211 1212 postVideoEvent_l(); 1213} 1214 1215void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 1216 if (mVideoEventPending) { 1217 return; 1218 } 1219 1220 mVideoEventPending = true; 1221 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 1222} 1223 1224void AwesomePlayer::postStreamDoneEvent_l(status_t status) { 1225 if (mStreamDoneEventPending) { 1226 return; 1227 } 1228 mStreamDoneEventPending = true; 1229 1230 mStreamDoneStatus = status; 1231 mQueue.postEvent(mStreamDoneEvent); 1232} 1233 1234void AwesomePlayer::postBufferingEvent_l() { 1235 if (mBufferingEventPending) { 1236 return; 1237 } 1238 mBufferingEventPending = true; 1239 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll); 1240} 1241 1242void AwesomePlayer::postCheckAudioStatusEvent_l() { 1243 if (mAudioStatusEventPending) { 1244 return; 1245 } 1246 mAudioStatusEventPending = true; 1247 mQueue.postEvent(mCheckAudioStatusEvent); 1248} 1249 1250void AwesomePlayer::onCheckAudioStatus() { 1251 Mutex::Autolock autoLock(mLock); 1252 if (!mAudioStatusEventPending) { 1253 // Event was dispatched and while we were blocking on the mutex, 1254 // has already been cancelled. 1255 return; 1256 } 1257 1258 mAudioStatusEventPending = false; 1259 1260 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) { 1261 mWatchForAudioSeekComplete = false; 1262 1263 if (!mSeekNotificationSent) { 1264 notifyListener_l(MEDIA_SEEK_COMPLETE); 1265 mSeekNotificationSent = true; 1266 } 1267 1268 mSeeking = false; 1269 } 1270 1271 status_t finalStatus; 1272 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) { 1273 mWatchForAudioEOS = false; 1274 mFlags |= AUDIO_AT_EOS; 1275 mFlags |= FIRST_FRAME; 1276 postStreamDoneEvent_l(finalStatus); 1277 } 1278} 1279 1280status_t AwesomePlayer::prepare() { 1281 Mutex::Autolock autoLock(mLock); 1282 return prepare_l(); 1283} 1284 1285status_t AwesomePlayer::prepare_l() { 1286 if (mFlags & PREPARED) { 1287 return OK; 1288 } 1289 1290 if (mFlags & PREPARING) { 1291 return UNKNOWN_ERROR; 1292 } 1293 1294 mIsAsyncPrepare = false; 1295 status_t err = prepareAsync_l(); 1296 1297 if (err != OK) { 1298 return err; 1299 } 1300 1301 while (mFlags & PREPARING) { 1302 mPreparedCondition.wait(mLock); 1303 } 1304 1305 return mPrepareResult; 1306} 1307 1308status_t AwesomePlayer::prepareAsync() { 1309 Mutex::Autolock autoLock(mLock); 1310 1311 if (mFlags & PREPARING) { 1312 return UNKNOWN_ERROR; // async prepare already pending 1313 } 1314 1315 mIsAsyncPrepare = true; 1316 return prepareAsync_l(); 1317} 1318 1319status_t AwesomePlayer::prepareAsync_l() { 1320 if (mFlags & PREPARING) { 1321 return UNKNOWN_ERROR; // async prepare already pending 1322 } 1323 1324 if (!mQueueStarted) { 1325 mQueue.start(); 1326 mQueueStarted = true; 1327 } 1328 1329 mFlags |= PREPARING; 1330 mAsyncPrepareEvent = new AwesomeEvent( 1331 this, &AwesomePlayer::onPrepareAsyncEvent); 1332 1333 mQueue.postEvent(mAsyncPrepareEvent); 1334 1335 return OK; 1336} 1337 1338status_t AwesomePlayer::finishSetDataSource_l() { 1339 sp<DataSource> dataSource; 1340 1341 if (!strncasecmp("http://", mUri.string(), 7)) { 1342 mConnectingDataSource = new NuHTTPDataSource; 1343 1344 mLock.unlock(); 1345 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders); 1346 mLock.lock(); 1347 1348 if (err != OK) { 1349 mConnectingDataSource.clear(); 1350 1351 LOGI("mConnectingDataSource->connect() returned %d", err); 1352 return err; 1353 } 1354 1355#if 0 1356 mCachedSource = new NuCachedSource2( 1357 new ThrottledSource( 1358 mConnectingDataSource, 50 * 1024 /* bytes/sec */)); 1359#else 1360 mCachedSource = new NuCachedSource2(mConnectingDataSource); 1361#endif 1362 mConnectingDataSource.clear(); 1363 1364 dataSource = mCachedSource; 1365 } else if (!strncasecmp(mUri.string(), "httplive://", 11)) { 1366 String8 uri("http://"); 1367 uri.append(mUri.string() + 11); 1368 1369 sp<LiveSource> liveSource = new LiveSource(uri.string()); 1370 1371 mCachedSource = new NuCachedSource2(liveSource); 1372 dataSource = mCachedSource; 1373 1374 sp<MediaExtractor> extractor = 1375 MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS); 1376 1377 static_cast<MPEG2TSExtractor *>(extractor.get()) 1378 ->setLiveSource(liveSource); 1379 1380 return setDataSource_l(extractor); 1381 } else if (!strncmp("rtsp://gtalk/", mUri.string(), 13)) { 1382 if (mLooper == NULL) { 1383 mLooper = new ALooper; 1384 mLooper->setName("gtalk rtp"); 1385 mLooper->start( 1386 false /* runOnCallingThread */, 1387 false /* canCallJava */, 1388 PRIORITY_HIGHEST); 1389 } 1390 1391 const char *startOfCodecString = &mUri.string()[13]; 1392 const char *startOfSlash1 = strchr(startOfCodecString, '/'); 1393 if (startOfSlash1 == NULL) { 1394 return BAD_VALUE; 1395 } 1396 const char *startOfWidthString = &startOfSlash1[1]; 1397 const char *startOfSlash2 = strchr(startOfWidthString, '/'); 1398 if (startOfSlash2 == NULL) { 1399 return BAD_VALUE; 1400 } 1401 const char *startOfHeightString = &startOfSlash2[1]; 1402 1403 String8 codecString(startOfCodecString, startOfSlash1 - startOfCodecString); 1404 String8 widthString(startOfWidthString, startOfSlash2 - startOfWidthString); 1405 String8 heightString(startOfHeightString); 1406 1407#if 0 1408 mRTPPusher = new UDPPusher("/data/misc/rtpout.bin", 5434); 1409 mLooper->registerHandler(mRTPPusher); 1410 1411 mRTCPPusher = new UDPPusher("/data/misc/rtcpout.bin", 5435); 1412 mLooper->registerHandler(mRTCPPusher); 1413#endif 1414 1415 mRTPSession = new ARTPSession; 1416 mLooper->registerHandler(mRTPSession); 1417 1418#if 0 1419 // My AMR SDP 1420 static const char *raw = 1421 "v=0\r\n" 1422 "o=- 64 233572944 IN IP4 127.0.0.0\r\n" 1423 "s=QuickTime\r\n" 1424 "t=0 0\r\n" 1425 "a=range:npt=0-315\r\n" 1426 "a=isma-compliance:2,2.0,2\r\n" 1427 "m=audio 5434 RTP/AVP 97\r\n" 1428 "c=IN IP4 127.0.0.1\r\n" 1429 "b=AS:30\r\n" 1430 "a=rtpmap:97 AMR/8000/1\r\n" 1431 "a=fmtp:97 octet-align\r\n"; 1432#elif 1 1433 String8 sdp; 1434 sdp.appendFormat( 1435 "v=0\r\n" 1436 "o=- 64 233572944 IN IP4 127.0.0.0\r\n" 1437 "s=QuickTime\r\n" 1438 "t=0 0\r\n" 1439 "a=range:npt=0-315\r\n" 1440 "a=isma-compliance:2,2.0,2\r\n" 1441 "m=video 5434 RTP/AVP 97\r\n" 1442 "c=IN IP4 127.0.0.1\r\n" 1443 "b=AS:30\r\n" 1444 "a=rtpmap:97 %s/90000\r\n" 1445 "a=cliprect:0,0,%s,%s\r\n" 1446 "a=framesize:97 %s-%s\r\n", 1447 1448 codecString.string(), 1449 heightString.string(), widthString.string(), 1450 widthString.string(), heightString.string() 1451 ); 1452 const char *raw = sdp.string(); 1453 1454#endif 1455 1456 sp<ASessionDescription> desc = new ASessionDescription; 1457 CHECK(desc->setTo(raw, strlen(raw))); 1458 1459 CHECK_EQ(mRTPSession->setup(desc), (status_t)OK); 1460 1461 if (mRTPPusher != NULL) { 1462 mRTPPusher->start(); 1463 } 1464 1465 if (mRTCPPusher != NULL) { 1466 mRTCPPusher->start(); 1467 } 1468 1469 CHECK_EQ(mRTPSession->countTracks(), 1u); 1470 sp<MediaSource> source = mRTPSession->trackAt(0); 1471 1472#if 0 1473 bool eos; 1474 while (((APacketSource *)source.get()) 1475 ->getQueuedDuration(&eos) < 5000000ll && !eos) { 1476 usleep(100000ll); 1477 } 1478#endif 1479 1480 const char *mime; 1481 CHECK(source->getFormat()->findCString(kKeyMIMEType, &mime)); 1482 1483 if (!strncasecmp("video/", mime, 6)) { 1484 setVideoSource(source); 1485 } else { 1486 CHECK(!strncasecmp("audio/", mime, 6)); 1487 setAudioSource(source); 1488 } 1489 1490 mExtractorFlags = MediaExtractor::CAN_PAUSE; 1491 1492 return OK; 1493 } else if (!strncasecmp("rtsp://", mUri.string(), 7)) { 1494 if (mLooper == NULL) { 1495 mLooper = new ALooper; 1496 mLooper->setName("rtsp"); 1497 mLooper->start(); 1498 } 1499 mRTSPController = new ARTSPController(mLooper); 1500 status_t err = mRTSPController->connect(mUri.string()); 1501 1502 LOGI("ARTSPController::connect returned %d", err); 1503 1504 if (err != OK) { 1505 mRTSPController.clear(); 1506 return err; 1507 } 1508 1509 sp<MediaExtractor> extractor = mRTSPController.get(); 1510 return setDataSource_l(extractor); 1511 } else { 1512 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders); 1513 } 1514 1515 if (dataSource == NULL) { 1516 return UNKNOWN_ERROR; 1517 } 1518 1519 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); 1520 1521 if (extractor == NULL) { 1522 return UNKNOWN_ERROR; 1523 } 1524 1525 return setDataSource_l(extractor); 1526} 1527 1528void AwesomePlayer::abortPrepare(status_t err) { 1529 CHECK(err != OK); 1530 1531 if (mIsAsyncPrepare) { 1532 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 1533 } 1534 1535 mPrepareResult = err; 1536 mFlags &= ~(PREPARING|PREPARE_CANCELLED); 1537 mAsyncPrepareEvent = NULL; 1538 mPreparedCondition.broadcast(); 1539} 1540 1541// static 1542bool AwesomePlayer::ContinuePreparation(void *cookie) { 1543 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie); 1544 1545 return (me->mFlags & PREPARE_CANCELLED) == 0; 1546} 1547 1548void AwesomePlayer::onPrepareAsyncEvent() { 1549 Mutex::Autolock autoLock(mLock); 1550 1551 if (mFlags & PREPARE_CANCELLED) { 1552 LOGI("prepare was cancelled before doing anything"); 1553 abortPrepare(UNKNOWN_ERROR); 1554 return; 1555 } 1556 1557 if (mUri.size() > 0) { 1558 status_t err = finishSetDataSource_l(); 1559 1560 if (err != OK) { 1561 abortPrepare(err); 1562 return; 1563 } 1564 } 1565 1566 if (mVideoTrack != NULL && mVideoSource == NULL) { 1567 status_t err = initVideoDecoder(); 1568 1569 if (err != OK) { 1570 abortPrepare(err); 1571 return; 1572 } 1573 } 1574 1575 if (mAudioTrack != NULL && mAudioSource == NULL) { 1576 status_t err = initAudioDecoder(); 1577 1578 if (err != OK) { 1579 abortPrepare(err); 1580 return; 1581 } 1582 } 1583 1584 if (mCachedSource != NULL || mRTSPController != NULL) { 1585 postBufferingEvent_l(); 1586 } else { 1587 finishAsyncPrepare_l(); 1588 } 1589} 1590 1591void AwesomePlayer::finishAsyncPrepare_l() { 1592 if (mIsAsyncPrepare) { 1593 if (mVideoSource == NULL) { 1594 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); 1595 } else { 1596 notifyVideoSize_l(); 1597 } 1598 1599 notifyListener_l(MEDIA_PREPARED); 1600 } 1601 1602 mPrepareResult = OK; 1603 mFlags &= ~(PREPARING|PREPARE_CANCELLED); 1604 mFlags |= PREPARED; 1605 mAsyncPrepareEvent = NULL; 1606 mPreparedCondition.broadcast(); 1607} 1608 1609status_t AwesomePlayer::suspend() { 1610 LOGV("suspend"); 1611 Mutex::Autolock autoLock(mLock); 1612 1613 if (mSuspensionState != NULL) { 1614 if (mLastVideoBuffer == NULL) { 1615 //go into here if video is suspended again 1616 //after resuming without being played between 1617 //them 1618 SuspensionState *state = mSuspensionState; 1619 mSuspensionState = NULL; 1620 reset_l(); 1621 mSuspensionState = state; 1622 return OK; 1623 } 1624 1625 delete mSuspensionState; 1626 mSuspensionState = NULL; 1627 } 1628 1629 if (mFlags & PREPARING) { 1630 mFlags |= PREPARE_CANCELLED; 1631 if (mConnectingDataSource != NULL) { 1632 LOGI("interrupting the connection process"); 1633 mConnectingDataSource->disconnect(); 1634 } 1635 } 1636 1637 while (mFlags & PREPARING) { 1638 mPreparedCondition.wait(mLock); 1639 } 1640 1641 SuspensionState *state = new SuspensionState; 1642 state->mUri = mUri; 1643 state->mUriHeaders = mUriHeaders; 1644 state->mFileSource = mFileSource; 1645 1646 state->mFlags = mFlags & (PLAYING | AUTO_LOOPING | LOOPING | AT_EOS); 1647 getPosition(&state->mPositionUs); 1648 1649 if (mLastVideoBuffer) { 1650 size_t size = mLastVideoBuffer->range_length(); 1651 1652 if (size) { 1653 int32_t unreadable; 1654 if (!mLastVideoBuffer->meta_data()->findInt32( 1655 kKeyIsUnreadable, &unreadable) 1656 || unreadable == 0) { 1657 state->mLastVideoFrameSize = size; 1658 state->mLastVideoFrame = malloc(size); 1659 memcpy(state->mLastVideoFrame, 1660 (const uint8_t *)mLastVideoBuffer->data() 1661 + mLastVideoBuffer->range_offset(), 1662 size); 1663 1664 state->mVideoWidth = mVideoWidth; 1665 state->mVideoHeight = mVideoHeight; 1666 1667 sp<MetaData> meta = mVideoSource->getFormat(); 1668 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat)); 1669 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth)); 1670 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight)); 1671 } else { 1672 LOGV("Unable to save last video frame, we have no access to " 1673 "the decoded video data."); 1674 } 1675 } 1676 } 1677 1678 reset_l(); 1679 1680 mSuspensionState = state; 1681 1682 return OK; 1683} 1684 1685status_t AwesomePlayer::resume() { 1686 LOGV("resume"); 1687 Mutex::Autolock autoLock(mLock); 1688 1689 if (mSuspensionState == NULL) { 1690 return INVALID_OPERATION; 1691 } 1692 1693 SuspensionState *state = mSuspensionState; 1694 mSuspensionState = NULL; 1695 1696 status_t err; 1697 if (state->mFileSource != NULL) { 1698 err = setDataSource_l(state->mFileSource); 1699 1700 if (err == OK) { 1701 mFileSource = state->mFileSource; 1702 } 1703 } else { 1704 err = setDataSource_l(state->mUri, &state->mUriHeaders); 1705 } 1706 1707 if (err != OK) { 1708 delete state; 1709 state = NULL; 1710 1711 return err; 1712 } 1713 1714 seekTo_l(state->mPositionUs); 1715 1716 mFlags = state->mFlags & (AUTO_LOOPING | LOOPING | AT_EOS); 1717 1718 if (state->mLastVideoFrame && (mSurface != NULL || mISurface != NULL)) { 1719 mVideoRenderer = 1720 new AwesomeLocalRenderer( 1721 true, // previewOnly 1722 "", 1723 (OMX_COLOR_FORMATTYPE)state->mColorFormat, 1724 mISurface, 1725 mSurface, 1726 state->mVideoWidth, 1727 state->mVideoHeight, 1728 state->mDecodedWidth, 1729 state->mDecodedHeight); 1730 1731 mVideoRendererIsPreview = true; 1732 1733 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render( 1734 state->mLastVideoFrame, state->mLastVideoFrameSize); 1735 } 1736 1737 if (state->mFlags & PLAYING) { 1738 play_l(); 1739 } 1740 1741 mSuspensionState = state; 1742 state = NULL; 1743 1744 return OK; 1745} 1746 1747uint32_t AwesomePlayer::flags() const { 1748 return mExtractorFlags; 1749} 1750 1751void AwesomePlayer::postAudioEOS() { 1752 postCheckAudioStatusEvent_l(); 1753} 1754 1755void AwesomePlayer::postAudioSeekComplete() { 1756 postCheckAudioStatusEvent_l(); 1757} 1758 1759} // namespace android 1760 1761