blob: 51ad51a85780339746622c0a8781acf43a5c4496 [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"
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080030#include "include/NuCachedSource2.h"
31#include "include/ThrottledSource.h"
32
33
34#include "PreviewRenderer.h"
35
36#include <binder/IPCThreadState.h>
37#include <media/stagefright/DataSource.h>
38#include <media/stagefright/FileSource.h>
39#include <media/stagefright/MediaBuffer.h>
40#include <media/stagefright/MediaDefs.h>
41#include <media/stagefright/MediaExtractor.h>
42#include <media/stagefright/MediaDebug.h>
43#include <media/stagefright/MediaSource.h>
44#include <media/stagefright/MetaData.h>
45#include <media/stagefright/OMXCodec.h>
46
47#include <surfaceflinger/Surface.h>
48#include <media/stagefright/foundation/ALooper.h>
49
50namespace android {
51
52
53struct PreviewPlayerEvent : public TimedEventQueue::Event {
54 PreviewPlayerEvent(
55 PreviewPlayer *player,
56 void (PreviewPlayer::*method)())
57 : mPlayer(player),
58 mMethod(method) {
59 }
60
61protected:
62 virtual ~PreviewPlayerEvent() {}
63
64 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
65 (mPlayer->*mMethod)();
66 }
67
68private:
69 PreviewPlayer *mPlayer;
70 void (PreviewPlayer::*mMethod)();
71
72 PreviewPlayerEvent(const PreviewPlayerEvent &);
73 PreviewPlayerEvent &operator=(const PreviewPlayerEvent &);
74};
75
76
77struct PreviewLocalRenderer : public PreviewPlayerRenderer {
Santosh Madhavabfece172011-02-03 16:59:47 -080078
79 static PreviewLocalRenderer* initPreviewLocalRenderer (
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080080 bool previewOnly,
81 OMX_COLOR_FORMATTYPE colorFormat,
82 const sp<Surface> &surface,
83 size_t displayWidth, size_t displayHeight,
84 size_t decodedWidth, size_t decodedHeight,
85 int32_t rotationDegrees = 0)
Santosh Madhavabfece172011-02-03 16:59:47 -080086 {
87 PreviewLocalRenderer* mLocalRenderer = new
88 PreviewLocalRenderer(
89 previewOnly,
90 colorFormat,
91 surface,
92 displayWidth, displayHeight,
93 decodedWidth, decodedHeight,
94 rotationDegrees);
95
96 if ( mLocalRenderer->init(previewOnly,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080097 colorFormat, surface,
98 displayWidth, displayHeight,
99 decodedWidth, decodedHeight,
Santosh Madhavabfece172011-02-03 16:59:47 -0800100 rotationDegrees) != OK )
101 {
102 delete mLocalRenderer;
103 return NULL;
104 }
105 return mLocalRenderer;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800106 }
107
108 virtual void render(MediaBuffer *buffer) {
109 render((const uint8_t *)buffer->data() + buffer->range_offset(),
110 buffer->range_length());
111 }
112
113 void render(const void *data, size_t size) {
114 mTarget->render(data, size, NULL);
115 }
116 void render() {
117 mTarget->renderYV12();
118 }
119 void getBuffer(uint8_t **data, size_t *stride) {
120 mTarget->getBufferYV12(data, stride);
121 }
122
123protected:
124 virtual ~PreviewLocalRenderer() {
125 delete mTarget;
126 mTarget = NULL;
127 }
128
129private:
130 PreviewRenderer *mTarget;
131
Santosh Madhavabfece172011-02-03 16:59:47 -0800132 PreviewLocalRenderer(
133 bool previewOnly,
134 OMX_COLOR_FORMATTYPE colorFormat,
135 const sp<Surface> &surface,
136 size_t displayWidth, size_t displayHeight,
137 size_t decodedWidth, size_t decodedHeight,
138 int32_t rotationDegrees = 0)
139 : mTarget(NULL) {
140 }
141
142
143 int init(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800144 bool previewOnly,
145 OMX_COLOR_FORMATTYPE colorFormat,
146 const sp<Surface> &surface,
147 size_t displayWidth, size_t displayHeight,
148 size_t decodedWidth, size_t decodedHeight,
149 int32_t rotationDegrees = 0);
150
151 PreviewLocalRenderer(const PreviewLocalRenderer &);
152 PreviewLocalRenderer &operator=(const PreviewLocalRenderer &);;
153};
154
Santosh Madhavabfece172011-02-03 16:59:47 -0800155int PreviewLocalRenderer::init(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800156 bool previewOnly,
157 OMX_COLOR_FORMATTYPE colorFormat,
158 const sp<Surface> &surface,
159 size_t displayWidth, size_t displayHeight,
160 size_t decodedWidth, size_t decodedHeight,
161 int32_t rotationDegrees) {
Santosh Madhavabfece172011-02-03 16:59:47 -0800162
163 mTarget = PreviewRenderer::CreatePreviewRenderer (
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800164 colorFormat, surface, displayWidth, displayHeight,
165 decodedWidth, decodedHeight, rotationDegrees);
Santosh Madhavabfece172011-02-03 16:59:47 -0800166 if (mTarget == M4OSA_NULL) {
167 return UNKNOWN_ERROR;
168 }
169 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800170}
171
172PreviewPlayer::PreviewPlayer()
173 : AwesomePlayer(),
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -0800174 mCurrFramingEffectIndex(0) ,
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800175 mReportedWidth(0),
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800176 mReportedHeight(0),
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -0800177 mFrameRGBBuffer(NULL),
178 mFrameYUVBuffer(NULL){
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800179
180 mVideoRenderer = NULL;
181 mLastVideoBuffer = NULL;
182 mSuspensionState = NULL;
183 mEffectsSettings = NULL;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800184 mVeAudioPlayer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800185 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;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800195 mIsChangeSourceRequired = true;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800196
197 mVideoEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoEvent);
198 mVideoEventPending = false;
199 mStreamDoneEvent = new PreviewPlayerEvent(this,
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800200 &PreviewPlayer::onStreamDone);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800201
202 mStreamDoneEventPending = false;
203
204 mCheckAudioStatusEvent = new PreviewPlayerEvent(
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800205 this, &AwesomePlayer::onCheckAudioStatus);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800206
207 mAudioStatusEventPending = false;
208
209 mProgressCbEvent = new PreviewPlayerEvent(this,
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800210 &PreviewPlayer::onProgressCbEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800211
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800212 mOverlayUpdateEvent = new PreviewPlayerEvent(this,
213 &PreviewPlayer::onUpdateOverlayEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800214 mProgressCbEventPending = false;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800215
216 mOverlayUpdateEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800217 mResizedVideoBuffer = NULL;
218 mVideoResizedOrCropped = false;
219 mRenderingMode = (M4xVSS_MediaRendering)MEDIA_RENDERING_INVALID;
220 mIsFiftiesEffectStarted = false;
221 reset();
222}
223
224PreviewPlayer::~PreviewPlayer() {
225
226 if (mQueueStarted) {
227 mQueue.stop();
228 }
229
230 reset();
231
232 if(mResizedVideoBuffer != NULL) {
233 M4OSA_free((M4OSA_MemAddr32)(mResizedVideoBuffer->data()));
234 mResizedVideoBuffer = NULL;
235 }
236
237 mVideoRenderer.clear();
238 mVideoRenderer = NULL;
239}
240
241void PreviewPlayer::cancelPlayerEvents(bool keepBufferingGoing) {
242 mQueue.cancelEvent(mVideoEvent->eventID());
243 mVideoEventPending = false;
244 mQueue.cancelEvent(mStreamDoneEvent->eventID());
245 mStreamDoneEventPending = false;
246 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
247 mAudioStatusEventPending = false;
248
249 mQueue.cancelEvent(mProgressCbEvent->eventID());
250 mProgressCbEventPending = false;
251}
252
253status_t PreviewPlayer::setDataSource(
254 const char *uri, const KeyedVector<String8, String8> *headers) {
255 Mutex::Autolock autoLock(mLock);
256 return setDataSource_l(uri, headers);
257}
258
259status_t PreviewPlayer::setDataSource_l(
260 const char *uri, const KeyedVector<String8, String8> *headers) {
261 reset_l();
262
263 mUri = uri;
264
265 if (headers) {
266 mUriHeaders = *headers;
267 }
268
269 // The actual work will be done during preparation in the call to
270 // ::finishSetDataSource_l to avoid blocking the calling thread in
271 // setDataSource for any significant time.
272 return OK;
273}
274
275status_t PreviewPlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
276 bool haveAudio = false;
277 bool haveVideo = false;
278 for (size_t i = 0; i < extractor->countTracks(); ++i) {
279 sp<MetaData> meta = extractor->getTrackMetaData(i);
280
281 const char *mime;
282 CHECK(meta->findCString(kKeyMIMEType, &mime));
283
284 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
285 setVideoSource(extractor->getTrack(i));
286 haveVideo = true;
287 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
288 setAudioSource(extractor->getTrack(i));
289 haveAudio = true;
290
291 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
292 // Only do this for vorbis audio, none of the other audio
293 // formats even support this ringtone specific hack and
294 // retrieving the metadata on some extractors may turn out
295 // to be very expensive.
296 sp<MetaData> fileMeta = extractor->getMetaData();
297 int32_t loop;
298 if (fileMeta != NULL
299 && fileMeta->findInt32(kKeyAutoLoop, &loop)
300 && loop != 0) {
301 mFlags |= AUTO_LOOPING;
302 }
303 }
304 }
305
306 if (haveAudio && haveVideo) {
307 break;
308 }
309 }
310
311 /* Add the support for Dummy audio*/
312 if( !haveAudio ){
313 LOGV("PreviewPlayer: setDataSource_l Dummyaudiocreation started");
314
315 mAudioTrack = DummyAudioSource::Create(32000, 2, 20000,
316 ((mPlayEndTimeMsec)*1000));
317 LOGV("PreviewPlayer: setDataSource_l Dummyauiosource created");
318 if(mAudioTrack != NULL) {
319 haveAudio = true;
320 }
321 }
322
323 if (!haveAudio && !haveVideo) {
324 return UNKNOWN_ERROR;
325 }
326
327 mExtractorFlags = extractor->flags();
328 return OK;
329}
330
331status_t PreviewPlayer::setDataSource_l_jpg() {
332 M4OSA_ERR err = M4NO_ERROR;
333 LOGV("PreviewPlayer: setDataSource_l_jpg started");
334
335 mAudioSource = DummyAudioSource::Create(32000, 2, 20000,
336 ((mPlayEndTimeMsec)*1000));
337 LOGV("PreviewPlayer: setDataSource_l_jpg Dummyaudiosource created");
338 if(mAudioSource != NULL) {
339 setAudioSource(mAudioSource);
340 }
341 status_t error = mAudioSource->start();
342 if (error != OK) {
343 LOGV("Error starting dummy audio source");
344 mAudioSource.clear();
345 return err;
346 }
347
348 mDurationUs = (mPlayEndTimeMsec - mPlayBeginTimeMsec)*1000;
349
350 mVideoSource = DummyVideoSource::Create(mVideoWidth, mVideoHeight,
351 mDurationUs, mUri);
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800352 mReportedWidth = mVideoWidth;
353 mReportedHeight = mVideoHeight;
354
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800355 setVideoSource(mVideoSource);
356 status_t err1 = mVideoSource->start();
357 if (err1 != OK) {
358 mVideoSource.clear();
359 return err;
360 }
361
362 mIsVideoSourceJpg = true;
363 return OK;
364}
365
366void PreviewPlayer::reset() {
367 Mutex::Autolock autoLock(mLock);
368 reset_l();
369}
370
371void PreviewPlayer::reset_l() {
372
373 if (mFlags & PREPARING) {
374 mFlags |= PREPARE_CANCELLED;
375 }
376
377 while (mFlags & PREPARING) {
378 mPreparedCondition.wait(mLock);
379 }
380
381 cancelPlayerEvents();
382 mAudioTrack.clear();
383 mVideoTrack.clear();
384
385 // Shutdown audio first, so that the respone to the reset request
386 // appears to happen instantaneously as far as the user is concerned
387 // If we did this later, audio would continue playing while we
388 // shutdown the video-related resources and the player appear to
389 // not be as responsive to a reset request.
390 if (mAudioPlayer == NULL && mAudioSource != NULL) {
391 // If we had an audio player, it would have effectively
392 // taken possession of the audio source and stopped it when
393 // _it_ is stopped. Otherwise this is still our responsibility.
394 mAudioSource->stop();
395 }
396 mAudioSource.clear();
397
398 mTimeSource = NULL;
399
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800400 //Single audio player instance used
401 //So donot delete it here
402 //It is deleted from PreviewController class
403 //delete mAudioPlayer;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800404 mAudioPlayer = NULL;
405
406 if (mLastVideoBuffer) {
407 mLastVideoBuffer->release();
408 mLastVideoBuffer = NULL;
409 }
410
411 if (mVideoBuffer) {
412 mVideoBuffer->release();
413 mVideoBuffer = NULL;
414 }
415
416 if (mVideoSource != NULL) {
417 mVideoSource->stop();
418
419 // The following hack is necessary to ensure that the OMX
420 // component is completely released by the time we may try
421 // to instantiate it again.
422 wp<MediaSource> tmp = mVideoSource;
423 mVideoSource.clear();
424 while (tmp.promote() != NULL) {
425 usleep(1000);
426 }
427 IPCThreadState::self()->flushCommands();
428 }
429
430 mDurationUs = -1;
431 mFlags = 0;
432 mExtractorFlags = 0;
433 mVideoWidth = mVideoHeight = -1;
434 mTimeSourceDeltaUs = 0;
435 mVideoTimeUs = 0;
436
Andreas Hubera5872f72011-02-24 15:25:21 -0800437 mSeeking = NO_SEEK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800438 mSeekNotificationSent = false;
439 mSeekTimeUs = 0;
440
441 mUri.setTo("");
442 mUriHeaders.clear();
443
444 mFileSource.clear();
445
446 delete mSuspensionState;
447 mSuspensionState = NULL;
448
449 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
450 mIsVideoSourceJpg = false;
451 mFrameRGBBuffer = NULL;
452 if(mFrameYUVBuffer != NULL) {
453 M4OSA_free((M4OSA_MemAddr32)mFrameYUVBuffer);
454 mFrameYUVBuffer = NULL;
455 }
456}
457
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800458status_t PreviewPlayer::play() {
459 Mutex::Autolock autoLock(mLock);
460
461 mFlags &= ~CACHE_UNDERRUN;
462
463 return play_l();
464}
465
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800466status_t PreviewPlayer::startAudioPlayer_l() {
467 CHECK(!(mFlags & AUDIO_RUNNING));
468
469 if (mAudioSource == NULL || mAudioPlayer == NULL) {
470 return OK;
471 }
472
473 if (!(mFlags & AUDIOPLAYER_STARTED)) {
474 mFlags |= AUDIOPLAYER_STARTED;
475
476 // We've already started the MediaSource in order to enable
477 // the prefetcher to read its data.
478 status_t err = mVeAudioPlayer->start(
479 true /* sourceAlreadyStarted */);
480
481 if (err != OK) {
482 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
483 return err;
484 }
485 } else {
486 mVeAudioPlayer->resume();
487 }
488
489 mFlags |= AUDIO_RUNNING;
490
491 mWatchForAudioEOS = true;
492
493 return OK;
494}
495
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800496status_t PreviewPlayer::setAudioPlayer(AudioPlayer *audioPlayer) {
497 Mutex::Autolock autoLock(mLock);
498 CHECK(!(mFlags & PLAYING));
499 mAudioPlayer = audioPlayer;
500
501 LOGV("SetAudioPlayer");
502 mIsChangeSourceRequired = true;
503 mVeAudioPlayer =
504 (VideoEditorAudioPlayer*)mAudioPlayer;
505
506 // check if the new and old source are dummy
507 sp<MediaSource> anAudioSource = mVeAudioPlayer->getSource();
508 if (anAudioSource == NULL) {
509 // Audio player does not have any source set.
510 LOGV("setAudioPlayer: Audio player does not have any source set");
511 return OK;
512 }
513
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800514 // If new video source is not dummy, then always change source
515 // Else audio player continues using old audio source and there are
516 // frame drops to maintain AV sync
517 sp<MetaData> meta;
518 if (mVideoSource != NULL) {
519 meta = mVideoSource->getFormat();
520 const char *pVidSrcType;
521 if (meta->findCString(kKeyDecoderComponent, &pVidSrcType)) {
522 if (strcmp(pVidSrcType, "DummyVideoSource") != 0) {
523 LOGV(" Video clip with silent audio; need to change source");
524 return OK;
525 }
526 }
527 }
528
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800529 const char *pSrcType1;
530 const char *pSrcType2;
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800531 meta = anAudioSource->getFormat();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800532
533 if (meta->findCString(kKeyDecoderComponent, &pSrcType1)) {
534 if (strcmp(pSrcType1, "DummyAudioSource") == 0) {
535 meta = mAudioSource->getFormat();
536 if (meta->findCString(kKeyDecoderComponent, &pSrcType2)) {
537 if (strcmp(pSrcType2, "DummyAudioSource") == 0) {
538 mIsChangeSourceRequired = false;
539 // Just set the new play duration for the existing source
540 MediaSource *pMediaSrc = anAudioSource.get();
541 DummyAudioSource *pDummyAudioSource = (DummyAudioSource*)pMediaSrc;
542 //Increment the duration of audio source
543 pDummyAudioSource->setDuration((int64_t)((mPlayEndTimeMsec)*1000));
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800544
545 // Stop the new audio source
546 // since we continue using old source
547 LOGV("setAudioPlayer: stop new audio source");
548 mAudioSource->stop();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800549 }
550 }
551 }
552 }
553
554 return OK;
555}
556
557void PreviewPlayer::onStreamDone() {
558 // Posted whenever any stream finishes playing.
559
560 Mutex::Autolock autoLock(mLock);
561 if (!mStreamDoneEventPending) {
562 return;
563 }
564 mStreamDoneEventPending = false;
565
566 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
567 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
568
569 notifyListener_l(
570 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
571
572 pause_l(true /* at eos */);
573
574 mFlags |= AT_EOS;
575 return;
576 }
577
578 const bool allDone =
579 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
580 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
581
582 if (!allDone) {
583 return;
584 }
585
586 if (mFlags & (LOOPING | AUTO_LOOPING)) {
587 seekTo_l(0);
588
589 if (mVideoSource != NULL) {
590 postVideoEvent_l();
591 }
592 } else {
593 LOGV("MEDIA_PLAYBACK_COMPLETE");
594 //pause before sending event
595 pause_l(true /* at eos */);
596 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
597
598 mFlags |= AT_EOS;
599 }
600}
601
602
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800603status_t PreviewPlayer::play_l() {
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800604
Rajneesh Chowdury8b95de22011-02-16 15:32:06 -0800605 mFlags &= ~SEEK_PREVIEW;
606
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800607 if (mFlags & PLAYING) {
608 return OK;
609 }
610 mStartNextPlayer = false;
611
612 if (!(mFlags & PREPARED)) {
613 status_t err = prepare_l();
614
615 if (err != OK) {
616 return err;
617 }
618 }
619
620 mFlags |= PLAYING;
621 mFlags |= FIRST_FRAME;
622
623 bool deferredAudioSeek = false;
624
625 if (mAudioSource != NULL) {
626 if (mAudioPlayer == NULL) {
627 if (mAudioSink != NULL) {
628
629 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800630 mVeAudioPlayer =
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800631 (VideoEditorAudioPlayer*)mAudioPlayer;
632
633 mAudioPlayer->setSource(mAudioSource);
634
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800635 mVeAudioPlayer->setAudioMixSettings(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800636 mPreviewPlayerAudioMixSettings);
637
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800638 mVeAudioPlayer->setAudioMixPCMFileHandle(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800639 mAudioMixPCMFileHandle);
640
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800641 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800642 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
643 mCurrentMediaVolumeValue);
644
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800645 mFlags |= AUDIOPLAYER_STARTED;
646 // We've already started the MediaSource in order to enable
647 // the prefetcher to read its data.
648 status_t err = mVeAudioPlayer->start(
649 true /* sourceAlreadyStarted */);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800650
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800651 if (err != OK) {
652 //delete mAudioPlayer;
653 mAudioPlayer = NULL;
654
655 mFlags &= ~(PLAYING | FIRST_FRAME);
656 return err;
657 }
658
659 mTimeSource = mVeAudioPlayer;
660 mFlags |= AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800661 deferredAudioSeek = true;
662 mWatchForAudioSeekComplete = false;
663 mWatchForAudioEOS = true;
664 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800665 } else {
666 mVeAudioPlayer = (VideoEditorAudioPlayer*)mAudioPlayer;
667 bool isAudioPlayerStarted = mVeAudioPlayer->isStarted();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800668
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800669 if (mIsChangeSourceRequired == true) {
670 LOGV("play_l: Change audio source required");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800671
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800672 if (isAudioPlayerStarted == true) {
673 mVeAudioPlayer->pause();
674 }
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800675
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800676 mVeAudioPlayer->setSource(mAudioSource);
677 mVeAudioPlayer->setObserver(this);
678
679 mVeAudioPlayer->setAudioMixSettings(
680 mPreviewPlayerAudioMixSettings);
681
682 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
683 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
684 mCurrentMediaVolumeValue);
685
686 if (isAudioPlayerStarted == true) {
687 mVeAudioPlayer->resume();
688 } else {
689 status_t err = OK;
690 err = mVeAudioPlayer->start(true);
691 if (err != OK) {
692 mAudioPlayer = NULL;
693 mVeAudioPlayer = NULL;
694
695 mFlags &= ~(PLAYING | FIRST_FRAME);
696 return err;
697 }
698 }
699 } else {
700 LOGV("play_l: No Source change required");
701 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
702 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
703 mCurrentMediaVolumeValue);
704
705 mVeAudioPlayer->resume();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800706 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800707
708 mFlags |= AUDIOPLAYER_STARTED;
709 mFlags |= AUDIO_RUNNING;
710 mTimeSource = mVeAudioPlayer;
711 deferredAudioSeek = true;
712 mWatchForAudioSeekComplete = false;
713 mWatchForAudioEOS = true;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800714 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800715 }
716
717 if (mTimeSource == NULL && mAudioPlayer == NULL) {
718 mTimeSource = &mSystemTimeSource;
719 }
720
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800721 // Set the seek option for Image source files and read.
722 // This resets the timestamping for image play
723 if (mIsVideoSourceJpg) {
724 MediaSource::ReadOptions options;
725 MediaBuffer *aLocalBuffer;
726 options.setSeekTo(mSeekTimeUs);
727 mVideoSource->read(&aLocalBuffer, &options);
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800728 aLocalBuffer->release();
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800729 }
730
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800731 if (mVideoSource != NULL) {
732 // Kick off video playback
733 postVideoEvent_l();
734 }
735
736 if (deferredAudioSeek) {
737 // If there was a seek request while we were paused
738 // and we're just starting up again, honor the request now.
739 seekAudioIfNecessary_l();
740 }
741
742 if (mFlags & AT_EOS) {
743 // Legacy behaviour, if a stream finishes playing and then
744 // is started again, we play from the start...
745 seekTo_l(0);
746 }
747
748 return OK;
749}
750
751
Santosh Madhavabfece172011-02-03 16:59:47 -0800752status_t PreviewPlayer::initRenderer_l() {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800753 if (mSurface != NULL || mISurface != NULL) {
754 sp<MetaData> meta = mVideoSource->getFormat();
755
756 int32_t format;
757 const char *component;
758 int32_t decodedWidth, decodedHeight;
759 CHECK(meta->findInt32(kKeyColorFormat, &format));
760 CHECK(meta->findCString(kKeyDecoderComponent, &component));
761 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
762 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
763
764 // Must ensure that mVideoRenderer's destructor is actually executed
765 // before creating a new one.
766 IPCThreadState::self()->flushCommands();
767
768 // always use localrenderer since decoded buffers are modified
769 // by postprocessing module
770 // Other decoders are instantiated locally and as a consequence
771 // allocate their buffers in local address space.
772 if(mVideoRenderer == NULL) {
773
Santosh Madhavabfece172011-02-03 16:59:47 -0800774 mVideoRenderer = PreviewLocalRenderer:: initPreviewLocalRenderer (
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800775 false, // previewOnly
776 (OMX_COLOR_FORMATTYPE)format,
777 mSurface,
778 mOutputVideoWidth, mOutputVideoHeight,
779 mOutputVideoWidth, mOutputVideoHeight);
Santosh Madhavabfece172011-02-03 16:59:47 -0800780
781 if ( mVideoRenderer == NULL )
782 {
783 return UNKNOWN_ERROR;
784 }
785 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800786 }
787 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800788 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800789}
790
791
792void PreviewPlayer::setISurface(const sp<ISurface> &isurface) {
793 Mutex::Autolock autoLock(mLock);
794 mISurface = isurface;
795}
796
797
798status_t PreviewPlayer::seekTo(int64_t timeUs) {
799
800 if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) {
801 Mutex::Autolock autoLock(mLock);
802 return seekTo_l(timeUs);
803 }
804
805 return OK;
806}
807
808
809status_t PreviewPlayer::getVideoDimensions(
810 int32_t *width, int32_t *height) const {
811 Mutex::Autolock autoLock(mLock);
812
813 if (mVideoWidth < 0 || mVideoHeight < 0) {
814 return UNKNOWN_ERROR;
815 }
816
817 *width = mVideoWidth;
818 *height = mVideoHeight;
819
820 return OK;
821}
822
823
824status_t PreviewPlayer::initAudioDecoder() {
825 sp<MetaData> meta = mAudioTrack->getFormat();
826 const char *mime;
827 CHECK(meta->findCString(kKeyMIMEType, &mime));
828
829 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
830 mAudioSource = mAudioTrack;
831 } else {
832 sp<MediaSource> aRawSource;
833 aRawSource = OMXCodec::Create(
834 mClient.interface(), mAudioTrack->getFormat(),
835 false, // createEncoder
836 mAudioTrack);
837
838 if(aRawSource != NULL) {
839 LOGV("initAudioDecoder: new VideoEditorSRC");
840 mAudioSource = new VideoEditorSRC(aRawSource);
841 }
842 }
843
844 if (mAudioSource != NULL) {
845 int64_t durationUs;
846 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
847 Mutex::Autolock autoLock(mMiscStateLock);
848 if (mDurationUs < 0 || durationUs > mDurationUs) {
849 mDurationUs = durationUs;
850 }
851 }
852 status_t err = mAudioSource->start();
853
854 if (err != OK) {
855 mAudioSource.clear();
856 return err;
857 }
858 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
859 // For legacy reasons we're simply going to ignore the absence
860 // of an audio decoder for QCELP instead of aborting playback
861 // altogether.
862 return OK;
863 }
864
865 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
866}
867
868
869status_t PreviewPlayer::initVideoDecoder(uint32_t flags) {
870
871 mVideoSource = OMXCodec::Create(
872 mClient.interface(), mVideoTrack->getFormat(),
873 false,
874 mVideoTrack,
875 NULL, flags);
876
877 if (mVideoSource != NULL) {
878 int64_t durationUs;
879 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
880 Mutex::Autolock autoLock(mMiscStateLock);
881 if (mDurationUs < 0 || durationUs > mDurationUs) {
882 mDurationUs = durationUs;
883 }
884 }
885
886 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
887 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
888
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800889 mReportedWidth = mVideoWidth;
890 mReportedHeight = mVideoHeight;
891
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800892 status_t err = mVideoSource->start();
893
894 if (err != OK) {
895 mVideoSource.clear();
896 return err;
897 }
898 }
899
900 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
901}
902
903
904void PreviewPlayer::onVideoEvent() {
905 uint32_t i=0;
906 bool bAppliedVideoEffect = false;
907 M4OSA_ERR err1 = M4NO_ERROR;
908 int64_t imageFrameTimeUs = 0;
909
910 Mutex::Autolock autoLock(mLock);
911 if (!mVideoEventPending) {
912 // The event has been cancelled in reset_l() but had already
913 // been scheduled for execution at that time.
914 return;
915 }
916 mVideoEventPending = false;
917
Andreas Huber9e4c36a2011-02-08 13:12:32 -0800918 if (mFlags & SEEK_PREVIEW) {
919 mFlags &= ~SEEK_PREVIEW;
920 return;
921 }
922
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800923 TimeSource *ts_st = &mSystemTimeSource;
924 int64_t timeStartUs = ts_st->getRealTimeUs();
925
Andreas Hubera5872f72011-02-24 15:25:21 -0800926 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800927 if (mLastVideoBuffer) {
928 mLastVideoBuffer->release();
929 mLastVideoBuffer = NULL;
930 }
931
932
933 if(mAudioSource != NULL) {
934
935 // We're going to seek the video source first, followed by
936 // the audio source.
937 // In order to avoid jumps in the DataSource offset caused by
938 // the audio codec prefetching data from the old locations
939 // while the video codec is already reading data from the new
940 // locations, we'll "pause" the audio source, causing it to
941 // stop reading input data until a subsequent seek.
942
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800943 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800944 mAudioPlayer->pause();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800945 mFlags &= ~AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800946 }
947 mAudioSource->pause();
948 }
949 }
950
951 if (!mVideoBuffer) {
952 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -0800953 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800954 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
955 mSeekTimeUs / 1E6);
956
957 options.setSeekTo(
958 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
959 }
960 for (;;) {
961 status_t err = mVideoSource->read(&mVideoBuffer, &options);
962 options.clearSeekTo();
963
964 if (err != OK) {
965 CHECK_EQ(mVideoBuffer, NULL);
966
967 if (err == INFO_FORMAT_CHANGED) {
968 LOGV("LV PLAYER VideoSource signalled format change");
969 notifyVideoSize_l();
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800970 sp<MetaData> meta = mVideoSource->getFormat();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800971
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800972 CHECK(meta->findInt32(kKeyWidth, &mReportedWidth));
973 CHECK(meta->findInt32(kKeyHeight, &mReportedHeight));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800974 if (mVideoRenderer != NULL) {
975 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -0800976 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800977 if (err != OK) {
978 postStreamDoneEvent_l(err);
979 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800980
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800981 }
982 continue;
983 }
984 // So video playback is complete, but we may still have
Santosh Madhava342f9322011-01-27 16:27:12 -0800985 // a seek request pending that needs to be applied to the audio track
Andreas Hubera5872f72011-02-24 15:25:21 -0800986 if (mSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800987 LOGV("video stream ended while seeking!");
988 }
989 finishSeekIfNecessary(-1);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800990 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
991 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800992 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800993 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800994 postStreamDoneEvent_l(err);
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800995 // Set the last decoded timestamp to duration
996 mDecodedVideoTs = (mPlayEndTimeMsec*1000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800997 return;
998 }
999
1000 if (mVideoBuffer->range_length() == 0) {
1001 // Some decoders, notably the PV AVC software decoder
1002 // return spurious empty buffers that we just want to ignore.
1003
1004 mVideoBuffer->release();
1005 mVideoBuffer = NULL;
1006 continue;
1007 }
1008
1009 int64_t videoTimeUs;
1010 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
1011
Andreas Hubera5872f72011-02-24 15:25:21 -08001012 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001013 if (videoTimeUs < mSeekTimeUs) {
1014 // buffers are before seek time
1015 // ignore them
1016 mVideoBuffer->release();
1017 mVideoBuffer = NULL;
1018 continue;
1019 }
1020 } else {
1021 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
1022 // Frames are before begin cut time
1023 // Donot render
1024 mVideoBuffer->release();
1025 mVideoBuffer = NULL;
1026 continue;
1027 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001028 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001029 break;
1030 }
1031 }
1032
1033 mNumberDecVideoFrames++;
1034
1035 int64_t timeUs;
1036 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1037
1038 {
1039 Mutex::Autolock autoLock(mMiscStateLock);
1040 mVideoTimeUs = timeUs;
1041 }
1042
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001043
1044 if(!mStartNextPlayer) {
1045 int64_t playbackTimeRemaining = (mPlayEndTimeMsec*1000) - timeUs;
1046 if(playbackTimeRemaining <= 1500000) {
1047 //When less than 1.5 sec of playback left
1048 // send notification to start next player
1049
1050 mStartNextPlayer = true;
1051 notifyListener_l(0xAAAAAAAA);
1052 }
1053 }
1054
Andreas Hubera5872f72011-02-24 15:25:21 -08001055 SeekType wasSeeking = mSeeking;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001056 finishSeekIfNecessary(timeUs);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -08001057 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING))) {
1058 status_t err = startAudioPlayer_l();
1059 if (err != OK) {
1060 LOGE("Starting the audio player failed w/ err %d", err);
1061 return;
1062 }
1063 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001064
1065 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
1066
1067 if(ts == NULL) {
1068 mVideoBuffer->release();
1069 mVideoBuffer = NULL;
1070 return;
1071 }
1072
1073 if(!mIsVideoSourceJpg) {
1074 if (mFlags & FIRST_FRAME) {
1075 mFlags &= ~FIRST_FRAME;
1076
1077 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
1078 }
1079
1080 int64_t realTimeUs, mediaTimeUs;
1081 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
1082 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1083 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1084 }
1085
1086 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1087
1088 int64_t latenessUs = nowUs - timeUs;
1089
Andreas Hubera5872f72011-02-24 15:25:21 -08001090 if (wasSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -08001091 // Let's display the first frame after seeking right away.
1092 latenessUs = 0;
1093 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001094 LOGV("Audio time stamp = %lld and video time stamp = %lld",
1095 ts->getRealTimeUs(),timeUs);
1096 if (latenessUs > 40000) {
1097 // We're more than 40ms late.
1098
1099 LOGV("LV PLAYER we're late by %lld us (%.2f secs)",
1100 latenessUs, latenessUs / 1E6);
1101
1102 mVideoBuffer->release();
1103 mVideoBuffer = NULL;
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001104 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001105 return;
1106 }
1107
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001108 if (latenessUs < -25000) {
1109 // We're more than 25ms early.
1110 LOGV("We're more than 25ms early, lateness %lld", latenessUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001111
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001112 postVideoEvent_l(25000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001113 return;
1114 }
1115 }
1116
1117 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
1118 mVideoRendererIsPreview = false;
1119
Santosh Madhavabfece172011-02-03 16:59:47 -08001120 status_t err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001121 if (err != OK) {
1122 postStreamDoneEvent_l(err);
1123 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001124 }
1125
1126 // If timestamp exceeds endCutTime of clip, donot render
1127 if((timeUs/1000) > mPlayEndTimeMsec) {
1128 if (mLastVideoBuffer) {
1129 mLastVideoBuffer->release();
1130 mLastVideoBuffer = NULL;
1131 }
1132 mLastVideoBuffer = mVideoBuffer;
1133 mVideoBuffer = NULL;
1134 mFlags |= VIDEO_AT_EOS;
1135 mFlags |= AUDIO_AT_EOS;
Santosh Madhavabfece172011-02-03 16:59:47 -08001136 LOGV("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS..");
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001137 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001138 // Set the last decoded timestamp to duration
1139 mDecodedVideoTs = (mPlayEndTimeMsec*1000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001140 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1141 return;
1142 }
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001143 // Capture the frame timestamp to be rendered
1144 mDecodedVideoTs = timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001145
1146 // Post processing to apply video effects
1147 for(i=0;i<mNumberEffects;i++) {
1148 // First check if effect starttime matches the clip being previewed
1149 if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) ||
1150 (mEffectsSettings[i].uiStartTime >=
1151 ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec)))
1152 {
1153 // This effect doesn't belong to this clip, check next one
1154 continue;
1155 }
1156 // Check if effect applies to this particular frame timestamp
1157 if((mEffectsSettings[i].uiStartTime <=
1158 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) &&
1159 ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=
1160 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec))
1161 && (mEffectsSettings[i].uiDuration != 0)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001162 setVideoPostProcessingNode(
1163 mEffectsSettings[i].VideoEffectType, TRUE);
1164 }
1165 else {
1166 setVideoPostProcessingNode(
1167 mEffectsSettings[i].VideoEffectType, FALSE);
1168 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001169 }
1170
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001171 //Provide the overlay Update indication when there is an overlay effect
Dharmaray Kundargid01ef562011-01-26 21:11:00 -08001172 if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) {
1173 mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here.
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001174 if (!mOverlayUpdateEventPosted) {
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001175 // Find the effect in effectSettings array
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001176 M4OSA_UInt32 index;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001177 for (index = 0; index < mNumberEffects; index++) {
1178 M4OSA_UInt32 timeMs = mDecodedVideoTs/1000;
1179 M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000;
1180 if(mEffectsSettings[index].VideoEffectType ==
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001181 (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001182 if (((mEffectsSettings[index].uiStartTime + 1) <=
1183 timeMs + timeOffset - mPlayBeginTimeMsec) &&
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001184 ((mEffectsSettings[index].uiStartTime - 1 +
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001185 mEffectsSettings[index].uiDuration) >=
1186 timeMs + timeOffset - mPlayBeginTimeMsec))
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001187 {
1188 break;
1189 }
1190 }
1191 }
1192 if (index < mNumberEffects) {
1193 mCurrFramingEffectIndex = index;
1194 mOverlayUpdateEventPosted = true;
1195 postOverlayUpdateEvent_l();
1196 LOGV("Framing index = %d", mCurrFramingEffectIndex);
1197 } else {
1198 LOGV("No framing effects found");
1199 }
1200 }
1201
1202 } else if (mOverlayUpdateEventPosted) {
1203 //Post the event when the overlay is no more valid
1204 LOGV("Overlay is Done");
1205 mOverlayUpdateEventPosted = false;
1206 postOverlayUpdateEvent_l();
1207 }
1208
1209
1210 if (mCurrentVideoEffect != VIDEO_EFFECT_NONE) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001211 err1 = doVideoPostProcessing();
1212 if(err1 != M4NO_ERROR) {
1213 LOGE("doVideoPostProcessing returned err");
1214 bAppliedVideoEffect = false;
1215 }
1216 else {
1217 bAppliedVideoEffect = true;
1218 }
1219 }
1220 else {
1221 bAppliedVideoEffect = false;
1222 if(mRenderingMode != MEDIA_RENDERING_INVALID) {
1223 // No effects to be applied, but media rendering to be done
1224 err1 = doMediaRendering();
1225 if(err1 != M4NO_ERROR) {
1226 LOGE("doMediaRendering returned err");
1227 //Use original mVideoBuffer for rendering
1228 mVideoResizedOrCropped = false;
1229 }
1230 }
1231 }
1232
1233 if (mVideoRenderer != NULL) {
1234 LOGV("mVideoRenderer CALL render()");
1235 mVideoRenderer->render();
1236 }
1237
1238 if (mLastVideoBuffer) {
1239 mLastVideoBuffer->release();
1240 mLastVideoBuffer = NULL;
1241 }
1242
1243 mLastVideoBuffer = mVideoBuffer;
1244 mVideoBuffer = NULL;
1245
1246 // Post progress callback based on callback interval set
1247 if(mNumberDecVideoFrames >= mProgressCbInterval) {
1248 postProgressCallbackEvent_l();
1249 mNumberDecVideoFrames = 0; // reset counter
1250 }
1251
1252 // if reached EndCutTime of clip, post EOS event
1253 if((timeUs/1000) >= mPlayEndTimeMsec) {
1254 LOGV("PreviewPlayer: onVideoEvent EOS.");
1255 mFlags |= VIDEO_AT_EOS;
1256 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001257 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001258 // Set the last decoded timestamp to duration
1259 mDecodedVideoTs = (mPlayEndTimeMsec*1000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001260 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1261 }
1262 else {
Andreas Hubera5872f72011-02-24 15:25:21 -08001263 if ((wasSeeking != NO_SEEK) && (mFlags & SEEK_PREVIEW)) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001264 mFlags &= ~SEEK_PREVIEW;
1265 return;
1266 }
1267
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001268 if(!mIsVideoSourceJpg) {
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001269 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001270 }
1271 else {
1272 postVideoEvent_l(33000);
1273 }
1274 }
1275}
1276
1277status_t PreviewPlayer::prepare() {
1278 Mutex::Autolock autoLock(mLock);
1279 return prepare_l();
1280}
1281
1282status_t PreviewPlayer::prepare_l() {
1283 if (mFlags & PREPARED) {
1284 return OK;
1285 }
1286
1287 if (mFlags & PREPARING) {
1288 return UNKNOWN_ERROR;
1289 }
1290
1291 mIsAsyncPrepare = false;
1292 status_t err = prepareAsync_l();
1293
1294 if (err != OK) {
1295 return err;
1296 }
1297
1298 while (mFlags & PREPARING) {
1299 mPreparedCondition.wait(mLock);
1300 }
1301
1302 return mPrepareResult;
1303}
1304
1305status_t PreviewPlayer::prepareAsync_l() {
1306 if (mFlags & PREPARING) {
1307 return UNKNOWN_ERROR; // async prepare already pending
1308 }
1309
1310 if (!mQueueStarted) {
1311 mQueue.start();
1312 mQueueStarted = true;
1313 }
1314
1315 mFlags |= PREPARING;
1316 mAsyncPrepareEvent = new PreviewPlayerEvent(
1317 this, &PreviewPlayer::onPrepareAsyncEvent);
1318
1319 mQueue.postEvent(mAsyncPrepareEvent);
1320
1321 return OK;
1322}
1323
1324status_t PreviewPlayer::finishSetDataSource_l() {
1325 sp<DataSource> dataSource;
1326 sp<MediaExtractor> extractor;
1327
1328 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1329
1330 if (dataSource == NULL) {
1331 return UNKNOWN_ERROR;
1332 }
1333
1334 //If file type is .rgb, then no need to check for Extractor
1335 int uriLen = strlen(mUri);
1336 int startOffset = uriLen - 4;
1337 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) {
1338 extractor = NULL;
1339 }
1340 else {
1341 extractor = MediaExtractor::Create(dataSource,
1342 MEDIA_MIMETYPE_CONTAINER_MPEG4);
1343 }
1344
1345 if (extractor == NULL) {
1346 LOGV("PreviewPlayer::finishSetDataSource_l extractor == NULL");
1347 return setDataSource_l_jpg();
1348 }
1349
1350 return setDataSource_l(extractor);
1351}
1352
1353
1354// static
1355bool PreviewPlayer::ContinuePreparation(void *cookie) {
1356 PreviewPlayer *me = static_cast<PreviewPlayer *>(cookie);
1357
1358 return (me->mFlags & PREPARE_CANCELLED) == 0;
1359}
1360
1361void PreviewPlayer::onPrepareAsyncEvent() {
1362 Mutex::Autolock autoLock(mLock);
1363 LOGV("onPrepareAsyncEvent");
1364
1365 if (mFlags & PREPARE_CANCELLED) {
Santosh Madhavabfece172011-02-03 16:59:47 -08001366 LOGV("LV PLAYER prepare was cancelled before doing anything");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001367 abortPrepare(UNKNOWN_ERROR);
1368 return;
1369 }
1370
1371 if (mUri.size() > 0) {
1372 status_t err = finishSetDataSource_l();
1373
1374 if (err != OK) {
1375 abortPrepare(err);
1376 return;
1377 }
1378 }
1379
1380 if (mVideoTrack != NULL && mVideoSource == NULL) {
1381 status_t err = initVideoDecoder(OMXCodec::kHardwareCodecsOnly);
1382
1383 if (err != OK) {
1384 abortPrepare(err);
1385 return;
1386 }
1387 }
1388
1389 if (mAudioTrack != NULL && mAudioSource == NULL) {
1390 status_t err = initAudioDecoder();
1391
1392 if (err != OK) {
1393 abortPrepare(err);
1394 return;
1395 }
1396 }
1397 finishAsyncPrepare_l();
1398
1399}
1400
1401void PreviewPlayer::finishAsyncPrepare_l() {
1402 if (mIsAsyncPrepare) {
1403 if (mVideoSource == NULL) {
1404 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE 0 0 ");
1405 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1406 } else {
1407 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE");
1408 notifyVideoSize_l();
1409 }
1410 LOGV("finishAsyncPrepare_l: MEDIA_PREPARED");
1411 notifyListener_l(MEDIA_PREPARED);
1412 }
1413
1414 mPrepareResult = OK;
1415 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1416 mFlags |= PREPARED;
1417 mAsyncPrepareEvent = NULL;
1418 mPreparedCondition.broadcast();
1419}
1420
1421status_t PreviewPlayer::suspend() {
1422 LOGV("suspend");
1423 Mutex::Autolock autoLock(mLock);
1424
1425 if (mSuspensionState != NULL) {
1426 if (mLastVideoBuffer == NULL) {
1427 //go into here if video is suspended again
1428 //after resuming without being played between
1429 //them
1430 SuspensionState *state = mSuspensionState;
1431 mSuspensionState = NULL;
1432 reset_l();
1433 mSuspensionState = state;
1434 return OK;
1435 }
1436
1437 delete mSuspensionState;
1438 mSuspensionState = NULL;
1439 }
1440
1441 if (mFlags & PREPARING) {
1442 mFlags |= PREPARE_CANCELLED;
1443 }
1444
1445 while (mFlags & PREPARING) {
1446 mPreparedCondition.wait(mLock);
1447 }
1448
1449 SuspensionState *state = new SuspensionState;
1450 state->mUri = mUri;
1451 state->mUriHeaders = mUriHeaders;
1452 state->mFileSource = mFileSource;
1453
1454 state->mFlags = mFlags & (PLAYING | AUTO_LOOPING | LOOPING | AT_EOS);
1455 getPosition(&state->mPositionUs);
1456
1457 if (mLastVideoBuffer) {
1458 size_t size = mLastVideoBuffer->range_length();
1459 if (size) {
1460 int32_t unreadable;
1461 if (!mLastVideoBuffer->meta_data()->findInt32(
1462 kKeyIsUnreadable, &unreadable)
1463 || unreadable == 0) {
1464 state->mLastVideoFrameSize = size;
1465 state->mLastVideoFrame = malloc(size);
1466 memcpy(state->mLastVideoFrame,
1467 (const uint8_t *)mLastVideoBuffer->data()
1468 + mLastVideoBuffer->range_offset(),
1469 size);
1470
1471 state->mVideoWidth = mVideoWidth;
1472 state->mVideoHeight = mVideoHeight;
1473
1474 sp<MetaData> meta = mVideoSource->getFormat();
1475 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1476 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1477 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1478 } else {
1479 LOGV("Unable to save last video frame, we have no access to "
1480 "the decoded video data.");
1481 }
1482 }
1483 }
1484
1485 reset_l();
1486
1487 mSuspensionState = state;
1488
1489 return OK;
1490}
1491
1492status_t PreviewPlayer::resume() {
1493 LOGV("resume");
1494 Mutex::Autolock autoLock(mLock);
1495
1496 if (mSuspensionState == NULL) {
1497 return INVALID_OPERATION;
1498 }
1499
1500 SuspensionState *state = mSuspensionState;
1501 mSuspensionState = NULL;
1502
1503 status_t err;
1504 if (state->mFileSource != NULL) {
1505 err = AwesomePlayer::setDataSource_l(state->mFileSource);
1506
1507 if (err == OK) {
1508 mFileSource = state->mFileSource;
1509 }
1510 } else {
1511 err = AwesomePlayer::setDataSource_l(state->mUri, &state->mUriHeaders);
1512 }
1513
1514 if (err != OK) {
1515 delete state;
1516 state = NULL;
1517
1518 return err;
1519 }
1520
1521 seekTo_l(state->mPositionUs);
1522
1523 mFlags = state->mFlags & (AUTO_LOOPING | LOOPING | AT_EOS);
1524
1525 if (state->mLastVideoFrame && (mSurface != NULL || mISurface != NULL)) {
1526 mVideoRenderer =
Santosh Madhavabfece172011-02-03 16:59:47 -08001527 PreviewLocalRenderer::initPreviewLocalRenderer(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001528 true, // previewOnly
1529 (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1530 mSurface,
1531 state->mVideoWidth,
1532 state->mVideoHeight,
1533 state->mDecodedWidth,
1534 state->mDecodedHeight);
1535
1536 mVideoRendererIsPreview = true;
1537
1538 ((PreviewLocalRenderer *)mVideoRenderer.get())->render(
1539 state->mLastVideoFrame, state->mLastVideoFrameSize);
1540 }
1541
1542 if (state->mFlags & PLAYING) {
1543 play_l();
1544 }
1545
1546 mSuspensionState = state;
1547 state = NULL;
1548
1549 return OK;
1550}
1551
1552
1553status_t PreviewPlayer::loadEffectsSettings(
1554 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) {
1555 M4OSA_UInt32 i = 0, rgbSize = 0;
1556 M4VIFI_UInt8 *tmp = M4OSA_NULL;
1557
1558 mNumberEffects = nEffects;
1559 mEffectsSettings = pEffectSettings;
1560 return OK;
1561}
1562
1563status_t PreviewPlayer::loadAudioMixSettings(
1564 M4xVSS_AudioMixingSettings* pAudioMixSettings) {
1565
1566 LOGV("PreviewPlayer: loadAudioMixSettings: ");
1567 mPreviewPlayerAudioMixSettings = pAudioMixSettings;
1568 return OK;
1569}
1570
1571status_t PreviewPlayer::setAudioMixPCMFileHandle(
1572 M4OSA_Context pAudioMixPCMFileHandle) {
1573
1574 LOGV("PreviewPlayer: setAudioMixPCMFileHandle: ");
1575 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle;
1576 return OK;
1577}
1578
1579status_t PreviewPlayer::setAudioMixStoryBoardParam(
1580 M4OSA_UInt32 audioMixStoryBoardTS,
1581 M4OSA_UInt32 currentMediaBeginCutTime,
1582 M4OSA_UInt32 primaryTrackVolValue ) {
1583
1584 mAudioMixStoryBoardTS = audioMixStoryBoardTS;
1585 mCurrentMediaBeginCutTime = currentMediaBeginCutTime;
1586 mCurrentMediaVolumeValue = primaryTrackVolValue;
1587 return OK;
1588}
1589
1590status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) {
1591
1592 mPlayBeginTimeMsec = msec;
1593 return OK;
1594}
1595
1596status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) {
1597
1598 mPlayEndTimeMsec = msec;
1599 return OK;
1600}
1601
1602status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) {
1603
1604 mStoryboardStartTimeMsec = msec;
1605 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000;
1606 return OK;
1607}
1608
1609status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) {
1610
1611 mProgressCbInterval = cbInterval;
1612 return OK;
1613}
1614
1615
1616status_t PreviewPlayer::setMediaRenderingMode(
1617 M4xVSS_MediaRendering mode,
1618 M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
1619
1620 mRenderingMode = mode;
1621
1622 /* reset boolean for each clip*/
1623 mVideoResizedOrCropped = false;
1624
1625 switch(outputVideoSize) {
1626 case M4VIDEOEDITING_kSQCIF:
1627 mOutputVideoWidth = 128;
1628 mOutputVideoHeight = 96;
1629 break;
1630
1631 case M4VIDEOEDITING_kQQVGA:
1632 mOutputVideoWidth = 160;
1633 mOutputVideoHeight = 120;
1634 break;
1635
1636 case M4VIDEOEDITING_kQCIF:
1637 mOutputVideoWidth = 176;
1638 mOutputVideoHeight = 144;
1639 break;
1640
1641 case M4VIDEOEDITING_kQVGA:
1642 mOutputVideoWidth = 320;
1643 mOutputVideoHeight = 240;
1644 break;
1645
1646 case M4VIDEOEDITING_kCIF:
1647 mOutputVideoWidth = 352;
1648 mOutputVideoHeight = 288;
1649 break;
1650
1651 case M4VIDEOEDITING_kVGA:
1652 mOutputVideoWidth = 640;
1653 mOutputVideoHeight = 480;
1654 break;
1655
1656 case M4VIDEOEDITING_kWVGA:
1657 mOutputVideoWidth = 800;
1658 mOutputVideoHeight = 480;
1659 break;
1660
1661 case M4VIDEOEDITING_kNTSC:
1662 mOutputVideoWidth = 720;
1663 mOutputVideoHeight = 480;
1664 break;
1665
1666 case M4VIDEOEDITING_k640_360:
1667 mOutputVideoWidth = 640;
1668 mOutputVideoHeight = 360;
1669 break;
1670
1671 case M4VIDEOEDITING_k854_480:
1672 mOutputVideoWidth = 854;
1673 mOutputVideoHeight = 480;
1674 break;
1675
1676 case M4VIDEOEDITING_kHD1280:
1677 mOutputVideoWidth = 1280;
1678 mOutputVideoHeight = 720;
1679 break;
1680
1681 case M4VIDEOEDITING_kHD1080:
1682 mOutputVideoWidth = 1080;
1683 mOutputVideoHeight = 720;
1684 break;
1685
1686 case M4VIDEOEDITING_kHD960:
1687 mOutputVideoWidth = 960;
1688 mOutputVideoHeight = 720;
1689 break;
1690
1691 default:
1692 LOGE("unsupported output video size set");
1693 return BAD_VALUE;
1694 }
1695
1696 return OK;
1697}
1698
1699M4OSA_ERR PreviewPlayer::doMediaRendering() {
1700 M4OSA_ERR err = M4NO_ERROR;
1701 M4VIFI_ImagePlane planeIn[3], planeOut[3];
1702 M4VIFI_UInt8 *inBuffer = M4OSA_NULL, *finalOutputBuffer = M4OSA_NULL;
1703 M4VIFI_UInt8 *tempOutputBuffer= M4OSA_NULL;
1704 size_t videoBufferSize = 0;
1705 M4OSA_UInt32 frameSize = 0, i=0, index =0, nFrameCount =0, bufferOffset =0;
1706 int32_t colorFormat = 0;
1707
1708 if(!mIsVideoSourceJpg) {
1709 sp<MetaData> meta = mVideoSource->getFormat();
1710 CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
1711 }
1712 else {
1713 colorFormat = OMX_COLOR_FormatYUV420Planar;
1714 }
1715
1716 videoBufferSize = mVideoBuffer->size();
1717 frameSize = (mVideoWidth*mVideoHeight*3) >> 1;
1718
1719 uint8_t* outBuffer;
1720 size_t outBufferStride = 0;
1721
1722 mVideoRenderer->getBuffer(&outBuffer, &outBufferStride);
1723
1724 bufferOffset = index*frameSize;
1725 inBuffer = (M4OSA_UInt8 *)mVideoBuffer->data()+
1726 mVideoBuffer->range_offset()+bufferOffset;
1727
1728
1729 /* In plane*/
1730 prepareYUV420ImagePlane(planeIn, mVideoWidth,
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001731 mVideoHeight, (M4VIFI_UInt8 *)inBuffer, mReportedWidth, mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001732
1733 // Set the output YUV420 plane to be compatible with YV12 format
1734 // W & H even
1735 // YVU instead of YUV
1736 // align buffers on 32 bits
1737
1738 //In YV12 format, sizes must be even
1739 M4OSA_UInt32 yv12PlaneWidth = ((mOutputVideoWidth +1)>>1)<<1;
1740 M4OSA_UInt32 yv12PlaneHeight = ((mOutputVideoHeight+1)>>1)<<1;
1741
1742 prepareYV12ImagePlane(planeOut, yv12PlaneWidth, yv12PlaneHeight,
1743 (M4OSA_UInt32)outBufferStride, (M4VIFI_UInt8 *)outBuffer);
1744
1745
1746 err = applyRenderingMode(planeIn, planeOut, mRenderingMode);
1747
1748 if(err != M4NO_ERROR)
1749 {
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001750 LOGE("doMediaRendering: applyRenderingMode returned err=0x%x", (int)err);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001751 return err;
1752 }
1753 mVideoResizedOrCropped = true;
1754
1755 return err;
1756}
1757
1758status_t PreviewPlayer::resetJniCallbackTimeStamp() {
1759
1760 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000;
1761 return OK;
1762}
1763
1764void PreviewPlayer::postProgressCallbackEvent_l() {
1765 if (mProgressCbEventPending) {
1766 return;
1767 }
1768 mProgressCbEventPending = true;
1769
1770 mQueue.postEvent(mProgressCbEvent);
1771}
1772
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001773
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001774void PreviewPlayer::onProgressCbEvent() {
1775 Mutex::Autolock autoLock(mLock);
1776 if (!mProgressCbEventPending) {
1777 return;
1778 }
1779 mProgressCbEventPending = false;
1780 // If playback starts from previous I-frame,
1781 // then send frame storyboard duration
1782 if((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) {
1783 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000);
1784 }
1785 else {
1786 notifyListener_l(MEDIA_INFO, 0,
1787 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec));
1788 }
1789}
1790
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001791void PreviewPlayer::postOverlayUpdateEvent_l() {
1792 if (mOverlayUpdateEventPending) {
1793 return;
1794 }
1795 mOverlayUpdateEventPending = true;
1796 mQueue.postEvent(mOverlayUpdateEvent);
1797}
1798
1799void PreviewPlayer::onUpdateOverlayEvent() {
1800 Mutex::Autolock autoLock(mLock);
1801
1802 if (!mOverlayUpdateEventPending) {
1803 return;
1804 }
1805 mOverlayUpdateEventPending = false;
1806
1807 int updateState;
1808 if (mOverlayUpdateEventPosted) {
1809 updateState = 1;
1810 } else {
1811 updateState = 0;
1812 }
1813 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex);
1814}
1815
1816
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001817void PreviewPlayer::setVideoPostProcessingNode(
1818 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
1819
1820 uint32_t effect = VIDEO_EFFECT_NONE;
1821
1822 //Map M4VSS3GPP_VideoEffectType to local enum
1823 switch(type) {
1824 case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
1825 effect = VIDEO_EFFECT_FADEFROMBLACK;
1826 break;
1827
1828 case M4VSS3GPP_kVideoEffectType_FadeToBlack:
1829 effect = VIDEO_EFFECT_FADETOBLACK;
1830 break;
1831
1832 case M4VSS3GPP_kVideoEffectType_CurtainOpening:
1833 effect = VIDEO_EFFECT_CURTAINOPEN;
1834 break;
1835
1836 case M4VSS3GPP_kVideoEffectType_CurtainClosing:
1837 effect = VIDEO_EFFECT_CURTAINCLOSE;
1838 break;
1839
1840 case M4xVSS_kVideoEffectType_BlackAndWhite:
1841 effect = VIDEO_EFFECT_BLACKANDWHITE;
1842 break;
1843
1844 case M4xVSS_kVideoEffectType_Pink:
1845 effect = VIDEO_EFFECT_PINK;
1846 break;
1847
1848 case M4xVSS_kVideoEffectType_Green:
1849 effect = VIDEO_EFFECT_GREEN;
1850 break;
1851
1852 case M4xVSS_kVideoEffectType_Sepia:
1853 effect = VIDEO_EFFECT_SEPIA;
1854 break;
1855
1856 case M4xVSS_kVideoEffectType_Negative:
1857 effect = VIDEO_EFFECT_NEGATIVE;
1858 break;
1859
1860 case M4xVSS_kVideoEffectType_Framing:
1861 effect = VIDEO_EFFECT_FRAMING;
1862 break;
1863
1864 case M4xVSS_kVideoEffectType_Fifties:
1865 effect = VIDEO_EFFECT_FIFTIES;
1866 break;
1867
1868 case M4xVSS_kVideoEffectType_ColorRGB16:
1869 effect = VIDEO_EFFECT_COLOR_RGB16;
1870 break;
1871
1872 case M4xVSS_kVideoEffectType_Gradient:
1873 effect = VIDEO_EFFECT_GRADIENT;
1874 break;
1875
1876 default:
1877 effect = VIDEO_EFFECT_NONE;
1878 break;
1879 }
1880
1881 if(enable == M4OSA_TRUE) {
1882 //If already set, then no need to set again
1883 if(!(mCurrentVideoEffect & effect)) {
1884 mCurrentVideoEffect |= effect;
1885 if(effect == VIDEO_EFFECT_FIFTIES) {
1886 mIsFiftiesEffectStarted = true;
1887 }
1888 }
1889 }
1890 else {
1891 //Reset only if already set
1892 if(mCurrentVideoEffect & effect) {
1893 mCurrentVideoEffect &= ~effect;
1894 }
1895 }
1896}
1897
1898status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) {
1899 mVideoWidth = width;
1900 mVideoHeight = height;
1901 return OK;
1902}
1903
1904
1905M4OSA_ERR PreviewPlayer::doVideoPostProcessing() {
1906 M4OSA_ERR err = M4NO_ERROR;
1907 vePostProcessParams postProcessParams;
1908 int32_t colorFormat = 0;
1909
1910
1911 if(!mIsVideoSourceJpg) {
1912 sp<MetaData> meta = mVideoSource->getFormat();
1913 CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
1914 }
1915 else {
1916 colorFormat = OMX_COLOR_FormatYUV420Planar;
1917 }
1918
1919 if((colorFormat == OMX_COLOR_FormatYUV420SemiPlanar) ||
1920 (colorFormat == 0x7FA30C00)) {
1921 LOGE("doVideoPostProcessing: colorFormat YUV420Sp not supported");
1922 return M4ERR_UNSUPPORTED_MEDIA_TYPE;
1923 }
1924
1925 postProcessParams.vidBuffer = (M4VIFI_UInt8*)mVideoBuffer->data()
1926 + mVideoBuffer->range_offset();
1927
1928 postProcessParams.videoWidth = mVideoWidth;
1929 postProcessParams.videoHeight = mVideoHeight;
1930 postProcessParams.timeMs = mDecodedVideoTs/1000;
1931 postProcessParams.timeOffset = mDecVideoTsStoryBoard/1000;
1932 postProcessParams.effectsSettings = mEffectsSettings;
1933 postProcessParams.numberEffects = mNumberEffects;
1934 postProcessParams.outVideoWidth = mOutputVideoWidth;
1935 postProcessParams.outVideoHeight = mOutputVideoHeight;
1936 postProcessParams.currentVideoEffect = mCurrentVideoEffect;
1937 postProcessParams.renderingMode = mRenderingMode;
1938 if(mIsFiftiesEffectStarted == M4OSA_TRUE) {
1939 postProcessParams.isFiftiesEffectStarted = M4OSA_TRUE;
1940 mIsFiftiesEffectStarted = M4OSA_FALSE;
1941 }
1942 else {
1943 postProcessParams.isFiftiesEffectStarted = M4OSA_FALSE;
1944 }
1945
1946 postProcessParams.overlayFrameRGBBuffer = mFrameRGBBuffer;
1947 postProcessParams.overlayFrameYUVBuffer = mFrameYUVBuffer;
1948 mVideoRenderer->getBuffer(&(postProcessParams.pOutBuffer), &(postProcessParams.outBufferStride));
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001949 err = applyEffectsAndRenderingMode(&postProcessParams, mReportedWidth, mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001950
1951 return err;
1952}
1953
1954status_t PreviewPlayer::readFirstVideoFrame() {
1955 LOGV("PreviewPlayer::readFirstVideoFrame");
1956
1957 if (!mVideoBuffer) {
1958 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -08001959 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001960 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
1961 mSeekTimeUs / 1E6);
1962
1963 options.setSeekTo(
1964 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
1965 }
1966 for (;;) {
1967 status_t err = mVideoSource->read(&mVideoBuffer, &options);
1968 options.clearSeekTo();
1969
1970 if (err != OK) {
1971 CHECK_EQ(mVideoBuffer, NULL);
1972
1973 if (err == INFO_FORMAT_CHANGED) {
1974 LOGV("LV PLAYER VideoSource signalled format change");
1975 notifyVideoSize_l();
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001976 sp<MetaData> meta = mVideoSource->getFormat();
1977
1978 CHECK(meta->findInt32(kKeyWidth, &mReportedWidth));
1979 CHECK(meta->findInt32(kKeyHeight, &mReportedHeight));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001980
1981 if (mVideoRenderer != NULL) {
1982 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -08001983 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001984 if (err != OK) {
1985 postStreamDoneEvent_l(err);
1986 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001987 }
1988 continue;
1989 }
1990 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
1991 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001992 mFlags |= AUDIO_AT_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001993 postStreamDoneEvent_l(err);
1994 return OK;
1995 }
1996
1997 if (mVideoBuffer->range_length() == 0) {
1998 // Some decoders, notably the PV AVC software decoder
1999 // return spurious empty buffers that we just want to ignore.
2000
2001 mVideoBuffer->release();
2002 mVideoBuffer = NULL;
2003 continue;
2004 }
2005
2006 int64_t videoTimeUs;
2007 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
Andreas Hubera5872f72011-02-24 15:25:21 -08002008 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08002009 if (videoTimeUs < mSeekTimeUs) {
2010 // buffers are before seek time
2011 // ignore them
2012 mVideoBuffer->release();
2013 mVideoBuffer = NULL;
2014 continue;
2015 }
2016 } else {
2017 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
2018 // buffers are before begin cut time
2019 // ignore them
2020 mVideoBuffer->release();
2021 mVideoBuffer = NULL;
2022 continue;
2023 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002024 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002025 break;
2026 }
2027 }
2028
2029 int64_t timeUs;
2030 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
2031
2032 {
2033 Mutex::Autolock autoLock(mMiscStateLock);
2034 mVideoTimeUs = timeUs;
2035 }
2036
2037 mDecodedVideoTs = timeUs;
2038
2039 return OK;
2040
2041}
2042
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08002043status_t PreviewPlayer::getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs) {
2044 *lastRenderedTimeMs = (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec);
2045 return OK;
2046}
2047
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002048} // namespace android