PreviewPlayer.cpp revision 53c567c3355255ed12dd9f5d5a1c58f821770329
1/* 2 * Copyright (C) 2011 NXP Software 3 * Copyright (C) 2011 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18#define LOG_NDEBUG 1 19#define LOG_TAG "PreviewPlayer" 20#include <utils/Log.h> 21 22#include <dlfcn.h> 23 24#include "include/ARTSPController.h" 25#include "PreviewPlayer.h" 26#include "DummyAudioSource.h" 27#include "DummyVideoSource.h" 28#include "VideoEditorSRC.h" 29#include "include/LiveSession.h" 30#include "include/NuCachedSource2.h" 31#include "include/ThrottledSource.h" 32 33 34#include "PreviewRenderer.h" 35 36#include <binder/IPCThreadState.h> 37#include <media/stagefright/DataSource.h> 38#include <media/stagefright/FileSource.h> 39#include <media/stagefright/MediaBuffer.h> 40#include <media/stagefright/MediaDefs.h> 41#include <media/stagefright/MediaExtractor.h> 42#include <media/stagefright/MediaDebug.h> 43#include <media/stagefright/MediaSource.h> 44#include <media/stagefright/MetaData.h> 45#include <media/stagefright/OMXCodec.h> 46 47#include <surfaceflinger/Surface.h> 48#include <media/stagefright/foundation/ALooper.h> 49 50namespace android { 51 52 53struct PreviewPlayerEvent : public TimedEventQueue::Event { 54 PreviewPlayerEvent( 55 PreviewPlayer *player, 56 void (PreviewPlayer::*method)()) 57 : mPlayer(player), 58 mMethod(method) { 59 } 60 61protected: 62 virtual ~PreviewPlayerEvent() {} 63 64 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { 65 (mPlayer->*mMethod)(); 66 } 67 68private: 69 PreviewPlayer *mPlayer; 70 void (PreviewPlayer::*mMethod)(); 71 72 PreviewPlayerEvent(const PreviewPlayerEvent &); 73 PreviewPlayerEvent &operator=(const PreviewPlayerEvent &); 74}; 75 76 77struct PreviewLocalRenderer : public PreviewPlayerRenderer { 78 PreviewLocalRenderer( 79 bool previewOnly, 80 OMX_COLOR_FORMATTYPE colorFormat, 81 const sp<Surface> &surface, 82 size_t displayWidth, size_t displayHeight, 83 size_t decodedWidth, size_t decodedHeight, 84 int32_t rotationDegrees = 0) 85 : mTarget(NULL) { 86 init(previewOnly, 87 colorFormat, surface, 88 displayWidth, displayHeight, 89 decodedWidth, decodedHeight, 90 rotationDegrees); 91 } 92 93 virtual void render(MediaBuffer *buffer) { 94 render((const uint8_t *)buffer->data() + buffer->range_offset(), 95 buffer->range_length()); 96 } 97 98 void render(const void *data, size_t size) { 99 mTarget->render(data, size, NULL); 100 } 101 void render() { 102 mTarget->renderYV12(); 103 } 104 void getBuffer(uint8_t **data, size_t *stride) { 105 mTarget->getBufferYV12(data, stride); 106 } 107 108protected: 109 virtual ~PreviewLocalRenderer() { 110 delete mTarget; 111 mTarget = NULL; 112 } 113 114private: 115 PreviewRenderer *mTarget; 116 117 void init( 118 bool previewOnly, 119 OMX_COLOR_FORMATTYPE colorFormat, 120 const sp<Surface> &surface, 121 size_t displayWidth, size_t displayHeight, 122 size_t decodedWidth, size_t decodedHeight, 123 int32_t rotationDegrees = 0); 124 125 PreviewLocalRenderer(const PreviewLocalRenderer &); 126 PreviewLocalRenderer &operator=(const PreviewLocalRenderer &);; 127}; 128 129void PreviewLocalRenderer::init( 130 bool previewOnly, 131 OMX_COLOR_FORMATTYPE colorFormat, 132 const sp<Surface> &surface, 133 size_t displayWidth, size_t displayHeight, 134 size_t decodedWidth, size_t decodedHeight, 135 int32_t rotationDegrees) { 136 mTarget = new PreviewRenderer( 137 colorFormat, surface, displayWidth, displayHeight, 138 decodedWidth, decodedHeight, rotationDegrees); 139} 140 141PreviewPlayer::PreviewPlayer() 142 : AwesomePlayer(), 143 mFrameRGBBuffer(NULL), 144 mFrameYUVBuffer(NULL), 145 mReportedWidth(0), 146 mReportedHeight(0), 147 mCurrFramingEffectIndex(0) { 148 149 mVideoRenderer = NULL; 150 mLastVideoBuffer = NULL; 151 mSuspensionState = NULL; 152 mEffectsSettings = NULL; 153 mAudioMixStoryBoardTS = 0; 154 mCurrentMediaBeginCutTime = 0; 155 mCurrentMediaVolumeValue = 0; 156 mNumberEffects = 0; 157 mDecodedVideoTs = 0; 158 mDecVideoTsStoryBoard = 0; 159 mCurrentVideoEffect = VIDEO_EFFECT_NONE; 160 mProgressCbInterval = 0; 161 mNumberDecVideoFrames = 0; 162 mOverlayUpdateEventPosted = false; 163 164 mVideoEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoEvent); 165 mVideoEventPending = false; 166 mStreamDoneEvent = new PreviewPlayerEvent(this, 167 &AwesomePlayer::onStreamDone); 168 169 mStreamDoneEventPending = false; 170 171 mCheckAudioStatusEvent = new PreviewPlayerEvent( 172 this, &AwesomePlayer::onCheckAudioStatus); 173 174 mAudioStatusEventPending = false; 175 176 mProgressCbEvent = new PreviewPlayerEvent(this, 177 &PreviewPlayer::onProgressCbEvent); 178 179 mOverlayUpdateEvent = new PreviewPlayerEvent(this, 180 &PreviewPlayer::onUpdateOverlayEvent); 181 mProgressCbEventPending = false; 182 183 mOverlayUpdateEventPending = false; 184 mResizedVideoBuffer = NULL; 185 mVideoResizedOrCropped = false; 186 mRenderingMode = (M4xVSS_MediaRendering)MEDIA_RENDERING_INVALID; 187 mIsFiftiesEffectStarted = false; 188 reset(); 189} 190 191PreviewPlayer::~PreviewPlayer() { 192 193 if (mQueueStarted) { 194 mQueue.stop(); 195 } 196 197 reset(); 198 199 if(mResizedVideoBuffer != NULL) { 200 M4OSA_free((M4OSA_MemAddr32)(mResizedVideoBuffer->data())); 201 mResizedVideoBuffer = NULL; 202 } 203 204 mVideoRenderer.clear(); 205 mVideoRenderer = NULL; 206} 207 208void PreviewPlayer::cancelPlayerEvents(bool keepBufferingGoing) { 209 mQueue.cancelEvent(mVideoEvent->eventID()); 210 mVideoEventPending = false; 211 mQueue.cancelEvent(mStreamDoneEvent->eventID()); 212 mStreamDoneEventPending = false; 213 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID()); 214 mAudioStatusEventPending = false; 215 216 mQueue.cancelEvent(mProgressCbEvent->eventID()); 217 mProgressCbEventPending = false; 218} 219 220status_t PreviewPlayer::setDataSource( 221 const char *uri, const KeyedVector<String8, String8> *headers) { 222 Mutex::Autolock autoLock(mLock); 223 return setDataSource_l(uri, headers); 224} 225 226status_t PreviewPlayer::setDataSource_l( 227 const char *uri, const KeyedVector<String8, String8> *headers) { 228 reset_l(); 229 230 mUri = uri; 231 232 if (headers) { 233 mUriHeaders = *headers; 234 } 235 236 // The actual work will be done during preparation in the call to 237 // ::finishSetDataSource_l to avoid blocking the calling thread in 238 // setDataSource for any significant time. 239 return OK; 240} 241 242status_t PreviewPlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { 243 bool haveAudio = false; 244 bool haveVideo = false; 245 for (size_t i = 0; i < extractor->countTracks(); ++i) { 246 sp<MetaData> meta = extractor->getTrackMetaData(i); 247 248 const char *mime; 249 CHECK(meta->findCString(kKeyMIMEType, &mime)); 250 251 if (!haveVideo && !strncasecmp(mime, "video/", 6)) { 252 setVideoSource(extractor->getTrack(i)); 253 haveVideo = true; 254 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) { 255 setAudioSource(extractor->getTrack(i)); 256 haveAudio = true; 257 258 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { 259 // Only do this for vorbis audio, none of the other audio 260 // formats even support this ringtone specific hack and 261 // retrieving the metadata on some extractors may turn out 262 // to be very expensive. 263 sp<MetaData> fileMeta = extractor->getMetaData(); 264 int32_t loop; 265 if (fileMeta != NULL 266 && fileMeta->findInt32(kKeyAutoLoop, &loop) 267 && loop != 0) { 268 mFlags |= AUTO_LOOPING; 269 } 270 } 271 } 272 273 if (haveAudio && haveVideo) { 274 break; 275 } 276 } 277 278 /* Add the support for Dummy audio*/ 279 if( !haveAudio ){ 280 LOGV("PreviewPlayer: setDataSource_l Dummyaudiocreation started"); 281 282 mAudioTrack = DummyAudioSource::Create(32000, 2, 20000, 283 ((mPlayEndTimeMsec)*1000)); 284 LOGV("PreviewPlayer: setDataSource_l Dummyauiosource created"); 285 if(mAudioTrack != NULL) { 286 haveAudio = true; 287 } 288 } 289 290 if (!haveAudio && !haveVideo) { 291 return UNKNOWN_ERROR; 292 } 293 294 mExtractorFlags = extractor->flags(); 295 return OK; 296} 297 298status_t PreviewPlayer::setDataSource_l_jpg() { 299 M4OSA_ERR err = M4NO_ERROR; 300 LOGV("PreviewPlayer: setDataSource_l_jpg started"); 301 302 mAudioSource = DummyAudioSource::Create(32000, 2, 20000, 303 ((mPlayEndTimeMsec)*1000)); 304 LOGV("PreviewPlayer: setDataSource_l_jpg Dummyaudiosource created"); 305 if(mAudioSource != NULL) { 306 setAudioSource(mAudioSource); 307 } 308 status_t error = mAudioSource->start(); 309 if (error != OK) { 310 LOGV("Error starting dummy audio source"); 311 mAudioSource.clear(); 312 return err; 313 } 314 315 mDurationUs = (mPlayEndTimeMsec - mPlayBeginTimeMsec)*1000; 316 317 mVideoSource = DummyVideoSource::Create(mVideoWidth, mVideoHeight, 318 mDurationUs, mUri); 319 mReportedWidth = mVideoWidth; 320 mReportedHeight = mVideoHeight; 321 322 setVideoSource(mVideoSource); 323 status_t err1 = mVideoSource->start(); 324 if (err1 != OK) { 325 mVideoSource.clear(); 326 return err; 327 } 328 329 mIsVideoSourceJpg = true; 330 return OK; 331} 332 333void PreviewPlayer::reset() { 334 Mutex::Autolock autoLock(mLock); 335 reset_l(); 336} 337 338void PreviewPlayer::reset_l() { 339 340 if (mFlags & PREPARING) { 341 mFlags |= PREPARE_CANCELLED; 342 } 343 344 while (mFlags & PREPARING) { 345 mPreparedCondition.wait(mLock); 346 } 347 348 cancelPlayerEvents(); 349 mAudioTrack.clear(); 350 mVideoTrack.clear(); 351 352 // Shutdown audio first, so that the respone to the reset request 353 // appears to happen instantaneously as far as the user is concerned 354 // If we did this later, audio would continue playing while we 355 // shutdown the video-related resources and the player appear to 356 // not be as responsive to a reset request. 357 if (mAudioPlayer == NULL && mAudioSource != NULL) { 358 // If we had an audio player, it would have effectively 359 // taken possession of the audio source and stopped it when 360 // _it_ is stopped. Otherwise this is still our responsibility. 361 mAudioSource->stop(); 362 } 363 mAudioSource.clear(); 364 365 mTimeSource = NULL; 366 367 delete mAudioPlayer; 368 mAudioPlayer = NULL; 369 370 if (mLastVideoBuffer) { 371 mLastVideoBuffer->release(); 372 mLastVideoBuffer = NULL; 373 } 374 375 if (mVideoBuffer) { 376 mVideoBuffer->release(); 377 mVideoBuffer = NULL; 378 } 379 380 if (mVideoSource != NULL) { 381 mVideoSource->stop(); 382 383 // The following hack is necessary to ensure that the OMX 384 // component is completely released by the time we may try 385 // to instantiate it again. 386 wp<MediaSource> tmp = mVideoSource; 387 mVideoSource.clear(); 388 while (tmp.promote() != NULL) { 389 usleep(1000); 390 } 391 IPCThreadState::self()->flushCommands(); 392 } 393 394 mDurationUs = -1; 395 mFlags = 0; 396 mExtractorFlags = 0; 397 mVideoWidth = mVideoHeight = -1; 398 mTimeSourceDeltaUs = 0; 399 mVideoTimeUs = 0; 400 401 mSeeking = false; 402 mSeekNotificationSent = false; 403 mSeekTimeUs = 0; 404 405 mUri.setTo(""); 406 mUriHeaders.clear(); 407 408 mFileSource.clear(); 409 410 delete mSuspensionState; 411 mSuspensionState = NULL; 412 413 mCurrentVideoEffect = VIDEO_EFFECT_NONE; 414 mIsVideoSourceJpg = false; 415 mFrameRGBBuffer = NULL; 416 if(mFrameYUVBuffer != NULL) { 417 M4OSA_free((M4OSA_MemAddr32)mFrameYUVBuffer); 418 mFrameYUVBuffer = NULL; 419 } 420} 421 422void PreviewPlayer::partial_reset_l() { 423 424 if (mLastVideoBuffer) { 425 mLastVideoBuffer->release(); 426 mLastVideoBuffer = NULL; 427 } 428 429 /* call base struct */ 430 AwesomePlayer::partial_reset_l(); 431 432} 433 434status_t PreviewPlayer::play() { 435 Mutex::Autolock autoLock(mLock); 436 437 mFlags &= ~CACHE_UNDERRUN; 438 439 return play_l(); 440} 441 442status_t PreviewPlayer::play_l() { 443VideoEditorAudioPlayer *mVePlayer; 444 if (mFlags & PLAYING) { 445 return OK; 446 } 447 mStartNextPlayer = false; 448 449 if (!(mFlags & PREPARED)) { 450 status_t err = prepare_l(); 451 452 if (err != OK) { 453 return err; 454 } 455 } 456 457 mFlags |= PLAYING; 458 mFlags |= FIRST_FRAME; 459 460 bool deferredAudioSeek = false; 461 462 if (mAudioSource != NULL) { 463 if (mAudioPlayer == NULL) { 464 if (mAudioSink != NULL) { 465 466 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this); 467 mVePlayer = 468 (VideoEditorAudioPlayer*)mAudioPlayer; 469 470 mAudioPlayer->setSource(mAudioSource); 471 472 mVePlayer->setAudioMixSettings( 473 mPreviewPlayerAudioMixSettings); 474 475 mVePlayer->setAudioMixPCMFileHandle( 476 mAudioMixPCMFileHandle); 477 478 mVePlayer->setAudioMixStoryBoardSkimTimeStamp( 479 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime, 480 mCurrentMediaVolumeValue); 481 482 // We've already started the MediaSource in order to enable 483 // the prefetcher to read its data. 484 status_t err = mVePlayer->start( 485 true /* sourceAlreadyStarted */); 486 487 if (err != OK) { 488 delete mAudioPlayer; 489 mAudioPlayer = NULL; 490 491 mFlags &= ~(PLAYING | FIRST_FRAME); 492 return err; 493 } 494 495 mTimeSource = mVePlayer; //mAudioPlayer; 496 497 deferredAudioSeek = true; 498 mWatchForAudioSeekComplete = false; 499 mWatchForAudioEOS = true; 500 } 501 } else { 502 mVePlayer->resume(); 503 } 504 505 } 506 507 if (mTimeSource == NULL && mAudioPlayer == NULL) { 508 mTimeSource = &mSystemTimeSource; 509 } 510 511 // Set the seek option for Image source files and read. 512 // This resets the timestamping for image play 513 if (mIsVideoSourceJpg) { 514 MediaSource::ReadOptions options; 515 MediaBuffer *aLocalBuffer; 516 options.setSeekTo(mSeekTimeUs); 517 mVideoSource->read(&aLocalBuffer, &options); 518 } 519 520 if (mVideoSource != NULL) { 521 // Kick off video playback 522 postVideoEvent_l(); 523 } 524 525 if (deferredAudioSeek) { 526 // If there was a seek request while we were paused 527 // and we're just starting up again, honor the request now. 528 seekAudioIfNecessary_l(); 529 } 530 531 if (mFlags & AT_EOS) { 532 // Legacy behaviour, if a stream finishes playing and then 533 // is started again, we play from the start... 534 seekTo_l(0); 535 } 536 537 return OK; 538} 539 540 541void PreviewPlayer::initRenderer_l() { 542 if (mSurface != NULL || mISurface != NULL) { 543 sp<MetaData> meta = mVideoSource->getFormat(); 544 545 int32_t format; 546 const char *component; 547 int32_t decodedWidth, decodedHeight; 548 CHECK(meta->findInt32(kKeyColorFormat, &format)); 549 CHECK(meta->findCString(kKeyDecoderComponent, &component)); 550 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 551 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 552 553 // Must ensure that mVideoRenderer's destructor is actually executed 554 // before creating a new one. 555 IPCThreadState::self()->flushCommands(); 556 557 // always use localrenderer since decoded buffers are modified 558 // by postprocessing module 559 // Other decoders are instantiated locally and as a consequence 560 // allocate their buffers in local address space. 561 if(mVideoRenderer == NULL) { 562 563 mVideoRenderer = new PreviewLocalRenderer( 564 false, // previewOnly 565 (OMX_COLOR_FORMATTYPE)format, 566 mSurface, 567 mOutputVideoWidth, mOutputVideoHeight, 568 mOutputVideoWidth, mOutputVideoHeight); 569 } 570 } 571} 572 573 574void PreviewPlayer::setISurface(const sp<ISurface> &isurface) { 575 Mutex::Autolock autoLock(mLock); 576 mISurface = isurface; 577} 578 579 580status_t PreviewPlayer::seekTo(int64_t timeUs) { 581 582 if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) { 583 Mutex::Autolock autoLock(mLock); 584 return seekTo_l(timeUs); 585 } 586 587 return OK; 588} 589 590 591status_t PreviewPlayer::getVideoDimensions( 592 int32_t *width, int32_t *height) const { 593 Mutex::Autolock autoLock(mLock); 594 595 if (mVideoWidth < 0 || mVideoHeight < 0) { 596 return UNKNOWN_ERROR; 597 } 598 599 *width = mVideoWidth; 600 *height = mVideoHeight; 601 602 return OK; 603} 604 605 606status_t PreviewPlayer::initAudioDecoder() { 607 sp<MetaData> meta = mAudioTrack->getFormat(); 608 const char *mime; 609 CHECK(meta->findCString(kKeyMIMEType, &mime)); 610 611 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 612 mAudioSource = mAudioTrack; 613 } else { 614 sp<MediaSource> aRawSource; 615 aRawSource = OMXCodec::Create( 616 mClient.interface(), mAudioTrack->getFormat(), 617 false, // createEncoder 618 mAudioTrack); 619 620 if(aRawSource != NULL) { 621 LOGV("initAudioDecoder: new VideoEditorSRC"); 622 mAudioSource = new VideoEditorSRC(aRawSource); 623 } 624 } 625 626 if (mAudioSource != NULL) { 627 int64_t durationUs; 628 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 629 Mutex::Autolock autoLock(mMiscStateLock); 630 if (mDurationUs < 0 || durationUs > mDurationUs) { 631 mDurationUs = durationUs; 632 } 633 } 634 status_t err = mAudioSource->start(); 635 636 if (err != OK) { 637 mAudioSource.clear(); 638 return err; 639 } 640 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) { 641 // For legacy reasons we're simply going to ignore the absence 642 // of an audio decoder for QCELP instead of aborting playback 643 // altogether. 644 return OK; 645 } 646 647 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 648} 649 650 651status_t PreviewPlayer::initVideoDecoder(uint32_t flags) { 652 653 mVideoSource = OMXCodec::Create( 654 mClient.interface(), mVideoTrack->getFormat(), 655 false, 656 mVideoTrack, 657 NULL, flags); 658 659 if (mVideoSource != NULL) { 660 int64_t durationUs; 661 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) { 662 Mutex::Autolock autoLock(mMiscStateLock); 663 if (mDurationUs < 0 || durationUs > mDurationUs) { 664 mDurationUs = durationUs; 665 } 666 } 667 668 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth)); 669 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight)); 670 671 mReportedWidth = mVideoWidth; 672 mReportedHeight = mVideoHeight; 673 674 status_t err = mVideoSource->start(); 675 676 if (err != OK) { 677 mVideoSource.clear(); 678 return err; 679 } 680 } 681 682 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 683} 684 685 686void PreviewPlayer::onVideoEvent() { 687 uint32_t i=0; 688 bool bAppliedVideoEffect = false; 689 M4OSA_ERR err1 = M4NO_ERROR; 690 int64_t imageFrameTimeUs = 0; 691 692 Mutex::Autolock autoLock(mLock); 693 if (!mVideoEventPending) { 694 // The event has been cancelled in reset_l() but had already 695 // been scheduled for execution at that time. 696 return; 697 } 698 mVideoEventPending = false; 699 700 TimeSource *ts_st = &mSystemTimeSource; 701 int64_t timeStartUs = ts_st->getRealTimeUs(); 702 703 if (mSeeking) { 704 if (mLastVideoBuffer) { 705 mLastVideoBuffer->release(); 706 mLastVideoBuffer = NULL; 707 } 708 709 710 if(mAudioSource != NULL) { 711 712 // We're going to seek the video source first, followed by 713 // the audio source. 714 // In order to avoid jumps in the DataSource offset caused by 715 // the audio codec prefetching data from the old locations 716 // while the video codec is already reading data from the new 717 // locations, we'll "pause" the audio source, causing it to 718 // stop reading input data until a subsequent seek. 719 720 if (mAudioPlayer != NULL) { 721 mAudioPlayer->pause(); 722 } 723 mAudioSource->pause(); 724 } 725 } 726 727 if (!mVideoBuffer) { 728 MediaSource::ReadOptions options; 729 if (mSeeking) { 730 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs, 731 mSeekTimeUs / 1E6); 732 733 options.setSeekTo( 734 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST); 735 } 736 for (;;) { 737 status_t err = mVideoSource->read(&mVideoBuffer, &options); 738 options.clearSeekTo(); 739 740 if (err != OK) { 741 CHECK_EQ(mVideoBuffer, NULL); 742 743 if (err == INFO_FORMAT_CHANGED) { 744 LOGV("LV PLAYER VideoSource signalled format change"); 745 notifyVideoSize_l(); 746 sp<MetaData> meta = mVideoSource->getFormat(); 747 748 CHECK(meta->findInt32(kKeyWidth, &mReportedWidth)); 749 CHECK(meta->findInt32(kKeyHeight, &mReportedHeight)); 750 if (mVideoRenderer != NULL) { 751 mVideoRendererIsPreview = false; 752 initRenderer_l(); 753 } 754 continue; 755 } 756 // So video playback is complete, but we may still have 757 // a seek request pending that needs to be applied to the audio track 758 if (mSeeking) { 759 LOGV("video stream ended while seeking!"); 760 } 761 finishSeekIfNecessary(-1); 762 LOGV("PreviewPlayer: onVideoEvent EOS reached."); 763 mFlags |= VIDEO_AT_EOS; 764 if (mOverlayUpdateEventPosted) { 765 mOverlayUpdateEventPosted = false; 766 postOverlayUpdateEvent_l(); 767 } 768 postStreamDoneEvent_l(err); 769 return; 770 } 771 772 if (mVideoBuffer->range_length() == 0) { 773 // Some decoders, notably the PV AVC software decoder 774 // return spurious empty buffers that we just want to ignore. 775 776 mVideoBuffer->release(); 777 mVideoBuffer = NULL; 778 continue; 779 } 780 781 int64_t videoTimeUs; 782 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs)); 783 784 if((videoTimeUs/1000) < mPlayBeginTimeMsec) { 785 // Frames are before begin cut time 786 // Donot render 787 mVideoBuffer->release(); 788 mVideoBuffer = NULL; 789 continue; 790 } 791 792 break; 793 } 794 } 795 796 mNumberDecVideoFrames++; 797 798 int64_t timeUs; 799 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 800 801 { 802 Mutex::Autolock autoLock(mMiscStateLock); 803 mVideoTimeUs = timeUs; 804 } 805 806 mDecodedVideoTs = timeUs; 807 808 if(!mStartNextPlayer) { 809 int64_t playbackTimeRemaining = (mPlayEndTimeMsec*1000) - timeUs; 810 if(playbackTimeRemaining <= 1500000) { 811 //When less than 1.5 sec of playback left 812 // send notification to start next player 813 814 mStartNextPlayer = true; 815 notifyListener_l(0xAAAAAAAA); 816 } 817 } 818 819 bool wasSeeking = mSeeking; 820 finishSeekIfNecessary(timeUs); 821 822 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource; 823 824 if(ts == NULL) { 825 mVideoBuffer->release(); 826 mVideoBuffer = NULL; 827 return; 828 } 829 830 if(!mIsVideoSourceJpg) { 831 if (mFlags & FIRST_FRAME) { 832 mFlags &= ~FIRST_FRAME; 833 834 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs; 835 } 836 837 int64_t realTimeUs, mediaTimeUs; 838 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL 839 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 840 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 841 } 842 843 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs; 844 845 int64_t latenessUs = nowUs - timeUs; 846 847 if (wasSeeking) { 848 // Let's display the first frame after seeking right away. 849 latenessUs = 0; 850 } 851 LOGV("Audio time stamp = %lld and video time stamp = %lld", 852 ts->getRealTimeUs(),timeUs); 853 if (latenessUs > 40000) { 854 // We're more than 40ms late. 855 856 LOGV("LV PLAYER we're late by %lld us (%.2f secs)", 857 latenessUs, latenessUs / 1E6); 858 859 mVideoBuffer->release(); 860 mVideoBuffer = NULL; 861 862 postVideoEvent_l(); 863 return; 864 } 865 866 if (latenessUs < -10000) { 867 // We're more than 10ms early. 868 LOGV("We're more than 10ms early, lateness %lld", latenessUs); 869 870 postVideoEvent_l(10000); 871 return; 872 } 873 } 874 875 if (mVideoRendererIsPreview || mVideoRenderer == NULL) { 876 mVideoRendererIsPreview = false; 877 878 initRenderer_l(); 879 } 880 881 // If timestamp exceeds endCutTime of clip, donot render 882 if((timeUs/1000) > mPlayEndTimeMsec) { 883 if (mLastVideoBuffer) { 884 mLastVideoBuffer->release(); 885 mLastVideoBuffer = NULL; 886 } 887 mLastVideoBuffer = mVideoBuffer; 888 mVideoBuffer = NULL; 889 mFlags |= VIDEO_AT_EOS; 890 mFlags |= AUDIO_AT_EOS; 891 LOGI("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS.."); 892 if (mOverlayUpdateEventPosted) { 893 mOverlayUpdateEventPosted = false; 894 postOverlayUpdateEvent_l(); 895 } 896 postStreamDoneEvent_l(ERROR_END_OF_STREAM); 897 return; 898 } 899 900 // Post processing to apply video effects 901 for(i=0;i<mNumberEffects;i++) { 902 // First check if effect starttime matches the clip being previewed 903 if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) || 904 (mEffectsSettings[i].uiStartTime >= 905 ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec))) 906 { 907 // This effect doesn't belong to this clip, check next one 908 continue; 909 } 910 // Check if effect applies to this particular frame timestamp 911 if((mEffectsSettings[i].uiStartTime <= 912 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) && 913 ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >= 914 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) 915 && (mEffectsSettings[i].uiDuration != 0)) { 916 917 setVideoPostProcessingNode( 918 mEffectsSettings[i].VideoEffectType, TRUE); 919 } 920 else { 921 setVideoPostProcessingNode( 922 mEffectsSettings[i].VideoEffectType, FALSE); 923 } 924 } 925 926 //Provide the overlay Update indication when there is an overlay effect 927 if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) { 928 mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here. 929 if (!mOverlayUpdateEventPosted) { 930 931 // Find the effect in effectSettings array 932 int index; 933 for (index = 0; index < mNumberEffects; index++) { 934 M4OSA_UInt32 timeMs = mDecodedVideoTs/1000; 935 M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000; 936 if(mEffectsSettings[index].VideoEffectType == 937 M4xVSS_kVideoEffectType_Framing) { 938 if (((mEffectsSettings[index].uiStartTime + 1) <= 939 timeMs + timeOffset - mPlayBeginTimeMsec) && 940 ((mEffectsSettings[index].uiStartTime - 1 + 941 mEffectsSettings[index].uiDuration) >= 942 timeMs + timeOffset - mPlayBeginTimeMsec)) 943 { 944 break; 945 } 946 } 947 } 948 if (index < mNumberEffects) { 949 mCurrFramingEffectIndex = index; 950 mOverlayUpdateEventPosted = true; 951 postOverlayUpdateEvent_l(); 952 LOGV("Framing index = %d", mCurrFramingEffectIndex); 953 } else { 954 LOGV("No framing effects found"); 955 } 956 } 957 958 } else if (mOverlayUpdateEventPosted) { 959 //Post the event when the overlay is no more valid 960 LOGV("Overlay is Done"); 961 mOverlayUpdateEventPosted = false; 962 postOverlayUpdateEvent_l(); 963 } 964 965 966 if (mCurrentVideoEffect != VIDEO_EFFECT_NONE) { 967 err1 = doVideoPostProcessing(); 968 if(err1 != M4NO_ERROR) { 969 LOGE("doVideoPostProcessing returned err"); 970 bAppliedVideoEffect = false; 971 } 972 else { 973 bAppliedVideoEffect = true; 974 } 975 } 976 else { 977 bAppliedVideoEffect = false; 978 if(mRenderingMode != MEDIA_RENDERING_INVALID) { 979 // No effects to be applied, but media rendering to be done 980 err1 = doMediaRendering(); 981 if(err1 != M4NO_ERROR) { 982 LOGE("doMediaRendering returned err"); 983 //Use original mVideoBuffer for rendering 984 mVideoResizedOrCropped = false; 985 } 986 } 987 } 988 989 if (mVideoRenderer != NULL) { 990 LOGV("mVideoRenderer CALL render()"); 991 mVideoRenderer->render(); 992 } 993 994 if (mLastVideoBuffer) { 995 mLastVideoBuffer->release(); 996 mLastVideoBuffer = NULL; 997 } 998 999 mLastVideoBuffer = mVideoBuffer; 1000 mVideoBuffer = NULL; 1001 1002 // Post progress callback based on callback interval set 1003 if(mNumberDecVideoFrames >= mProgressCbInterval) { 1004 postProgressCallbackEvent_l(); 1005 mNumberDecVideoFrames = 0; // reset counter 1006 } 1007 1008 // if reached EndCutTime of clip, post EOS event 1009 if((timeUs/1000) >= mPlayEndTimeMsec) { 1010 LOGV("PreviewPlayer: onVideoEvent EOS."); 1011 mFlags |= VIDEO_AT_EOS; 1012 mFlags |= AUDIO_AT_EOS; 1013 if (mOverlayUpdateEventPosted) { 1014 mOverlayUpdateEventPosted = false; 1015 postOverlayUpdateEvent_l(); 1016 } 1017 postStreamDoneEvent_l(ERROR_END_OF_STREAM); 1018 } 1019 else { 1020 if(!mIsVideoSourceJpg) { 1021 postVideoEvent_l(); 1022 } 1023 else { 1024 postVideoEvent_l(33000); 1025 } 1026 } 1027} 1028 1029status_t PreviewPlayer::prepare() { 1030 Mutex::Autolock autoLock(mLock); 1031 return prepare_l(); 1032} 1033 1034status_t PreviewPlayer::prepare_l() { 1035 if (mFlags & PREPARED) { 1036 return OK; 1037 } 1038 1039 if (mFlags & PREPARING) { 1040 return UNKNOWN_ERROR; 1041 } 1042 1043 mIsAsyncPrepare = false; 1044 status_t err = prepareAsync_l(); 1045 1046 if (err != OK) { 1047 return err; 1048 } 1049 1050 while (mFlags & PREPARING) { 1051 mPreparedCondition.wait(mLock); 1052 } 1053 1054 return mPrepareResult; 1055} 1056 1057status_t PreviewPlayer::prepareAsync_l() { 1058 if (mFlags & PREPARING) { 1059 return UNKNOWN_ERROR; // async prepare already pending 1060 } 1061 1062 if (!mQueueStarted) { 1063 mQueue.start(); 1064 mQueueStarted = true; 1065 } 1066 1067 mFlags |= PREPARING; 1068 mAsyncPrepareEvent = new PreviewPlayerEvent( 1069 this, &PreviewPlayer::onPrepareAsyncEvent); 1070 1071 mQueue.postEvent(mAsyncPrepareEvent); 1072 1073 return OK; 1074} 1075 1076status_t PreviewPlayer::finishSetDataSource_l() { 1077 sp<DataSource> dataSource; 1078 sp<MediaExtractor> extractor; 1079 1080 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders); 1081 1082 if (dataSource == NULL) { 1083 return UNKNOWN_ERROR; 1084 } 1085 1086 //If file type is .rgb, then no need to check for Extractor 1087 int uriLen = strlen(mUri); 1088 int startOffset = uriLen - 4; 1089 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) { 1090 extractor = NULL; 1091 } 1092 else { 1093 extractor = MediaExtractor::Create(dataSource, 1094 MEDIA_MIMETYPE_CONTAINER_MPEG4); 1095 } 1096 1097 if (extractor == NULL) { 1098 LOGV("PreviewPlayer::finishSetDataSource_l extractor == NULL"); 1099 return setDataSource_l_jpg(); 1100 } 1101 1102 return setDataSource_l(extractor); 1103} 1104 1105 1106// static 1107bool PreviewPlayer::ContinuePreparation(void *cookie) { 1108 PreviewPlayer *me = static_cast<PreviewPlayer *>(cookie); 1109 1110 return (me->mFlags & PREPARE_CANCELLED) == 0; 1111} 1112 1113void PreviewPlayer::onPrepareAsyncEvent() { 1114 Mutex::Autolock autoLock(mLock); 1115 LOGV("onPrepareAsyncEvent"); 1116 1117 if (mFlags & PREPARE_CANCELLED) { 1118 LOGI("LV PLAYER prepare was cancelled before doing anything"); 1119 abortPrepare(UNKNOWN_ERROR); 1120 return; 1121 } 1122 1123 if (mUri.size() > 0) { 1124 status_t err = finishSetDataSource_l(); 1125 1126 if (err != OK) { 1127 abortPrepare(err); 1128 return; 1129 } 1130 } 1131 1132 if (mVideoTrack != NULL && mVideoSource == NULL) { 1133 status_t err = initVideoDecoder(OMXCodec::kHardwareCodecsOnly); 1134 1135 if (err != OK) { 1136 abortPrepare(err); 1137 return; 1138 } 1139 } 1140 1141 if (mAudioTrack != NULL && mAudioSource == NULL) { 1142 status_t err = initAudioDecoder(); 1143 1144 if (err != OK) { 1145 abortPrepare(err); 1146 return; 1147 } 1148 } 1149 finishAsyncPrepare_l(); 1150 1151} 1152 1153void PreviewPlayer::finishAsyncPrepare_l() { 1154 if (mIsAsyncPrepare) { 1155 if (mVideoSource == NULL) { 1156 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE 0 0 "); 1157 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0); 1158 } else { 1159 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE"); 1160 notifyVideoSize_l(); 1161 } 1162 LOGV("finishAsyncPrepare_l: MEDIA_PREPARED"); 1163 notifyListener_l(MEDIA_PREPARED); 1164 } 1165 1166 mPrepareResult = OK; 1167 mFlags &= ~(PREPARING|PREPARE_CANCELLED); 1168 mFlags |= PREPARED; 1169 mAsyncPrepareEvent = NULL; 1170 mPreparedCondition.broadcast(); 1171} 1172 1173status_t PreviewPlayer::suspend() { 1174 LOGV("suspend"); 1175 Mutex::Autolock autoLock(mLock); 1176 1177 if (mSuspensionState != NULL) { 1178 if (mLastVideoBuffer == NULL) { 1179 //go into here if video is suspended again 1180 //after resuming without being played between 1181 //them 1182 SuspensionState *state = mSuspensionState; 1183 mSuspensionState = NULL; 1184 reset_l(); 1185 mSuspensionState = state; 1186 return OK; 1187 } 1188 1189 delete mSuspensionState; 1190 mSuspensionState = NULL; 1191 } 1192 1193 if (mFlags & PREPARING) { 1194 mFlags |= PREPARE_CANCELLED; 1195 } 1196 1197 while (mFlags & PREPARING) { 1198 mPreparedCondition.wait(mLock); 1199 } 1200 1201 SuspensionState *state = new SuspensionState; 1202 state->mUri = mUri; 1203 state->mUriHeaders = mUriHeaders; 1204 state->mFileSource = mFileSource; 1205 1206 state->mFlags = mFlags & (PLAYING | AUTO_LOOPING | LOOPING | AT_EOS); 1207 getPosition(&state->mPositionUs); 1208 1209 if (mLastVideoBuffer) { 1210 size_t size = mLastVideoBuffer->range_length(); 1211 if (size) { 1212 int32_t unreadable; 1213 if (!mLastVideoBuffer->meta_data()->findInt32( 1214 kKeyIsUnreadable, &unreadable) 1215 || unreadable == 0) { 1216 state->mLastVideoFrameSize = size; 1217 state->mLastVideoFrame = malloc(size); 1218 memcpy(state->mLastVideoFrame, 1219 (const uint8_t *)mLastVideoBuffer->data() 1220 + mLastVideoBuffer->range_offset(), 1221 size); 1222 1223 state->mVideoWidth = mVideoWidth; 1224 state->mVideoHeight = mVideoHeight; 1225 1226 sp<MetaData> meta = mVideoSource->getFormat(); 1227 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat)); 1228 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth)); 1229 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight)); 1230 } else { 1231 LOGV("Unable to save last video frame, we have no access to " 1232 "the decoded video data."); 1233 } 1234 } 1235 } 1236 1237 reset_l(); 1238 1239 mSuspensionState = state; 1240 1241 return OK; 1242} 1243 1244status_t PreviewPlayer::resume() { 1245 LOGV("resume"); 1246 Mutex::Autolock autoLock(mLock); 1247 1248 if (mSuspensionState == NULL) { 1249 return INVALID_OPERATION; 1250 } 1251 1252 SuspensionState *state = mSuspensionState; 1253 mSuspensionState = NULL; 1254 1255 status_t err; 1256 if (state->mFileSource != NULL) { 1257 err = AwesomePlayer::setDataSource_l(state->mFileSource); 1258 1259 if (err == OK) { 1260 mFileSource = state->mFileSource; 1261 } 1262 } else { 1263 err = AwesomePlayer::setDataSource_l(state->mUri, &state->mUriHeaders); 1264 } 1265 1266 if (err != OK) { 1267 delete state; 1268 state = NULL; 1269 1270 return err; 1271 } 1272 1273 seekTo_l(state->mPositionUs); 1274 1275 mFlags = state->mFlags & (AUTO_LOOPING | LOOPING | AT_EOS); 1276 1277 if (state->mLastVideoFrame && (mSurface != NULL || mISurface != NULL)) { 1278 mVideoRenderer = 1279 new PreviewLocalRenderer( 1280 true, // previewOnly 1281 (OMX_COLOR_FORMATTYPE)state->mColorFormat, 1282 mSurface, 1283 state->mVideoWidth, 1284 state->mVideoHeight, 1285 state->mDecodedWidth, 1286 state->mDecodedHeight); 1287 1288 mVideoRendererIsPreview = true; 1289 1290 ((PreviewLocalRenderer *)mVideoRenderer.get())->render( 1291 state->mLastVideoFrame, state->mLastVideoFrameSize); 1292 } 1293 1294 if (state->mFlags & PLAYING) { 1295 play_l(); 1296 } 1297 1298 mSuspensionState = state; 1299 state = NULL; 1300 1301 return OK; 1302} 1303 1304 1305status_t PreviewPlayer::loadEffectsSettings( 1306 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) { 1307 M4OSA_UInt32 i = 0, rgbSize = 0; 1308 M4VIFI_UInt8 *tmp = M4OSA_NULL; 1309 1310 mNumberEffects = nEffects; 1311 mEffectsSettings = pEffectSettings; 1312 return OK; 1313} 1314 1315status_t PreviewPlayer::loadAudioMixSettings( 1316 M4xVSS_AudioMixingSettings* pAudioMixSettings) { 1317 1318 LOGV("PreviewPlayer: loadAudioMixSettings: "); 1319 mPreviewPlayerAudioMixSettings = pAudioMixSettings; 1320 return OK; 1321} 1322 1323status_t PreviewPlayer::setAudioMixPCMFileHandle( 1324 M4OSA_Context pAudioMixPCMFileHandle) { 1325 1326 LOGV("PreviewPlayer: setAudioMixPCMFileHandle: "); 1327 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle; 1328 return OK; 1329} 1330 1331status_t PreviewPlayer::setAudioMixStoryBoardParam( 1332 M4OSA_UInt32 audioMixStoryBoardTS, 1333 M4OSA_UInt32 currentMediaBeginCutTime, 1334 M4OSA_UInt32 primaryTrackVolValue ) { 1335 1336 mAudioMixStoryBoardTS = audioMixStoryBoardTS; 1337 mCurrentMediaBeginCutTime = currentMediaBeginCutTime; 1338 mCurrentMediaVolumeValue = primaryTrackVolValue; 1339 return OK; 1340} 1341 1342status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) { 1343 1344 mPlayBeginTimeMsec = msec; 1345 return OK; 1346} 1347 1348status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) { 1349 1350 mPlayEndTimeMsec = msec; 1351 return OK; 1352} 1353 1354status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) { 1355 1356 mStoryboardStartTimeMsec = msec; 1357 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000; 1358 return OK; 1359} 1360 1361status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) { 1362 1363 mProgressCbInterval = cbInterval; 1364 return OK; 1365} 1366 1367 1368status_t PreviewPlayer::setMediaRenderingMode( 1369 M4xVSS_MediaRendering mode, 1370 M4VIDEOEDITING_VideoFrameSize outputVideoSize) { 1371 1372 mRenderingMode = mode; 1373 1374 /* reset boolean for each clip*/ 1375 mVideoResizedOrCropped = false; 1376 1377 switch(outputVideoSize) { 1378 case M4VIDEOEDITING_kSQCIF: 1379 mOutputVideoWidth = 128; 1380 mOutputVideoHeight = 96; 1381 break; 1382 1383 case M4VIDEOEDITING_kQQVGA: 1384 mOutputVideoWidth = 160; 1385 mOutputVideoHeight = 120; 1386 break; 1387 1388 case M4VIDEOEDITING_kQCIF: 1389 mOutputVideoWidth = 176; 1390 mOutputVideoHeight = 144; 1391 break; 1392 1393 case M4VIDEOEDITING_kQVGA: 1394 mOutputVideoWidth = 320; 1395 mOutputVideoHeight = 240; 1396 break; 1397 1398 case M4VIDEOEDITING_kCIF: 1399 mOutputVideoWidth = 352; 1400 mOutputVideoHeight = 288; 1401 break; 1402 1403 case M4VIDEOEDITING_kVGA: 1404 mOutputVideoWidth = 640; 1405 mOutputVideoHeight = 480; 1406 break; 1407 1408 case M4VIDEOEDITING_kWVGA: 1409 mOutputVideoWidth = 800; 1410 mOutputVideoHeight = 480; 1411 break; 1412 1413 case M4VIDEOEDITING_kNTSC: 1414 mOutputVideoWidth = 720; 1415 mOutputVideoHeight = 480; 1416 break; 1417 1418 case M4VIDEOEDITING_k640_360: 1419 mOutputVideoWidth = 640; 1420 mOutputVideoHeight = 360; 1421 break; 1422 1423 case M4VIDEOEDITING_k854_480: 1424 mOutputVideoWidth = 854; 1425 mOutputVideoHeight = 480; 1426 break; 1427 1428 case M4VIDEOEDITING_kHD1280: 1429 mOutputVideoWidth = 1280; 1430 mOutputVideoHeight = 720; 1431 break; 1432 1433 case M4VIDEOEDITING_kHD1080: 1434 mOutputVideoWidth = 1080; 1435 mOutputVideoHeight = 720; 1436 break; 1437 1438 case M4VIDEOEDITING_kHD960: 1439 mOutputVideoWidth = 960; 1440 mOutputVideoHeight = 720; 1441 break; 1442 1443 default: 1444 LOGE("unsupported output video size set"); 1445 return BAD_VALUE; 1446 } 1447 1448 return OK; 1449} 1450 1451M4OSA_ERR PreviewPlayer::doMediaRendering() { 1452 M4OSA_ERR err = M4NO_ERROR; 1453 M4VIFI_ImagePlane planeIn[3], planeOut[3]; 1454 M4VIFI_UInt8 *inBuffer = M4OSA_NULL, *finalOutputBuffer = M4OSA_NULL; 1455 M4VIFI_UInt8 *tempOutputBuffer= M4OSA_NULL; 1456 size_t videoBufferSize = 0; 1457 M4OSA_UInt32 frameSize = 0, i=0, index =0, nFrameCount =0, bufferOffset =0; 1458 int32_t colorFormat = 0; 1459 1460 if(!mIsVideoSourceJpg) { 1461 sp<MetaData> meta = mVideoSource->getFormat(); 1462 CHECK(meta->findInt32(kKeyColorFormat, &colorFormat)); 1463 } 1464 else { 1465 colorFormat = OMX_COLOR_FormatYUV420Planar; 1466 } 1467 1468 videoBufferSize = mVideoBuffer->size(); 1469 frameSize = (mVideoWidth*mVideoHeight*3) >> 1; 1470 1471 uint8_t* outBuffer; 1472 size_t outBufferStride = 0; 1473 1474 mVideoRenderer->getBuffer(&outBuffer, &outBufferStride); 1475 1476 bufferOffset = index*frameSize; 1477 inBuffer = (M4OSA_UInt8 *)mVideoBuffer->data()+ 1478 mVideoBuffer->range_offset()+bufferOffset; 1479 1480 1481 /* In plane*/ 1482 prepareYUV420ImagePlane(planeIn, mVideoWidth, 1483 mVideoHeight, (M4VIFI_UInt8 *)inBuffer, mReportedWidth, mReportedHeight); 1484 1485 // Set the output YUV420 plane to be compatible with YV12 format 1486 // W & H even 1487 // YVU instead of YUV 1488 // align buffers on 32 bits 1489 1490 //In YV12 format, sizes must be even 1491 M4OSA_UInt32 yv12PlaneWidth = ((mOutputVideoWidth +1)>>1)<<1; 1492 M4OSA_UInt32 yv12PlaneHeight = ((mOutputVideoHeight+1)>>1)<<1; 1493 1494 prepareYV12ImagePlane(planeOut, yv12PlaneWidth, yv12PlaneHeight, 1495 (M4OSA_UInt32)outBufferStride, (M4VIFI_UInt8 *)outBuffer); 1496 1497 1498 err = applyRenderingMode(planeIn, planeOut, mRenderingMode); 1499 1500 if(err != M4NO_ERROR) 1501 { 1502 LOGE("doMediaRendering: applyRenderingMode returned err=0x%x", err); 1503 return err; 1504 } 1505 mVideoResizedOrCropped = true; 1506 1507 return err; 1508} 1509 1510status_t PreviewPlayer::resetJniCallbackTimeStamp() { 1511 1512 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000; 1513 return OK; 1514} 1515 1516void PreviewPlayer::postProgressCallbackEvent_l() { 1517 if (mProgressCbEventPending) { 1518 return; 1519 } 1520 mProgressCbEventPending = true; 1521 1522 mQueue.postEvent(mProgressCbEvent); 1523} 1524 1525 1526void PreviewPlayer::onProgressCbEvent() { 1527 Mutex::Autolock autoLock(mLock); 1528 if (!mProgressCbEventPending) { 1529 return; 1530 } 1531 mProgressCbEventPending = false; 1532 // If playback starts from previous I-frame, 1533 // then send frame storyboard duration 1534 if((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) { 1535 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000); 1536 } 1537 else { 1538 notifyListener_l(MEDIA_INFO, 0, 1539 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)); 1540 } 1541} 1542 1543void PreviewPlayer::postOverlayUpdateEvent_l() { 1544 if (mOverlayUpdateEventPending) { 1545 return; 1546 } 1547 mOverlayUpdateEventPending = true; 1548 mQueue.postEvent(mOverlayUpdateEvent); 1549} 1550 1551void PreviewPlayer::onUpdateOverlayEvent() { 1552 Mutex::Autolock autoLock(mLock); 1553 1554 if (!mOverlayUpdateEventPending) { 1555 return; 1556 } 1557 mOverlayUpdateEventPending = false; 1558 1559 int updateState; 1560 if (mOverlayUpdateEventPosted) { 1561 updateState = 1; 1562 } else { 1563 updateState = 0; 1564 } 1565 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex); 1566} 1567 1568 1569void PreviewPlayer::setVideoPostProcessingNode( 1570 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) { 1571 1572 uint32_t effect = VIDEO_EFFECT_NONE; 1573 1574 //Map M4VSS3GPP_VideoEffectType to local enum 1575 switch(type) { 1576 case M4VSS3GPP_kVideoEffectType_FadeFromBlack: 1577 effect = VIDEO_EFFECT_FADEFROMBLACK; 1578 break; 1579 1580 case M4VSS3GPP_kVideoEffectType_FadeToBlack: 1581 effect = VIDEO_EFFECT_FADETOBLACK; 1582 break; 1583 1584 case M4VSS3GPP_kVideoEffectType_CurtainOpening: 1585 effect = VIDEO_EFFECT_CURTAINOPEN; 1586 break; 1587 1588 case M4VSS3GPP_kVideoEffectType_CurtainClosing: 1589 effect = VIDEO_EFFECT_CURTAINCLOSE; 1590 break; 1591 1592 case M4xVSS_kVideoEffectType_BlackAndWhite: 1593 effect = VIDEO_EFFECT_BLACKANDWHITE; 1594 break; 1595 1596 case M4xVSS_kVideoEffectType_Pink: 1597 effect = VIDEO_EFFECT_PINK; 1598 break; 1599 1600 case M4xVSS_kVideoEffectType_Green: 1601 effect = VIDEO_EFFECT_GREEN; 1602 break; 1603 1604 case M4xVSS_kVideoEffectType_Sepia: 1605 effect = VIDEO_EFFECT_SEPIA; 1606 break; 1607 1608 case M4xVSS_kVideoEffectType_Negative: 1609 effect = VIDEO_EFFECT_NEGATIVE; 1610 break; 1611 1612 case M4xVSS_kVideoEffectType_Framing: 1613 effect = VIDEO_EFFECT_FRAMING; 1614 break; 1615 1616 case M4xVSS_kVideoEffectType_Fifties: 1617 effect = VIDEO_EFFECT_FIFTIES; 1618 break; 1619 1620 case M4xVSS_kVideoEffectType_ColorRGB16: 1621 effect = VIDEO_EFFECT_COLOR_RGB16; 1622 break; 1623 1624 case M4xVSS_kVideoEffectType_Gradient: 1625 effect = VIDEO_EFFECT_GRADIENT; 1626 break; 1627 1628 default: 1629 effect = VIDEO_EFFECT_NONE; 1630 break; 1631 } 1632 1633 if(enable == M4OSA_TRUE) { 1634 //If already set, then no need to set again 1635 if(!(mCurrentVideoEffect & effect)) { 1636 mCurrentVideoEffect |= effect; 1637 if(effect == VIDEO_EFFECT_FIFTIES) { 1638 mIsFiftiesEffectStarted = true; 1639 } 1640 } 1641 } 1642 else { 1643 //Reset only if already set 1644 if(mCurrentVideoEffect & effect) { 1645 mCurrentVideoEffect &= ~effect; 1646 } 1647 } 1648} 1649 1650status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) { 1651 mVideoWidth = width; 1652 mVideoHeight = height; 1653 return OK; 1654} 1655 1656 1657M4OSA_ERR PreviewPlayer::doVideoPostProcessing() { 1658 M4OSA_ERR err = M4NO_ERROR; 1659 vePostProcessParams postProcessParams; 1660 int32_t colorFormat = 0; 1661 1662 1663 if(!mIsVideoSourceJpg) { 1664 sp<MetaData> meta = mVideoSource->getFormat(); 1665 CHECK(meta->findInt32(kKeyColorFormat, &colorFormat)); 1666 } 1667 else { 1668 colorFormat = OMX_COLOR_FormatYUV420Planar; 1669 } 1670 1671 if((colorFormat == OMX_COLOR_FormatYUV420SemiPlanar) || 1672 (colorFormat == 0x7FA30C00)) { 1673 LOGE("doVideoPostProcessing: colorFormat YUV420Sp not supported"); 1674 return M4ERR_UNSUPPORTED_MEDIA_TYPE; 1675 } 1676 1677 postProcessParams.vidBuffer = (M4VIFI_UInt8*)mVideoBuffer->data() 1678 + mVideoBuffer->range_offset(); 1679 1680 postProcessParams.videoWidth = mVideoWidth; 1681 postProcessParams.videoHeight = mVideoHeight; 1682 postProcessParams.timeMs = mDecodedVideoTs/1000; 1683 postProcessParams.timeOffset = mDecVideoTsStoryBoard/1000; 1684 postProcessParams.effectsSettings = mEffectsSettings; 1685 postProcessParams.numberEffects = mNumberEffects; 1686 postProcessParams.outVideoWidth = mOutputVideoWidth; 1687 postProcessParams.outVideoHeight = mOutputVideoHeight; 1688 postProcessParams.currentVideoEffect = mCurrentVideoEffect; 1689 postProcessParams.renderingMode = mRenderingMode; 1690 if(mIsFiftiesEffectStarted == M4OSA_TRUE) { 1691 postProcessParams.isFiftiesEffectStarted = M4OSA_TRUE; 1692 mIsFiftiesEffectStarted = M4OSA_FALSE; 1693 } 1694 else { 1695 postProcessParams.isFiftiesEffectStarted = M4OSA_FALSE; 1696 } 1697 1698 postProcessParams.overlayFrameRGBBuffer = mFrameRGBBuffer; 1699 postProcessParams.overlayFrameYUVBuffer = mFrameYUVBuffer; 1700 mVideoRenderer->getBuffer(&(postProcessParams.pOutBuffer), &(postProcessParams.outBufferStride)); 1701 err = applyEffectsAndRenderingMode(&postProcessParams, mReportedWidth, mReportedHeight); 1702 1703 return err; 1704} 1705 1706status_t PreviewPlayer::readFirstVideoFrame() { 1707 LOGV("PreviewPlayer::readFirstVideoFrame"); 1708 1709 if (!mVideoBuffer) { 1710 MediaSource::ReadOptions options; 1711 if (mSeeking) { 1712 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs, 1713 mSeekTimeUs / 1E6); 1714 1715 options.setSeekTo( 1716 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST); 1717 } 1718 for (;;) { 1719 status_t err = mVideoSource->read(&mVideoBuffer, &options); 1720 options.clearSeekTo(); 1721 1722 if (err != OK) { 1723 CHECK_EQ(mVideoBuffer, NULL); 1724 1725 if (err == INFO_FORMAT_CHANGED) { 1726 LOGV("LV PLAYER VideoSource signalled format change"); 1727 notifyVideoSize_l(); 1728 sp<MetaData> meta = mVideoSource->getFormat(); 1729 1730 CHECK(meta->findInt32(kKeyWidth, &mReportedWidth)); 1731 CHECK(meta->findInt32(kKeyHeight, &mReportedHeight)); 1732 1733 if (mVideoRenderer != NULL) { 1734 mVideoRendererIsPreview = false; 1735 initRenderer_l(); 1736 } 1737 continue; 1738 } 1739 LOGV("PreviewPlayer: onVideoEvent EOS reached."); 1740 mFlags |= VIDEO_AT_EOS; 1741 postStreamDoneEvent_l(err); 1742 return OK; 1743 } 1744 1745 if (mVideoBuffer->range_length() == 0) { 1746 // Some decoders, notably the PV AVC software decoder 1747 // return spurious empty buffers that we just want to ignore. 1748 1749 mVideoBuffer->release(); 1750 mVideoBuffer = NULL; 1751 continue; 1752 } 1753 1754 int64_t videoTimeUs; 1755 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs)); 1756 1757 if((videoTimeUs/1000) < mPlayBeginTimeMsec) { 1758 // buffers are before begin cut time 1759 // ignore them 1760 //LOGI("PreviewPlayer: Ignoring buffers before begin cut time"); 1761 mVideoBuffer->release(); 1762 mVideoBuffer = NULL; 1763 continue; 1764 } 1765 1766 break; 1767 } 1768 } 1769 1770 int64_t timeUs; 1771 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 1772 1773 { 1774 Mutex::Autolock autoLock(mMiscStateLock); 1775 mVideoTimeUs = timeUs; 1776 } 1777 1778 mDecodedVideoTs = timeUs; 1779 1780 return OK; 1781 1782} 1783 1784} // namespace android 1785