blob: e655daaed8037c854ffc6a7c4d6970e3145498aa [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
514 const char *pSrcType1;
515 const char *pSrcType2;
516 sp<MetaData> meta = anAudioSource->getFormat();
517
518 if (meta->findCString(kKeyDecoderComponent, &pSrcType1)) {
519 if (strcmp(pSrcType1, "DummyAudioSource") == 0) {
520 meta = mAudioSource->getFormat();
521 if (meta->findCString(kKeyDecoderComponent, &pSrcType2)) {
522 if (strcmp(pSrcType2, "DummyAudioSource") == 0) {
523 mIsChangeSourceRequired = false;
524 // Just set the new play duration for the existing source
525 MediaSource *pMediaSrc = anAudioSource.get();
526 DummyAudioSource *pDummyAudioSource = (DummyAudioSource*)pMediaSrc;
527 //Increment the duration of audio source
528 pDummyAudioSource->setDuration((int64_t)((mPlayEndTimeMsec)*1000));
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800529
530 // Stop the new audio source
531 // since we continue using old source
532 LOGV("setAudioPlayer: stop new audio source");
533 mAudioSource->stop();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800534 }
535 }
536 }
537 }
538
539 return OK;
540}
541
542void PreviewPlayer::onStreamDone() {
543 // Posted whenever any stream finishes playing.
544
545 Mutex::Autolock autoLock(mLock);
546 if (!mStreamDoneEventPending) {
547 return;
548 }
549 mStreamDoneEventPending = false;
550
551 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
552 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
553
554 notifyListener_l(
555 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
556
557 pause_l(true /* at eos */);
558
559 mFlags |= AT_EOS;
560 return;
561 }
562
563 const bool allDone =
564 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
565 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
566
567 if (!allDone) {
568 return;
569 }
570
571 if (mFlags & (LOOPING | AUTO_LOOPING)) {
572 seekTo_l(0);
573
574 if (mVideoSource != NULL) {
575 postVideoEvent_l();
576 }
577 } else {
578 LOGV("MEDIA_PLAYBACK_COMPLETE");
579 //pause before sending event
580 pause_l(true /* at eos */);
581 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
582
583 mFlags |= AT_EOS;
584 }
585}
586
587
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800588status_t PreviewPlayer::play_l() {
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800589
Rajneesh Chowdury8b95de22011-02-16 15:32:06 -0800590 mFlags &= ~SEEK_PREVIEW;
591
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800592 if (mFlags & PLAYING) {
593 return OK;
594 }
595 mStartNextPlayer = false;
596
597 if (!(mFlags & PREPARED)) {
598 status_t err = prepare_l();
599
600 if (err != OK) {
601 return err;
602 }
603 }
604
605 mFlags |= PLAYING;
606 mFlags |= FIRST_FRAME;
607
608 bool deferredAudioSeek = false;
609
610 if (mAudioSource != NULL) {
611 if (mAudioPlayer == NULL) {
612 if (mAudioSink != NULL) {
613
614 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800615 mVeAudioPlayer =
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800616 (VideoEditorAudioPlayer*)mAudioPlayer;
617
618 mAudioPlayer->setSource(mAudioSource);
619
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800620 mVeAudioPlayer->setAudioMixSettings(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800621 mPreviewPlayerAudioMixSettings);
622
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800623 mVeAudioPlayer->setAudioMixPCMFileHandle(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800624 mAudioMixPCMFileHandle);
625
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800626 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800627 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
628 mCurrentMediaVolumeValue);
629
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800630 mFlags |= AUDIOPLAYER_STARTED;
631 // We've already started the MediaSource in order to enable
632 // the prefetcher to read its data.
633 status_t err = mVeAudioPlayer->start(
634 true /* sourceAlreadyStarted */);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800635
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800636 if (err != OK) {
637 //delete mAudioPlayer;
638 mAudioPlayer = NULL;
639
640 mFlags &= ~(PLAYING | FIRST_FRAME);
641 return err;
642 }
643
644 mTimeSource = mVeAudioPlayer;
645 mFlags |= AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800646 deferredAudioSeek = true;
647 mWatchForAudioSeekComplete = false;
648 mWatchForAudioEOS = true;
649 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800650 } else {
651 mVeAudioPlayer = (VideoEditorAudioPlayer*)mAudioPlayer;
652 bool isAudioPlayerStarted = mVeAudioPlayer->isStarted();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800653
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800654 if (mIsChangeSourceRequired == true) {
655 LOGV("play_l: Change audio source required");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800656
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800657 if (isAudioPlayerStarted == true) {
658 mVeAudioPlayer->pause();
659 }
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800660
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800661 mVeAudioPlayer->setSource(mAudioSource);
662 mVeAudioPlayer->setObserver(this);
663
664 mVeAudioPlayer->setAudioMixSettings(
665 mPreviewPlayerAudioMixSettings);
666
667 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
668 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
669 mCurrentMediaVolumeValue);
670
671 if (isAudioPlayerStarted == true) {
672 mVeAudioPlayer->resume();
673 } else {
674 status_t err = OK;
675 err = mVeAudioPlayer->start(true);
676 if (err != OK) {
677 mAudioPlayer = NULL;
678 mVeAudioPlayer = NULL;
679
680 mFlags &= ~(PLAYING | FIRST_FRAME);
681 return err;
682 }
683 }
684 } else {
685 LOGV("play_l: No Source change required");
686 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
687 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
688 mCurrentMediaVolumeValue);
689
690 mVeAudioPlayer->resume();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800691 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800692
693 mFlags |= AUDIOPLAYER_STARTED;
694 mFlags |= AUDIO_RUNNING;
695 mTimeSource = mVeAudioPlayer;
696 deferredAudioSeek = true;
697 mWatchForAudioSeekComplete = false;
698 mWatchForAudioEOS = true;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800699 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800700 }
701
702 if (mTimeSource == NULL && mAudioPlayer == NULL) {
703 mTimeSource = &mSystemTimeSource;
704 }
705
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800706 // Set the seek option for Image source files and read.
707 // This resets the timestamping for image play
708 if (mIsVideoSourceJpg) {
709 MediaSource::ReadOptions options;
710 MediaBuffer *aLocalBuffer;
711 options.setSeekTo(mSeekTimeUs);
712 mVideoSource->read(&aLocalBuffer, &options);
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800713 aLocalBuffer->release();
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800714 }
715
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800716 if (mVideoSource != NULL) {
717 // Kick off video playback
718 postVideoEvent_l();
719 }
720
721 if (deferredAudioSeek) {
722 // If there was a seek request while we were paused
723 // and we're just starting up again, honor the request now.
724 seekAudioIfNecessary_l();
725 }
726
727 if (mFlags & AT_EOS) {
728 // Legacy behaviour, if a stream finishes playing and then
729 // is started again, we play from the start...
730 seekTo_l(0);
731 }
732
733 return OK;
734}
735
736
Santosh Madhavabfece172011-02-03 16:59:47 -0800737status_t PreviewPlayer::initRenderer_l() {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800738 if (mSurface != NULL || mISurface != NULL) {
739 sp<MetaData> meta = mVideoSource->getFormat();
740
741 int32_t format;
742 const char *component;
743 int32_t decodedWidth, decodedHeight;
744 CHECK(meta->findInt32(kKeyColorFormat, &format));
745 CHECK(meta->findCString(kKeyDecoderComponent, &component));
746 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
747 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
748
749 // Must ensure that mVideoRenderer's destructor is actually executed
750 // before creating a new one.
751 IPCThreadState::self()->flushCommands();
752
753 // always use localrenderer since decoded buffers are modified
754 // by postprocessing module
755 // Other decoders are instantiated locally and as a consequence
756 // allocate their buffers in local address space.
757 if(mVideoRenderer == NULL) {
758
Santosh Madhavabfece172011-02-03 16:59:47 -0800759 mVideoRenderer = PreviewLocalRenderer:: initPreviewLocalRenderer (
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800760 false, // previewOnly
761 (OMX_COLOR_FORMATTYPE)format,
762 mSurface,
763 mOutputVideoWidth, mOutputVideoHeight,
764 mOutputVideoWidth, mOutputVideoHeight);
Santosh Madhavabfece172011-02-03 16:59:47 -0800765
766 if ( mVideoRenderer == NULL )
767 {
768 return UNKNOWN_ERROR;
769 }
770 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800771 }
772 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800773 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800774}
775
776
777void PreviewPlayer::setISurface(const sp<ISurface> &isurface) {
778 Mutex::Autolock autoLock(mLock);
779 mISurface = isurface;
780}
781
782
783status_t PreviewPlayer::seekTo(int64_t timeUs) {
784
785 if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) {
786 Mutex::Autolock autoLock(mLock);
787 return seekTo_l(timeUs);
788 }
789
790 return OK;
791}
792
793
794status_t PreviewPlayer::getVideoDimensions(
795 int32_t *width, int32_t *height) const {
796 Mutex::Autolock autoLock(mLock);
797
798 if (mVideoWidth < 0 || mVideoHeight < 0) {
799 return UNKNOWN_ERROR;
800 }
801
802 *width = mVideoWidth;
803 *height = mVideoHeight;
804
805 return OK;
806}
807
808
809status_t PreviewPlayer::initAudioDecoder() {
810 sp<MetaData> meta = mAudioTrack->getFormat();
811 const char *mime;
812 CHECK(meta->findCString(kKeyMIMEType, &mime));
813
814 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
815 mAudioSource = mAudioTrack;
816 } else {
817 sp<MediaSource> aRawSource;
818 aRawSource = OMXCodec::Create(
819 mClient.interface(), mAudioTrack->getFormat(),
820 false, // createEncoder
821 mAudioTrack);
822
823 if(aRawSource != NULL) {
824 LOGV("initAudioDecoder: new VideoEditorSRC");
825 mAudioSource = new VideoEditorSRC(aRawSource);
826 }
827 }
828
829 if (mAudioSource != NULL) {
830 int64_t durationUs;
831 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
832 Mutex::Autolock autoLock(mMiscStateLock);
833 if (mDurationUs < 0 || durationUs > mDurationUs) {
834 mDurationUs = durationUs;
835 }
836 }
837 status_t err = mAudioSource->start();
838
839 if (err != OK) {
840 mAudioSource.clear();
841 return err;
842 }
843 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
844 // For legacy reasons we're simply going to ignore the absence
845 // of an audio decoder for QCELP instead of aborting playback
846 // altogether.
847 return OK;
848 }
849
850 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
851}
852
853
854status_t PreviewPlayer::initVideoDecoder(uint32_t flags) {
855
856 mVideoSource = OMXCodec::Create(
857 mClient.interface(), mVideoTrack->getFormat(),
858 false,
859 mVideoTrack,
860 NULL, flags);
861
862 if (mVideoSource != NULL) {
863 int64_t durationUs;
864 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
865 Mutex::Autolock autoLock(mMiscStateLock);
866 if (mDurationUs < 0 || durationUs > mDurationUs) {
867 mDurationUs = durationUs;
868 }
869 }
870
871 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
872 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
873
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800874 mReportedWidth = mVideoWidth;
875 mReportedHeight = mVideoHeight;
876
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800877 status_t err = mVideoSource->start();
878
879 if (err != OK) {
880 mVideoSource.clear();
881 return err;
882 }
883 }
884
885 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
886}
887
888
889void PreviewPlayer::onVideoEvent() {
890 uint32_t i=0;
891 bool bAppliedVideoEffect = false;
892 M4OSA_ERR err1 = M4NO_ERROR;
893 int64_t imageFrameTimeUs = 0;
894
895 Mutex::Autolock autoLock(mLock);
896 if (!mVideoEventPending) {
897 // The event has been cancelled in reset_l() but had already
898 // been scheduled for execution at that time.
899 return;
900 }
901 mVideoEventPending = false;
902
Andreas Huber9e4c36a2011-02-08 13:12:32 -0800903 if (mFlags & SEEK_PREVIEW) {
904 mFlags &= ~SEEK_PREVIEW;
905 return;
906 }
907
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800908 TimeSource *ts_st = &mSystemTimeSource;
909 int64_t timeStartUs = ts_st->getRealTimeUs();
910
Andreas Hubera5872f72011-02-24 15:25:21 -0800911 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800912 if (mLastVideoBuffer) {
913 mLastVideoBuffer->release();
914 mLastVideoBuffer = NULL;
915 }
916
917
918 if(mAudioSource != NULL) {
919
920 // We're going to seek the video source first, followed by
921 // the audio source.
922 // In order to avoid jumps in the DataSource offset caused by
923 // the audio codec prefetching data from the old locations
924 // while the video codec is already reading data from the new
925 // locations, we'll "pause" the audio source, causing it to
926 // stop reading input data until a subsequent seek.
927
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800928 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800929 mAudioPlayer->pause();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800930 mFlags &= ~AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800931 }
932 mAudioSource->pause();
933 }
934 }
935
936 if (!mVideoBuffer) {
937 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -0800938 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800939 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
940 mSeekTimeUs / 1E6);
941
942 options.setSeekTo(
943 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
944 }
945 for (;;) {
946 status_t err = mVideoSource->read(&mVideoBuffer, &options);
947 options.clearSeekTo();
948
949 if (err != OK) {
950 CHECK_EQ(mVideoBuffer, NULL);
951
952 if (err == INFO_FORMAT_CHANGED) {
953 LOGV("LV PLAYER VideoSource signalled format change");
954 notifyVideoSize_l();
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800955 sp<MetaData> meta = mVideoSource->getFormat();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800956
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800957 CHECK(meta->findInt32(kKeyWidth, &mReportedWidth));
958 CHECK(meta->findInt32(kKeyHeight, &mReportedHeight));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800959 if (mVideoRenderer != NULL) {
960 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -0800961 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800962 if (err != OK) {
963 postStreamDoneEvent_l(err);
964 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800965
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800966 }
967 continue;
968 }
969 // So video playback is complete, but we may still have
Santosh Madhava342f9322011-01-27 16:27:12 -0800970 // a seek request pending that needs to be applied to the audio track
Andreas Hubera5872f72011-02-24 15:25:21 -0800971 if (mSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800972 LOGV("video stream ended while seeking!");
973 }
974 finishSeekIfNecessary(-1);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800975 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
976 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800977 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800978 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800979 postStreamDoneEvent_l(err);
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800980 // Set the last decoded timestamp to duration
981 mDecodedVideoTs = (mPlayEndTimeMsec*1000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800982 return;
983 }
984
985 if (mVideoBuffer->range_length() == 0) {
986 // Some decoders, notably the PV AVC software decoder
987 // return spurious empty buffers that we just want to ignore.
988
989 mVideoBuffer->release();
990 mVideoBuffer = NULL;
991 continue;
992 }
993
994 int64_t videoTimeUs;
995 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
996
Andreas Hubera5872f72011-02-24 15:25:21 -0800997 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800998 if (videoTimeUs < mSeekTimeUs) {
999 // buffers are before seek time
1000 // ignore them
1001 mVideoBuffer->release();
1002 mVideoBuffer = NULL;
1003 continue;
1004 }
1005 } else {
1006 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
1007 // Frames are before begin cut time
1008 // Donot render
1009 mVideoBuffer->release();
1010 mVideoBuffer = NULL;
1011 continue;
1012 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001013 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001014 break;
1015 }
1016 }
1017
1018 mNumberDecVideoFrames++;
1019
1020 int64_t timeUs;
1021 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1022
1023 {
1024 Mutex::Autolock autoLock(mMiscStateLock);
1025 mVideoTimeUs = timeUs;
1026 }
1027
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001028
1029 if(!mStartNextPlayer) {
1030 int64_t playbackTimeRemaining = (mPlayEndTimeMsec*1000) - timeUs;
1031 if(playbackTimeRemaining <= 1500000) {
1032 //When less than 1.5 sec of playback left
1033 // send notification to start next player
1034
1035 mStartNextPlayer = true;
1036 notifyListener_l(0xAAAAAAAA);
1037 }
1038 }
1039
Andreas Hubera5872f72011-02-24 15:25:21 -08001040 SeekType wasSeeking = mSeeking;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001041 finishSeekIfNecessary(timeUs);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -08001042 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING))) {
1043 status_t err = startAudioPlayer_l();
1044 if (err != OK) {
1045 LOGE("Starting the audio player failed w/ err %d", err);
1046 return;
1047 }
1048 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001049
1050 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
1051
1052 if(ts == NULL) {
1053 mVideoBuffer->release();
1054 mVideoBuffer = NULL;
1055 return;
1056 }
1057
1058 if(!mIsVideoSourceJpg) {
1059 if (mFlags & FIRST_FRAME) {
1060 mFlags &= ~FIRST_FRAME;
1061
1062 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
1063 }
1064
1065 int64_t realTimeUs, mediaTimeUs;
1066 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
1067 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1068 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1069 }
1070
1071 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1072
1073 int64_t latenessUs = nowUs - timeUs;
1074
Andreas Hubera5872f72011-02-24 15:25:21 -08001075 if (wasSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -08001076 // Let's display the first frame after seeking right away.
1077 latenessUs = 0;
1078 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001079 LOGV("Audio time stamp = %lld and video time stamp = %lld",
1080 ts->getRealTimeUs(),timeUs);
1081 if (latenessUs > 40000) {
1082 // We're more than 40ms late.
1083
1084 LOGV("LV PLAYER we're late by %lld us (%.2f secs)",
1085 latenessUs, latenessUs / 1E6);
1086
1087 mVideoBuffer->release();
1088 mVideoBuffer = NULL;
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001089 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001090 return;
1091 }
1092
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001093 if (latenessUs < -25000) {
1094 // We're more than 25ms early.
1095 LOGV("We're more than 25ms early, lateness %lld", latenessUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001096
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001097 postVideoEvent_l(25000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001098 return;
1099 }
1100 }
1101
1102 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
1103 mVideoRendererIsPreview = false;
1104
Santosh Madhavabfece172011-02-03 16:59:47 -08001105 status_t err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001106 if (err != OK) {
1107 postStreamDoneEvent_l(err);
1108 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001109 }
1110
1111 // If timestamp exceeds endCutTime of clip, donot render
1112 if((timeUs/1000) > mPlayEndTimeMsec) {
1113 if (mLastVideoBuffer) {
1114 mLastVideoBuffer->release();
1115 mLastVideoBuffer = NULL;
1116 }
1117 mLastVideoBuffer = mVideoBuffer;
1118 mVideoBuffer = NULL;
1119 mFlags |= VIDEO_AT_EOS;
1120 mFlags |= AUDIO_AT_EOS;
Santosh Madhavabfece172011-02-03 16:59:47 -08001121 LOGV("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS..");
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001122 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001123 // Set the last decoded timestamp to duration
1124 mDecodedVideoTs = (mPlayEndTimeMsec*1000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001125 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1126 return;
1127 }
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001128 // Capture the frame timestamp to be rendered
1129 mDecodedVideoTs = timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001130
1131 // Post processing to apply video effects
1132 for(i=0;i<mNumberEffects;i++) {
1133 // First check if effect starttime matches the clip being previewed
1134 if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) ||
1135 (mEffectsSettings[i].uiStartTime >=
1136 ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec)))
1137 {
1138 // This effect doesn't belong to this clip, check next one
1139 continue;
1140 }
1141 // Check if effect applies to this particular frame timestamp
1142 if((mEffectsSettings[i].uiStartTime <=
1143 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) &&
1144 ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=
1145 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec))
1146 && (mEffectsSettings[i].uiDuration != 0)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001147 setVideoPostProcessingNode(
1148 mEffectsSettings[i].VideoEffectType, TRUE);
1149 }
1150 else {
1151 setVideoPostProcessingNode(
1152 mEffectsSettings[i].VideoEffectType, FALSE);
1153 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001154 }
1155
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001156 //Provide the overlay Update indication when there is an overlay effect
Dharmaray Kundargid01ef562011-01-26 21:11:00 -08001157 if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) {
1158 mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here.
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001159 if (!mOverlayUpdateEventPosted) {
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001160 // Find the effect in effectSettings array
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001161 M4OSA_UInt32 index;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001162 for (index = 0; index < mNumberEffects; index++) {
1163 M4OSA_UInt32 timeMs = mDecodedVideoTs/1000;
1164 M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000;
1165 if(mEffectsSettings[index].VideoEffectType ==
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001166 (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001167 if (((mEffectsSettings[index].uiStartTime + 1) <=
1168 timeMs + timeOffset - mPlayBeginTimeMsec) &&
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001169 ((mEffectsSettings[index].uiStartTime - 1 +
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001170 mEffectsSettings[index].uiDuration) >=
1171 timeMs + timeOffset - mPlayBeginTimeMsec))
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001172 {
1173 break;
1174 }
1175 }
1176 }
1177 if (index < mNumberEffects) {
1178 mCurrFramingEffectIndex = index;
1179 mOverlayUpdateEventPosted = true;
1180 postOverlayUpdateEvent_l();
1181 LOGV("Framing index = %d", mCurrFramingEffectIndex);
1182 } else {
1183 LOGV("No framing effects found");
1184 }
1185 }
1186
1187 } else if (mOverlayUpdateEventPosted) {
1188 //Post the event when the overlay is no more valid
1189 LOGV("Overlay is Done");
1190 mOverlayUpdateEventPosted = false;
1191 postOverlayUpdateEvent_l();
1192 }
1193
1194
1195 if (mCurrentVideoEffect != VIDEO_EFFECT_NONE) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001196 err1 = doVideoPostProcessing();
1197 if(err1 != M4NO_ERROR) {
1198 LOGE("doVideoPostProcessing returned err");
1199 bAppliedVideoEffect = false;
1200 }
1201 else {
1202 bAppliedVideoEffect = true;
1203 }
1204 }
1205 else {
1206 bAppliedVideoEffect = false;
1207 if(mRenderingMode != MEDIA_RENDERING_INVALID) {
1208 // No effects to be applied, but media rendering to be done
1209 err1 = doMediaRendering();
1210 if(err1 != M4NO_ERROR) {
1211 LOGE("doMediaRendering returned err");
1212 //Use original mVideoBuffer for rendering
1213 mVideoResizedOrCropped = false;
1214 }
1215 }
1216 }
1217
1218 if (mVideoRenderer != NULL) {
1219 LOGV("mVideoRenderer CALL render()");
1220 mVideoRenderer->render();
1221 }
1222
1223 if (mLastVideoBuffer) {
1224 mLastVideoBuffer->release();
1225 mLastVideoBuffer = NULL;
1226 }
1227
1228 mLastVideoBuffer = mVideoBuffer;
1229 mVideoBuffer = NULL;
1230
1231 // Post progress callback based on callback interval set
1232 if(mNumberDecVideoFrames >= mProgressCbInterval) {
1233 postProgressCallbackEvent_l();
1234 mNumberDecVideoFrames = 0; // reset counter
1235 }
1236
1237 // if reached EndCutTime of clip, post EOS event
1238 if((timeUs/1000) >= mPlayEndTimeMsec) {
1239 LOGV("PreviewPlayer: onVideoEvent EOS.");
1240 mFlags |= VIDEO_AT_EOS;
1241 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001242 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001243 // Set the last decoded timestamp to duration
1244 mDecodedVideoTs = (mPlayEndTimeMsec*1000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001245 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1246 }
1247 else {
Andreas Hubera5872f72011-02-24 15:25:21 -08001248 if ((wasSeeking != NO_SEEK) && (mFlags & SEEK_PREVIEW)) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001249 mFlags &= ~SEEK_PREVIEW;
1250 return;
1251 }
1252
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001253 if(!mIsVideoSourceJpg) {
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001254 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001255 }
1256 else {
1257 postVideoEvent_l(33000);
1258 }
1259 }
1260}
1261
1262status_t PreviewPlayer::prepare() {
1263 Mutex::Autolock autoLock(mLock);
1264 return prepare_l();
1265}
1266
1267status_t PreviewPlayer::prepare_l() {
1268 if (mFlags & PREPARED) {
1269 return OK;
1270 }
1271
1272 if (mFlags & PREPARING) {
1273 return UNKNOWN_ERROR;
1274 }
1275
1276 mIsAsyncPrepare = false;
1277 status_t err = prepareAsync_l();
1278
1279 if (err != OK) {
1280 return err;
1281 }
1282
1283 while (mFlags & PREPARING) {
1284 mPreparedCondition.wait(mLock);
1285 }
1286
1287 return mPrepareResult;
1288}
1289
1290status_t PreviewPlayer::prepareAsync_l() {
1291 if (mFlags & PREPARING) {
1292 return UNKNOWN_ERROR; // async prepare already pending
1293 }
1294
1295 if (!mQueueStarted) {
1296 mQueue.start();
1297 mQueueStarted = true;
1298 }
1299
1300 mFlags |= PREPARING;
1301 mAsyncPrepareEvent = new PreviewPlayerEvent(
1302 this, &PreviewPlayer::onPrepareAsyncEvent);
1303
1304 mQueue.postEvent(mAsyncPrepareEvent);
1305
1306 return OK;
1307}
1308
1309status_t PreviewPlayer::finishSetDataSource_l() {
1310 sp<DataSource> dataSource;
1311 sp<MediaExtractor> extractor;
1312
1313 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1314
1315 if (dataSource == NULL) {
1316 return UNKNOWN_ERROR;
1317 }
1318
1319 //If file type is .rgb, then no need to check for Extractor
1320 int uriLen = strlen(mUri);
1321 int startOffset = uriLen - 4;
1322 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) {
1323 extractor = NULL;
1324 }
1325 else {
1326 extractor = MediaExtractor::Create(dataSource,
1327 MEDIA_MIMETYPE_CONTAINER_MPEG4);
1328 }
1329
1330 if (extractor == NULL) {
1331 LOGV("PreviewPlayer::finishSetDataSource_l extractor == NULL");
1332 return setDataSource_l_jpg();
1333 }
1334
1335 return setDataSource_l(extractor);
1336}
1337
1338
1339// static
1340bool PreviewPlayer::ContinuePreparation(void *cookie) {
1341 PreviewPlayer *me = static_cast<PreviewPlayer *>(cookie);
1342
1343 return (me->mFlags & PREPARE_CANCELLED) == 0;
1344}
1345
1346void PreviewPlayer::onPrepareAsyncEvent() {
1347 Mutex::Autolock autoLock(mLock);
1348 LOGV("onPrepareAsyncEvent");
1349
1350 if (mFlags & PREPARE_CANCELLED) {
Santosh Madhavabfece172011-02-03 16:59:47 -08001351 LOGV("LV PLAYER prepare was cancelled before doing anything");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001352 abortPrepare(UNKNOWN_ERROR);
1353 return;
1354 }
1355
1356 if (mUri.size() > 0) {
1357 status_t err = finishSetDataSource_l();
1358
1359 if (err != OK) {
1360 abortPrepare(err);
1361 return;
1362 }
1363 }
1364
1365 if (mVideoTrack != NULL && mVideoSource == NULL) {
1366 status_t err = initVideoDecoder(OMXCodec::kHardwareCodecsOnly);
1367
1368 if (err != OK) {
1369 abortPrepare(err);
1370 return;
1371 }
1372 }
1373
1374 if (mAudioTrack != NULL && mAudioSource == NULL) {
1375 status_t err = initAudioDecoder();
1376
1377 if (err != OK) {
1378 abortPrepare(err);
1379 return;
1380 }
1381 }
1382 finishAsyncPrepare_l();
1383
1384}
1385
1386void PreviewPlayer::finishAsyncPrepare_l() {
1387 if (mIsAsyncPrepare) {
1388 if (mVideoSource == NULL) {
1389 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE 0 0 ");
1390 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1391 } else {
1392 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE");
1393 notifyVideoSize_l();
1394 }
1395 LOGV("finishAsyncPrepare_l: MEDIA_PREPARED");
1396 notifyListener_l(MEDIA_PREPARED);
1397 }
1398
1399 mPrepareResult = OK;
1400 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1401 mFlags |= PREPARED;
1402 mAsyncPrepareEvent = NULL;
1403 mPreparedCondition.broadcast();
1404}
1405
1406status_t PreviewPlayer::suspend() {
1407 LOGV("suspend");
1408 Mutex::Autolock autoLock(mLock);
1409
1410 if (mSuspensionState != NULL) {
1411 if (mLastVideoBuffer == NULL) {
1412 //go into here if video is suspended again
1413 //after resuming without being played between
1414 //them
1415 SuspensionState *state = mSuspensionState;
1416 mSuspensionState = NULL;
1417 reset_l();
1418 mSuspensionState = state;
1419 return OK;
1420 }
1421
1422 delete mSuspensionState;
1423 mSuspensionState = NULL;
1424 }
1425
1426 if (mFlags & PREPARING) {
1427 mFlags |= PREPARE_CANCELLED;
1428 }
1429
1430 while (mFlags & PREPARING) {
1431 mPreparedCondition.wait(mLock);
1432 }
1433
1434 SuspensionState *state = new SuspensionState;
1435 state->mUri = mUri;
1436 state->mUriHeaders = mUriHeaders;
1437 state->mFileSource = mFileSource;
1438
1439 state->mFlags = mFlags & (PLAYING | AUTO_LOOPING | LOOPING | AT_EOS);
1440 getPosition(&state->mPositionUs);
1441
1442 if (mLastVideoBuffer) {
1443 size_t size = mLastVideoBuffer->range_length();
1444 if (size) {
1445 int32_t unreadable;
1446 if (!mLastVideoBuffer->meta_data()->findInt32(
1447 kKeyIsUnreadable, &unreadable)
1448 || unreadable == 0) {
1449 state->mLastVideoFrameSize = size;
1450 state->mLastVideoFrame = malloc(size);
1451 memcpy(state->mLastVideoFrame,
1452 (const uint8_t *)mLastVideoBuffer->data()
1453 + mLastVideoBuffer->range_offset(),
1454 size);
1455
1456 state->mVideoWidth = mVideoWidth;
1457 state->mVideoHeight = mVideoHeight;
1458
1459 sp<MetaData> meta = mVideoSource->getFormat();
1460 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1461 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1462 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1463 } else {
1464 LOGV("Unable to save last video frame, we have no access to "
1465 "the decoded video data.");
1466 }
1467 }
1468 }
1469
1470 reset_l();
1471
1472 mSuspensionState = state;
1473
1474 return OK;
1475}
1476
1477status_t PreviewPlayer::resume() {
1478 LOGV("resume");
1479 Mutex::Autolock autoLock(mLock);
1480
1481 if (mSuspensionState == NULL) {
1482 return INVALID_OPERATION;
1483 }
1484
1485 SuspensionState *state = mSuspensionState;
1486 mSuspensionState = NULL;
1487
1488 status_t err;
1489 if (state->mFileSource != NULL) {
1490 err = AwesomePlayer::setDataSource_l(state->mFileSource);
1491
1492 if (err == OK) {
1493 mFileSource = state->mFileSource;
1494 }
1495 } else {
1496 err = AwesomePlayer::setDataSource_l(state->mUri, &state->mUriHeaders);
1497 }
1498
1499 if (err != OK) {
1500 delete state;
1501 state = NULL;
1502
1503 return err;
1504 }
1505
1506 seekTo_l(state->mPositionUs);
1507
1508 mFlags = state->mFlags & (AUTO_LOOPING | LOOPING | AT_EOS);
1509
1510 if (state->mLastVideoFrame && (mSurface != NULL || mISurface != NULL)) {
1511 mVideoRenderer =
Santosh Madhavabfece172011-02-03 16:59:47 -08001512 PreviewLocalRenderer::initPreviewLocalRenderer(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001513 true, // previewOnly
1514 (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1515 mSurface,
1516 state->mVideoWidth,
1517 state->mVideoHeight,
1518 state->mDecodedWidth,
1519 state->mDecodedHeight);
1520
1521 mVideoRendererIsPreview = true;
1522
1523 ((PreviewLocalRenderer *)mVideoRenderer.get())->render(
1524 state->mLastVideoFrame, state->mLastVideoFrameSize);
1525 }
1526
1527 if (state->mFlags & PLAYING) {
1528 play_l();
1529 }
1530
1531 mSuspensionState = state;
1532 state = NULL;
1533
1534 return OK;
1535}
1536
1537
1538status_t PreviewPlayer::loadEffectsSettings(
1539 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) {
1540 M4OSA_UInt32 i = 0, rgbSize = 0;
1541 M4VIFI_UInt8 *tmp = M4OSA_NULL;
1542
1543 mNumberEffects = nEffects;
1544 mEffectsSettings = pEffectSettings;
1545 return OK;
1546}
1547
1548status_t PreviewPlayer::loadAudioMixSettings(
1549 M4xVSS_AudioMixingSettings* pAudioMixSettings) {
1550
1551 LOGV("PreviewPlayer: loadAudioMixSettings: ");
1552 mPreviewPlayerAudioMixSettings = pAudioMixSettings;
1553 return OK;
1554}
1555
1556status_t PreviewPlayer::setAudioMixPCMFileHandle(
1557 M4OSA_Context pAudioMixPCMFileHandle) {
1558
1559 LOGV("PreviewPlayer: setAudioMixPCMFileHandle: ");
1560 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle;
1561 return OK;
1562}
1563
1564status_t PreviewPlayer::setAudioMixStoryBoardParam(
1565 M4OSA_UInt32 audioMixStoryBoardTS,
1566 M4OSA_UInt32 currentMediaBeginCutTime,
1567 M4OSA_UInt32 primaryTrackVolValue ) {
1568
1569 mAudioMixStoryBoardTS = audioMixStoryBoardTS;
1570 mCurrentMediaBeginCutTime = currentMediaBeginCutTime;
1571 mCurrentMediaVolumeValue = primaryTrackVolValue;
1572 return OK;
1573}
1574
1575status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) {
1576
1577 mPlayBeginTimeMsec = msec;
1578 return OK;
1579}
1580
1581status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) {
1582
1583 mPlayEndTimeMsec = msec;
1584 return OK;
1585}
1586
1587status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) {
1588
1589 mStoryboardStartTimeMsec = msec;
1590 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000;
1591 return OK;
1592}
1593
1594status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) {
1595
1596 mProgressCbInterval = cbInterval;
1597 return OK;
1598}
1599
1600
1601status_t PreviewPlayer::setMediaRenderingMode(
1602 M4xVSS_MediaRendering mode,
1603 M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
1604
1605 mRenderingMode = mode;
1606
1607 /* reset boolean for each clip*/
1608 mVideoResizedOrCropped = false;
1609
1610 switch(outputVideoSize) {
1611 case M4VIDEOEDITING_kSQCIF:
1612 mOutputVideoWidth = 128;
1613 mOutputVideoHeight = 96;
1614 break;
1615
1616 case M4VIDEOEDITING_kQQVGA:
1617 mOutputVideoWidth = 160;
1618 mOutputVideoHeight = 120;
1619 break;
1620
1621 case M4VIDEOEDITING_kQCIF:
1622 mOutputVideoWidth = 176;
1623 mOutputVideoHeight = 144;
1624 break;
1625
1626 case M4VIDEOEDITING_kQVGA:
1627 mOutputVideoWidth = 320;
1628 mOutputVideoHeight = 240;
1629 break;
1630
1631 case M4VIDEOEDITING_kCIF:
1632 mOutputVideoWidth = 352;
1633 mOutputVideoHeight = 288;
1634 break;
1635
1636 case M4VIDEOEDITING_kVGA:
1637 mOutputVideoWidth = 640;
1638 mOutputVideoHeight = 480;
1639 break;
1640
1641 case M4VIDEOEDITING_kWVGA:
1642 mOutputVideoWidth = 800;
1643 mOutputVideoHeight = 480;
1644 break;
1645
1646 case M4VIDEOEDITING_kNTSC:
1647 mOutputVideoWidth = 720;
1648 mOutputVideoHeight = 480;
1649 break;
1650
1651 case M4VIDEOEDITING_k640_360:
1652 mOutputVideoWidth = 640;
1653 mOutputVideoHeight = 360;
1654 break;
1655
1656 case M4VIDEOEDITING_k854_480:
1657 mOutputVideoWidth = 854;
1658 mOutputVideoHeight = 480;
1659 break;
1660
1661 case M4VIDEOEDITING_kHD1280:
1662 mOutputVideoWidth = 1280;
1663 mOutputVideoHeight = 720;
1664 break;
1665
1666 case M4VIDEOEDITING_kHD1080:
1667 mOutputVideoWidth = 1080;
1668 mOutputVideoHeight = 720;
1669 break;
1670
1671 case M4VIDEOEDITING_kHD960:
1672 mOutputVideoWidth = 960;
1673 mOutputVideoHeight = 720;
1674 break;
1675
1676 default:
1677 LOGE("unsupported output video size set");
1678 return BAD_VALUE;
1679 }
1680
1681 return OK;
1682}
1683
1684M4OSA_ERR PreviewPlayer::doMediaRendering() {
1685 M4OSA_ERR err = M4NO_ERROR;
1686 M4VIFI_ImagePlane planeIn[3], planeOut[3];
1687 M4VIFI_UInt8 *inBuffer = M4OSA_NULL, *finalOutputBuffer = M4OSA_NULL;
1688 M4VIFI_UInt8 *tempOutputBuffer= M4OSA_NULL;
1689 size_t videoBufferSize = 0;
1690 M4OSA_UInt32 frameSize = 0, i=0, index =0, nFrameCount =0, bufferOffset =0;
1691 int32_t colorFormat = 0;
1692
1693 if(!mIsVideoSourceJpg) {
1694 sp<MetaData> meta = mVideoSource->getFormat();
1695 CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
1696 }
1697 else {
1698 colorFormat = OMX_COLOR_FormatYUV420Planar;
1699 }
1700
1701 videoBufferSize = mVideoBuffer->size();
1702 frameSize = (mVideoWidth*mVideoHeight*3) >> 1;
1703
1704 uint8_t* outBuffer;
1705 size_t outBufferStride = 0;
1706
1707 mVideoRenderer->getBuffer(&outBuffer, &outBufferStride);
1708
1709 bufferOffset = index*frameSize;
1710 inBuffer = (M4OSA_UInt8 *)mVideoBuffer->data()+
1711 mVideoBuffer->range_offset()+bufferOffset;
1712
1713
1714 /* In plane*/
1715 prepareYUV420ImagePlane(planeIn, mVideoWidth,
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001716 mVideoHeight, (M4VIFI_UInt8 *)inBuffer, mReportedWidth, mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001717
1718 // Set the output YUV420 plane to be compatible with YV12 format
1719 // W & H even
1720 // YVU instead of YUV
1721 // align buffers on 32 bits
1722
1723 //In YV12 format, sizes must be even
1724 M4OSA_UInt32 yv12PlaneWidth = ((mOutputVideoWidth +1)>>1)<<1;
1725 M4OSA_UInt32 yv12PlaneHeight = ((mOutputVideoHeight+1)>>1)<<1;
1726
1727 prepareYV12ImagePlane(planeOut, yv12PlaneWidth, yv12PlaneHeight,
1728 (M4OSA_UInt32)outBufferStride, (M4VIFI_UInt8 *)outBuffer);
1729
1730
1731 err = applyRenderingMode(planeIn, planeOut, mRenderingMode);
1732
1733 if(err != M4NO_ERROR)
1734 {
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001735 LOGE("doMediaRendering: applyRenderingMode returned err=0x%x", (int)err);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001736 return err;
1737 }
1738 mVideoResizedOrCropped = true;
1739
1740 return err;
1741}
1742
1743status_t PreviewPlayer::resetJniCallbackTimeStamp() {
1744
1745 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000;
1746 return OK;
1747}
1748
1749void PreviewPlayer::postProgressCallbackEvent_l() {
1750 if (mProgressCbEventPending) {
1751 return;
1752 }
1753 mProgressCbEventPending = true;
1754
1755 mQueue.postEvent(mProgressCbEvent);
1756}
1757
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001758
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001759void PreviewPlayer::onProgressCbEvent() {
1760 Mutex::Autolock autoLock(mLock);
1761 if (!mProgressCbEventPending) {
1762 return;
1763 }
1764 mProgressCbEventPending = false;
1765 // If playback starts from previous I-frame,
1766 // then send frame storyboard duration
1767 if((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) {
1768 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000);
1769 }
1770 else {
1771 notifyListener_l(MEDIA_INFO, 0,
1772 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec));
1773 }
1774}
1775
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001776void PreviewPlayer::postOverlayUpdateEvent_l() {
1777 if (mOverlayUpdateEventPending) {
1778 return;
1779 }
1780 mOverlayUpdateEventPending = true;
1781 mQueue.postEvent(mOverlayUpdateEvent);
1782}
1783
1784void PreviewPlayer::onUpdateOverlayEvent() {
1785 Mutex::Autolock autoLock(mLock);
1786
1787 if (!mOverlayUpdateEventPending) {
1788 return;
1789 }
1790 mOverlayUpdateEventPending = false;
1791
1792 int updateState;
1793 if (mOverlayUpdateEventPosted) {
1794 updateState = 1;
1795 } else {
1796 updateState = 0;
1797 }
1798 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex);
1799}
1800
1801
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001802void PreviewPlayer::setVideoPostProcessingNode(
1803 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
1804
1805 uint32_t effect = VIDEO_EFFECT_NONE;
1806
1807 //Map M4VSS3GPP_VideoEffectType to local enum
1808 switch(type) {
1809 case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
1810 effect = VIDEO_EFFECT_FADEFROMBLACK;
1811 break;
1812
1813 case M4VSS3GPP_kVideoEffectType_FadeToBlack:
1814 effect = VIDEO_EFFECT_FADETOBLACK;
1815 break;
1816
1817 case M4VSS3GPP_kVideoEffectType_CurtainOpening:
1818 effect = VIDEO_EFFECT_CURTAINOPEN;
1819 break;
1820
1821 case M4VSS3GPP_kVideoEffectType_CurtainClosing:
1822 effect = VIDEO_EFFECT_CURTAINCLOSE;
1823 break;
1824
1825 case M4xVSS_kVideoEffectType_BlackAndWhite:
1826 effect = VIDEO_EFFECT_BLACKANDWHITE;
1827 break;
1828
1829 case M4xVSS_kVideoEffectType_Pink:
1830 effect = VIDEO_EFFECT_PINK;
1831 break;
1832
1833 case M4xVSS_kVideoEffectType_Green:
1834 effect = VIDEO_EFFECT_GREEN;
1835 break;
1836
1837 case M4xVSS_kVideoEffectType_Sepia:
1838 effect = VIDEO_EFFECT_SEPIA;
1839 break;
1840
1841 case M4xVSS_kVideoEffectType_Negative:
1842 effect = VIDEO_EFFECT_NEGATIVE;
1843 break;
1844
1845 case M4xVSS_kVideoEffectType_Framing:
1846 effect = VIDEO_EFFECT_FRAMING;
1847 break;
1848
1849 case M4xVSS_kVideoEffectType_Fifties:
1850 effect = VIDEO_EFFECT_FIFTIES;
1851 break;
1852
1853 case M4xVSS_kVideoEffectType_ColorRGB16:
1854 effect = VIDEO_EFFECT_COLOR_RGB16;
1855 break;
1856
1857 case M4xVSS_kVideoEffectType_Gradient:
1858 effect = VIDEO_EFFECT_GRADIENT;
1859 break;
1860
1861 default:
1862 effect = VIDEO_EFFECT_NONE;
1863 break;
1864 }
1865
1866 if(enable == M4OSA_TRUE) {
1867 //If already set, then no need to set again
1868 if(!(mCurrentVideoEffect & effect)) {
1869 mCurrentVideoEffect |= effect;
1870 if(effect == VIDEO_EFFECT_FIFTIES) {
1871 mIsFiftiesEffectStarted = true;
1872 }
1873 }
1874 }
1875 else {
1876 //Reset only if already set
1877 if(mCurrentVideoEffect & effect) {
1878 mCurrentVideoEffect &= ~effect;
1879 }
1880 }
1881}
1882
1883status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) {
1884 mVideoWidth = width;
1885 mVideoHeight = height;
1886 return OK;
1887}
1888
1889
1890M4OSA_ERR PreviewPlayer::doVideoPostProcessing() {
1891 M4OSA_ERR err = M4NO_ERROR;
1892 vePostProcessParams postProcessParams;
1893 int32_t colorFormat = 0;
1894
1895
1896 if(!mIsVideoSourceJpg) {
1897 sp<MetaData> meta = mVideoSource->getFormat();
1898 CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
1899 }
1900 else {
1901 colorFormat = OMX_COLOR_FormatYUV420Planar;
1902 }
1903
1904 if((colorFormat == OMX_COLOR_FormatYUV420SemiPlanar) ||
1905 (colorFormat == 0x7FA30C00)) {
1906 LOGE("doVideoPostProcessing: colorFormat YUV420Sp not supported");
1907 return M4ERR_UNSUPPORTED_MEDIA_TYPE;
1908 }
1909
1910 postProcessParams.vidBuffer = (M4VIFI_UInt8*)mVideoBuffer->data()
1911 + mVideoBuffer->range_offset();
1912
1913 postProcessParams.videoWidth = mVideoWidth;
1914 postProcessParams.videoHeight = mVideoHeight;
1915 postProcessParams.timeMs = mDecodedVideoTs/1000;
1916 postProcessParams.timeOffset = mDecVideoTsStoryBoard/1000;
1917 postProcessParams.effectsSettings = mEffectsSettings;
1918 postProcessParams.numberEffects = mNumberEffects;
1919 postProcessParams.outVideoWidth = mOutputVideoWidth;
1920 postProcessParams.outVideoHeight = mOutputVideoHeight;
1921 postProcessParams.currentVideoEffect = mCurrentVideoEffect;
1922 postProcessParams.renderingMode = mRenderingMode;
1923 if(mIsFiftiesEffectStarted == M4OSA_TRUE) {
1924 postProcessParams.isFiftiesEffectStarted = M4OSA_TRUE;
1925 mIsFiftiesEffectStarted = M4OSA_FALSE;
1926 }
1927 else {
1928 postProcessParams.isFiftiesEffectStarted = M4OSA_FALSE;
1929 }
1930
1931 postProcessParams.overlayFrameRGBBuffer = mFrameRGBBuffer;
1932 postProcessParams.overlayFrameYUVBuffer = mFrameYUVBuffer;
1933 mVideoRenderer->getBuffer(&(postProcessParams.pOutBuffer), &(postProcessParams.outBufferStride));
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001934 err = applyEffectsAndRenderingMode(&postProcessParams, mReportedWidth, mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001935
1936 return err;
1937}
1938
1939status_t PreviewPlayer::readFirstVideoFrame() {
1940 LOGV("PreviewPlayer::readFirstVideoFrame");
1941
1942 if (!mVideoBuffer) {
1943 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -08001944 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001945 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
1946 mSeekTimeUs / 1E6);
1947
1948 options.setSeekTo(
1949 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
1950 }
1951 for (;;) {
1952 status_t err = mVideoSource->read(&mVideoBuffer, &options);
1953 options.clearSeekTo();
1954
1955 if (err != OK) {
1956 CHECK_EQ(mVideoBuffer, NULL);
1957
1958 if (err == INFO_FORMAT_CHANGED) {
1959 LOGV("LV PLAYER VideoSource signalled format change");
1960 notifyVideoSize_l();
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001961 sp<MetaData> meta = mVideoSource->getFormat();
1962
1963 CHECK(meta->findInt32(kKeyWidth, &mReportedWidth));
1964 CHECK(meta->findInt32(kKeyHeight, &mReportedHeight));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001965
1966 if (mVideoRenderer != NULL) {
1967 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -08001968 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001969 if (err != OK) {
1970 postStreamDoneEvent_l(err);
1971 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001972 }
1973 continue;
1974 }
1975 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
1976 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001977 mFlags |= AUDIO_AT_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001978 postStreamDoneEvent_l(err);
1979 return OK;
1980 }
1981
1982 if (mVideoBuffer->range_length() == 0) {
1983 // Some decoders, notably the PV AVC software decoder
1984 // return spurious empty buffers that we just want to ignore.
1985
1986 mVideoBuffer->release();
1987 mVideoBuffer = NULL;
1988 continue;
1989 }
1990
1991 int64_t videoTimeUs;
1992 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
Andreas Hubera5872f72011-02-24 15:25:21 -08001993 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001994 if (videoTimeUs < mSeekTimeUs) {
1995 // buffers are before seek time
1996 // ignore them
1997 mVideoBuffer->release();
1998 mVideoBuffer = NULL;
1999 continue;
2000 }
2001 } else {
2002 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
2003 // buffers are before begin cut time
2004 // ignore them
2005 mVideoBuffer->release();
2006 mVideoBuffer = NULL;
2007 continue;
2008 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002009 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002010 break;
2011 }
2012 }
2013
2014 int64_t timeUs;
2015 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
2016
2017 {
2018 Mutex::Autolock autoLock(mMiscStateLock);
2019 mVideoTimeUs = timeUs;
2020 }
2021
2022 mDecodedVideoTs = timeUs;
2023
2024 return OK;
2025
2026}
2027
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08002028status_t PreviewPlayer::getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs) {
2029 *lastRenderedTimeMs = (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec);
2030 return OK;
2031}
2032
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002033} // namespace android