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