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