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