blob: 20640043d2687d1527063288ba12fc9a6abec2b9 [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,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700316 ((mPlayEndTimeMsec)*1000LL));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800317 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,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700336 ((mPlayEndTimeMsec)*1000LL));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800337 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
Raghavender Pallaebf40152011-03-14 20:15:12 -0700348 mDurationUs = (mPlayEndTimeMsec - mPlayBeginTimeMsec)*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800349
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
Raghavender Pallaebf40152011-03-14 20:15:12 -0700543 pDummyAudioSource->setDuration(
544 (int64_t)((mPlayEndTimeMsec)*1000LL));
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800545
546 // Stop the new audio source
547 // since we continue using old source
548 LOGV("setAudioPlayer: stop new audio source");
549 mAudioSource->stop();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800550 }
551 }
552 }
553 }
554
555 return OK;
556}
557
558void PreviewPlayer::onStreamDone() {
559 // Posted whenever any stream finishes playing.
560
561 Mutex::Autolock autoLock(mLock);
562 if (!mStreamDoneEventPending) {
563 return;
564 }
565 mStreamDoneEventPending = false;
566
567 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
568 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
569
570 notifyListener_l(
571 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
572
573 pause_l(true /* at eos */);
574
575 mFlags |= AT_EOS;
576 return;
577 }
578
579 const bool allDone =
580 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
581 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
582
583 if (!allDone) {
584 return;
585 }
586
587 if (mFlags & (LOOPING | AUTO_LOOPING)) {
588 seekTo_l(0);
589
590 if (mVideoSource != NULL) {
591 postVideoEvent_l();
592 }
593 } else {
594 LOGV("MEDIA_PLAYBACK_COMPLETE");
595 //pause before sending event
596 pause_l(true /* at eos */);
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700597
598 //This lock is used to syncronize onStreamDone() in PreviewPlayer and
599 //stopPreview() in PreviewController
600 Mutex::Autolock autoLock(mLockControl);
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800601 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
602
603 mFlags |= AT_EOS;
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700604 LOGV("onStreamDone end");
605 return;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800606 }
607}
608
609
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800610status_t PreviewPlayer::play_l() {
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800611
Rajneesh Chowdury8b95de22011-02-16 15:32:06 -0800612 mFlags &= ~SEEK_PREVIEW;
613
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800614 if (mFlags & PLAYING) {
615 return OK;
616 }
617 mStartNextPlayer = false;
618
619 if (!(mFlags & PREPARED)) {
620 status_t err = prepare_l();
621
622 if (err != OK) {
623 return err;
624 }
625 }
626
627 mFlags |= PLAYING;
628 mFlags |= FIRST_FRAME;
629
630 bool deferredAudioSeek = false;
631
632 if (mAudioSource != NULL) {
633 if (mAudioPlayer == NULL) {
634 if (mAudioSink != NULL) {
635
636 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800637 mVeAudioPlayer =
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800638 (VideoEditorAudioPlayer*)mAudioPlayer;
639
640 mAudioPlayer->setSource(mAudioSource);
641
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800642 mVeAudioPlayer->setAudioMixSettings(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800643 mPreviewPlayerAudioMixSettings);
644
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800645 mVeAudioPlayer->setAudioMixPCMFileHandle(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800646 mAudioMixPCMFileHandle);
647
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800648 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800649 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
650 mCurrentMediaVolumeValue);
651
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800652 mFlags |= AUDIOPLAYER_STARTED;
653 // We've already started the MediaSource in order to enable
654 // the prefetcher to read its data.
655 status_t err = mVeAudioPlayer->start(
656 true /* sourceAlreadyStarted */);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800657
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800658 if (err != OK) {
659 //delete mAudioPlayer;
660 mAudioPlayer = NULL;
661
662 mFlags &= ~(PLAYING | FIRST_FRAME);
663 return err;
664 }
665
666 mTimeSource = mVeAudioPlayer;
667 mFlags |= AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800668 deferredAudioSeek = true;
669 mWatchForAudioSeekComplete = false;
670 mWatchForAudioEOS = true;
671 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800672 } else {
673 mVeAudioPlayer = (VideoEditorAudioPlayer*)mAudioPlayer;
674 bool isAudioPlayerStarted = mVeAudioPlayer->isStarted();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800675
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800676 if (mIsChangeSourceRequired == true) {
677 LOGV("play_l: Change audio source required");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800678
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800679 if (isAudioPlayerStarted == true) {
680 mVeAudioPlayer->pause();
681 }
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800682
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800683 mVeAudioPlayer->setSource(mAudioSource);
684 mVeAudioPlayer->setObserver(this);
685
686 mVeAudioPlayer->setAudioMixSettings(
687 mPreviewPlayerAudioMixSettings);
688
689 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
690 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
691 mCurrentMediaVolumeValue);
692
693 if (isAudioPlayerStarted == true) {
694 mVeAudioPlayer->resume();
695 } else {
696 status_t err = OK;
697 err = mVeAudioPlayer->start(true);
698 if (err != OK) {
699 mAudioPlayer = NULL;
700 mVeAudioPlayer = NULL;
701
702 mFlags &= ~(PLAYING | FIRST_FRAME);
703 return err;
704 }
705 }
706 } else {
707 LOGV("play_l: No Source change required");
708 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
709 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
710 mCurrentMediaVolumeValue);
711
712 mVeAudioPlayer->resume();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800713 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800714
715 mFlags |= AUDIOPLAYER_STARTED;
716 mFlags |= AUDIO_RUNNING;
717 mTimeSource = mVeAudioPlayer;
718 deferredAudioSeek = true;
719 mWatchForAudioSeekComplete = false;
720 mWatchForAudioEOS = true;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800721 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800722 }
723
724 if (mTimeSource == NULL && mAudioPlayer == NULL) {
725 mTimeSource = &mSystemTimeSource;
726 }
727
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800728 // Set the seek option for Image source files and read.
729 // This resets the timestamping for image play
730 if (mIsVideoSourceJpg) {
731 MediaSource::ReadOptions options;
732 MediaBuffer *aLocalBuffer;
733 options.setSeekTo(mSeekTimeUs);
734 mVideoSource->read(&aLocalBuffer, &options);
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800735 aLocalBuffer->release();
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800736 }
737
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800738 if (mVideoSource != NULL) {
739 // Kick off video playback
740 postVideoEvent_l();
741 }
742
743 if (deferredAudioSeek) {
744 // If there was a seek request while we were paused
745 // and we're just starting up again, honor the request now.
746 seekAudioIfNecessary_l();
747 }
748
749 if (mFlags & AT_EOS) {
750 // Legacy behaviour, if a stream finishes playing and then
751 // is started again, we play from the start...
752 seekTo_l(0);
753 }
754
755 return OK;
756}
757
758
Santosh Madhavabfece172011-02-03 16:59:47 -0800759status_t PreviewPlayer::initRenderer_l() {
Mathias Agopian6e224292011-04-05 15:38:24 -0700760 if (mSurface != NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800761 sp<MetaData> meta = mVideoSource->getFormat();
762
763 int32_t format;
764 const char *component;
765 int32_t decodedWidth, decodedHeight;
766 CHECK(meta->findInt32(kKeyColorFormat, &format));
767 CHECK(meta->findCString(kKeyDecoderComponent, &component));
768 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
769 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
770
771 // Must ensure that mVideoRenderer's destructor is actually executed
772 // before creating a new one.
773 IPCThreadState::self()->flushCommands();
774
775 // always use localrenderer since decoded buffers are modified
776 // by postprocessing module
777 // Other decoders are instantiated locally and as a consequence
778 // allocate their buffers in local address space.
779 if(mVideoRenderer == NULL) {
780
Santosh Madhavabfece172011-02-03 16:59:47 -0800781 mVideoRenderer = PreviewLocalRenderer:: initPreviewLocalRenderer (
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800782 false, // previewOnly
783 (OMX_COLOR_FORMATTYPE)format,
784 mSurface,
785 mOutputVideoWidth, mOutputVideoHeight,
786 mOutputVideoWidth, mOutputVideoHeight);
Santosh Madhavabfece172011-02-03 16:59:47 -0800787
788 if ( mVideoRenderer == NULL )
789 {
790 return UNKNOWN_ERROR;
791 }
792 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800793 }
794 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800795 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800796}
797
798
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800799status_t PreviewPlayer::seekTo(int64_t timeUs) {
800
801 if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) {
802 Mutex::Autolock autoLock(mLock);
803 return seekTo_l(timeUs);
804 }
805
806 return OK;
807}
808
809
810status_t PreviewPlayer::getVideoDimensions(
811 int32_t *width, int32_t *height) const {
812 Mutex::Autolock autoLock(mLock);
813
814 if (mVideoWidth < 0 || mVideoHeight < 0) {
815 return UNKNOWN_ERROR;
816 }
817
818 *width = mVideoWidth;
819 *height = mVideoHeight;
820
821 return OK;
822}
823
824
825status_t PreviewPlayer::initAudioDecoder() {
826 sp<MetaData> meta = mAudioTrack->getFormat();
827 const char *mime;
828 CHECK(meta->findCString(kKeyMIMEType, &mime));
829
830 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
831 mAudioSource = mAudioTrack;
832 } else {
833 sp<MediaSource> aRawSource;
834 aRawSource = OMXCodec::Create(
835 mClient.interface(), mAudioTrack->getFormat(),
836 false, // createEncoder
837 mAudioTrack);
838
839 if(aRawSource != NULL) {
840 LOGV("initAudioDecoder: new VideoEditorSRC");
841 mAudioSource = new VideoEditorSRC(aRawSource);
842 }
843 }
844
845 if (mAudioSource != NULL) {
846 int64_t durationUs;
847 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
848 Mutex::Autolock autoLock(mMiscStateLock);
849 if (mDurationUs < 0 || durationUs > mDurationUs) {
850 mDurationUs = durationUs;
851 }
852 }
853 status_t err = mAudioSource->start();
854
855 if (err != OK) {
856 mAudioSource.clear();
857 return err;
858 }
859 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
860 // For legacy reasons we're simply going to ignore the absence
861 // of an audio decoder for QCELP instead of aborting playback
862 // altogether.
863 return OK;
864 }
865
866 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
867}
868
869
870status_t PreviewPlayer::initVideoDecoder(uint32_t flags) {
871
872 mVideoSource = OMXCodec::Create(
873 mClient.interface(), mVideoTrack->getFormat(),
874 false,
875 mVideoTrack,
876 NULL, flags);
877
878 if (mVideoSource != NULL) {
879 int64_t durationUs;
880 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
881 Mutex::Autolock autoLock(mMiscStateLock);
882 if (mDurationUs < 0 || durationUs > mDurationUs) {
883 mDurationUs = durationUs;
884 }
885 }
886
887 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
888 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
889
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800890 mReportedWidth = mVideoWidth;
891 mReportedHeight = mVideoHeight;
892
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800893 status_t err = mVideoSource->start();
894
895 if (err != OK) {
896 mVideoSource.clear();
897 return err;
898 }
899 }
900
901 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
902}
903
904
905void PreviewPlayer::onVideoEvent() {
906 uint32_t i=0;
907 bool bAppliedVideoEffect = false;
908 M4OSA_ERR err1 = M4NO_ERROR;
909 int64_t imageFrameTimeUs = 0;
910
911 Mutex::Autolock autoLock(mLock);
912 if (!mVideoEventPending) {
913 // The event has been cancelled in reset_l() but had already
914 // been scheduled for execution at that time.
915 return;
916 }
917 mVideoEventPending = false;
918
Andreas Huber9e4c36a2011-02-08 13:12:32 -0800919 if (mFlags & SEEK_PREVIEW) {
920 mFlags &= ~SEEK_PREVIEW;
921 return;
922 }
923
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800924 TimeSource *ts_st = &mSystemTimeSource;
925 int64_t timeStartUs = ts_st->getRealTimeUs();
926
Andreas Hubera5872f72011-02-24 15:25:21 -0800927 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800928 if (mLastVideoBuffer) {
929 mLastVideoBuffer->release();
930 mLastVideoBuffer = NULL;
931 }
932
933
934 if(mAudioSource != NULL) {
935
936 // We're going to seek the video source first, followed by
937 // the audio source.
938 // In order to avoid jumps in the DataSource offset caused by
939 // the audio codec prefetching data from the old locations
940 // while the video codec is already reading data from the new
941 // locations, we'll "pause" the audio source, causing it to
942 // stop reading input data until a subsequent seek.
943
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800944 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800945 mAudioPlayer->pause();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800946 mFlags &= ~AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800947 }
948 mAudioSource->pause();
949 }
950 }
951
952 if (!mVideoBuffer) {
953 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -0800954 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800955 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
956 mSeekTimeUs / 1E6);
957
958 options.setSeekTo(
959 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
960 }
961 for (;;) {
962 status_t err = mVideoSource->read(&mVideoBuffer, &options);
963 options.clearSeekTo();
964
965 if (err != OK) {
966 CHECK_EQ(mVideoBuffer, NULL);
967
968 if (err == INFO_FORMAT_CHANGED) {
969 LOGV("LV PLAYER VideoSource signalled format change");
970 notifyVideoSize_l();
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800971 sp<MetaData> meta = mVideoSource->getFormat();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800972
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800973 CHECK(meta->findInt32(kKeyWidth, &mReportedWidth));
974 CHECK(meta->findInt32(kKeyHeight, &mReportedHeight));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800975 if (mVideoRenderer != NULL) {
976 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -0800977 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800978 if (err != OK) {
979 postStreamDoneEvent_l(err);
980 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800981
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800982 }
983 continue;
984 }
985 // So video playback is complete, but we may still have
Santosh Madhava342f9322011-01-27 16:27:12 -0800986 // a seek request pending that needs to be applied to the audio track
Andreas Hubera5872f72011-02-24 15:25:21 -0800987 if (mSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800988 LOGV("video stream ended while seeking!");
989 }
990 finishSeekIfNecessary(-1);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800991 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
992 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800993 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800994 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800995 postStreamDoneEvent_l(err);
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800996 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -0700997 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800998 return;
999 }
1000
1001 if (mVideoBuffer->range_length() == 0) {
1002 // Some decoders, notably the PV AVC software decoder
1003 // return spurious empty buffers that we just want to ignore.
1004
1005 mVideoBuffer->release();
1006 mVideoBuffer = NULL;
1007 continue;
1008 }
1009
1010 int64_t videoTimeUs;
1011 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
1012
Andreas Hubera5872f72011-02-24 15:25:21 -08001013 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001014 if (videoTimeUs < mSeekTimeUs) {
1015 // buffers are before seek time
1016 // ignore them
1017 mVideoBuffer->release();
1018 mVideoBuffer = NULL;
1019 continue;
1020 }
1021 } else {
1022 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
1023 // Frames are before begin cut time
1024 // Donot render
1025 mVideoBuffer->release();
1026 mVideoBuffer = NULL;
1027 continue;
1028 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001029 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001030 break;
1031 }
1032 }
1033
1034 mNumberDecVideoFrames++;
1035
1036 int64_t timeUs;
1037 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1038
1039 {
1040 Mutex::Autolock autoLock(mMiscStateLock);
1041 mVideoTimeUs = timeUs;
1042 }
1043
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001044
1045 if(!mStartNextPlayer) {
Raghavender Pallaebf40152011-03-14 20:15:12 -07001046 int64_t playbackTimeRemaining = (mPlayEndTimeMsec*1000LL) - timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001047 if(playbackTimeRemaining <= 1500000) {
1048 //When less than 1.5 sec of playback left
1049 // send notification to start next player
1050
1051 mStartNextPlayer = true;
1052 notifyListener_l(0xAAAAAAAA);
1053 }
1054 }
1055
Andreas Hubera5872f72011-02-24 15:25:21 -08001056 SeekType wasSeeking = mSeeking;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001057 finishSeekIfNecessary(timeUs);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -08001058 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING))) {
1059 status_t err = startAudioPlayer_l();
1060 if (err != OK) {
1061 LOGE("Starting the audio player failed w/ err %d", err);
1062 return;
1063 }
1064 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001065
1066 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
1067
1068 if(ts == NULL) {
1069 mVideoBuffer->release();
1070 mVideoBuffer = NULL;
1071 return;
1072 }
1073
1074 if(!mIsVideoSourceJpg) {
1075 if (mFlags & FIRST_FRAME) {
1076 mFlags &= ~FIRST_FRAME;
1077
1078 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
1079 }
1080
1081 int64_t realTimeUs, mediaTimeUs;
1082 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
1083 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1084 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1085 }
1086
1087 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1088
1089 int64_t latenessUs = nowUs - timeUs;
1090
Andreas Hubera5872f72011-02-24 15:25:21 -08001091 if (wasSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -08001092 // Let's display the first frame after seeking right away.
1093 latenessUs = 0;
1094 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001095 LOGV("Audio time stamp = %lld and video time stamp = %lld",
1096 ts->getRealTimeUs(),timeUs);
1097 if (latenessUs > 40000) {
1098 // We're more than 40ms late.
1099
1100 LOGV("LV PLAYER we're late by %lld us (%.2f secs)",
1101 latenessUs, latenessUs / 1E6);
1102
1103 mVideoBuffer->release();
1104 mVideoBuffer = NULL;
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001105 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001106 return;
1107 }
1108
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001109 if (latenessUs < -25000) {
1110 // We're more than 25ms early.
1111 LOGV("We're more than 25ms early, lateness %lld", latenessUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001112
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001113 postVideoEvent_l(25000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001114 return;
1115 }
1116 }
1117
1118 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
1119 mVideoRendererIsPreview = false;
1120
Santosh Madhavabfece172011-02-03 16:59:47 -08001121 status_t err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001122 if (err != OK) {
1123 postStreamDoneEvent_l(err);
1124 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001125 }
1126
1127 // If timestamp exceeds endCutTime of clip, donot render
1128 if((timeUs/1000) > mPlayEndTimeMsec) {
1129 if (mLastVideoBuffer) {
1130 mLastVideoBuffer->release();
1131 mLastVideoBuffer = NULL;
1132 }
1133 mLastVideoBuffer = mVideoBuffer;
1134 mVideoBuffer = NULL;
1135 mFlags |= VIDEO_AT_EOS;
1136 mFlags |= AUDIO_AT_EOS;
Santosh Madhavabfece172011-02-03 16:59:47 -08001137 LOGV("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS..");
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001138 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001139 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001140 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001141 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1142 return;
1143 }
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001144 // Capture the frame timestamp to be rendered
1145 mDecodedVideoTs = timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001146
1147 // Post processing to apply video effects
1148 for(i=0;i<mNumberEffects;i++) {
1149 // First check if effect starttime matches the clip being previewed
1150 if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) ||
1151 (mEffectsSettings[i].uiStartTime >=
1152 ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec)))
1153 {
1154 // This effect doesn't belong to this clip, check next one
1155 continue;
1156 }
1157 // Check if effect applies to this particular frame timestamp
1158 if((mEffectsSettings[i].uiStartTime <=
1159 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) &&
1160 ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=
1161 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec))
1162 && (mEffectsSettings[i].uiDuration != 0)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001163 setVideoPostProcessingNode(
1164 mEffectsSettings[i].VideoEffectType, TRUE);
1165 }
1166 else {
1167 setVideoPostProcessingNode(
1168 mEffectsSettings[i].VideoEffectType, FALSE);
1169 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001170 }
1171
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001172 //Provide the overlay Update indication when there is an overlay effect
Dharmaray Kundargid01ef562011-01-26 21:11:00 -08001173 if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) {
1174 mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here.
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001175 if (!mOverlayUpdateEventPosted) {
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001176 // Find the effect in effectSettings array
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001177 M4OSA_UInt32 index;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001178 for (index = 0; index < mNumberEffects; index++) {
1179 M4OSA_UInt32 timeMs = mDecodedVideoTs/1000;
1180 M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000;
1181 if(mEffectsSettings[index].VideoEffectType ==
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001182 (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001183 if (((mEffectsSettings[index].uiStartTime + 1) <=
1184 timeMs + timeOffset - mPlayBeginTimeMsec) &&
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001185 ((mEffectsSettings[index].uiStartTime - 1 +
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001186 mEffectsSettings[index].uiDuration) >=
1187 timeMs + timeOffset - mPlayBeginTimeMsec))
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001188 {
1189 break;
1190 }
1191 }
1192 }
1193 if (index < mNumberEffects) {
1194 mCurrFramingEffectIndex = index;
1195 mOverlayUpdateEventPosted = true;
1196 postOverlayUpdateEvent_l();
1197 LOGV("Framing index = %d", mCurrFramingEffectIndex);
1198 } else {
1199 LOGV("No framing effects found");
1200 }
1201 }
1202
1203 } else if (mOverlayUpdateEventPosted) {
1204 //Post the event when the overlay is no more valid
1205 LOGV("Overlay is Done");
1206 mOverlayUpdateEventPosted = false;
1207 postOverlayUpdateEvent_l();
1208 }
1209
1210
1211 if (mCurrentVideoEffect != VIDEO_EFFECT_NONE) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001212 err1 = doVideoPostProcessing();
1213 if(err1 != M4NO_ERROR) {
1214 LOGE("doVideoPostProcessing returned err");
1215 bAppliedVideoEffect = false;
1216 }
1217 else {
1218 bAppliedVideoEffect = true;
1219 }
1220 }
1221 else {
1222 bAppliedVideoEffect = false;
1223 if(mRenderingMode != MEDIA_RENDERING_INVALID) {
1224 // No effects to be applied, but media rendering to be done
1225 err1 = doMediaRendering();
1226 if(err1 != M4NO_ERROR) {
1227 LOGE("doMediaRendering returned err");
1228 //Use original mVideoBuffer for rendering
1229 mVideoResizedOrCropped = false;
1230 }
1231 }
1232 }
1233
1234 if (mVideoRenderer != NULL) {
1235 LOGV("mVideoRenderer CALL render()");
1236 mVideoRenderer->render();
1237 }
1238
1239 if (mLastVideoBuffer) {
1240 mLastVideoBuffer->release();
1241 mLastVideoBuffer = NULL;
1242 }
1243
1244 mLastVideoBuffer = mVideoBuffer;
1245 mVideoBuffer = NULL;
1246
1247 // Post progress callback based on callback interval set
1248 if(mNumberDecVideoFrames >= mProgressCbInterval) {
1249 postProgressCallbackEvent_l();
1250 mNumberDecVideoFrames = 0; // reset counter
1251 }
1252
1253 // if reached EndCutTime of clip, post EOS event
1254 if((timeUs/1000) >= mPlayEndTimeMsec) {
1255 LOGV("PreviewPlayer: onVideoEvent EOS.");
1256 mFlags |= VIDEO_AT_EOS;
1257 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001258 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001259 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001260 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001261 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1262 }
1263 else {
Andreas Hubera5872f72011-02-24 15:25:21 -08001264 if ((wasSeeking != NO_SEEK) && (mFlags & SEEK_PREVIEW)) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001265 mFlags &= ~SEEK_PREVIEW;
1266 return;
1267 }
1268
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001269 if(!mIsVideoSourceJpg) {
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001270 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001271 }
1272 else {
1273 postVideoEvent_l(33000);
1274 }
1275 }
1276}
1277
1278status_t PreviewPlayer::prepare() {
1279 Mutex::Autolock autoLock(mLock);
1280 return prepare_l();
1281}
1282
1283status_t PreviewPlayer::prepare_l() {
1284 if (mFlags & PREPARED) {
1285 return OK;
1286 }
1287
1288 if (mFlags & PREPARING) {
1289 return UNKNOWN_ERROR;
1290 }
1291
1292 mIsAsyncPrepare = false;
1293 status_t err = prepareAsync_l();
1294
1295 if (err != OK) {
1296 return err;
1297 }
1298
1299 while (mFlags & PREPARING) {
1300 mPreparedCondition.wait(mLock);
1301 }
1302
1303 return mPrepareResult;
1304}
1305
1306status_t PreviewPlayer::prepareAsync_l() {
1307 if (mFlags & PREPARING) {
1308 return UNKNOWN_ERROR; // async prepare already pending
1309 }
1310
1311 if (!mQueueStarted) {
1312 mQueue.start();
1313 mQueueStarted = true;
1314 }
1315
1316 mFlags |= PREPARING;
1317 mAsyncPrepareEvent = new PreviewPlayerEvent(
1318 this, &PreviewPlayer::onPrepareAsyncEvent);
1319
1320 mQueue.postEvent(mAsyncPrepareEvent);
1321
1322 return OK;
1323}
1324
1325status_t PreviewPlayer::finishSetDataSource_l() {
1326 sp<DataSource> dataSource;
1327 sp<MediaExtractor> extractor;
1328
1329 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1330
1331 if (dataSource == NULL) {
1332 return UNKNOWN_ERROR;
1333 }
1334
1335 //If file type is .rgb, then no need to check for Extractor
1336 int uriLen = strlen(mUri);
1337 int startOffset = uriLen - 4;
1338 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) {
1339 extractor = NULL;
1340 }
1341 else {
1342 extractor = MediaExtractor::Create(dataSource,
1343 MEDIA_MIMETYPE_CONTAINER_MPEG4);
1344 }
1345
1346 if (extractor == NULL) {
1347 LOGV("PreviewPlayer::finishSetDataSource_l extractor == NULL");
1348 return setDataSource_l_jpg();
1349 }
1350
1351 return setDataSource_l(extractor);
1352}
1353
1354
1355// static
1356bool PreviewPlayer::ContinuePreparation(void *cookie) {
1357 PreviewPlayer *me = static_cast<PreviewPlayer *>(cookie);
1358
1359 return (me->mFlags & PREPARE_CANCELLED) == 0;
1360}
1361
1362void PreviewPlayer::onPrepareAsyncEvent() {
1363 Mutex::Autolock autoLock(mLock);
1364 LOGV("onPrepareAsyncEvent");
1365
1366 if (mFlags & PREPARE_CANCELLED) {
Santosh Madhavabfece172011-02-03 16:59:47 -08001367 LOGV("LV PLAYER prepare was cancelled before doing anything");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001368 abortPrepare(UNKNOWN_ERROR);
1369 return;
1370 }
1371
1372 if (mUri.size() > 0) {
1373 status_t err = finishSetDataSource_l();
1374
1375 if (err != OK) {
1376 abortPrepare(err);
1377 return;
1378 }
1379 }
1380
1381 if (mVideoTrack != NULL && mVideoSource == NULL) {
1382 status_t err = initVideoDecoder(OMXCodec::kHardwareCodecsOnly);
1383
1384 if (err != OK) {
1385 abortPrepare(err);
1386 return;
1387 }
1388 }
1389
1390 if (mAudioTrack != NULL && mAudioSource == NULL) {
1391 status_t err = initAudioDecoder();
1392
1393 if (err != OK) {
1394 abortPrepare(err);
1395 return;
1396 }
1397 }
1398 finishAsyncPrepare_l();
1399
1400}
1401
1402void PreviewPlayer::finishAsyncPrepare_l() {
1403 if (mIsAsyncPrepare) {
1404 if (mVideoSource == NULL) {
1405 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE 0 0 ");
1406 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1407 } else {
1408 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE");
1409 notifyVideoSize_l();
1410 }
1411 LOGV("finishAsyncPrepare_l: MEDIA_PREPARED");
1412 notifyListener_l(MEDIA_PREPARED);
1413 }
1414
1415 mPrepareResult = OK;
1416 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1417 mFlags |= PREPARED;
1418 mAsyncPrepareEvent = NULL;
1419 mPreparedCondition.broadcast();
1420}
1421
1422status_t PreviewPlayer::suspend() {
1423 LOGV("suspend");
1424 Mutex::Autolock autoLock(mLock);
1425
1426 if (mSuspensionState != NULL) {
1427 if (mLastVideoBuffer == NULL) {
1428 //go into here if video is suspended again
1429 //after resuming without being played between
1430 //them
1431 SuspensionState *state = mSuspensionState;
1432 mSuspensionState = NULL;
1433 reset_l();
1434 mSuspensionState = state;
1435 return OK;
1436 }
1437
1438 delete mSuspensionState;
1439 mSuspensionState = NULL;
1440 }
1441
1442 if (mFlags & PREPARING) {
1443 mFlags |= PREPARE_CANCELLED;
1444 }
1445
1446 while (mFlags & PREPARING) {
1447 mPreparedCondition.wait(mLock);
1448 }
1449
1450 SuspensionState *state = new SuspensionState;
1451 state->mUri = mUri;
1452 state->mUriHeaders = mUriHeaders;
1453 state->mFileSource = mFileSource;
1454
1455 state->mFlags = mFlags & (PLAYING | AUTO_LOOPING | LOOPING | AT_EOS);
1456 getPosition(&state->mPositionUs);
1457
1458 if (mLastVideoBuffer) {
1459 size_t size = mLastVideoBuffer->range_length();
1460 if (size) {
1461 int32_t unreadable;
1462 if (!mLastVideoBuffer->meta_data()->findInt32(
1463 kKeyIsUnreadable, &unreadable)
1464 || unreadable == 0) {
1465 state->mLastVideoFrameSize = size;
1466 state->mLastVideoFrame = malloc(size);
1467 memcpy(state->mLastVideoFrame,
1468 (const uint8_t *)mLastVideoBuffer->data()
1469 + mLastVideoBuffer->range_offset(),
1470 size);
1471
1472 state->mVideoWidth = mVideoWidth;
1473 state->mVideoHeight = mVideoHeight;
1474
1475 sp<MetaData> meta = mVideoSource->getFormat();
1476 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1477 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1478 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1479 } else {
1480 LOGV("Unable to save last video frame, we have no access to "
1481 "the decoded video data.");
1482 }
1483 }
1484 }
1485
1486 reset_l();
1487
1488 mSuspensionState = state;
1489
1490 return OK;
1491}
1492
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001493void PreviewPlayer::acquireLock() {
1494 LOGV("acquireLock");
1495 mLockControl.lock();
1496}
1497
1498void PreviewPlayer::releaseLock() {
1499 LOGV("releaseLock");
1500 mLockControl.unlock();
1501}
1502
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001503status_t PreviewPlayer::resume() {
1504 LOGV("resume");
1505 Mutex::Autolock autoLock(mLock);
1506
1507 if (mSuspensionState == NULL) {
1508 return INVALID_OPERATION;
1509 }
1510
1511 SuspensionState *state = mSuspensionState;
1512 mSuspensionState = NULL;
1513
1514 status_t err;
1515 if (state->mFileSource != NULL) {
1516 err = AwesomePlayer::setDataSource_l(state->mFileSource);
1517
1518 if (err == OK) {
1519 mFileSource = state->mFileSource;
1520 }
1521 } else {
1522 err = AwesomePlayer::setDataSource_l(state->mUri, &state->mUriHeaders);
1523 }
1524
1525 if (err != OK) {
1526 delete state;
1527 state = NULL;
1528
1529 return err;
1530 }
1531
1532 seekTo_l(state->mPositionUs);
1533
1534 mFlags = state->mFlags & (AUTO_LOOPING | LOOPING | AT_EOS);
1535
Mathias Agopian6e224292011-04-05 15:38:24 -07001536 if (state->mLastVideoFrame && (mSurface != NULL)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001537 mVideoRenderer =
Santosh Madhavabfece172011-02-03 16:59:47 -08001538 PreviewLocalRenderer::initPreviewLocalRenderer(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001539 true, // previewOnly
1540 (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1541 mSurface,
1542 state->mVideoWidth,
1543 state->mVideoHeight,
1544 state->mDecodedWidth,
1545 state->mDecodedHeight);
1546
1547 mVideoRendererIsPreview = true;
1548
1549 ((PreviewLocalRenderer *)mVideoRenderer.get())->render(
1550 state->mLastVideoFrame, state->mLastVideoFrameSize);
1551 }
1552
1553 if (state->mFlags & PLAYING) {
1554 play_l();
1555 }
1556
1557 mSuspensionState = state;
1558 state = NULL;
1559
1560 return OK;
1561}
1562
1563
1564status_t PreviewPlayer::loadEffectsSettings(
1565 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) {
1566 M4OSA_UInt32 i = 0, rgbSize = 0;
1567 M4VIFI_UInt8 *tmp = M4OSA_NULL;
1568
1569 mNumberEffects = nEffects;
1570 mEffectsSettings = pEffectSettings;
1571 return OK;
1572}
1573
1574status_t PreviewPlayer::loadAudioMixSettings(
1575 M4xVSS_AudioMixingSettings* pAudioMixSettings) {
1576
1577 LOGV("PreviewPlayer: loadAudioMixSettings: ");
1578 mPreviewPlayerAudioMixSettings = pAudioMixSettings;
1579 return OK;
1580}
1581
1582status_t PreviewPlayer::setAudioMixPCMFileHandle(
1583 M4OSA_Context pAudioMixPCMFileHandle) {
1584
1585 LOGV("PreviewPlayer: setAudioMixPCMFileHandle: ");
1586 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle;
1587 return OK;
1588}
1589
1590status_t PreviewPlayer::setAudioMixStoryBoardParam(
1591 M4OSA_UInt32 audioMixStoryBoardTS,
1592 M4OSA_UInt32 currentMediaBeginCutTime,
1593 M4OSA_UInt32 primaryTrackVolValue ) {
1594
1595 mAudioMixStoryBoardTS = audioMixStoryBoardTS;
1596 mCurrentMediaBeginCutTime = currentMediaBeginCutTime;
1597 mCurrentMediaVolumeValue = primaryTrackVolValue;
1598 return OK;
1599}
1600
1601status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) {
1602
1603 mPlayBeginTimeMsec = msec;
1604 return OK;
1605}
1606
1607status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) {
1608
1609 mPlayEndTimeMsec = msec;
1610 return OK;
1611}
1612
1613status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) {
1614
1615 mStoryboardStartTimeMsec = msec;
Raghavender Pallaebf40152011-03-14 20:15:12 -07001616 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001617 return OK;
1618}
1619
1620status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) {
1621
1622 mProgressCbInterval = cbInterval;
1623 return OK;
1624}
1625
1626
1627status_t PreviewPlayer::setMediaRenderingMode(
1628 M4xVSS_MediaRendering mode,
1629 M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
1630
1631 mRenderingMode = mode;
1632
1633 /* reset boolean for each clip*/
1634 mVideoResizedOrCropped = false;
1635
1636 switch(outputVideoSize) {
1637 case M4VIDEOEDITING_kSQCIF:
1638 mOutputVideoWidth = 128;
1639 mOutputVideoHeight = 96;
1640 break;
1641
1642 case M4VIDEOEDITING_kQQVGA:
1643 mOutputVideoWidth = 160;
1644 mOutputVideoHeight = 120;
1645 break;
1646
1647 case M4VIDEOEDITING_kQCIF:
1648 mOutputVideoWidth = 176;
1649 mOutputVideoHeight = 144;
1650 break;
1651
1652 case M4VIDEOEDITING_kQVGA:
1653 mOutputVideoWidth = 320;
1654 mOutputVideoHeight = 240;
1655 break;
1656
1657 case M4VIDEOEDITING_kCIF:
1658 mOutputVideoWidth = 352;
1659 mOutputVideoHeight = 288;
1660 break;
1661
1662 case M4VIDEOEDITING_kVGA:
1663 mOutputVideoWidth = 640;
1664 mOutputVideoHeight = 480;
1665 break;
1666
1667 case M4VIDEOEDITING_kWVGA:
1668 mOutputVideoWidth = 800;
1669 mOutputVideoHeight = 480;
1670 break;
1671
1672 case M4VIDEOEDITING_kNTSC:
1673 mOutputVideoWidth = 720;
1674 mOutputVideoHeight = 480;
1675 break;
1676
1677 case M4VIDEOEDITING_k640_360:
1678 mOutputVideoWidth = 640;
1679 mOutputVideoHeight = 360;
1680 break;
1681
1682 case M4VIDEOEDITING_k854_480:
1683 mOutputVideoWidth = 854;
1684 mOutputVideoHeight = 480;
1685 break;
1686
1687 case M4VIDEOEDITING_kHD1280:
1688 mOutputVideoWidth = 1280;
1689 mOutputVideoHeight = 720;
1690 break;
1691
1692 case M4VIDEOEDITING_kHD1080:
1693 mOutputVideoWidth = 1080;
1694 mOutputVideoHeight = 720;
1695 break;
1696
1697 case M4VIDEOEDITING_kHD960:
1698 mOutputVideoWidth = 960;
1699 mOutputVideoHeight = 720;
1700 break;
1701
1702 default:
1703 LOGE("unsupported output video size set");
1704 return BAD_VALUE;
1705 }
1706
1707 return OK;
1708}
1709
1710M4OSA_ERR PreviewPlayer::doMediaRendering() {
1711 M4OSA_ERR err = M4NO_ERROR;
1712 M4VIFI_ImagePlane planeIn[3], planeOut[3];
1713 M4VIFI_UInt8 *inBuffer = M4OSA_NULL, *finalOutputBuffer = M4OSA_NULL;
1714 M4VIFI_UInt8 *tempOutputBuffer= M4OSA_NULL;
1715 size_t videoBufferSize = 0;
1716 M4OSA_UInt32 frameSize = 0, i=0, index =0, nFrameCount =0, bufferOffset =0;
1717 int32_t colorFormat = 0;
1718
1719 if(!mIsVideoSourceJpg) {
1720 sp<MetaData> meta = mVideoSource->getFormat();
1721 CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
1722 }
1723 else {
1724 colorFormat = OMX_COLOR_FormatYUV420Planar;
1725 }
1726
1727 videoBufferSize = mVideoBuffer->size();
1728 frameSize = (mVideoWidth*mVideoHeight*3) >> 1;
1729
1730 uint8_t* outBuffer;
1731 size_t outBufferStride = 0;
1732
1733 mVideoRenderer->getBuffer(&outBuffer, &outBufferStride);
1734
1735 bufferOffset = index*frameSize;
1736 inBuffer = (M4OSA_UInt8 *)mVideoBuffer->data()+
1737 mVideoBuffer->range_offset()+bufferOffset;
1738
1739
1740 /* In plane*/
1741 prepareYUV420ImagePlane(planeIn, mVideoWidth,
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001742 mVideoHeight, (M4VIFI_UInt8 *)inBuffer, mReportedWidth, mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001743
1744 // Set the output YUV420 plane to be compatible with YV12 format
1745 // W & H even
1746 // YVU instead of YUV
1747 // align buffers on 32 bits
1748
1749 //In YV12 format, sizes must be even
1750 M4OSA_UInt32 yv12PlaneWidth = ((mOutputVideoWidth +1)>>1)<<1;
1751 M4OSA_UInt32 yv12PlaneHeight = ((mOutputVideoHeight+1)>>1)<<1;
1752
1753 prepareYV12ImagePlane(planeOut, yv12PlaneWidth, yv12PlaneHeight,
1754 (M4OSA_UInt32)outBufferStride, (M4VIFI_UInt8 *)outBuffer);
1755
1756
1757 err = applyRenderingMode(planeIn, planeOut, mRenderingMode);
1758
1759 if(err != M4NO_ERROR)
1760 {
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001761 LOGE("doMediaRendering: applyRenderingMode returned err=0x%x", (int)err);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001762 return err;
1763 }
1764 mVideoResizedOrCropped = true;
1765
1766 return err;
1767}
1768
1769status_t PreviewPlayer::resetJniCallbackTimeStamp() {
1770
Raghavender Pallaebf40152011-03-14 20:15:12 -07001771 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001772 return OK;
1773}
1774
1775void PreviewPlayer::postProgressCallbackEvent_l() {
1776 if (mProgressCbEventPending) {
1777 return;
1778 }
1779 mProgressCbEventPending = true;
1780
1781 mQueue.postEvent(mProgressCbEvent);
1782}
1783
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001784
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001785void PreviewPlayer::onProgressCbEvent() {
1786 Mutex::Autolock autoLock(mLock);
1787 if (!mProgressCbEventPending) {
1788 return;
1789 }
1790 mProgressCbEventPending = false;
1791 // If playback starts from previous I-frame,
1792 // then send frame storyboard duration
1793 if((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) {
1794 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000);
1795 }
1796 else {
1797 notifyListener_l(MEDIA_INFO, 0,
1798 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec));
1799 }
1800}
1801
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001802void PreviewPlayer::postOverlayUpdateEvent_l() {
1803 if (mOverlayUpdateEventPending) {
1804 return;
1805 }
1806 mOverlayUpdateEventPending = true;
1807 mQueue.postEvent(mOverlayUpdateEvent);
1808}
1809
1810void PreviewPlayer::onUpdateOverlayEvent() {
1811 Mutex::Autolock autoLock(mLock);
1812
1813 if (!mOverlayUpdateEventPending) {
1814 return;
1815 }
1816 mOverlayUpdateEventPending = false;
1817
1818 int updateState;
1819 if (mOverlayUpdateEventPosted) {
1820 updateState = 1;
1821 } else {
1822 updateState = 0;
1823 }
1824 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex);
1825}
1826
1827
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001828void PreviewPlayer::setVideoPostProcessingNode(
1829 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
1830
1831 uint32_t effect = VIDEO_EFFECT_NONE;
1832
1833 //Map M4VSS3GPP_VideoEffectType to local enum
1834 switch(type) {
1835 case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
1836 effect = VIDEO_EFFECT_FADEFROMBLACK;
1837 break;
1838
1839 case M4VSS3GPP_kVideoEffectType_FadeToBlack:
1840 effect = VIDEO_EFFECT_FADETOBLACK;
1841 break;
1842
1843 case M4VSS3GPP_kVideoEffectType_CurtainOpening:
1844 effect = VIDEO_EFFECT_CURTAINOPEN;
1845 break;
1846
1847 case M4VSS3GPP_kVideoEffectType_CurtainClosing:
1848 effect = VIDEO_EFFECT_CURTAINCLOSE;
1849 break;
1850
1851 case M4xVSS_kVideoEffectType_BlackAndWhite:
1852 effect = VIDEO_EFFECT_BLACKANDWHITE;
1853 break;
1854
1855 case M4xVSS_kVideoEffectType_Pink:
1856 effect = VIDEO_EFFECT_PINK;
1857 break;
1858
1859 case M4xVSS_kVideoEffectType_Green:
1860 effect = VIDEO_EFFECT_GREEN;
1861 break;
1862
1863 case M4xVSS_kVideoEffectType_Sepia:
1864 effect = VIDEO_EFFECT_SEPIA;
1865 break;
1866
1867 case M4xVSS_kVideoEffectType_Negative:
1868 effect = VIDEO_EFFECT_NEGATIVE;
1869 break;
1870
1871 case M4xVSS_kVideoEffectType_Framing:
1872 effect = VIDEO_EFFECT_FRAMING;
1873 break;
1874
1875 case M4xVSS_kVideoEffectType_Fifties:
1876 effect = VIDEO_EFFECT_FIFTIES;
1877 break;
1878
1879 case M4xVSS_kVideoEffectType_ColorRGB16:
1880 effect = VIDEO_EFFECT_COLOR_RGB16;
1881 break;
1882
1883 case M4xVSS_kVideoEffectType_Gradient:
1884 effect = VIDEO_EFFECT_GRADIENT;
1885 break;
1886
1887 default:
1888 effect = VIDEO_EFFECT_NONE;
1889 break;
1890 }
1891
1892 if(enable == M4OSA_TRUE) {
1893 //If already set, then no need to set again
1894 if(!(mCurrentVideoEffect & effect)) {
1895 mCurrentVideoEffect |= effect;
1896 if(effect == VIDEO_EFFECT_FIFTIES) {
1897 mIsFiftiesEffectStarted = true;
1898 }
1899 }
1900 }
1901 else {
1902 //Reset only if already set
1903 if(mCurrentVideoEffect & effect) {
1904 mCurrentVideoEffect &= ~effect;
1905 }
1906 }
1907}
1908
1909status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) {
1910 mVideoWidth = width;
1911 mVideoHeight = height;
1912 return OK;
1913}
1914
1915
1916M4OSA_ERR PreviewPlayer::doVideoPostProcessing() {
1917 M4OSA_ERR err = M4NO_ERROR;
1918 vePostProcessParams postProcessParams;
1919 int32_t colorFormat = 0;
1920
1921
1922 if(!mIsVideoSourceJpg) {
1923 sp<MetaData> meta = mVideoSource->getFormat();
1924 CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
1925 }
1926 else {
1927 colorFormat = OMX_COLOR_FormatYUV420Planar;
1928 }
1929
1930 if((colorFormat == OMX_COLOR_FormatYUV420SemiPlanar) ||
1931 (colorFormat == 0x7FA30C00)) {
1932 LOGE("doVideoPostProcessing: colorFormat YUV420Sp not supported");
1933 return M4ERR_UNSUPPORTED_MEDIA_TYPE;
1934 }
1935
1936 postProcessParams.vidBuffer = (M4VIFI_UInt8*)mVideoBuffer->data()
1937 + mVideoBuffer->range_offset();
1938
1939 postProcessParams.videoWidth = mVideoWidth;
1940 postProcessParams.videoHeight = mVideoHeight;
1941 postProcessParams.timeMs = mDecodedVideoTs/1000;
1942 postProcessParams.timeOffset = mDecVideoTsStoryBoard/1000;
1943 postProcessParams.effectsSettings = mEffectsSettings;
1944 postProcessParams.numberEffects = mNumberEffects;
1945 postProcessParams.outVideoWidth = mOutputVideoWidth;
1946 postProcessParams.outVideoHeight = mOutputVideoHeight;
1947 postProcessParams.currentVideoEffect = mCurrentVideoEffect;
1948 postProcessParams.renderingMode = mRenderingMode;
1949 if(mIsFiftiesEffectStarted == M4OSA_TRUE) {
1950 postProcessParams.isFiftiesEffectStarted = M4OSA_TRUE;
1951 mIsFiftiesEffectStarted = M4OSA_FALSE;
1952 }
1953 else {
1954 postProcessParams.isFiftiesEffectStarted = M4OSA_FALSE;
1955 }
1956
1957 postProcessParams.overlayFrameRGBBuffer = mFrameRGBBuffer;
1958 postProcessParams.overlayFrameYUVBuffer = mFrameYUVBuffer;
1959 mVideoRenderer->getBuffer(&(postProcessParams.pOutBuffer), &(postProcessParams.outBufferStride));
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001960 err = applyEffectsAndRenderingMode(&postProcessParams, mReportedWidth, mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001961
1962 return err;
1963}
1964
1965status_t PreviewPlayer::readFirstVideoFrame() {
1966 LOGV("PreviewPlayer::readFirstVideoFrame");
1967
1968 if (!mVideoBuffer) {
1969 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -08001970 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001971 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
1972 mSeekTimeUs / 1E6);
1973
1974 options.setSeekTo(
1975 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
1976 }
1977 for (;;) {
1978 status_t err = mVideoSource->read(&mVideoBuffer, &options);
1979 options.clearSeekTo();
1980
1981 if (err != OK) {
1982 CHECK_EQ(mVideoBuffer, NULL);
1983
1984 if (err == INFO_FORMAT_CHANGED) {
1985 LOGV("LV PLAYER VideoSource signalled format change");
1986 notifyVideoSize_l();
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001987 sp<MetaData> meta = mVideoSource->getFormat();
1988
1989 CHECK(meta->findInt32(kKeyWidth, &mReportedWidth));
1990 CHECK(meta->findInt32(kKeyHeight, &mReportedHeight));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001991
1992 if (mVideoRenderer != NULL) {
1993 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -08001994 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001995 if (err != OK) {
1996 postStreamDoneEvent_l(err);
1997 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001998 }
1999 continue;
2000 }
2001 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
2002 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08002003 mFlags |= AUDIO_AT_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002004 postStreamDoneEvent_l(err);
2005 return OK;
2006 }
2007
2008 if (mVideoBuffer->range_length() == 0) {
2009 // Some decoders, notably the PV AVC software decoder
2010 // return spurious empty buffers that we just want to ignore.
2011
2012 mVideoBuffer->release();
2013 mVideoBuffer = NULL;
2014 continue;
2015 }
2016
2017 int64_t videoTimeUs;
2018 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
Andreas Hubera5872f72011-02-24 15:25:21 -08002019 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08002020 if (videoTimeUs < mSeekTimeUs) {
2021 // buffers are before seek time
2022 // ignore them
2023 mVideoBuffer->release();
2024 mVideoBuffer = NULL;
2025 continue;
2026 }
2027 } else {
2028 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
2029 // buffers are before begin cut time
2030 // ignore them
2031 mVideoBuffer->release();
2032 mVideoBuffer = NULL;
2033 continue;
2034 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002035 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002036 break;
2037 }
2038 }
2039
2040 int64_t timeUs;
2041 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
2042
2043 {
2044 Mutex::Autolock autoLock(mMiscStateLock);
2045 mVideoTimeUs = timeUs;
2046 }
2047
2048 mDecodedVideoTs = timeUs;
2049
2050 return OK;
2051
2052}
2053
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08002054status_t PreviewPlayer::getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs) {
2055 *lastRenderedTimeMs = (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec);
2056 return OK;
2057}
2058
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002059} // namespace android