1 /* 2 * Copyright (C) 2011 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 18 // #define LOG_NDEBUG 0 19 #define LOG_TAG "PreviewPlayer" 20 #include <utils/Log.h> 21 22 #include <binder/IPCThreadState.h> 23 #include <binder/IServiceManager.h> 24 #include <media/IMediaPlayerService.h> 25 #include <media/stagefright/DataSource.h> 26 #include <media/stagefright/MediaBuffer.h> 27 #include <media/stagefright/MediaDefs.h> 28 #include <media/stagefright/MediaExtractor.h> 29 #include <media/stagefright/MediaSource.h> 30 #include <media/stagefright/MetaData.h> 31 #include <media/stagefright/OMXCodec.h> 32 #include <media/stagefright/foundation/ADebug.h> 33 #include <gui/Surface.h> 34 #include <gui/IGraphicBufferProducer.h> 35 #include <gui/Surface.h> 36 37 #include "VideoEditorPreviewController.h" 38 #include "DummyAudioSource.h" 39 #include "DummyVideoSource.h" 40 #include "VideoEditorSRC.h" 41 #include "PreviewPlayer.h" 42 43 namespace android { 44 45 46 void addBatteryData(uint32_t params) { 47 sp<IBinder> binder = 48 defaultServiceManager()->getService(String16("media.player")); 49 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 50 CHECK(service.get() != NULL); 51 52 service->addBatteryData(params); 53 } 54 55 struct PreviewPlayerEvent : public TimedEventQueue::Event { 56 PreviewPlayerEvent( 57 PreviewPlayer *player, 58 void (PreviewPlayer::*method)()) 59 : mPlayer(player), 60 mMethod(method) { 61 } 62 63 protected: 64 virtual ~PreviewPlayerEvent() {} 65 66 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { 67 (mPlayer->*mMethod)(); 68 } 69 70 private: 71 PreviewPlayer *mPlayer; 72 void (PreviewPlayer::*mMethod)(); 73 74 PreviewPlayerEvent(const PreviewPlayerEvent &); 75 PreviewPlayerEvent &operator=(const PreviewPlayerEvent &); 76 }; 77 78 PreviewPlayer::PreviewPlayer(NativeWindowRenderer* renderer) 79 : mQueueStarted(false), 80 mTimeSource(NULL), 81 mVideoRendererIsPreview(false), 82 mAudioPlayer(NULL), 83 mDisplayWidth(0), 84 mDisplayHeight(0), 85 mFlags(0), 86 mExtractorFlags(0), 87 mVideoBuffer(NULL), 88 mLastVideoTimeUs(-1), 89 mNativeWindowRenderer(renderer), 90 mCurrFramingEffectIndex(0), 91 mFrameRGBBuffer(NULL), 92 mFrameYUVBuffer(NULL) { 93 94 CHECK_EQ(mClient.connect(), (status_t)OK); 95 DataSource::RegisterDefaultSniffers(); 96 97 98 mVideoRenderer = NULL; 99 mEffectsSettings = NULL; 100 mAudioPlayer = NULL; 101 mAudioMixStoryBoardTS = 0; 102 mCurrentMediaBeginCutTime = 0; 103 mCurrentMediaVolumeValue = 0; 104 mNumberEffects = 0; 105 mDecodedVideoTs = 0; 106 mDecVideoTsStoryBoard = 0; 107 mCurrentVideoEffect = VIDEO_EFFECT_NONE; 108 mProgressCbInterval = 0; 109 mNumberDecVideoFrames = 0; 110 mOverlayUpdateEventPosted = false; 111 mIsChangeSourceRequired = true; 112 113 mVideoEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoEvent); 114 mVideoEventPending = false; 115 mVideoLagEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoLagUpdate); 116 mVideoEventPending = false; 117 mCheckAudioStatusEvent = new PreviewPlayerEvent( 118 this, &PreviewPlayer::onCheckAudioStatus); 119 mAudioStatusEventPending = false; 120 mStreamDoneEvent = new PreviewPlayerEvent( 121 this, &PreviewPlayer::onStreamDone); 122 mStreamDoneEventPending = false; 123 mProgressCbEvent = new PreviewPlayerEvent(this, 124 &PreviewPlayer::onProgressCbEvent); 125 126 mOverlayUpdateEvent = new PreviewPlayerEvent(this, 127 &PreviewPlayer::onUpdateOverlayEvent); 128 mProgressCbEventPending = false; 129 130 mOverlayUpdateEventPending = false; 131 mRenderingMode = (M4xVSS_MediaRendering)MEDIA_RENDERING_INVALID; 132 mIsFiftiesEffectStarted = false; 133 reset(); 134 } 135 136 PreviewPlayer::~PreviewPlayer() { 137 138 if (mQueueStarted) { 139 mQueue.stop(); 140 } 141 142 reset(); 143 144 if (mVideoRenderer) { 145 mNativeWindowRenderer->destroyRenderInput(mVideoRenderer); 146 } 147 148 Mutex::Autolock lock(mLock); 149 clear_l(); 150 mClient.disconnect(); 151 } 152 153 void PreviewPlayer::cancelPlayerEvents_l(bool updateProgressCb) { 154 mQueue.cancelEvent(mVideoEvent->eventID()); 155 mVideoEventPending = false; 156 mQueue.cancelEvent(mStreamDoneEvent->eventID()); 157 mStreamDoneEventPending = false; 158 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID()); 159 mAudioStatusEventPending = false; 160 mQueue.cancelEvent(mVideoLagEvent->eventID()); 161 mVideoLagEventPending = false; 162 if (updateProgressCb) { 163 mQueue.cancelEvent(mProgressCbEvent->eventID()); 164 mProgressCbEventPending = false; 165 } 166 } 167 168 status_t PreviewPlayer::setDataSource(const char *path) { 169 Mutex::Autolock autoLock(mLock); 170 return setDataSource_l(path); 171 } 172 173 status_t PreviewPlayer::setDataSource_l(const char *path) { 174 reset_l(); 175 176 mUri = path; 177 178 // The actual work will be done during preparation in the call to 179 // ::finishSetDataSource_l to avoid blocking the calling thread in 180 // setDataSource for any significant time. 181 return OK; 182 } 183 184 status_t PreviewPlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { 185 bool haveAudio = false; 186 bool haveVideo = false; 187 for (size_t i = 0; i < extractor->countTracks(); ++i) { 188 sp<MetaData> meta = extractor->getTrackMetaData(i); 189 190 const char *mime; 191 CHECK(meta->findCString(kKeyMIMEType, &mime)); 192 193 if (!haveVideo && !strncasecmp(mime, "video/", 6)) { 194 setVideoSource(extractor->getTrack(i)); 195 haveVideo = true; 196 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) { 197 setAudioSource(extractor->getTrack(i)); 198 haveAudio = true; 199 200 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { 201 // Only do this for vorbis audio, none of the other audio 202 // formats even support this ringtone specific hack and 203 // retrieving the metadata on some extractors may turn out 204 // to be very expensive. 205 sp<MetaData> fileMeta = extractor->getMetaData(); 206 int32_t loop; 207 if (fileMeta != NULL 208 && fileMeta->findInt32(kKeyAutoLoop, &loop) 209 && loop != 0) { 210 mFlags |= AUTO_LOOPING; 211 } 212 } 213 } 214 215 if (haveAudio && haveVideo) { 216 break; 217 } 218 } 219 220 /* Add the support for Dummy audio*/ 221 if( !haveAudio ){ 222 mAudioTrack = DummyAudioSource::Create(32000, 2, 20000, 223 ((mPlayEndTimeMsec)*1000LL)); 224 if(mAudioTrack != NULL) { 225 haveAudio = true; 226 } 227 } 228 229 if (!haveAudio && !haveVideo) { 230 return UNKNOWN_ERROR; 231 } 232 233 mExtractorFlags = extractor->flags(); 234 return OK; 235 } 236 237 status_t PreviewPlayer::setDataSource_l_jpg() { 238 ALOGV("setDataSource_l_jpg"); 239 240 M4OSA_ERR err = M4NO_ERROR; 241 242 mAudioSource = DummyAudioSource::Create(32000, 2, 20000, 243 ((mPlayEndTimeMsec)*1000LL)); 244 if(mAudioSource != NULL) { 245 setAudioSource(mAudioSource); 246 } 247 status_t error = mAudioSource->start(); 248 if (error != OK) { 249 ALOGE("Error starting dummy audio source"); 250 mAudioSource.clear(); 251 return err; 252 } 253 254 mDurationUs = (mPlayEndTimeMsec - mPlayBeginTimeMsec)*1000LL; 255 256 mVideoSource = DummyVideoSource::Create(mVideoWidth, mVideoHeight, 257 mDurationUs, mUri); 258 259 updateSizeToRender(mVideoSource->getFormat()); 260 setVideoSource(mVideoSource); 261 status_t err1 = mVideoSource->start(); 262 if (err1 != OK) { 263 mVideoSource.clear(); 264 return err; 265 } 266 267 mIsVideoSourceJpg = true; 268 return OK; 269 } 270 271 void PreviewPlayer::reset_l() { 272 273 if (mFlags & PREPARING) { 274 mFlags |= PREPARE_CANCELLED; 275 } 276 277 while (mFlags & PREPARING) { 278 mPreparedCondition.wait(mLock); 279 } 280 281 cancelPlayerEvents_l(); 282 mAudioTrack.clear(); 283 mVideoTrack.clear(); 284 285 // Shutdown audio first, so that the respone to the reset request 286 // appears to happen instantaneously as far as the user is concerned 287 // If we did this later, audio would continue playing while we 288 // shutdown the video-related resources and the player appear to 289 // not be as responsive to a reset request. 290 if (mAudioPlayer == NULL && mAudioSource != NULL) { 291 // If we had an audio player, it would have effectively 292 // taken possession of the audio source and stopped it when 293 // _it_ is stopped. Otherwise this is still our responsibility. 294 mAudioSource->stop(); 295 } 296 mAudioSource.clear(); 297 298 mTimeSource = NULL; 299 300 //Single audio player instance used 301 //So donot delete it here 302 //It is deleted from PreviewController class 303 //delete mAudioPlayer; 304 mAudioPlayer = NULL; 305 306 if (mVideoBuffer) { 307 mVideoBuffer->release(); 308 mVideoBuffer = NULL; 309 } 310 311 if (mVideoSource != NULL) { 312 mVideoSource->stop(); 313 314 // The following hack is necessary to ensure that the OMX 315 // component is completely released by the time we may try 316 // to instantiate it again. 317 wp<MediaSource> tmp = mVideoSource; 318 mVideoSource.clear(); 319 while (tmp.promote() != NULL) { 320 usleep(1000); 321 } 322 IPCThreadState::self()->flushCommands(); 323 } 324 325 mDurationUs = -1; 326 mFlags = 0; 327 mExtractorFlags = 0; 328 mVideoWidth = mVideoHeight = -1; 329 mTimeSourceDeltaUs = 0; 330 mVideoTimeUs = 0; 331 332 mSeeking = NO_SEEK; 333 mSeekNotificationSent = false; 334 mSeekTimeUs = 0; 335 336 mUri.setTo(""); 337 338 mCurrentVideoEffect = VIDEO_EFFECT_NONE; 339 mIsVideoSourceJpg = false; 340 mFrameRGBBuffer = NULL; 341 if(mFrameYUVBuffer != NULL) { 342 free(mFrameYUVBuffer); 343 mFrameYUVBuffer = NULL; 344 } 345 } 346 347 status_t PreviewPlayer::play() { 348 ALOGV("play"); 349 Mutex::Autolock autoLock(mLock); 350 351 mFlags &= ~CACHE_UNDERRUN; 352 mFlags &= ~INFORMED_AV_EOS; 353 return play_l(); 354 } 355 356 status_t PreviewPlayer::startAudioPlayer_l() { 357 ALOGV("startAudioPlayer_l"); 358 CHECK(!(mFlags & AUDIO_RUNNING)); 359 360 if (mAudioSource == NULL || mAudioPlayer == NULL) { 361 return OK; 362 } 363 364 if (!(mFlags & AUDIOPLAYER_STARTED)) { 365 mFlags |= AUDIOPLAYER_STARTED; 366 367 // We've already started the MediaSource in order to enable 368 // the prefetcher to read its data. 369 status_t err = mAudioPlayer->start( 370 true /* sourceAlreadyStarted */); 371 372 if (err != OK) { 373 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 374 return err; 375 } 376 } else { 377 mAudioPlayer->resume(); 378 } 379 380 mFlags |= AUDIO_RUNNING; 381 382 mWatchForAudioEOS = true; 383 384 return OK; 385 } 386 387 status_t PreviewPlayer::setAudioPlayer(VideoEditorAudioPlayer *audioPlayer) { 388 ALOGV("setAudioPlayer"); 389 Mutex::Autolock autoLock(mLock); 390 CHECK(!(mFlags & PLAYING)); 391 mAudioPlayer = audioPlayer; 392 393 ALOGV("SetAudioPlayer"); 394 mIsChangeSourceRequired = true; 395 396 // check if the new and old source are dummy 397 sp<MediaSource> anAudioSource = mAudioPlayer->getSource(); 398 if (anAudioSource == NULL) { 399 // Audio player does not have any source set. 400 ALOGV("setAudioPlayer: Audio player does not have any source set"); 401 return OK; 402 } 403 404 // If new video source is not dummy, then always change source 405 // Else audio player continues using old audio source and there are 406 // frame drops to maintain AV sync 407 sp<MetaData> meta; 408 if (mVideoSource != NULL) { 409 meta = mVideoSource->getFormat(); 410 const char *pVidSrcType; 411 if (meta->findCString(kKeyDecoderComponent, &pVidSrcType)) { 412 if (strcmp(pVidSrcType, "DummyVideoSource") != 0) { 413 ALOGV(" Video clip with silent audio; need to change source"); 414 return OK; 415 } 416 } 417 } 418 419 const char *pSrcType1; 420 const char *pSrcType2; 421 meta = anAudioSource->getFormat(); 422 423 if (meta->findCString(kKeyDecoderComponent, &pSrcType1)) { 424 if (strcmp(pSrcType1, "DummyAudioSource") == 0) { 425 meta = mAudioSource->getFormat(); 426 if (meta->findCString(kKeyDecoderComponent, &pSrcType2)) { 427 if (strcmp(pSrcType2, "DummyAudioSource") == 0) { 428 mIsChangeSourceRequired = false; 429 // Just set the new play duration for the existing source 430 MediaSource *pMediaSrc = anAudioSource.get(); 431 DummyAudioSource *pDummyAudioSource = (DummyAudioSource*)pMediaSrc; 432 //Increment the duration of audio source 433 pDummyAudioSource->setDuration( 434 (int64_t)((mPlayEndTimeMsec)*1000LL)); 435 436 // Stop the new audio source 437 // since we continue using old source 438 ALOGV("setAudioPlayer: stop new audio source"); 439 mAudioSource->stop(); 440 } 441 } 442 } 443 } 444 445 return OK; 446 } 447 448 void PreviewPlayer::onStreamDone() { 449 ALOGV("onStreamDone"); 450 // Posted whenever any stream finishes playing. 451 452 Mutex::Autolock autoLock(mLock); 453 if (!mStreamDoneEventPending) { 454 return; 455 } 456 mStreamDoneEventPending = false; 457 458 if (mStreamDoneStatus != ERROR_END_OF_STREAM) { 459 ALOGV("MEDIA_ERROR %d", mStreamDoneStatus); 460 461 notifyListener_l( 462 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus); 463 464 pause_l(true /* at eos */); 465 466 mFlags |= AT_EOS; 467 return; 468 } 469 470 const bool allDone = 471 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS)) 472 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS)); 473 474 if (!allDone) { 475 return; 476 } 477 478 if (mFlags & (LOOPING | AUTO_LOOPING)) { 479 seekTo_l(0); 480 481 if (mVideoSource != NULL) { 482 postVideoEvent_l(); 483 } 484 } else { 485 ALOGV("MEDIA_PLAYBACK_COMPLETE"); 486 //pause before sending event 487 pause_l(true /* at eos */); 488 489 //This lock is used to syncronize onStreamDone() in PreviewPlayer and 490 //stopPreview() in PreviewController 491 Mutex::Autolock autoLock(mLockControl); 492 /* Make sure PreviewPlayer only notifies MEDIA_PLAYBACK_COMPLETE once for each clip! 493 * It happens twice in following scenario. 494 * To make the clips in preview storyboard are played and switched smoothly, 495 * PreviewController uses two PreviewPlayer instances and one AudioPlayer. 496 * The two PreviewPlayer use the same AudioPlayer to play the audio, 497 * and change the audio source of the AudioPlayer. 498 * If the audio source of current playing clip and next clip are dummy 499 * audio source(image or video without audio), it will not change the audio source 500 * to avoid the "audio glitch", and keep using the current audio source. 501 * When the video of current clip reached the EOS, PreviewPlayer will set EOS flag 502 * for video and audio, and it will notify MEDIA_PLAYBACK_COMPLETE. 503 * But the audio(dummy audio source) is still playing(for next clip), 504 * and when it reached the EOS, and video reached EOS, 505 * PreviewPlayer will notify MEDIA_PLAYBACK_COMPLETE again. */ 506 if (!(mFlags & INFORMED_AV_EOS)) { 507 notifyListener_l(MEDIA_PLAYBACK_COMPLETE); 508 mFlags |= INFORMED_AV_EOS; 509 } 510 mFlags |= AT_EOS; 511 ALOGV("onStreamDone end"); 512 return; 513 } 514 } 515 516 517 status_t PreviewPlayer::play_l() { 518 ALOGV("play_l"); 519 520 mFlags &= ~SEEK_PREVIEW; 521 522 if (mFlags & PLAYING) { 523 return OK; 524 } 525 mStartNextPlayer = false; 526 527 if (!(mFlags & PREPARED)) { 528 status_t err = prepare_l(); 529 530 if (err != OK) { 531 return err; 532 } 533 } 534 535 mFlags |= PLAYING; 536 mFlags |= FIRST_FRAME; 537 538 bool deferredAudioSeek = false; 539 540 if (mAudioSource != NULL) { 541 if (mAudioPlayer == NULL) { 542 if (mAudioSink != NULL) { 543 544 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this); 545 mAudioPlayer->setSource(mAudioSource); 546 547 mAudioPlayer->setAudioMixSettings( 548 mPreviewPlayerAudioMixSettings); 549 550 mAudioPlayer->setAudioMixPCMFileHandle( 551 mAudioMixPCMFileHandle); 552 553 mAudioPlayer->setAudioMixStoryBoardSkimTimeStamp( 554 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime, 555 mCurrentMediaVolumeValue); 556 557 mFlags |= AUDIOPLAYER_STARTED; 558 // We've already started the MediaSource in order to enable 559 // the prefetcher to read its data. 560 status_t err = mAudioPlayer->start( 561 true /* sourceAlreadyStarted */); 562 563 if (err != OK) { 564 //delete mAudioPlayer; 565 mAudioPlayer = NULL; 566 567 mFlags &= ~(PLAYING | FIRST_FRAME); 568 return err; 569 } 570 571 mTimeSource = mAudioPlayer; 572 mFlags |= AUDIO_RUNNING; 573 deferredAudioSeek = true; 574 mWatchForAudioSeekComplete = false; 575 mWatchForAudioEOS = true; 576 } 577 } else { 578 bool isAudioPlayerStarted = mAudioPlayer->isStarted(); 579 580 if (mIsChangeSourceRequired == true) { 581 ALOGV("play_l: Change audio source required"); 582 583 if (isAudioPlayerStarted == true) { 584 mAudioPlayer->pause(); 585 } 586 587 mAudioPlayer->setSource(mAudioSource); 588 mAudioPlayer->setObserver(this); 589 590 mAudioPlayer->setAudioMixSettings( 591 mPreviewPlayerAudioMixSettings); 592 593 mAudioPlayer->setAudioMixStoryBoardSkimTimeStamp( 594 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime, 595 mCurrentMediaVolumeValue); 596 597 if (isAudioPlayerStarted == true) { 598 mAudioPlayer->resume(); 599 } else { 600 status_t err = OK; 601 err = mAudioPlayer->start(true); 602 if (err != OK) { 603 mAudioPlayer = NULL; 604 mAudioPlayer = NULL; 605 606 mFlags &= ~(PLAYING | FIRST_FRAME); 607 return err; 608 } 609 } 610 } else { 611 ALOGV("play_l: No Source change required"); 612 mAudioPlayer->setAudioMixStoryBoardSkimTimeStamp( 613 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime, 614 mCurrentMediaVolumeValue); 615 616 mAudioPlayer->resume(); 617 } 618 619 mFlags |= AUDIOPLAYER_STARTED; 620 mFlags |= AUDIO_RUNNING; 621 mTimeSource = mAudioPlayer; 622 deferredAudioSeek = true; 623 mWatchForAudioSeekComplete = false; 624 mWatchForAudioEOS = true; 625 } 626 } 627 628 if (mTimeSource == NULL && mAudioPlayer == NULL) { 629 mTimeSource = &mSystemTimeSource; 630 } 631 632 // Set the seek option for Image source files and read. 633 // This resets the timestamping for image play 634 if (mIsVideoSourceJpg) { 635 MediaSource::ReadOptions options; 636 MediaBuffer *aLocalBuffer; 637 options.setSeekTo(mSeekTimeUs); 638 mVideoSource->read(&aLocalBuffer, &options); 639 aLocalBuffer->release(); 640 } 641 642 if (mVideoSource != NULL) { 643 // Kick off video playback 644 postVideoEvent_l(); 645 } 646 647 if (deferredAudioSeek) { 648 // If there was a seek request while we were paused 649 // and we're just starting up again, honor the request now. 650 seekAudioIfNecessary_l(); 651 } 652 653 if (mFlags & AT_EOS) { 654 // Legacy behaviour, if a stream finishes playing and then 655 // is started again, we play from the start... 656 seekTo_l(0); 657 } 658 659 return OK; 660 } 661 662 663 status_t PreviewPlayer::initRenderer_l() { 664 if (mSurface != NULL) { 665 if(mVideoRenderer == NULL) { 666 mVideoRenderer = mNativeWindowRenderer->createRenderInput(); 667 if (mVideoSource != NULL) { 668 updateSizeToRender(mVideoSource->getFormat()); 669 } 670 } 671 } 672 return OK; 673 } 674 675 676 status_t PreviewPlayer::seekTo(int64_t timeUs) { 677 Mutex::Autolock autoLock(mLock); 678 if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) { 679 return seekTo_l(timeUs); 680 } 681 682 return OK; 683 } 684 685 686 status_t PreviewPlayer::getVideoDimensions( 687 int32_t *width, int32_t *height) const { 688 Mutex::Autolock autoLock(mLock); 689 690 if (mVideoWidth < 0 || mVideoHeight < 0) { 691 return UNKNOWN_ERROR; 692 } 693 694 *width = mVideoWidth; 695 *height = mVideoHeight; 696 697 return OK; 698 } 699 700 701 status_t PreviewPlayer::initAudioDecoder_l() { 702 sp<MetaData> meta = mAudioTrack->getFormat(); 703 const char *mime; 704 CHECK(meta->findCString(kKeyMIMEType, &mime)); 705 706 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 707 mAudioSource = mAudioTrack; 708 } else { 709 sp<MediaSource> aRawSource; 710 aRawSource = OMXCodec::Create( 711 mClient.interface(), mAudioTrack->getFormat(), 712 false, // createEncoder 713 mAudioTrack); 714 715 if(aRawSource != NULL) { 716 mAudioSource = new VideoEditorSRC(aRawSource); 717 } 718 } 719 720 if (mAudioSource != NULL) { 721 int64_t durationUs; 722 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 723 setDuration_l(durationUs); 724 } 725 status_t err = mAudioSource->start(); 726 727 if (err != OK) { 728 mAudioSource.clear(); 729 return err; 730 } 731 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) { 732 // For legacy reasons we're simply going to ignore the absence 733 // of an audio decoder for QCELP instead of aborting playback 734 // altogether. 735 return OK; 736 } 737 738 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 739 } 740 741 status_t PreviewPlayer::initVideoDecoder_l(uint32_t flags) { 742 initRenderer_l(); 743 744 if (mVideoRenderer == NULL) { 745 ALOGE("Cannot create renderer"); 746 return UNKNOWN_ERROR; 747 } 748 749 mVideoSource = OMXCodec::Create( 750 mClient.interface(), mVideoTrack->getFormat(), 751 false, 752 mVideoTrack, 753 NULL, flags, mVideoRenderer->getTargetWindow()); 754 755 if (mVideoSource != NULL) { 756 int64_t durationUs; 757 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 758 setDuration_l(durationUs); 759 } 760 761 updateSizeToRender(mVideoTrack->getFormat()); 762 763 status_t err = mVideoSource->start(); 764 765 if (err != OK) { 766 mVideoSource.clear(); 767 return err; 768 } 769 } 770 771 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 772 } 773 774 775 void PreviewPlayer::onVideoEvent() { 776 uint32_t i=0; 777 M4OSA_ERR err1 = M4NO_ERROR; 778 int64_t imageFrameTimeUs = 0; 779 780 Mutex::Autolock autoLock(mLock); 781 if (!mVideoEventPending) { 782 // The event has been cancelled in reset_l() but had already 783 // been scheduled for execution at that time. 784 return; 785 } 786 mVideoEventPending = false; 787 788 if (mFlags & SEEK_PREVIEW) { 789 mFlags &= ~SEEK_PREVIEW; 790 return; 791 } 792 793 TimeSource *ts_st = &mSystemTimeSource; 794 int64_t timeStartUs = ts_st->getRealTimeUs(); 795 796 if (mSeeking != NO_SEEK) { 797 798 if(mAudioSource != NULL) { 799 800 // We're going to seek the video source first, followed by 801 // the audio source. 802 // In order to avoid jumps in the DataSource offset caused by 803 // the audio codec prefetching data from the old locations 804 // while the video codec is already reading data from the new 805 // locations, we'll "pause" the audio source, causing it to 806 // stop reading input data until a subsequent seek. 807 808 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) { 809 mAudioPlayer->pause(); 810 mFlags &= ~AUDIO_RUNNING; 811 } 812 mAudioSource->pause(); 813 } 814 } 815 816 if (!mVideoBuffer) { 817 MediaSource::ReadOptions options; 818 if (mSeeking != NO_SEEK) { 819 ALOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs, 820 mSeekTimeUs / 1E6); 821 822 options.setSeekTo( 823 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST); 824 } 825 for (;;) { 826 status_t err = mVideoSource->read(&mVideoBuffer, &options); 827 options.clearSeekTo(); 828 829 if (err != OK) { 830 CHECK(!mVideoBuffer); 831 832 if (err == INFO_FORMAT_CHANGED) { 833 ALOGV("LV PLAYER VideoSource signalled format change"); 834 notifyVideoSize_l(); 835 836 if (mVideoRenderer != NULL) { 837 mVideoRendererIsPreview = false; 838 err = initRenderer_l(); 839 if (err != OK) { 840 postStreamDoneEvent_l(err); 841 } 842 843 } 844 845 updateSizeToRender(mVideoSource->getFormat()); 846 continue; 847 } 848 // So video playback is complete, but we may still have 849 // a seek request pending that needs to be applied to the audio track 850 if (mSeeking != NO_SEEK) { 851 ALOGV("video stream ended while seeking!"); 852 } 853 finishSeekIfNecessary(-1); 854 ALOGV("PreviewPlayer: onVideoEvent EOS reached."); 855 mFlags |= VIDEO_AT_EOS; 856 mFlags |= AUDIO_AT_EOS; 857 mOverlayUpdateEventPosted = false; 858 postStreamDoneEvent_l(err); 859 // Set the last decoded timestamp to duration 860 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL); 861 return; 862 } 863 864 if (mVideoBuffer->range_length() == 0) { 865 // Some decoders, notably the PV AVC software decoder 866 // return spurious empty buffers that we just want to ignore. 867 868 mVideoBuffer->release(); 869 mVideoBuffer = NULL; 870 continue; 871 } 872 873 int64_t videoTimeUs; 874 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs)); 875 876 if (mSeeking != NO_SEEK) { 877 if (videoTimeUs < mSeekTimeUs) { 878 // buffers are before seek time 879 // ignore them 880 mVideoBuffer->release(); 881 mVideoBuffer = NULL; 882 continue; 883 } 884 } else { 885 if((videoTimeUs/1000) < mPlayBeginTimeMsec) { 886 // Frames are before begin cut time 887 // Donot render 888 mVideoBuffer->release(); 889 mVideoBuffer = NULL; 890 continue; 891 } 892 } 893 break; 894 } 895 } 896 897 mNumberDecVideoFrames++; 898 899 int64_t timeUs; 900 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 901 setPosition_l(timeUs); 902 903 if (!mStartNextPlayer) { 904 int64_t playbackTimeRemaining = (mPlayEndTimeMsec * 1000LL) - timeUs; 905 if (playbackTimeRemaining <= 1500000) { 906 //When less than 1.5 sec of playback left 907 // send notification to start next player 908 909 mStartNextPlayer = true; 910 notifyListener_l(0xAAAAAAAA); 911 } 912 } 913 914 SeekType wasSeeking = mSeeking; 915 finishSeekIfNecessary(timeUs); 916 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING))) { 917 status_t err = startAudioPlayer_l(); 918 if (err != OK) { 919 ALOGE("Starting the audio player failed w/ err %d", err); 920 return; 921 } 922 } 923 924 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource; 925 926 if(ts == NULL) { 927 mVideoBuffer->release(); 928 mVideoBuffer = NULL; 929 return; 930 } 931 932 if(!mIsVideoSourceJpg) { 933 if (mFlags & FIRST_FRAME) { 934 mFlags &= ~FIRST_FRAME; 935 936 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs; 937 } 938 939 int64_t realTimeUs, mediaTimeUs; 940 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL 941 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 942 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 943 } 944 945 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs; 946 947 int64_t latenessUs = nowUs - timeUs; 948 949 if (wasSeeking != NO_SEEK) { 950 // Let's display the first frame after seeking right away. 951 latenessUs = 0; 952 } 953 ALOGV("Audio time stamp = %lld and video time stamp = %lld", 954 ts->getRealTimeUs(),timeUs); 955 if (latenessUs > 40000) { 956 // We're more than 40ms late. 957 958 ALOGV("LV PLAYER we're late by %lld us (%.2f secs)", 959 latenessUs, latenessUs / 1E6); 960 961 mVideoBuffer->release(); 962 mVideoBuffer = NULL; 963 postVideoEvent_l(0); 964 return; 965 } 966 967 if (latenessUs < -25000) { 968 // We're more than 25ms early. 969 ALOGV("We're more than 25ms early, lateness %lld", latenessUs); 970 971 postVideoEvent_l(25000); 972 return; 973 } 974 } 975 976 if (mVideoRendererIsPreview || mVideoRenderer == NULL) { 977 mVideoRendererIsPreview = false; 978 979 status_t err = initRenderer_l(); 980 if (err != OK) { 981 postStreamDoneEvent_l(err); 982 } 983 } 984 985 // If timestamp exceeds endCutTime of clip, donot render 986 if((timeUs/1000) > mPlayEndTimeMsec) { 987 mVideoBuffer->release(); 988 mVideoBuffer = NULL; 989 mFlags |= VIDEO_AT_EOS; 990 mFlags |= AUDIO_AT_EOS; 991 ALOGV("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS.."); 992 mOverlayUpdateEventPosted = false; 993 // Set the last decoded timestamp to duration 994 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL); 995 postStreamDoneEvent_l(ERROR_END_OF_STREAM); 996 return; 997 } 998 // Capture the frame timestamp to be rendered 999 mDecodedVideoTs = timeUs; 1000 1001 // Post processing to apply video effects 1002 for(i=0;i<mNumberEffects;i++) { 1003 // First check if effect starttime matches the clip being previewed 1004 if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) || 1005 (mEffectsSettings[i].uiStartTime >= 1006 ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec))) 1007 { 1008 // This effect doesn't belong to this clip, check next one 1009 continue; 1010 } 1011 // Check if effect applies to this particular frame timestamp 1012 if((mEffectsSettings[i].uiStartTime <= 1013 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) && 1014 ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >= 1015 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) 1016 && (mEffectsSettings[i].uiDuration != 0)) { 1017 setVideoPostProcessingNode( 1018 mEffectsSettings[i].VideoEffectType, TRUE); 1019 } 1020 else { 1021 setVideoPostProcessingNode( 1022 mEffectsSettings[i].VideoEffectType, FALSE); 1023 } 1024 } 1025 1026 //Provide the overlay Update indication when there is an overlay effect 1027 if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) { 1028 mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here. 1029 if (!mOverlayUpdateEventPosted) { 1030 // Find the effect in effectSettings array 1031 M4OSA_UInt32 index; 1032 for (index = 0; index < mNumberEffects; index++) { 1033 M4OSA_UInt32 timeMs = mDecodedVideoTs/1000; 1034 M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000; 1035 if(mEffectsSettings[index].VideoEffectType == 1036 (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) { 1037 if (((mEffectsSettings[index].uiStartTime + 1) <= 1038 timeMs + timeOffset - mPlayBeginTimeMsec) && 1039 ((mEffectsSettings[index].uiStartTime - 1 + 1040 mEffectsSettings[index].uiDuration) >= 1041 timeMs + timeOffset - mPlayBeginTimeMsec)) 1042 { 1043 break; 1044 } 1045 } 1046 } 1047 if (index < mNumberEffects) { 1048 mCurrFramingEffectIndex = index; 1049 mOverlayUpdateEventPosted = true; 1050 postOverlayUpdateEvent_l(); 1051 ALOGV("Framing index = %ld", mCurrFramingEffectIndex); 1052 } else { 1053 ALOGV("No framing effects found"); 1054 } 1055 } 1056 1057 } else if (mOverlayUpdateEventPosted) { 1058 //Post the event when the overlay is no more valid 1059 ALOGV("Overlay is Done"); 1060 mOverlayUpdateEventPosted = false; 1061 postOverlayUpdateEvent_l(); 1062 } 1063 1064 if (mVideoRenderer != NULL) { 1065 mVideoRenderer->render(mVideoBuffer, mCurrentVideoEffect, 1066 mRenderingMode, mIsVideoSourceJpg); 1067 } 1068 1069 mVideoBuffer->release(); 1070 mVideoBuffer = NULL; 1071 1072 // Post progress callback based on callback interval set 1073 if(mNumberDecVideoFrames >= mProgressCbInterval) { 1074 postProgressCallbackEvent_l(); 1075 mNumberDecVideoFrames = 0; // reset counter 1076 } 1077 1078 // if reached EndCutTime of clip, post EOS event 1079 if((timeUs/1000) >= mPlayEndTimeMsec) { 1080 ALOGV("PreviewPlayer: onVideoEvent EOS."); 1081 mFlags |= VIDEO_AT_EOS; 1082 mFlags |= AUDIO_AT_EOS; 1083 mOverlayUpdateEventPosted = false; 1084 // Set the last decoded timestamp to duration 1085 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL); 1086 postStreamDoneEvent_l(ERROR_END_OF_STREAM); 1087 } 1088 else { 1089 if ((wasSeeking != NO_SEEK) && (mFlags & SEEK_PREVIEW)) { 1090 mFlags &= ~SEEK_PREVIEW; 1091 return; 1092 } 1093 1094 if(!mIsVideoSourceJpg) { 1095 postVideoEvent_l(0); 1096 } 1097 else { 1098 postVideoEvent_l(33000); 1099 } 1100 } 1101 } 1102 1103 status_t PreviewPlayer::prepare() { 1104 ALOGV("prepare"); 1105 Mutex::Autolock autoLock(mLock); 1106 return prepare_l(); 1107 } 1108 1109 status_t PreviewPlayer::prepare_l() { 1110 ALOGV("prepare_l"); 1111 if (mFlags & PREPARED) { 1112 return OK; 1113 } 1114 1115 if (mFlags & PREPARING) { 1116 return UNKNOWN_ERROR; 1117 } 1118 1119 mIsAsyncPrepare = false; 1120 status_t err = prepareAsync_l(); 1121 1122 if (err != OK) { 1123 return err; 1124 } 1125 1126 while (mFlags & PREPARING) { 1127 mPreparedCondition.wait(mLock); 1128 } 1129 1130 return mPrepareResult; 1131 } 1132 1133 status_t PreviewPlayer::prepareAsync() { 1134 ALOGV("prepareAsync"); 1135 Mutex::Autolock autoLock(mLock); 1136 return prepareAsync_l(); 1137 } 1138 1139 status_t PreviewPlayer::prepareAsync_l() { 1140 ALOGV("prepareAsync_l"); 1141 if (mFlags & PREPARING) { 1142 return UNKNOWN_ERROR; // async prepare already pending 1143 } 1144 1145 if (!mQueueStarted) { 1146 mQueue.start(); 1147 mQueueStarted = true; 1148 } 1149 1150 mFlags |= PREPARING; 1151 mAsyncPrepareEvent = new PreviewPlayerEvent( 1152 this, &PreviewPlayer::onPrepareAsyncEvent); 1153 1154 mQueue.postEvent(mAsyncPrepareEvent); 1155 1156 return OK; 1157 } 1158 1159 status_t PreviewPlayer::finishSetDataSource_l() { 1160 sp<DataSource> dataSource; 1161 sp<MediaExtractor> extractor; 1162 1163 dataSource = DataSource::CreateFromURI(mUri.string(), NULL); 1164 1165 if (dataSource == NULL) { 1166 return UNKNOWN_ERROR; 1167 } 1168 1169 //If file type is .rgb, then no need to check for Extractor 1170 int uriLen = strlen(mUri); 1171 int startOffset = uriLen - 4; 1172 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) { 1173 extractor = NULL; 1174 } 1175 else { 1176 extractor = MediaExtractor::Create(dataSource, 1177 MEDIA_MIMETYPE_CONTAINER_MPEG4); 1178 } 1179 1180 if (extractor == NULL) { 1181 ALOGV("finishSetDataSource_l: failed to create extractor"); 1182 return setDataSource_l_jpg(); 1183 } 1184 1185 return setDataSource_l(extractor); 1186 } 1187 1188 void PreviewPlayer::onPrepareAsyncEvent() { 1189 Mutex::Autolock autoLock(mLock); 1190 ALOGV("onPrepareAsyncEvent"); 1191 1192 if (mFlags & PREPARE_CANCELLED) { 1193 ALOGV("prepare was cancelled before doing anything"); 1194 abortPrepare(UNKNOWN_ERROR); 1195 return; 1196 } 1197 1198 if (mUri.size() > 0) { 1199 status_t err = finishSetDataSource_l(); 1200 1201 if (err != OK) { 1202 abortPrepare(err); 1203 return; 1204 } 1205 } 1206 1207 if (mVideoTrack != NULL && mVideoSource == NULL) { 1208 status_t err = initVideoDecoder_l(OMXCodec::kHardwareCodecsOnly); 1209 1210 if (err != OK) { 1211 abortPrepare(err); 1212 return; 1213 } 1214 } 1215 1216 if (mAudioTrack != NULL && mAudioSource == NULL) { 1217 status_t err = initAudioDecoder_l(); 1218 1219 if (err != OK) { 1220 abortPrepare(err); 1221 return; 1222 } 1223 } 1224 finishAsyncPrepare_l(); 1225 1226 } 1227 1228 void PreviewPlayer::finishAsyncPrepare_l() { 1229 ALOGV("finishAsyncPrepare_l"); 1230 if (mIsAsyncPrepare) { 1231 if (mVideoSource == NULL) { 1232 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); 1233 } else { 1234 notifyVideoSize_l(); 1235 } 1236 notifyListener_l(MEDIA_PREPARED); 1237 } 1238 1239 mPrepareResult = OK; 1240 mFlags &= ~(PREPARING|PREPARE_CANCELLED); 1241 mFlags |= PREPARED; 1242 mAsyncPrepareEvent = NULL; 1243 mPreparedCondition.broadcast(); 1244 } 1245 1246 void PreviewPlayer::acquireLock() { 1247 ALOGV("acquireLock"); 1248 mLockControl.lock(); 1249 } 1250 1251 void PreviewPlayer::releaseLock() { 1252 ALOGV("releaseLock"); 1253 mLockControl.unlock(); 1254 } 1255 1256 status_t PreviewPlayer::loadEffectsSettings( 1257 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) { 1258 1259 ALOGV("loadEffectsSettings"); 1260 mNumberEffects = nEffects; 1261 mEffectsSettings = pEffectSettings; 1262 return OK; 1263 } 1264 1265 status_t PreviewPlayer::loadAudioMixSettings( 1266 M4xVSS_AudioMixingSettings* pAudioMixSettings) { 1267 1268 ALOGV("loadAudioMixSettings"); 1269 mPreviewPlayerAudioMixSettings = pAudioMixSettings; 1270 return OK; 1271 } 1272 1273 status_t PreviewPlayer::setAudioMixPCMFileHandle( 1274 M4OSA_Context pAudioMixPCMFileHandle) { 1275 1276 ALOGV("setAudioMixPCMFileHandle"); 1277 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle; 1278 return OK; 1279 } 1280 1281 status_t PreviewPlayer::setAudioMixStoryBoardParam( 1282 M4OSA_UInt32 audioMixStoryBoardTS, 1283 M4OSA_UInt32 currentMediaBeginCutTime, 1284 M4OSA_UInt32 primaryTrackVolValue ) { 1285 1286 ALOGV("setAudioMixStoryBoardParam"); 1287 mAudioMixStoryBoardTS = audioMixStoryBoardTS; 1288 mCurrentMediaBeginCutTime = currentMediaBeginCutTime; 1289 mCurrentMediaVolumeValue = primaryTrackVolValue; 1290 return OK; 1291 } 1292 1293 status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) { 1294 1295 mPlayBeginTimeMsec = msec; 1296 return OK; 1297 } 1298 1299 status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) { 1300 1301 mPlayEndTimeMsec = msec; 1302 return OK; 1303 } 1304 1305 status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) { 1306 1307 mStoryboardStartTimeMsec = msec; 1308 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec * 1000LL; 1309 return OK; 1310 } 1311 1312 status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) { 1313 1314 mProgressCbInterval = cbInterval; 1315 return OK; 1316 } 1317 1318 1319 status_t PreviewPlayer::setMediaRenderingMode( 1320 M4xVSS_MediaRendering mode, 1321 M4VIDEOEDITING_VideoFrameSize outputVideoSize) { 1322 1323 mRenderingMode = mode; 1324 1325 /* get the video width and height by resolution */ 1326 return getVideoSizeByResolution( 1327 outputVideoSize, 1328 &mOutputVideoWidth, &mOutputVideoHeight); 1329 1330 } 1331 1332 status_t PreviewPlayer::resetJniCallbackTimeStamp() { 1333 1334 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec * 1000LL; 1335 return OK; 1336 } 1337 1338 void PreviewPlayer::postProgressCallbackEvent_l() { 1339 if (mProgressCbEventPending) { 1340 return; 1341 } 1342 mProgressCbEventPending = true; 1343 1344 mQueue.postEvent(mProgressCbEvent); 1345 } 1346 1347 1348 void PreviewPlayer::onProgressCbEvent() { 1349 Mutex::Autolock autoLock(mLock); 1350 if (!mProgressCbEventPending) { 1351 return; 1352 } 1353 mProgressCbEventPending = false; 1354 // If playback starts from previous I-frame, 1355 // then send frame storyboard duration 1356 if ((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) { 1357 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000); 1358 } else { 1359 notifyListener_l(MEDIA_INFO, 0, 1360 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)); 1361 } 1362 } 1363 1364 void PreviewPlayer::postOverlayUpdateEvent_l() { 1365 if (mOverlayUpdateEventPending) { 1366 return; 1367 } 1368 mOverlayUpdateEventPending = true; 1369 mQueue.postEvent(mOverlayUpdateEvent); 1370 } 1371 1372 void PreviewPlayer::onUpdateOverlayEvent() { 1373 Mutex::Autolock autoLock(mLock); 1374 1375 if (!mOverlayUpdateEventPending) { 1376 return; 1377 } 1378 mOverlayUpdateEventPending = false; 1379 1380 int updateState = mOverlayUpdateEventPosted? 1: 0; 1381 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex); 1382 } 1383 1384 1385 void PreviewPlayer::setVideoPostProcessingNode( 1386 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) { 1387 1388 uint32_t effect = VIDEO_EFFECT_NONE; 1389 1390 //Map M4VSS3GPP_VideoEffectType to local enum 1391 switch(type) { 1392 case M4VSS3GPP_kVideoEffectType_FadeFromBlack: 1393 effect = VIDEO_EFFECT_FADEFROMBLACK; 1394 break; 1395 1396 case M4VSS3GPP_kVideoEffectType_FadeToBlack: 1397 effect = VIDEO_EFFECT_FADETOBLACK; 1398 break; 1399 1400 case M4xVSS_kVideoEffectType_BlackAndWhite: 1401 effect = VIDEO_EFFECT_BLACKANDWHITE; 1402 break; 1403 1404 case M4xVSS_kVideoEffectType_Pink: 1405 effect = VIDEO_EFFECT_PINK; 1406 break; 1407 1408 case M4xVSS_kVideoEffectType_Green: 1409 effect = VIDEO_EFFECT_GREEN; 1410 break; 1411 1412 case M4xVSS_kVideoEffectType_Sepia: 1413 effect = VIDEO_EFFECT_SEPIA; 1414 break; 1415 1416 case M4xVSS_kVideoEffectType_Negative: 1417 effect = VIDEO_EFFECT_NEGATIVE; 1418 break; 1419 1420 case M4xVSS_kVideoEffectType_Framing: 1421 effect = VIDEO_EFFECT_FRAMING; 1422 break; 1423 1424 case M4xVSS_kVideoEffectType_Fifties: 1425 effect = VIDEO_EFFECT_FIFTIES; 1426 break; 1427 1428 case M4xVSS_kVideoEffectType_ColorRGB16: 1429 effect = VIDEO_EFFECT_COLOR_RGB16; 1430 break; 1431 1432 case M4xVSS_kVideoEffectType_Gradient: 1433 effect = VIDEO_EFFECT_GRADIENT; 1434 break; 1435 1436 default: 1437 effect = VIDEO_EFFECT_NONE; 1438 break; 1439 } 1440 1441 if (enable == M4OSA_TRUE) { 1442 //If already set, then no need to set again 1443 if (!(mCurrentVideoEffect & effect)) { 1444 mCurrentVideoEffect |= effect; 1445 if (effect == VIDEO_EFFECT_FIFTIES) { 1446 mIsFiftiesEffectStarted = true; 1447 } 1448 } 1449 } else { 1450 //Reset only if already set 1451 if (mCurrentVideoEffect & effect) { 1452 mCurrentVideoEffect &= ~effect; 1453 } 1454 } 1455 } 1456 1457 status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) { 1458 mVideoWidth = width; 1459 mVideoHeight = height; 1460 return OK; 1461 } 1462 1463 status_t PreviewPlayer::readFirstVideoFrame() { 1464 ALOGV("readFirstVideoFrame"); 1465 1466 if (!mVideoBuffer) { 1467 MediaSource::ReadOptions options; 1468 if (mSeeking != NO_SEEK) { 1469 ALOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, 1470 mSeekTimeUs / 1E6); 1471 1472 options.setSeekTo( 1473 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST); 1474 } 1475 for (;;) { 1476 status_t err = mVideoSource->read(&mVideoBuffer, &options); 1477 options.clearSeekTo(); 1478 1479 if (err != OK) { 1480 CHECK(!mVideoBuffer); 1481 1482 if (err == INFO_FORMAT_CHANGED) { 1483 ALOGV("VideoSource signalled format change"); 1484 notifyVideoSize_l(); 1485 1486 if (mVideoRenderer != NULL) { 1487 mVideoRendererIsPreview = false; 1488 err = initRenderer_l(); 1489 if (err != OK) { 1490 postStreamDoneEvent_l(err); 1491 } 1492 } 1493 1494 updateSizeToRender(mVideoSource->getFormat()); 1495 continue; 1496 } 1497 ALOGV("EOS reached."); 1498 mFlags |= VIDEO_AT_EOS; 1499 mFlags |= AUDIO_AT_EOS; 1500 postStreamDoneEvent_l(err); 1501 return OK; 1502 } 1503 1504 if (mVideoBuffer->range_length() == 0) { 1505 // Some decoders, notably the PV AVC software decoder 1506 // return spurious empty buffers that we just want to ignore. 1507 1508 mVideoBuffer->release(); 1509 mVideoBuffer = NULL; 1510 continue; 1511 } 1512 1513 int64_t videoTimeUs; 1514 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs)); 1515 if (mSeeking != NO_SEEK) { 1516 if (videoTimeUs < mSeekTimeUs) { 1517 // buffers are before seek time 1518 // ignore them 1519 mVideoBuffer->release(); 1520 mVideoBuffer = NULL; 1521 continue; 1522 } 1523 } else { 1524 if ((videoTimeUs/1000) < mPlayBeginTimeMsec) { 1525 // buffers are before begin cut time 1526 // ignore them 1527 mVideoBuffer->release(); 1528 mVideoBuffer = NULL; 1529 continue; 1530 } 1531 } 1532 break; 1533 } 1534 } 1535 1536 int64_t timeUs; 1537 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 1538 setPosition_l(timeUs); 1539 1540 mDecodedVideoTs = timeUs; 1541 1542 return OK; 1543 1544 } 1545 1546 status_t PreviewPlayer::getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs) { 1547 *lastRenderedTimeMs = (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec); 1548 return OK; 1549 } 1550 1551 void PreviewPlayer::updateSizeToRender(sp<MetaData> meta) { 1552 if (mVideoRenderer) { 1553 mVideoRenderer->updateVideoSize(meta); 1554 } 1555 } 1556 1557 void PreviewPlayer::setListener(const wp<MediaPlayerBase> &listener) { 1558 Mutex::Autolock autoLock(mLock); 1559 mListener = listener; 1560 } 1561 1562 status_t PreviewPlayer::setDataSource(const sp<IStreamSource> &source) { 1563 return INVALID_OPERATION; 1564 } 1565 1566 void PreviewPlayer::reset() { 1567 Mutex::Autolock autoLock(mLock); 1568 reset_l(); 1569 } 1570 1571 void PreviewPlayer::clear_l() { 1572 mDisplayWidth = 0; 1573 mDisplayHeight = 0; 1574 1575 if (mFlags & PLAYING) { 1576 updateBatteryUsage_l(); 1577 } 1578 1579 if (mFlags & PREPARING) { 1580 mFlags |= PREPARE_CANCELLED; 1581 1582 if (mFlags & PREPARING_CONNECTED) { 1583 // We are basically done preparing, we're just buffering 1584 // enough data to start playback, we can safely interrupt that. 1585 finishAsyncPrepare_l(); 1586 } 1587 } 1588 1589 while (mFlags & PREPARING) { 1590 mPreparedCondition.wait(mLock); 1591 } 1592 1593 cancelPlayerEvents_l(true); 1594 1595 mAudioTrack.clear(); 1596 mVideoTrack.clear(); 1597 1598 // Shutdown audio first, so that the respone to the reset request 1599 // appears to happen instantaneously as far as the user is concerned 1600 // If we did this later, audio would continue playing while we 1601 // shutdown the video-related resources and the player appear to 1602 // not be as responsive to a reset request. 1603 if (mAudioPlayer == NULL && mAudioSource != NULL) { 1604 // If we had an audio player, it would have effectively 1605 // taken possession of the audio source and stopped it when 1606 // _it_ is stopped. Otherwise this is still our responsibility. 1607 mAudioSource->stop(); 1608 } 1609 mAudioSource.clear(); 1610 1611 mTimeSource = NULL; 1612 1613 delete mAudioPlayer; 1614 mAudioPlayer = NULL; 1615 1616 if (mVideoSource != NULL) { 1617 shutdownVideoDecoder_l(); 1618 } 1619 1620 mDurationUs = -1; 1621 mFlags = 0; 1622 mExtractorFlags = 0; 1623 mTimeSourceDeltaUs = 0; 1624 mVideoTimeUs = 0; 1625 1626 mSeeking = NO_SEEK; 1627 mSeekNotificationSent = false; 1628 mSeekTimeUs = 0; 1629 1630 mUri.setTo(""); 1631 1632 mBitrate = -1; 1633 mLastVideoTimeUs = -1; 1634 } 1635 1636 void PreviewPlayer::notifyListener_l(int msg, int ext1, int ext2) { 1637 if (mListener != NULL) { 1638 sp<MediaPlayerBase> listener = mListener.promote(); 1639 1640 if (listener != NULL) { 1641 listener->sendEvent(msg, ext1, ext2); 1642 } 1643 } 1644 } 1645 1646 void PreviewPlayer::onVideoLagUpdate() { 1647 Mutex::Autolock autoLock(mLock); 1648 if (!mVideoLagEventPending) { 1649 return; 1650 } 1651 mVideoLagEventPending = false; 1652 1653 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs(); 1654 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs; 1655 1656 if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) { 1657 ALOGV("video late by %lld ms.", videoLateByUs / 1000ll); 1658 1659 notifyListener_l( 1660 MEDIA_INFO, 1661 MEDIA_INFO_VIDEO_TRACK_LAGGING, 1662 videoLateByUs / 1000ll); 1663 } 1664 1665 postVideoLagEvent_l(); 1666 } 1667 1668 void PreviewPlayer::notifyVideoSize_l() { 1669 sp<MetaData> meta = mVideoSource->getFormat(); 1670 1671 int32_t vWidth, vHeight; 1672 int32_t cropLeft, cropTop, cropRight, cropBottom; 1673 1674 CHECK(meta->findInt32(kKeyWidth, &vWidth)); 1675 CHECK(meta->findInt32(kKeyHeight, &vHeight)); 1676 1677 mGivenWidth = vWidth; 1678 mGivenHeight = vHeight; 1679 1680 if (!meta->findRect( 1681 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) { 1682 1683 cropLeft = cropTop = 0; 1684 cropRight = vWidth - 1; 1685 cropBottom = vHeight - 1; 1686 1687 ALOGD("got dimensions only %d x %d", vWidth, vHeight); 1688 } else { 1689 ALOGD("got crop rect %d, %d, %d, %d", 1690 cropLeft, cropTop, cropRight, cropBottom); 1691 } 1692 1693 mCropRect.left = cropLeft; 1694 mCropRect.right = cropRight; 1695 mCropRect.top = cropTop; 1696 mCropRect.bottom = cropBottom; 1697 1698 int32_t displayWidth; 1699 if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) { 1700 ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth); 1701 mDisplayWidth = displayWidth; 1702 } 1703 int32_t displayHeight; 1704 if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) { 1705 ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight); 1706 mDisplayHeight = displayHeight; 1707 } 1708 1709 int32_t usableWidth = cropRight - cropLeft + 1; 1710 int32_t usableHeight = cropBottom - cropTop + 1; 1711 if (mDisplayWidth != 0) { 1712 usableWidth = mDisplayWidth; 1713 } 1714 if (mDisplayHeight != 0) { 1715 usableHeight = mDisplayHeight; 1716 } 1717 1718 int32_t rotationDegrees; 1719 if (!mVideoTrack->getFormat()->findInt32( 1720 kKeyRotation, &rotationDegrees)) { 1721 rotationDegrees = 0; 1722 } 1723 1724 if (rotationDegrees == 90 || rotationDegrees == 270) { 1725 notifyListener_l( 1726 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth); 1727 } else { 1728 notifyListener_l( 1729 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight); 1730 } 1731 } 1732 1733 status_t PreviewPlayer::pause() { 1734 Mutex::Autolock autoLock(mLock); 1735 1736 mFlags &= ~CACHE_UNDERRUN; 1737 1738 return pause_l(); 1739 } 1740 1741 status_t PreviewPlayer::pause_l(bool at_eos) { 1742 if (!(mFlags & PLAYING)) { 1743 return OK; 1744 } 1745 1746 cancelPlayerEvents_l(); 1747 1748 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) { 1749 if (at_eos) { 1750 // If we played the audio stream to completion we 1751 // want to make sure that all samples remaining in the audio 1752 // track's queue are played out. 1753 mAudioPlayer->pause(true /* playPendingSamples */); 1754 } else { 1755 mAudioPlayer->pause(); 1756 } 1757 1758 mFlags &= ~AUDIO_RUNNING; 1759 } 1760 1761 mFlags &= ~PLAYING; 1762 updateBatteryUsage_l(); 1763 1764 return OK; 1765 } 1766 1767 bool PreviewPlayer::isPlaying() const { 1768 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN); 1769 } 1770 1771 void PreviewPlayer::setSurface(const sp<Surface> &surface) { 1772 Mutex::Autolock autoLock(mLock); 1773 1774 mSurface = surface; 1775 setNativeWindow_l(surface); 1776 } 1777 1778 void PreviewPlayer::setSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer) { 1779 Mutex::Autolock autoLock(mLock); 1780 1781 mSurface.clear(); 1782 if (bufferProducer != NULL) { 1783 setNativeWindow_l(new Surface(bufferProducer)); 1784 } 1785 } 1786 1787 void PreviewPlayer::shutdownVideoDecoder_l() { 1788 if (mVideoBuffer) { 1789 mVideoBuffer->release(); 1790 mVideoBuffer = NULL; 1791 } 1792 1793 mVideoSource->stop(); 1794 1795 // The following hack is necessary to ensure that the OMX 1796 // component is completely released by the time we may try 1797 // to instantiate it again. 1798 wp<MediaSource> tmp = mVideoSource; 1799 mVideoSource.clear(); 1800 while (tmp.promote() != NULL) { 1801 usleep(1000); 1802 } 1803 IPCThreadState::self()->flushCommands(); 1804 } 1805 1806 void PreviewPlayer::setNativeWindow_l(const sp<ANativeWindow> &native) { 1807 mNativeWindow = native; 1808 1809 if (mVideoSource == NULL) { 1810 return; 1811 } 1812 1813 ALOGI("attempting to reconfigure to use new surface"); 1814 1815 bool wasPlaying = (mFlags & PLAYING) != 0; 1816 1817 pause_l(); 1818 1819 shutdownVideoDecoder_l(); 1820 1821 CHECK_EQ(initVideoDecoder_l(), (status_t)OK); 1822 1823 if (mLastVideoTimeUs >= 0) { 1824 mSeeking = SEEK; 1825 mSeekNotificationSent = true; 1826 mSeekTimeUs = mLastVideoTimeUs; 1827 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS); 1828 } 1829 1830 if (wasPlaying) { 1831 play_l(); 1832 } 1833 } 1834 1835 void PreviewPlayer::setAudioSink( 1836 const sp<MediaPlayerBase::AudioSink> &audioSink) { 1837 Mutex::Autolock autoLock(mLock); 1838 1839 mAudioSink = audioSink; 1840 } 1841 1842 status_t PreviewPlayer::setLooping(bool shouldLoop) { 1843 Mutex::Autolock autoLock(mLock); 1844 1845 mFlags = mFlags & ~LOOPING; 1846 1847 if (shouldLoop) { 1848 mFlags |= LOOPING; 1849 } 1850 1851 return OK; 1852 } 1853 1854 void PreviewPlayer::setDuration_l(int64_t durationUs) { 1855 if (mDurationUs < 0 || durationUs > mDurationUs) { 1856 mDurationUs = durationUs; 1857 } 1858 } 1859 1860 status_t PreviewPlayer::getDuration(int64_t *durationUs) { 1861 Mutex::Autolock autoLock(mLock); 1862 if (mDurationUs < 0) { 1863 return UNKNOWN_ERROR; 1864 } 1865 1866 *durationUs = mDurationUs; 1867 return OK; 1868 } 1869 1870 status_t PreviewPlayer::getPosition(int64_t *positionUs) { 1871 Mutex::Autolock autoLock(mLock); 1872 1873 if (mSeeking != NO_SEEK) { 1874 *positionUs = mSeekTimeUs; 1875 } else if (mVideoSource != NULL 1876 && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) { 1877 *positionUs = mVideoTimeUs; 1878 } else if (mAudioPlayer != NULL) { 1879 *positionUs = mAudioPlayer->getMediaTimeUs(); 1880 } else { 1881 *positionUs = 0; 1882 } 1883 1884 return OK; 1885 } 1886 1887 void PreviewPlayer::setPosition_l(int64_t timeUs) { 1888 mVideoTimeUs = timeUs; 1889 } 1890 1891 status_t PreviewPlayer::seekTo_l(int64_t timeUs) { 1892 ALOGV("seekTo_l"); 1893 if (mFlags & CACHE_UNDERRUN) { 1894 mFlags &= ~CACHE_UNDERRUN; 1895 play_l(); 1896 } 1897 1898 if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) { 1899 // Video playback completed before, there's no pending 1900 // video event right now. In order for this new seek 1901 // to be honored, we need to post one. 1902 1903 postVideoEvent_l(); 1904 } 1905 1906 mSeeking = SEEK; 1907 mSeekNotificationSent = false; 1908 mSeekTimeUs = timeUs; 1909 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS); 1910 1911 seekAudioIfNecessary_l(); 1912 1913 if (!(mFlags & PLAYING)) { 1914 ALOGV("seeking while paused, sending SEEK_COMPLETE notification" 1915 " immediately."); 1916 1917 notifyListener_l(MEDIA_SEEK_COMPLETE); 1918 mSeekNotificationSent = true; 1919 1920 if ((mFlags & PREPARED) && mVideoSource != NULL) { 1921 mFlags |= SEEK_PREVIEW; 1922 postVideoEvent_l(); 1923 } 1924 } 1925 1926 return OK; 1927 } 1928 1929 void PreviewPlayer::seekAudioIfNecessary_l() { 1930 if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) { 1931 mAudioPlayer->seekTo(mSeekTimeUs); 1932 1933 mWatchForAudioSeekComplete = true; 1934 mWatchForAudioEOS = true; 1935 } 1936 } 1937 1938 void PreviewPlayer::setAudioSource(const sp<MediaSource>& source) { 1939 CHECK(source != NULL); 1940 mAudioTrack = source; 1941 } 1942 1943 void PreviewPlayer::setVideoSource(const sp<MediaSource>& source) { 1944 CHECK(source != NULL); 1945 mVideoTrack = source; 1946 } 1947 1948 void PreviewPlayer::finishSeekIfNecessary(int64_t videoTimeUs) { 1949 if (mSeeking == SEEK_VIDEO_ONLY) { 1950 mSeeking = NO_SEEK; 1951 return; 1952 } 1953 1954 if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) { 1955 return; 1956 } 1957 1958 if (mAudioPlayer != NULL) { 1959 ALOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6); 1960 1961 // If we don't have a video time, seek audio to the originally 1962 // requested seek time instead. 1963 1964 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs); 1965 mWatchForAudioSeekComplete = true; 1966 mWatchForAudioEOS = true; 1967 } else if (!mSeekNotificationSent) { 1968 // If we're playing video only, report seek complete now, 1969 // otherwise audio player will notify us later. 1970 notifyListener_l(MEDIA_SEEK_COMPLETE); 1971 mSeekNotificationSent = true; 1972 } 1973 1974 mFlags |= FIRST_FRAME; 1975 mSeeking = NO_SEEK; 1976 } 1977 1978 void PreviewPlayer::onCheckAudioStatus() { 1979 Mutex::Autolock autoLock(mLock); 1980 if (!mAudioStatusEventPending) { 1981 // Event was dispatched and while we were blocking on the mutex, 1982 // has already been cancelled. 1983 return; 1984 } 1985 1986 mAudioStatusEventPending = false; 1987 1988 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) { 1989 mWatchForAudioSeekComplete = false; 1990 1991 if (!mSeekNotificationSent) { 1992 notifyListener_l(MEDIA_SEEK_COMPLETE); 1993 mSeekNotificationSent = true; 1994 } 1995 1996 mSeeking = NO_SEEK; 1997 } 1998 1999 status_t finalStatus; 2000 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) { 2001 mWatchForAudioEOS = false; 2002 mFlags |= AUDIO_AT_EOS; 2003 mFlags |= FIRST_FRAME; 2004 postStreamDoneEvent_l(finalStatus); 2005 } 2006 } 2007 2008 void PreviewPlayer::postVideoEvent_l(int64_t delayUs) { 2009 if (mVideoEventPending) { 2010 return; 2011 } 2012 2013 mVideoEventPending = true; 2014 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 2015 } 2016 2017 void PreviewPlayer::postStreamDoneEvent_l(status_t status) { 2018 if (mStreamDoneEventPending) { 2019 return; 2020 } 2021 mStreamDoneEventPending = true; 2022 2023 mStreamDoneStatus = status; 2024 mQueue.postEvent(mStreamDoneEvent); 2025 } 2026 2027 void PreviewPlayer::postVideoLagEvent_l() { 2028 if (mVideoLagEventPending) { 2029 return; 2030 } 2031 mVideoLagEventPending = true; 2032 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll); 2033 } 2034 2035 void PreviewPlayer::postCheckAudioStatusEvent_l(int64_t delayUs) { 2036 if (mAudioStatusEventPending) { 2037 return; 2038 } 2039 mAudioStatusEventPending = true; 2040 mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs); 2041 } 2042 2043 void PreviewPlayer::abortPrepare(status_t err) { 2044 CHECK(err != OK); 2045 2046 if (mIsAsyncPrepare) { 2047 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 2048 } 2049 2050 mPrepareResult = err; 2051 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED); 2052 mAsyncPrepareEvent = NULL; 2053 mPreparedCondition.broadcast(); 2054 } 2055 2056 uint32_t PreviewPlayer::getSourceSeekFlags() const { 2057 Mutex::Autolock lock(mLock); 2058 return mExtractorFlags; 2059 } 2060 2061 void PreviewPlayer::postAudioEOS(int64_t delayUs) { 2062 Mutex::Autolock autoLock(mLock); 2063 postCheckAudioStatusEvent_l(delayUs); 2064 } 2065 2066 void PreviewPlayer::postAudioSeekComplete() { 2067 Mutex::Autolock autoLock(mLock); 2068 postCheckAudioStatusEvent_l(0 /* delayUs */); 2069 } 2070 2071 void PreviewPlayer::updateBatteryUsage_l() { 2072 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder; 2073 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) { 2074 params |= IMediaPlayerService::kBatteryDataTrackAudio; 2075 } 2076 if (mVideoSource != NULL) { 2077 params |= IMediaPlayerService::kBatteryDataTrackVideo; 2078 } 2079 addBatteryData(params); 2080 } 2081 2082 } // namespace android 2083