blob: f2b82d99248a4671d940a0ca8dca4c40ae852d20 [file] [log] [blame]
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001/*
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Santosh Madhavabfece172011-02-03 16:59:47 -080017
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080018#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"
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080029#include "include/NuCachedSource2.h"
30#include "include/ThrottledSource.h"
31
32
33#include "PreviewRenderer.h"
34
35#include <binder/IPCThreadState.h>
36#include <media/stagefright/DataSource.h>
37#include <media/stagefright/FileSource.h>
38#include <media/stagefright/MediaBuffer.h>
39#include <media/stagefright/MediaDefs.h>
40#include <media/stagefright/MediaExtractor.h>
41#include <media/stagefright/MediaDebug.h>
42#include <media/stagefright/MediaSource.h>
43#include <media/stagefright/MetaData.h>
44#include <media/stagefright/OMXCodec.h>
45
46#include <surfaceflinger/Surface.h>
47#include <media/stagefright/foundation/ALooper.h>
48
49namespace android {
50
51
52struct PreviewPlayerEvent : public TimedEventQueue::Event {
53 PreviewPlayerEvent(
54 PreviewPlayer *player,
55 void (PreviewPlayer::*method)())
56 : mPlayer(player),
57 mMethod(method) {
58 }
59
60protected:
61 virtual ~PreviewPlayerEvent() {}
62
63 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
64 (mPlayer->*mMethod)();
65 }
66
67private:
68 PreviewPlayer *mPlayer;
69 void (PreviewPlayer::*mMethod)();
70
71 PreviewPlayerEvent(const PreviewPlayerEvent &);
72 PreviewPlayerEvent &operator=(const PreviewPlayerEvent &);
73};
74
75
76struct PreviewLocalRenderer : public PreviewPlayerRenderer {
Santosh Madhavabfece172011-02-03 16:59:47 -080077
78 static PreviewLocalRenderer* initPreviewLocalRenderer (
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080079 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)
Santosh Madhavabfece172011-02-03 16:59:47 -080085 {
86 PreviewLocalRenderer* mLocalRenderer = new
87 PreviewLocalRenderer(
88 previewOnly,
89 colorFormat,
90 surface,
91 displayWidth, displayHeight,
92 decodedWidth, decodedHeight,
93 rotationDegrees);
94
95 if ( mLocalRenderer->init(previewOnly,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080096 colorFormat, surface,
97 displayWidth, displayHeight,
98 decodedWidth, decodedHeight,
Santosh Madhavabfece172011-02-03 16:59:47 -080099 rotationDegrees) != OK )
100 {
101 delete mLocalRenderer;
102 return NULL;
103 }
104 return mLocalRenderer;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800105 }
106
107 virtual void render(MediaBuffer *buffer) {
108 render((const uint8_t *)buffer->data() + buffer->range_offset(),
109 buffer->range_length());
110 }
111
112 void render(const void *data, size_t size) {
113 mTarget->render(data, size, NULL);
114 }
115 void render() {
116 mTarget->renderYV12();
117 }
118 void getBuffer(uint8_t **data, size_t *stride) {
119 mTarget->getBufferYV12(data, stride);
120 }
121
122protected:
123 virtual ~PreviewLocalRenderer() {
124 delete mTarget;
125 mTarget = NULL;
126 }
127
128private:
129 PreviewRenderer *mTarget;
130
Santosh Madhavabfece172011-02-03 16:59:47 -0800131 PreviewLocalRenderer(
132 bool previewOnly,
133 OMX_COLOR_FORMATTYPE colorFormat,
134 const sp<Surface> &surface,
135 size_t displayWidth, size_t displayHeight,
136 size_t decodedWidth, size_t decodedHeight,
137 int32_t rotationDegrees = 0)
138 : mTarget(NULL) {
139 }
140
141
142 int init(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800143 bool previewOnly,
144 OMX_COLOR_FORMATTYPE colorFormat,
145 const sp<Surface> &surface,
146 size_t displayWidth, size_t displayHeight,
147 size_t decodedWidth, size_t decodedHeight,
148 int32_t rotationDegrees = 0);
149
150 PreviewLocalRenderer(const PreviewLocalRenderer &);
151 PreviewLocalRenderer &operator=(const PreviewLocalRenderer &);;
152};
153
Santosh Madhavabfece172011-02-03 16:59:47 -0800154int PreviewLocalRenderer::init(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800155 bool previewOnly,
156 OMX_COLOR_FORMATTYPE colorFormat,
157 const sp<Surface> &surface,
158 size_t displayWidth, size_t displayHeight,
159 size_t decodedWidth, size_t decodedHeight,
160 int32_t rotationDegrees) {
Santosh Madhavabfece172011-02-03 16:59:47 -0800161
162 mTarget = PreviewRenderer::CreatePreviewRenderer (
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800163 colorFormat, surface, displayWidth, displayHeight,
164 decodedWidth, decodedHeight, rotationDegrees);
Santosh Madhavabfece172011-02-03 16:59:47 -0800165 if (mTarget == M4OSA_NULL) {
166 return UNKNOWN_ERROR;
167 }
168 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800169}
170
171PreviewPlayer::PreviewPlayer()
James Dongc9dedc42011-05-01 12:36:22 -0700172 : PreviewPlayerBase(),
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -0800173 mCurrFramingEffectIndex(0) ,
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800174 mReportedWidth(0),
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800175 mReportedHeight(0),
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -0800176 mFrameRGBBuffer(NULL),
177 mFrameYUVBuffer(NULL){
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800178
179 mVideoRenderer = NULL;
180 mLastVideoBuffer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800181 mEffectsSettings = NULL;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800182 mVeAudioPlayer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800183 mAudioMixStoryBoardTS = 0;
184 mCurrentMediaBeginCutTime = 0;
185 mCurrentMediaVolumeValue = 0;
186 mNumberEffects = 0;
187 mDecodedVideoTs = 0;
188 mDecVideoTsStoryBoard = 0;
189 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
190 mProgressCbInterval = 0;
191 mNumberDecVideoFrames = 0;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800192 mOverlayUpdateEventPosted = false;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800193 mIsChangeSourceRequired = true;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800194
195 mVideoEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoEvent);
196 mVideoEventPending = false;
197 mStreamDoneEvent = new PreviewPlayerEvent(this,
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800198 &PreviewPlayer::onStreamDone);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800199
200 mStreamDoneEventPending = false;
201
202 mCheckAudioStatusEvent = new PreviewPlayerEvent(
James Dongc9dedc42011-05-01 12:36:22 -0700203 this, &PreviewPlayerBase::onCheckAudioStatus);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800204
205 mAudioStatusEventPending = false;
206
207 mProgressCbEvent = new PreviewPlayerEvent(this,
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800208 &PreviewPlayer::onProgressCbEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800209
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800210 mOverlayUpdateEvent = new PreviewPlayerEvent(this,
211 &PreviewPlayer::onUpdateOverlayEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800212 mProgressCbEventPending = false;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800213
214 mOverlayUpdateEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800215 mResizedVideoBuffer = NULL;
216 mVideoResizedOrCropped = false;
217 mRenderingMode = (M4xVSS_MediaRendering)MEDIA_RENDERING_INVALID;
218 mIsFiftiesEffectStarted = false;
219 reset();
220}
221
222PreviewPlayer::~PreviewPlayer() {
223
224 if (mQueueStarted) {
225 mQueue.stop();
226 }
227
228 reset();
229
230 if(mResizedVideoBuffer != NULL) {
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700231 free((mResizedVideoBuffer->data()));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800232 mResizedVideoBuffer = NULL;
233 }
234
235 mVideoRenderer.clear();
236 mVideoRenderer = NULL;
237}
238
239void PreviewPlayer::cancelPlayerEvents(bool keepBufferingGoing) {
240 mQueue.cancelEvent(mVideoEvent->eventID());
241 mVideoEventPending = false;
242 mQueue.cancelEvent(mStreamDoneEvent->eventID());
243 mStreamDoneEventPending = false;
244 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
245 mAudioStatusEventPending = false;
246
247 mQueue.cancelEvent(mProgressCbEvent->eventID());
248 mProgressCbEventPending = false;
249}
250
251status_t PreviewPlayer::setDataSource(
252 const char *uri, const KeyedVector<String8, String8> *headers) {
253 Mutex::Autolock autoLock(mLock);
254 return setDataSource_l(uri, headers);
255}
256
257status_t PreviewPlayer::setDataSource_l(
258 const char *uri, const KeyedVector<String8, String8> *headers) {
259 reset_l();
260
261 mUri = uri;
262
263 if (headers) {
264 mUriHeaders = *headers;
265 }
266
267 // The actual work will be done during preparation in the call to
268 // ::finishSetDataSource_l to avoid blocking the calling thread in
269 // setDataSource for any significant time.
270 return OK;
271}
272
273status_t PreviewPlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
274 bool haveAudio = false;
275 bool haveVideo = false;
276 for (size_t i = 0; i < extractor->countTracks(); ++i) {
277 sp<MetaData> meta = extractor->getTrackMetaData(i);
278
279 const char *mime;
280 CHECK(meta->findCString(kKeyMIMEType, &mime));
281
282 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
283 setVideoSource(extractor->getTrack(i));
284 haveVideo = true;
285 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
286 setAudioSource(extractor->getTrack(i));
287 haveAudio = true;
288
289 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
290 // Only do this for vorbis audio, none of the other audio
291 // formats even support this ringtone specific hack and
292 // retrieving the metadata on some extractors may turn out
293 // to be very expensive.
294 sp<MetaData> fileMeta = extractor->getMetaData();
295 int32_t loop;
296 if (fileMeta != NULL
297 && fileMeta->findInt32(kKeyAutoLoop, &loop)
298 && loop != 0) {
299 mFlags |= AUTO_LOOPING;
300 }
301 }
302 }
303
304 if (haveAudio && haveVideo) {
305 break;
306 }
307 }
308
309 /* Add the support for Dummy audio*/
310 if( !haveAudio ){
311 LOGV("PreviewPlayer: setDataSource_l Dummyaudiocreation started");
312
313 mAudioTrack = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700314 ((mPlayEndTimeMsec)*1000LL));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800315 LOGV("PreviewPlayer: setDataSource_l Dummyauiosource created");
316 if(mAudioTrack != NULL) {
317 haveAudio = true;
318 }
319 }
320
321 if (!haveAudio && !haveVideo) {
322 return UNKNOWN_ERROR;
323 }
324
325 mExtractorFlags = extractor->flags();
326 return OK;
327}
328
329status_t PreviewPlayer::setDataSource_l_jpg() {
330 M4OSA_ERR err = M4NO_ERROR;
331 LOGV("PreviewPlayer: setDataSource_l_jpg started");
332
333 mAudioSource = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700334 ((mPlayEndTimeMsec)*1000LL));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800335 LOGV("PreviewPlayer: setDataSource_l_jpg Dummyaudiosource created");
336 if(mAudioSource != NULL) {
337 setAudioSource(mAudioSource);
338 }
339 status_t error = mAudioSource->start();
340 if (error != OK) {
341 LOGV("Error starting dummy audio source");
342 mAudioSource.clear();
343 return err;
344 }
345
Raghavender Pallaebf40152011-03-14 20:15:12 -0700346 mDurationUs = (mPlayEndTimeMsec - mPlayBeginTimeMsec)*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800347
348 mVideoSource = DummyVideoSource::Create(mVideoWidth, mVideoHeight,
349 mDurationUs, mUri);
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800350 mReportedWidth = mVideoWidth;
351 mReportedHeight = mVideoHeight;
352
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800353 setVideoSource(mVideoSource);
354 status_t err1 = mVideoSource->start();
355 if (err1 != OK) {
356 mVideoSource.clear();
357 return err;
358 }
359
360 mIsVideoSourceJpg = true;
361 return OK;
362}
363
364void PreviewPlayer::reset() {
365 Mutex::Autolock autoLock(mLock);
366 reset_l();
367}
368
369void PreviewPlayer::reset_l() {
370
371 if (mFlags & PREPARING) {
372 mFlags |= PREPARE_CANCELLED;
373 }
374
375 while (mFlags & PREPARING) {
376 mPreparedCondition.wait(mLock);
377 }
378
379 cancelPlayerEvents();
380 mAudioTrack.clear();
381 mVideoTrack.clear();
382
383 // Shutdown audio first, so that the respone to the reset request
384 // appears to happen instantaneously as far as the user is concerned
385 // If we did this later, audio would continue playing while we
386 // shutdown the video-related resources and the player appear to
387 // not be as responsive to a reset request.
388 if (mAudioPlayer == NULL && mAudioSource != NULL) {
389 // If we had an audio player, it would have effectively
390 // taken possession of the audio source and stopped it when
391 // _it_ is stopped. Otherwise this is still our responsibility.
392 mAudioSource->stop();
393 }
394 mAudioSource.clear();
395
396 mTimeSource = NULL;
397
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800398 //Single audio player instance used
399 //So donot delete it here
400 //It is deleted from PreviewController class
401 //delete mAudioPlayer;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800402 mAudioPlayer = NULL;
403
404 if (mLastVideoBuffer) {
405 mLastVideoBuffer->release();
406 mLastVideoBuffer = NULL;
407 }
408
409 if (mVideoBuffer) {
410 mVideoBuffer->release();
411 mVideoBuffer = NULL;
412 }
413
414 if (mVideoSource != NULL) {
415 mVideoSource->stop();
416
417 // The following hack is necessary to ensure that the OMX
418 // component is completely released by the time we may try
419 // to instantiate it again.
420 wp<MediaSource> tmp = mVideoSource;
421 mVideoSource.clear();
422 while (tmp.promote() != NULL) {
423 usleep(1000);
424 }
425 IPCThreadState::self()->flushCommands();
426 }
427
428 mDurationUs = -1;
429 mFlags = 0;
430 mExtractorFlags = 0;
431 mVideoWidth = mVideoHeight = -1;
432 mTimeSourceDeltaUs = 0;
433 mVideoTimeUs = 0;
434
Andreas Hubera5872f72011-02-24 15:25:21 -0800435 mSeeking = NO_SEEK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800436 mSeekNotificationSent = false;
437 mSeekTimeUs = 0;
438
439 mUri.setTo("");
440 mUriHeaders.clear();
441
442 mFileSource.clear();
443
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800444 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
445 mIsVideoSourceJpg = false;
446 mFrameRGBBuffer = NULL;
447 if(mFrameYUVBuffer != NULL) {
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700448 free(mFrameYUVBuffer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800449 mFrameYUVBuffer = NULL;
450 }
451}
452
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800453status_t PreviewPlayer::play() {
454 Mutex::Autolock autoLock(mLock);
455
456 mFlags &= ~CACHE_UNDERRUN;
457
458 return play_l();
459}
460
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800461status_t PreviewPlayer::startAudioPlayer_l() {
462 CHECK(!(mFlags & AUDIO_RUNNING));
463
464 if (mAudioSource == NULL || mAudioPlayer == NULL) {
465 return OK;
466 }
467
468 if (!(mFlags & AUDIOPLAYER_STARTED)) {
469 mFlags |= AUDIOPLAYER_STARTED;
470
471 // We've already started the MediaSource in order to enable
472 // the prefetcher to read its data.
473 status_t err = mVeAudioPlayer->start(
474 true /* sourceAlreadyStarted */);
475
476 if (err != OK) {
477 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
478 return err;
479 }
480 } else {
481 mVeAudioPlayer->resume();
482 }
483
484 mFlags |= AUDIO_RUNNING;
485
486 mWatchForAudioEOS = true;
487
488 return OK;
489}
490
James Dongc9dedc42011-05-01 12:36:22 -0700491status_t PreviewPlayer::setAudioPlayer(AudioPlayerBase *audioPlayer) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800492 Mutex::Autolock autoLock(mLock);
493 CHECK(!(mFlags & PLAYING));
494 mAudioPlayer = audioPlayer;
495
496 LOGV("SetAudioPlayer");
497 mIsChangeSourceRequired = true;
498 mVeAudioPlayer =
499 (VideoEditorAudioPlayer*)mAudioPlayer;
500
501 // check if the new and old source are dummy
502 sp<MediaSource> anAudioSource = mVeAudioPlayer->getSource();
503 if (anAudioSource == NULL) {
504 // Audio player does not have any source set.
505 LOGV("setAudioPlayer: Audio player does not have any source set");
506 return OK;
507 }
508
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800509 // If new video source is not dummy, then always change source
510 // Else audio player continues using old audio source and there are
511 // frame drops to maintain AV sync
512 sp<MetaData> meta;
513 if (mVideoSource != NULL) {
514 meta = mVideoSource->getFormat();
515 const char *pVidSrcType;
516 if (meta->findCString(kKeyDecoderComponent, &pVidSrcType)) {
517 if (strcmp(pVidSrcType, "DummyVideoSource") != 0) {
518 LOGV(" Video clip with silent audio; need to change source");
519 return OK;
520 }
521 }
522 }
523
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800524 const char *pSrcType1;
525 const char *pSrcType2;
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800526 meta = anAudioSource->getFormat();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800527
528 if (meta->findCString(kKeyDecoderComponent, &pSrcType1)) {
529 if (strcmp(pSrcType1, "DummyAudioSource") == 0) {
530 meta = mAudioSource->getFormat();
531 if (meta->findCString(kKeyDecoderComponent, &pSrcType2)) {
532 if (strcmp(pSrcType2, "DummyAudioSource") == 0) {
533 mIsChangeSourceRequired = false;
534 // Just set the new play duration for the existing source
535 MediaSource *pMediaSrc = anAudioSource.get();
536 DummyAudioSource *pDummyAudioSource = (DummyAudioSource*)pMediaSrc;
537 //Increment the duration of audio source
Raghavender Pallaebf40152011-03-14 20:15:12 -0700538 pDummyAudioSource->setDuration(
539 (int64_t)((mPlayEndTimeMsec)*1000LL));
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800540
541 // Stop the new audio source
542 // since we continue using old source
543 LOGV("setAudioPlayer: stop new audio source");
544 mAudioSource->stop();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800545 }
546 }
547 }
548 }
549
550 return OK;
551}
552
553void PreviewPlayer::onStreamDone() {
554 // Posted whenever any stream finishes playing.
555
556 Mutex::Autolock autoLock(mLock);
557 if (!mStreamDoneEventPending) {
558 return;
559 }
560 mStreamDoneEventPending = false;
561
562 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
563 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
564
565 notifyListener_l(
566 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
567
568 pause_l(true /* at eos */);
569
570 mFlags |= AT_EOS;
571 return;
572 }
573
574 const bool allDone =
575 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
576 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
577
578 if (!allDone) {
579 return;
580 }
581
582 if (mFlags & (LOOPING | AUTO_LOOPING)) {
583 seekTo_l(0);
584
585 if (mVideoSource != NULL) {
586 postVideoEvent_l();
587 }
588 } else {
589 LOGV("MEDIA_PLAYBACK_COMPLETE");
590 //pause before sending event
591 pause_l(true /* at eos */);
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700592
593 //This lock is used to syncronize onStreamDone() in PreviewPlayer and
594 //stopPreview() in PreviewController
595 Mutex::Autolock autoLock(mLockControl);
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800596 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
597
598 mFlags |= AT_EOS;
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700599 LOGV("onStreamDone end");
600 return;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800601 }
602}
603
604
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800605status_t PreviewPlayer::play_l() {
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800606
Rajneesh Chowdury8b95de22011-02-16 15:32:06 -0800607 mFlags &= ~SEEK_PREVIEW;
608
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800609 if (mFlags & PLAYING) {
610 return OK;
611 }
612 mStartNextPlayer = false;
613
614 if (!(mFlags & PREPARED)) {
615 status_t err = prepare_l();
616
617 if (err != OK) {
618 return err;
619 }
620 }
621
622 mFlags |= PLAYING;
623 mFlags |= FIRST_FRAME;
624
625 bool deferredAudioSeek = false;
626
627 if (mAudioSource != NULL) {
628 if (mAudioPlayer == NULL) {
629 if (mAudioSink != NULL) {
630
631 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800632 mVeAudioPlayer =
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800633 (VideoEditorAudioPlayer*)mAudioPlayer;
634
635 mAudioPlayer->setSource(mAudioSource);
636
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800637 mVeAudioPlayer->setAudioMixSettings(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800638 mPreviewPlayerAudioMixSettings);
639
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800640 mVeAudioPlayer->setAudioMixPCMFileHandle(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800641 mAudioMixPCMFileHandle);
642
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800643 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800644 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
645 mCurrentMediaVolumeValue);
646
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800647 mFlags |= AUDIOPLAYER_STARTED;
648 // We've already started the MediaSource in order to enable
649 // the prefetcher to read its data.
650 status_t err = mVeAudioPlayer->start(
651 true /* sourceAlreadyStarted */);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800652
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800653 if (err != OK) {
654 //delete mAudioPlayer;
655 mAudioPlayer = NULL;
656
657 mFlags &= ~(PLAYING | FIRST_FRAME);
658 return err;
659 }
660
661 mTimeSource = mVeAudioPlayer;
662 mFlags |= AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800663 deferredAudioSeek = true;
664 mWatchForAudioSeekComplete = false;
665 mWatchForAudioEOS = true;
666 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800667 } else {
668 mVeAudioPlayer = (VideoEditorAudioPlayer*)mAudioPlayer;
669 bool isAudioPlayerStarted = mVeAudioPlayer->isStarted();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800670
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800671 if (mIsChangeSourceRequired == true) {
672 LOGV("play_l: Change audio source required");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800673
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800674 if (isAudioPlayerStarted == true) {
675 mVeAudioPlayer->pause();
676 }
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800677
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800678 mVeAudioPlayer->setSource(mAudioSource);
679 mVeAudioPlayer->setObserver(this);
680
681 mVeAudioPlayer->setAudioMixSettings(
682 mPreviewPlayerAudioMixSettings);
683
684 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
685 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
686 mCurrentMediaVolumeValue);
687
688 if (isAudioPlayerStarted == true) {
689 mVeAudioPlayer->resume();
690 } else {
691 status_t err = OK;
692 err = mVeAudioPlayer->start(true);
693 if (err != OK) {
694 mAudioPlayer = NULL;
695 mVeAudioPlayer = NULL;
696
697 mFlags &= ~(PLAYING | FIRST_FRAME);
698 return err;
699 }
700 }
701 } else {
702 LOGV("play_l: No Source change required");
703 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
704 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
705 mCurrentMediaVolumeValue);
706
707 mVeAudioPlayer->resume();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800708 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800709
710 mFlags |= AUDIOPLAYER_STARTED;
711 mFlags |= AUDIO_RUNNING;
712 mTimeSource = mVeAudioPlayer;
713 deferredAudioSeek = true;
714 mWatchForAudioSeekComplete = false;
715 mWatchForAudioEOS = true;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800716 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800717 }
718
719 if (mTimeSource == NULL && mAudioPlayer == NULL) {
720 mTimeSource = &mSystemTimeSource;
721 }
722
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800723 // Set the seek option for Image source files and read.
724 // This resets the timestamping for image play
725 if (mIsVideoSourceJpg) {
726 MediaSource::ReadOptions options;
727 MediaBuffer *aLocalBuffer;
728 options.setSeekTo(mSeekTimeUs);
729 mVideoSource->read(&aLocalBuffer, &options);
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800730 aLocalBuffer->release();
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800731 }
732
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800733 if (mVideoSource != NULL) {
734 // Kick off video playback
735 postVideoEvent_l();
736 }
737
738 if (deferredAudioSeek) {
739 // If there was a seek request while we were paused
740 // and we're just starting up again, honor the request now.
741 seekAudioIfNecessary_l();
742 }
743
744 if (mFlags & AT_EOS) {
745 // Legacy behaviour, if a stream finishes playing and then
746 // is started again, we play from the start...
747 seekTo_l(0);
748 }
749
750 return OK;
751}
752
753
Santosh Madhavabfece172011-02-03 16:59:47 -0800754status_t PreviewPlayer::initRenderer_l() {
Mathias Agopian6e224292011-04-05 15:38:24 -0700755 if (mSurface != NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800756 sp<MetaData> meta = mVideoSource->getFormat();
757
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800758 const char *component;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800759 CHECK(meta->findCString(kKeyDecoderComponent, &component));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800760
761 // Must ensure that mVideoRenderer's destructor is actually executed
762 // before creating a new one.
763 IPCThreadState::self()->flushCommands();
764
765 // always use localrenderer since decoded buffers are modified
766 // by postprocessing module
767 // Other decoders are instantiated locally and as a consequence
768 // allocate their buffers in local address space.
769 if(mVideoRenderer == NULL) {
770
Santosh Madhavabfece172011-02-03 16:59:47 -0800771 mVideoRenderer = PreviewLocalRenderer:: initPreviewLocalRenderer (
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800772 false, // previewOnly
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +0800773 OMX_COLOR_FormatYUV420Planar,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800774 mSurface,
775 mOutputVideoWidth, mOutputVideoHeight,
776 mOutputVideoWidth, mOutputVideoHeight);
Santosh Madhavabfece172011-02-03 16:59:47 -0800777
778 if ( mVideoRenderer == NULL )
779 {
780 return UNKNOWN_ERROR;
781 }
782 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800783 }
784 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800785 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800786}
787
788
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800789status_t PreviewPlayer::seekTo(int64_t timeUs) {
790
791 if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) {
792 Mutex::Autolock autoLock(mLock);
793 return seekTo_l(timeUs);
794 }
795
796 return OK;
797}
798
799
800status_t PreviewPlayer::getVideoDimensions(
801 int32_t *width, int32_t *height) const {
802 Mutex::Autolock autoLock(mLock);
803
804 if (mVideoWidth < 0 || mVideoHeight < 0) {
805 return UNKNOWN_ERROR;
806 }
807
808 *width = mVideoWidth;
809 *height = mVideoHeight;
810
811 return OK;
812}
813
814
815status_t PreviewPlayer::initAudioDecoder() {
816 sp<MetaData> meta = mAudioTrack->getFormat();
817 const char *mime;
818 CHECK(meta->findCString(kKeyMIMEType, &mime));
819
820 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
821 mAudioSource = mAudioTrack;
822 } else {
823 sp<MediaSource> aRawSource;
824 aRawSource = OMXCodec::Create(
825 mClient.interface(), mAudioTrack->getFormat(),
826 false, // createEncoder
827 mAudioTrack);
828
829 if(aRawSource != NULL) {
830 LOGV("initAudioDecoder: new VideoEditorSRC");
831 mAudioSource = new VideoEditorSRC(aRawSource);
832 }
833 }
834
835 if (mAudioSource != NULL) {
836 int64_t durationUs;
837 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
838 Mutex::Autolock autoLock(mMiscStateLock);
839 if (mDurationUs < 0 || durationUs > mDurationUs) {
840 mDurationUs = durationUs;
841 }
842 }
843 status_t err = mAudioSource->start();
844
845 if (err != OK) {
846 mAudioSource.clear();
847 return err;
848 }
849 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
850 // For legacy reasons we're simply going to ignore the absence
851 // of an audio decoder for QCELP instead of aborting playback
852 // altogether.
853 return OK;
854 }
855
856 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
857}
858
859
860status_t PreviewPlayer::initVideoDecoder(uint32_t flags) {
861
862 mVideoSource = OMXCodec::Create(
863 mClient.interface(), mVideoTrack->getFormat(),
864 false,
865 mVideoTrack,
866 NULL, flags);
867
868 if (mVideoSource != NULL) {
869 int64_t durationUs;
870 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
871 Mutex::Autolock autoLock(mMiscStateLock);
872 if (mDurationUs < 0 || durationUs > mDurationUs) {
873 mDurationUs = durationUs;
874 }
875 }
876
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +0800877 getVideoBufferSize(mVideoTrack->getFormat(), &mVideoWidth, &mVideoHeight);
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800878 mReportedWidth = mVideoWidth;
879 mReportedHeight = mVideoHeight;
880
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800881 status_t err = mVideoSource->start();
882
883 if (err != OK) {
884 mVideoSource.clear();
885 return err;
886 }
887 }
888
889 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
890}
891
892
893void PreviewPlayer::onVideoEvent() {
894 uint32_t i=0;
895 bool bAppliedVideoEffect = false;
896 M4OSA_ERR err1 = M4NO_ERROR;
897 int64_t imageFrameTimeUs = 0;
898
899 Mutex::Autolock autoLock(mLock);
900 if (!mVideoEventPending) {
901 // The event has been cancelled in reset_l() but had already
902 // been scheduled for execution at that time.
903 return;
904 }
905 mVideoEventPending = false;
906
Andreas Huber9e4c36a2011-02-08 13:12:32 -0800907 if (mFlags & SEEK_PREVIEW) {
908 mFlags &= ~SEEK_PREVIEW;
909 return;
910 }
911
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800912 TimeSource *ts_st = &mSystemTimeSource;
913 int64_t timeStartUs = ts_st->getRealTimeUs();
914
Andreas Hubera5872f72011-02-24 15:25:21 -0800915 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800916 if (mLastVideoBuffer) {
917 mLastVideoBuffer->release();
918 mLastVideoBuffer = NULL;
919 }
920
921
922 if(mAudioSource != NULL) {
923
924 // We're going to seek the video source first, followed by
925 // the audio source.
926 // In order to avoid jumps in the DataSource offset caused by
927 // the audio codec prefetching data from the old locations
928 // while the video codec is already reading data from the new
929 // locations, we'll "pause" the audio source, causing it to
930 // stop reading input data until a subsequent seek.
931
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800932 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800933 mAudioPlayer->pause();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800934 mFlags &= ~AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800935 }
936 mAudioSource->pause();
937 }
938 }
939
940 if (!mVideoBuffer) {
941 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -0800942 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800943 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
944 mSeekTimeUs / 1E6);
945
946 options.setSeekTo(
947 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
948 }
949 for (;;) {
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +0800950 status_t err = readYV12Buffer(mVideoSource, &mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800951 options.clearSeekTo();
952
953 if (err != OK) {
954 CHECK_EQ(mVideoBuffer, NULL);
955
956 if (err == INFO_FORMAT_CHANGED) {
957 LOGV("LV PLAYER VideoSource signalled format change");
958 notifyVideoSize_l();
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800959 sp<MetaData> meta = mVideoSource->getFormat();
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +0800960 getVideoBufferSize(meta, &mReportedWidth, &mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800961
962 if (mVideoRenderer != NULL) {
963 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -0800964 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800965 if (err != OK) {
966 postStreamDoneEvent_l(err);
967 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800968
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800969 }
970 continue;
971 }
972 // So video playback is complete, but we may still have
Santosh Madhava342f9322011-01-27 16:27:12 -0800973 // a seek request pending that needs to be applied to the audio track
Andreas Hubera5872f72011-02-24 15:25:21 -0800974 if (mSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800975 LOGV("video stream ended while seeking!");
976 }
977 finishSeekIfNecessary(-1);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800978 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
979 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800980 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800981 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800982 postStreamDoneEvent_l(err);
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800983 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -0700984 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800985 return;
986 }
987
988 if (mVideoBuffer->range_length() == 0) {
989 // Some decoders, notably the PV AVC software decoder
990 // return spurious empty buffers that we just want to ignore.
991
992 mVideoBuffer->release();
993 mVideoBuffer = NULL;
994 continue;
995 }
996
997 int64_t videoTimeUs;
998 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
999
Andreas Hubera5872f72011-02-24 15:25:21 -08001000 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001001 if (videoTimeUs < mSeekTimeUs) {
1002 // buffers are before seek time
1003 // ignore them
1004 mVideoBuffer->release();
1005 mVideoBuffer = NULL;
1006 continue;
1007 }
1008 } else {
1009 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
1010 // Frames are before begin cut time
1011 // Donot render
1012 mVideoBuffer->release();
1013 mVideoBuffer = NULL;
1014 continue;
1015 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001016 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001017 break;
1018 }
1019 }
1020
1021 mNumberDecVideoFrames++;
1022
1023 int64_t timeUs;
1024 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1025
1026 {
1027 Mutex::Autolock autoLock(mMiscStateLock);
1028 mVideoTimeUs = timeUs;
1029 }
1030
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001031
1032 if(!mStartNextPlayer) {
Raghavender Pallaebf40152011-03-14 20:15:12 -07001033 int64_t playbackTimeRemaining = (mPlayEndTimeMsec*1000LL) - timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001034 if(playbackTimeRemaining <= 1500000) {
1035 //When less than 1.5 sec of playback left
1036 // send notification to start next player
1037
1038 mStartNextPlayer = true;
1039 notifyListener_l(0xAAAAAAAA);
1040 }
1041 }
1042
Andreas Hubera5872f72011-02-24 15:25:21 -08001043 SeekType wasSeeking = mSeeking;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001044 finishSeekIfNecessary(timeUs);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -08001045 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING))) {
1046 status_t err = startAudioPlayer_l();
1047 if (err != OK) {
1048 LOGE("Starting the audio player failed w/ err %d", err);
1049 return;
1050 }
1051 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001052
1053 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
1054
1055 if(ts == NULL) {
1056 mVideoBuffer->release();
1057 mVideoBuffer = NULL;
1058 return;
1059 }
1060
1061 if(!mIsVideoSourceJpg) {
1062 if (mFlags & FIRST_FRAME) {
1063 mFlags &= ~FIRST_FRAME;
1064
1065 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
1066 }
1067
1068 int64_t realTimeUs, mediaTimeUs;
1069 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
1070 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1071 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1072 }
1073
1074 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1075
1076 int64_t latenessUs = nowUs - timeUs;
1077
Andreas Hubera5872f72011-02-24 15:25:21 -08001078 if (wasSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -08001079 // Let's display the first frame after seeking right away.
1080 latenessUs = 0;
1081 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001082 LOGV("Audio time stamp = %lld and video time stamp = %lld",
1083 ts->getRealTimeUs(),timeUs);
1084 if (latenessUs > 40000) {
1085 // We're more than 40ms late.
1086
1087 LOGV("LV PLAYER we're late by %lld us (%.2f secs)",
1088 latenessUs, latenessUs / 1E6);
1089
1090 mVideoBuffer->release();
1091 mVideoBuffer = NULL;
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001092 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001093 return;
1094 }
1095
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001096 if (latenessUs < -25000) {
1097 // We're more than 25ms early.
1098 LOGV("We're more than 25ms early, lateness %lld", latenessUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001099
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001100 postVideoEvent_l(25000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001101 return;
1102 }
1103 }
1104
1105 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
1106 mVideoRendererIsPreview = false;
1107
Santosh Madhavabfece172011-02-03 16:59:47 -08001108 status_t err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001109 if (err != OK) {
1110 postStreamDoneEvent_l(err);
1111 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001112 }
1113
1114 // If timestamp exceeds endCutTime of clip, donot render
1115 if((timeUs/1000) > mPlayEndTimeMsec) {
1116 if (mLastVideoBuffer) {
1117 mLastVideoBuffer->release();
1118 mLastVideoBuffer = NULL;
1119 }
1120 mLastVideoBuffer = mVideoBuffer;
1121 mVideoBuffer = NULL;
1122 mFlags |= VIDEO_AT_EOS;
1123 mFlags |= AUDIO_AT_EOS;
Santosh Madhavabfece172011-02-03 16:59:47 -08001124 LOGV("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS..");
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001125 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001126 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001127 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001128 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1129 return;
1130 }
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001131 // Capture the frame timestamp to be rendered
1132 mDecodedVideoTs = timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001133
1134 // Post processing to apply video effects
1135 for(i=0;i<mNumberEffects;i++) {
1136 // First check if effect starttime matches the clip being previewed
1137 if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) ||
1138 (mEffectsSettings[i].uiStartTime >=
1139 ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec)))
1140 {
1141 // This effect doesn't belong to this clip, check next one
1142 continue;
1143 }
1144 // Check if effect applies to this particular frame timestamp
1145 if((mEffectsSettings[i].uiStartTime <=
1146 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) &&
1147 ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=
1148 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec))
1149 && (mEffectsSettings[i].uiDuration != 0)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001150 setVideoPostProcessingNode(
1151 mEffectsSettings[i].VideoEffectType, TRUE);
1152 }
1153 else {
1154 setVideoPostProcessingNode(
1155 mEffectsSettings[i].VideoEffectType, FALSE);
1156 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001157 }
1158
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001159 //Provide the overlay Update indication when there is an overlay effect
Dharmaray Kundargid01ef562011-01-26 21:11:00 -08001160 if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) {
1161 mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here.
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001162 if (!mOverlayUpdateEventPosted) {
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001163 // Find the effect in effectSettings array
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001164 M4OSA_UInt32 index;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001165 for (index = 0; index < mNumberEffects; index++) {
1166 M4OSA_UInt32 timeMs = mDecodedVideoTs/1000;
1167 M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000;
1168 if(mEffectsSettings[index].VideoEffectType ==
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001169 (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001170 if (((mEffectsSettings[index].uiStartTime + 1) <=
1171 timeMs + timeOffset - mPlayBeginTimeMsec) &&
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001172 ((mEffectsSettings[index].uiStartTime - 1 +
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001173 mEffectsSettings[index].uiDuration) >=
1174 timeMs + timeOffset - mPlayBeginTimeMsec))
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001175 {
1176 break;
1177 }
1178 }
1179 }
1180 if (index < mNumberEffects) {
1181 mCurrFramingEffectIndex = index;
1182 mOverlayUpdateEventPosted = true;
1183 postOverlayUpdateEvent_l();
1184 LOGV("Framing index = %d", mCurrFramingEffectIndex);
1185 } else {
1186 LOGV("No framing effects found");
1187 }
1188 }
1189
1190 } else if (mOverlayUpdateEventPosted) {
1191 //Post the event when the overlay is no more valid
1192 LOGV("Overlay is Done");
1193 mOverlayUpdateEventPosted = false;
1194 postOverlayUpdateEvent_l();
1195 }
1196
1197
1198 if (mCurrentVideoEffect != VIDEO_EFFECT_NONE) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001199 err1 = doVideoPostProcessing();
1200 if(err1 != M4NO_ERROR) {
1201 LOGE("doVideoPostProcessing returned err");
1202 bAppliedVideoEffect = false;
1203 }
1204 else {
1205 bAppliedVideoEffect = true;
1206 }
1207 }
1208 else {
1209 bAppliedVideoEffect = false;
1210 if(mRenderingMode != MEDIA_RENDERING_INVALID) {
1211 // No effects to be applied, but media rendering to be done
1212 err1 = doMediaRendering();
1213 if(err1 != M4NO_ERROR) {
1214 LOGE("doMediaRendering returned err");
1215 //Use original mVideoBuffer for rendering
1216 mVideoResizedOrCropped = false;
1217 }
1218 }
1219 }
1220
1221 if (mVideoRenderer != NULL) {
1222 LOGV("mVideoRenderer CALL render()");
1223 mVideoRenderer->render();
1224 }
1225
1226 if (mLastVideoBuffer) {
1227 mLastVideoBuffer->release();
1228 mLastVideoBuffer = NULL;
1229 }
1230
1231 mLastVideoBuffer = mVideoBuffer;
1232 mVideoBuffer = NULL;
1233
1234 // Post progress callback based on callback interval set
1235 if(mNumberDecVideoFrames >= mProgressCbInterval) {
1236 postProgressCallbackEvent_l();
1237 mNumberDecVideoFrames = 0; // reset counter
1238 }
1239
1240 // if reached EndCutTime of clip, post EOS event
1241 if((timeUs/1000) >= mPlayEndTimeMsec) {
1242 LOGV("PreviewPlayer: onVideoEvent EOS.");
1243 mFlags |= VIDEO_AT_EOS;
1244 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001245 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001246 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001247 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001248 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1249 }
1250 else {
Andreas Hubera5872f72011-02-24 15:25:21 -08001251 if ((wasSeeking != NO_SEEK) && (mFlags & SEEK_PREVIEW)) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001252 mFlags &= ~SEEK_PREVIEW;
1253 return;
1254 }
1255
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001256 if(!mIsVideoSourceJpg) {
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001257 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001258 }
1259 else {
1260 postVideoEvent_l(33000);
1261 }
1262 }
1263}
1264
1265status_t PreviewPlayer::prepare() {
1266 Mutex::Autolock autoLock(mLock);
1267 return prepare_l();
1268}
1269
1270status_t PreviewPlayer::prepare_l() {
1271 if (mFlags & PREPARED) {
1272 return OK;
1273 }
1274
1275 if (mFlags & PREPARING) {
1276 return UNKNOWN_ERROR;
1277 }
1278
1279 mIsAsyncPrepare = false;
1280 status_t err = prepareAsync_l();
1281
1282 if (err != OK) {
1283 return err;
1284 }
1285
1286 while (mFlags & PREPARING) {
1287 mPreparedCondition.wait(mLock);
1288 }
1289
1290 return mPrepareResult;
1291}
1292
1293status_t PreviewPlayer::prepareAsync_l() {
1294 if (mFlags & PREPARING) {
1295 return UNKNOWN_ERROR; // async prepare already pending
1296 }
1297
1298 if (!mQueueStarted) {
1299 mQueue.start();
1300 mQueueStarted = true;
1301 }
1302
1303 mFlags |= PREPARING;
1304 mAsyncPrepareEvent = new PreviewPlayerEvent(
1305 this, &PreviewPlayer::onPrepareAsyncEvent);
1306
1307 mQueue.postEvent(mAsyncPrepareEvent);
1308
1309 return OK;
1310}
1311
1312status_t PreviewPlayer::finishSetDataSource_l() {
1313 sp<DataSource> dataSource;
1314 sp<MediaExtractor> extractor;
1315
1316 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1317
1318 if (dataSource == NULL) {
1319 return UNKNOWN_ERROR;
1320 }
1321
1322 //If file type is .rgb, then no need to check for Extractor
1323 int uriLen = strlen(mUri);
1324 int startOffset = uriLen - 4;
1325 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) {
1326 extractor = NULL;
1327 }
1328 else {
1329 extractor = MediaExtractor::Create(dataSource,
1330 MEDIA_MIMETYPE_CONTAINER_MPEG4);
1331 }
1332
1333 if (extractor == NULL) {
1334 LOGV("PreviewPlayer::finishSetDataSource_l extractor == NULL");
1335 return setDataSource_l_jpg();
1336 }
1337
1338 return setDataSource_l(extractor);
1339}
1340
1341
1342// static
1343bool PreviewPlayer::ContinuePreparation(void *cookie) {
1344 PreviewPlayer *me = static_cast<PreviewPlayer *>(cookie);
1345
1346 return (me->mFlags & PREPARE_CANCELLED) == 0;
1347}
1348
1349void PreviewPlayer::onPrepareAsyncEvent() {
1350 Mutex::Autolock autoLock(mLock);
1351 LOGV("onPrepareAsyncEvent");
1352
1353 if (mFlags & PREPARE_CANCELLED) {
Santosh Madhavabfece172011-02-03 16:59:47 -08001354 LOGV("LV PLAYER prepare was cancelled before doing anything");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001355 abortPrepare(UNKNOWN_ERROR);
1356 return;
1357 }
1358
1359 if (mUri.size() > 0) {
1360 status_t err = finishSetDataSource_l();
1361
1362 if (err != OK) {
1363 abortPrepare(err);
1364 return;
1365 }
1366 }
1367
1368 if (mVideoTrack != NULL && mVideoSource == NULL) {
1369 status_t err = initVideoDecoder(OMXCodec::kHardwareCodecsOnly);
1370
1371 if (err != OK) {
1372 abortPrepare(err);
1373 return;
1374 }
1375 }
1376
1377 if (mAudioTrack != NULL && mAudioSource == NULL) {
1378 status_t err = initAudioDecoder();
1379
1380 if (err != OK) {
1381 abortPrepare(err);
1382 return;
1383 }
1384 }
1385 finishAsyncPrepare_l();
1386
1387}
1388
1389void PreviewPlayer::finishAsyncPrepare_l() {
1390 if (mIsAsyncPrepare) {
1391 if (mVideoSource == NULL) {
1392 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE 0 0 ");
1393 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1394 } else {
1395 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE");
1396 notifyVideoSize_l();
1397 }
1398 LOGV("finishAsyncPrepare_l: MEDIA_PREPARED");
1399 notifyListener_l(MEDIA_PREPARED);
1400 }
1401
1402 mPrepareResult = OK;
1403 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1404 mFlags |= PREPARED;
1405 mAsyncPrepareEvent = NULL;
1406 mPreparedCondition.broadcast();
1407}
1408
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001409void PreviewPlayer::acquireLock() {
1410 LOGV("acquireLock");
1411 mLockControl.lock();
1412}
1413
1414void PreviewPlayer::releaseLock() {
1415 LOGV("releaseLock");
1416 mLockControl.unlock();
1417}
1418
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001419status_t PreviewPlayer::loadEffectsSettings(
1420 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) {
1421 M4OSA_UInt32 i = 0, rgbSize = 0;
1422 M4VIFI_UInt8 *tmp = M4OSA_NULL;
1423
1424 mNumberEffects = nEffects;
1425 mEffectsSettings = pEffectSettings;
1426 return OK;
1427}
1428
1429status_t PreviewPlayer::loadAudioMixSettings(
1430 M4xVSS_AudioMixingSettings* pAudioMixSettings) {
1431
1432 LOGV("PreviewPlayer: loadAudioMixSettings: ");
1433 mPreviewPlayerAudioMixSettings = pAudioMixSettings;
1434 return OK;
1435}
1436
1437status_t PreviewPlayer::setAudioMixPCMFileHandle(
1438 M4OSA_Context pAudioMixPCMFileHandle) {
1439
1440 LOGV("PreviewPlayer: setAudioMixPCMFileHandle: ");
1441 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle;
1442 return OK;
1443}
1444
1445status_t PreviewPlayer::setAudioMixStoryBoardParam(
1446 M4OSA_UInt32 audioMixStoryBoardTS,
1447 M4OSA_UInt32 currentMediaBeginCutTime,
1448 M4OSA_UInt32 primaryTrackVolValue ) {
1449
1450 mAudioMixStoryBoardTS = audioMixStoryBoardTS;
1451 mCurrentMediaBeginCutTime = currentMediaBeginCutTime;
1452 mCurrentMediaVolumeValue = primaryTrackVolValue;
1453 return OK;
1454}
1455
1456status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) {
1457
1458 mPlayBeginTimeMsec = msec;
1459 return OK;
1460}
1461
1462status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) {
1463
1464 mPlayEndTimeMsec = msec;
1465 return OK;
1466}
1467
1468status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) {
1469
1470 mStoryboardStartTimeMsec = msec;
Raghavender Pallaebf40152011-03-14 20:15:12 -07001471 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001472 return OK;
1473}
1474
1475status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) {
1476
1477 mProgressCbInterval = cbInterval;
1478 return OK;
1479}
1480
1481
1482status_t PreviewPlayer::setMediaRenderingMode(
1483 M4xVSS_MediaRendering mode,
1484 M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
1485
1486 mRenderingMode = mode;
1487
1488 /* reset boolean for each clip*/
1489 mVideoResizedOrCropped = false;
1490
Hong Teng8806b702011-07-06 18:29:28 -07001491 status_t err = OK;
1492 /* get the video width and height by resolution */
1493 err = getVideoSizeByResolution(outputVideoSize,
1494 &mOutputVideoWidth, &mOutputVideoHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001495
Hong Teng8806b702011-07-06 18:29:28 -07001496 return err;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001497}
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;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001506
1507 videoBufferSize = mVideoBuffer->size();
1508 frameSize = (mVideoWidth*mVideoHeight*3) >> 1;
1509
1510 uint8_t* outBuffer;
1511 size_t outBufferStride = 0;
1512
1513 mVideoRenderer->getBuffer(&outBuffer, &outBufferStride);
1514
1515 bufferOffset = index*frameSize;
1516 inBuffer = (M4OSA_UInt8 *)mVideoBuffer->data()+
1517 mVideoBuffer->range_offset()+bufferOffset;
1518
1519
1520 /* In plane*/
1521 prepareYUV420ImagePlane(planeIn, mVideoWidth,
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001522 mVideoHeight, (M4VIFI_UInt8 *)inBuffer, mReportedWidth, mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001523
1524 // Set the output YUV420 plane to be compatible with YV12 format
1525 // W & H even
1526 // YVU instead of YUV
1527 // align buffers on 32 bits
1528
1529 //In YV12 format, sizes must be even
1530 M4OSA_UInt32 yv12PlaneWidth = ((mOutputVideoWidth +1)>>1)<<1;
1531 M4OSA_UInt32 yv12PlaneHeight = ((mOutputVideoHeight+1)>>1)<<1;
1532
1533 prepareYV12ImagePlane(planeOut, yv12PlaneWidth, yv12PlaneHeight,
1534 (M4OSA_UInt32)outBufferStride, (M4VIFI_UInt8 *)outBuffer);
1535
1536
1537 err = applyRenderingMode(planeIn, planeOut, mRenderingMode);
1538
1539 if(err != M4NO_ERROR)
1540 {
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001541 LOGE("doMediaRendering: applyRenderingMode returned err=0x%x", (int)err);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001542 return err;
1543 }
1544 mVideoResizedOrCropped = true;
1545
1546 return err;
1547}
1548
1549status_t PreviewPlayer::resetJniCallbackTimeStamp() {
1550
Raghavender Pallaebf40152011-03-14 20:15:12 -07001551 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001552 return OK;
1553}
1554
1555void PreviewPlayer::postProgressCallbackEvent_l() {
1556 if (mProgressCbEventPending) {
1557 return;
1558 }
1559 mProgressCbEventPending = true;
1560
1561 mQueue.postEvent(mProgressCbEvent);
1562}
1563
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001564
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001565void PreviewPlayer::onProgressCbEvent() {
1566 Mutex::Autolock autoLock(mLock);
1567 if (!mProgressCbEventPending) {
1568 return;
1569 }
1570 mProgressCbEventPending = false;
1571 // If playback starts from previous I-frame,
1572 // then send frame storyboard duration
1573 if((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) {
1574 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000);
1575 }
1576 else {
1577 notifyListener_l(MEDIA_INFO, 0,
1578 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec));
1579 }
1580}
1581
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001582void PreviewPlayer::postOverlayUpdateEvent_l() {
1583 if (mOverlayUpdateEventPending) {
1584 return;
1585 }
1586 mOverlayUpdateEventPending = true;
1587 mQueue.postEvent(mOverlayUpdateEvent);
1588}
1589
1590void PreviewPlayer::onUpdateOverlayEvent() {
1591 Mutex::Autolock autoLock(mLock);
1592
1593 if (!mOverlayUpdateEventPending) {
1594 return;
1595 }
1596 mOverlayUpdateEventPending = false;
1597
1598 int updateState;
1599 if (mOverlayUpdateEventPosted) {
1600 updateState = 1;
1601 } else {
1602 updateState = 0;
1603 }
1604 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex);
1605}
1606
1607
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001608void PreviewPlayer::setVideoPostProcessingNode(
1609 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
1610
1611 uint32_t effect = VIDEO_EFFECT_NONE;
1612
1613 //Map M4VSS3GPP_VideoEffectType to local enum
1614 switch(type) {
1615 case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
1616 effect = VIDEO_EFFECT_FADEFROMBLACK;
1617 break;
1618
1619 case M4VSS3GPP_kVideoEffectType_FadeToBlack:
1620 effect = VIDEO_EFFECT_FADETOBLACK;
1621 break;
1622
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001623 case M4xVSS_kVideoEffectType_BlackAndWhite:
1624 effect = VIDEO_EFFECT_BLACKANDWHITE;
1625 break;
1626
1627 case M4xVSS_kVideoEffectType_Pink:
1628 effect = VIDEO_EFFECT_PINK;
1629 break;
1630
1631 case M4xVSS_kVideoEffectType_Green:
1632 effect = VIDEO_EFFECT_GREEN;
1633 break;
1634
1635 case M4xVSS_kVideoEffectType_Sepia:
1636 effect = VIDEO_EFFECT_SEPIA;
1637 break;
1638
1639 case M4xVSS_kVideoEffectType_Negative:
1640 effect = VIDEO_EFFECT_NEGATIVE;
1641 break;
1642
1643 case M4xVSS_kVideoEffectType_Framing:
1644 effect = VIDEO_EFFECT_FRAMING;
1645 break;
1646
1647 case M4xVSS_kVideoEffectType_Fifties:
1648 effect = VIDEO_EFFECT_FIFTIES;
1649 break;
1650
1651 case M4xVSS_kVideoEffectType_ColorRGB16:
1652 effect = VIDEO_EFFECT_COLOR_RGB16;
1653 break;
1654
1655 case M4xVSS_kVideoEffectType_Gradient:
1656 effect = VIDEO_EFFECT_GRADIENT;
1657 break;
1658
1659 default:
1660 effect = VIDEO_EFFECT_NONE;
1661 break;
1662 }
1663
1664 if(enable == M4OSA_TRUE) {
1665 //If already set, then no need to set again
1666 if(!(mCurrentVideoEffect & effect)) {
1667 mCurrentVideoEffect |= effect;
1668 if(effect == VIDEO_EFFECT_FIFTIES) {
1669 mIsFiftiesEffectStarted = true;
1670 }
1671 }
1672 }
1673 else {
1674 //Reset only if already set
1675 if(mCurrentVideoEffect & effect) {
1676 mCurrentVideoEffect &= ~effect;
1677 }
1678 }
1679}
1680
1681status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) {
1682 mVideoWidth = width;
1683 mVideoHeight = height;
1684 return OK;
1685}
1686
1687
1688M4OSA_ERR PreviewPlayer::doVideoPostProcessing() {
1689 M4OSA_ERR err = M4NO_ERROR;
1690 vePostProcessParams postProcessParams;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001691
1692 postProcessParams.vidBuffer = (M4VIFI_UInt8*)mVideoBuffer->data()
1693 + mVideoBuffer->range_offset();
1694
1695 postProcessParams.videoWidth = mVideoWidth;
1696 postProcessParams.videoHeight = mVideoHeight;
1697 postProcessParams.timeMs = mDecodedVideoTs/1000;
1698 postProcessParams.timeOffset = mDecVideoTsStoryBoard/1000;
1699 postProcessParams.effectsSettings = mEffectsSettings;
1700 postProcessParams.numberEffects = mNumberEffects;
1701 postProcessParams.outVideoWidth = mOutputVideoWidth;
1702 postProcessParams.outVideoHeight = mOutputVideoHeight;
1703 postProcessParams.currentVideoEffect = mCurrentVideoEffect;
1704 postProcessParams.renderingMode = mRenderingMode;
1705 if(mIsFiftiesEffectStarted == M4OSA_TRUE) {
1706 postProcessParams.isFiftiesEffectStarted = M4OSA_TRUE;
1707 mIsFiftiesEffectStarted = M4OSA_FALSE;
1708 }
1709 else {
1710 postProcessParams.isFiftiesEffectStarted = M4OSA_FALSE;
1711 }
1712
1713 postProcessParams.overlayFrameRGBBuffer = mFrameRGBBuffer;
1714 postProcessParams.overlayFrameYUVBuffer = mFrameYUVBuffer;
1715 mVideoRenderer->getBuffer(&(postProcessParams.pOutBuffer), &(postProcessParams.outBufferStride));
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001716 err = applyEffectsAndRenderingMode(&postProcessParams, mReportedWidth, mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001717
1718 return err;
1719}
1720
1721status_t PreviewPlayer::readFirstVideoFrame() {
1722 LOGV("PreviewPlayer::readFirstVideoFrame");
1723
1724 if (!mVideoBuffer) {
1725 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -08001726 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001727 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
1728 mSeekTimeUs / 1E6);
1729
1730 options.setSeekTo(
1731 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
1732 }
1733 for (;;) {
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +08001734 status_t err = readYV12Buffer(mVideoSource, &mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001735 options.clearSeekTo();
1736
1737 if (err != OK) {
1738 CHECK_EQ(mVideoBuffer, NULL);
1739
1740 if (err == INFO_FORMAT_CHANGED) {
1741 LOGV("LV PLAYER VideoSource signalled format change");
1742 notifyVideoSize_l();
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001743 sp<MetaData> meta = mVideoSource->getFormat();
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +08001744 getVideoBufferSize(meta, &mReportedWidth, &mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001745
1746 if (mVideoRenderer != NULL) {
1747 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -08001748 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001749 if (err != OK) {
1750 postStreamDoneEvent_l(err);
1751 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001752 }
1753 continue;
1754 }
1755 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
1756 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001757 mFlags |= AUDIO_AT_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001758 postStreamDoneEvent_l(err);
1759 return OK;
1760 }
1761
1762 if (mVideoBuffer->range_length() == 0) {
1763 // Some decoders, notably the PV AVC software decoder
1764 // return spurious empty buffers that we just want to ignore.
1765
1766 mVideoBuffer->release();
1767 mVideoBuffer = NULL;
1768 continue;
1769 }
1770
1771 int64_t videoTimeUs;
1772 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
Andreas Hubera5872f72011-02-24 15:25:21 -08001773 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001774 if (videoTimeUs < mSeekTimeUs) {
1775 // buffers are before seek time
1776 // ignore them
1777 mVideoBuffer->release();
1778 mVideoBuffer = NULL;
1779 continue;
1780 }
1781 } else {
1782 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
1783 // buffers are before begin cut time
1784 // ignore them
1785 mVideoBuffer->release();
1786 mVideoBuffer = NULL;
1787 continue;
1788 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001789 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001790 break;
1791 }
1792 }
1793
1794 int64_t timeUs;
1795 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1796
1797 {
1798 Mutex::Autolock autoLock(mMiscStateLock);
1799 mVideoTimeUs = timeUs;
1800 }
1801
1802 mDecodedVideoTs = timeUs;
1803
1804 return OK;
1805
1806}
1807
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001808status_t PreviewPlayer::getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs) {
1809 *lastRenderedTimeMs = (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec);
1810 return OK;
1811}
1812
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001813} // namespace android