blob: 78ca1cd40d48c44c0c512ebc59496f992415908a [file] [log] [blame]
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001/*
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Santosh Madhavabfece172011-02-03 16:59:47 -080017
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080018#define LOG_NDEBUG 1
19#define LOG_TAG "PreviewPlayer"
20#include <utils/Log.h>
21
22#include <dlfcn.h>
23
24#include "include/ARTSPController.h"
25#include "PreviewPlayer.h"
26#include "DummyAudioSource.h"
27#include "DummyVideoSource.h"
28#include "VideoEditorSRC.h"
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080029#include "include/NuCachedSource2.h"
30#include "include/ThrottledSource.h"
31
32
33#include "PreviewRenderer.h"
34
35#include <binder/IPCThreadState.h>
36#include <media/stagefright/DataSource.h>
37#include <media/stagefright/FileSource.h>
38#include <media/stagefright/MediaBuffer.h>
39#include <media/stagefright/MediaDefs.h>
40#include <media/stagefright/MediaExtractor.h>
41#include <media/stagefright/MediaDebug.h>
42#include <media/stagefright/MediaSource.h>
43#include <media/stagefright/MetaData.h>
44#include <media/stagefright/OMXCodec.h>
45
46#include <surfaceflinger/Surface.h>
47#include <media/stagefright/foundation/ALooper.h>
48
49namespace android {
50
51
52struct PreviewPlayerEvent : public TimedEventQueue::Event {
53 PreviewPlayerEvent(
54 PreviewPlayer *player,
55 void (PreviewPlayer::*method)())
56 : mPlayer(player),
57 mMethod(method) {
58 }
59
60protected:
61 virtual ~PreviewPlayerEvent() {}
62
63 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
64 (mPlayer->*mMethod)();
65 }
66
67private:
68 PreviewPlayer *mPlayer;
69 void (PreviewPlayer::*mMethod)();
70
71 PreviewPlayerEvent(const PreviewPlayerEvent &);
72 PreviewPlayerEvent &operator=(const PreviewPlayerEvent &);
73};
74
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080075PreviewPlayer::PreviewPlayer()
James Dongc9dedc42011-05-01 12:36:22 -070076 : PreviewPlayerBase(),
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -080077 mCurrFramingEffectIndex(0) ,
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -080078 mReportedWidth(0),
Dharmaray Kundargie6c07502011-01-21 16:58:31 -080079 mReportedHeight(0),
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -080080 mFrameRGBBuffer(NULL),
81 mFrameYUVBuffer(NULL){
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080082
83 mVideoRenderer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080084 mEffectsSettings = NULL;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -080085 mVeAudioPlayer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080086 mAudioMixStoryBoardTS = 0;
87 mCurrentMediaBeginCutTime = 0;
88 mCurrentMediaVolumeValue = 0;
89 mNumberEffects = 0;
90 mDecodedVideoTs = 0;
91 mDecVideoTsStoryBoard = 0;
92 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
93 mProgressCbInterval = 0;
94 mNumberDecVideoFrames = 0;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -080095 mOverlayUpdateEventPosted = false;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -080096 mIsChangeSourceRequired = true;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080097
98 mVideoEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoEvent);
99 mVideoEventPending = false;
100 mStreamDoneEvent = new PreviewPlayerEvent(this,
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800101 &PreviewPlayer::onStreamDone);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800102
103 mStreamDoneEventPending = false;
104
105 mCheckAudioStatusEvent = new PreviewPlayerEvent(
James Dongc9dedc42011-05-01 12:36:22 -0700106 this, &PreviewPlayerBase::onCheckAudioStatus);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800107
108 mAudioStatusEventPending = false;
109
110 mProgressCbEvent = new PreviewPlayerEvent(this,
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800111 &PreviewPlayer::onProgressCbEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800112
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800113 mOverlayUpdateEvent = new PreviewPlayerEvent(this,
114 &PreviewPlayer::onUpdateOverlayEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800115 mProgressCbEventPending = false;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800116
117 mOverlayUpdateEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800118 mResizedVideoBuffer = NULL;
119 mVideoResizedOrCropped = false;
120 mRenderingMode = (M4xVSS_MediaRendering)MEDIA_RENDERING_INVALID;
121 mIsFiftiesEffectStarted = false;
122 reset();
123}
124
125PreviewPlayer::~PreviewPlayer() {
126
127 if (mQueueStarted) {
128 mQueue.stop();
129 }
130
131 reset();
132
133 if(mResizedVideoBuffer != NULL) {
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700134 free((mResizedVideoBuffer->data()));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800135 mResizedVideoBuffer = NULL;
136 }
137
Chih-Chung Change048e902011-08-01 12:15:59 +0800138 delete mVideoRenderer;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800139}
140
141void PreviewPlayer::cancelPlayerEvents(bool keepBufferingGoing) {
142 mQueue.cancelEvent(mVideoEvent->eventID());
143 mVideoEventPending = false;
144 mQueue.cancelEvent(mStreamDoneEvent->eventID());
145 mStreamDoneEventPending = false;
146 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
147 mAudioStatusEventPending = false;
148
149 mQueue.cancelEvent(mProgressCbEvent->eventID());
150 mProgressCbEventPending = false;
151}
152
153status_t PreviewPlayer::setDataSource(
154 const char *uri, const KeyedVector<String8, String8> *headers) {
155 Mutex::Autolock autoLock(mLock);
156 return setDataSource_l(uri, headers);
157}
158
159status_t PreviewPlayer::setDataSource_l(
160 const char *uri, const KeyedVector<String8, String8> *headers) {
161 reset_l();
162
163 mUri = uri;
164
165 if (headers) {
166 mUriHeaders = *headers;
167 }
168
169 // The actual work will be done during preparation in the call to
170 // ::finishSetDataSource_l to avoid blocking the calling thread in
171 // setDataSource for any significant time.
172 return OK;
173}
174
175status_t PreviewPlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
176 bool haveAudio = false;
177 bool haveVideo = false;
178 for (size_t i = 0; i < extractor->countTracks(); ++i) {
179 sp<MetaData> meta = extractor->getTrackMetaData(i);
180
181 const char *mime;
182 CHECK(meta->findCString(kKeyMIMEType, &mime));
183
184 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
185 setVideoSource(extractor->getTrack(i));
186 haveVideo = true;
187 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
188 setAudioSource(extractor->getTrack(i));
189 haveAudio = true;
190
191 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
192 // Only do this for vorbis audio, none of the other audio
193 // formats even support this ringtone specific hack and
194 // retrieving the metadata on some extractors may turn out
195 // to be very expensive.
196 sp<MetaData> fileMeta = extractor->getMetaData();
197 int32_t loop;
198 if (fileMeta != NULL
199 && fileMeta->findInt32(kKeyAutoLoop, &loop)
200 && loop != 0) {
201 mFlags |= AUTO_LOOPING;
202 }
203 }
204 }
205
206 if (haveAudio && haveVideo) {
207 break;
208 }
209 }
210
211 /* Add the support for Dummy audio*/
212 if( !haveAudio ){
213 LOGV("PreviewPlayer: setDataSource_l Dummyaudiocreation started");
214
215 mAudioTrack = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700216 ((mPlayEndTimeMsec)*1000LL));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800217 LOGV("PreviewPlayer: setDataSource_l Dummyauiosource created");
218 if(mAudioTrack != NULL) {
219 haveAudio = true;
220 }
221 }
222
223 if (!haveAudio && !haveVideo) {
224 return UNKNOWN_ERROR;
225 }
226
227 mExtractorFlags = extractor->flags();
228 return OK;
229}
230
231status_t PreviewPlayer::setDataSource_l_jpg() {
232 M4OSA_ERR err = M4NO_ERROR;
233 LOGV("PreviewPlayer: setDataSource_l_jpg started");
234
235 mAudioSource = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700236 ((mPlayEndTimeMsec)*1000LL));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800237 LOGV("PreviewPlayer: setDataSource_l_jpg Dummyaudiosource created");
238 if(mAudioSource != NULL) {
239 setAudioSource(mAudioSource);
240 }
241 status_t error = mAudioSource->start();
242 if (error != OK) {
243 LOGV("Error starting dummy audio source");
244 mAudioSource.clear();
245 return err;
246 }
247
Raghavender Pallaebf40152011-03-14 20:15:12 -0700248 mDurationUs = (mPlayEndTimeMsec - mPlayBeginTimeMsec)*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800249
250 mVideoSource = DummyVideoSource::Create(mVideoWidth, mVideoHeight,
251 mDurationUs, mUri);
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800252 mReportedWidth = mVideoWidth;
253 mReportedHeight = mVideoHeight;
254
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800255 setVideoSource(mVideoSource);
256 status_t err1 = mVideoSource->start();
257 if (err1 != OK) {
258 mVideoSource.clear();
259 return err;
260 }
261
262 mIsVideoSourceJpg = true;
263 return OK;
264}
265
266void PreviewPlayer::reset() {
267 Mutex::Autolock autoLock(mLock);
268 reset_l();
269}
270
271void PreviewPlayer::reset_l() {
272
273 if (mFlags & PREPARING) {
274 mFlags |= PREPARE_CANCELLED;
275 }
276
277 while (mFlags & PREPARING) {
278 mPreparedCondition.wait(mLock);
279 }
280
281 cancelPlayerEvents();
282 mAudioTrack.clear();
283 mVideoTrack.clear();
284
285 // Shutdown audio first, so that the respone to the reset request
286 // appears to happen instantaneously as far as the user is concerned
287 // If we did this later, audio would continue playing while we
288 // shutdown the video-related resources and the player appear to
289 // not be as responsive to a reset request.
290 if (mAudioPlayer == NULL && mAudioSource != NULL) {
291 // If we had an audio player, it would have effectively
292 // taken possession of the audio source and stopped it when
293 // _it_ is stopped. Otherwise this is still our responsibility.
294 mAudioSource->stop();
295 }
296 mAudioSource.clear();
297
298 mTimeSource = NULL;
299
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800300 //Single audio player instance used
301 //So donot delete it here
302 //It is deleted from PreviewController class
303 //delete mAudioPlayer;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800304 mAudioPlayer = NULL;
305
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800306 if (mVideoBuffer) {
307 mVideoBuffer->release();
308 mVideoBuffer = NULL;
309 }
310
311 if (mVideoSource != NULL) {
312 mVideoSource->stop();
313
314 // The following hack is necessary to ensure that the OMX
315 // component is completely released by the time we may try
316 // to instantiate it again.
317 wp<MediaSource> tmp = mVideoSource;
318 mVideoSource.clear();
319 while (tmp.promote() != NULL) {
320 usleep(1000);
321 }
322 IPCThreadState::self()->flushCommands();
323 }
324
325 mDurationUs = -1;
326 mFlags = 0;
327 mExtractorFlags = 0;
328 mVideoWidth = mVideoHeight = -1;
329 mTimeSourceDeltaUs = 0;
330 mVideoTimeUs = 0;
331
Andreas Hubera5872f72011-02-24 15:25:21 -0800332 mSeeking = NO_SEEK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800333 mSeekNotificationSent = false;
334 mSeekTimeUs = 0;
335
336 mUri.setTo("");
337 mUriHeaders.clear();
338
339 mFileSource.clear();
340
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800341 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
342 mIsVideoSourceJpg = false;
343 mFrameRGBBuffer = NULL;
344 if(mFrameYUVBuffer != NULL) {
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700345 free(mFrameYUVBuffer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800346 mFrameYUVBuffer = NULL;
347 }
348}
349
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800350status_t PreviewPlayer::play() {
351 Mutex::Autolock autoLock(mLock);
352
353 mFlags &= ~CACHE_UNDERRUN;
354
355 return play_l();
356}
357
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800358status_t PreviewPlayer::startAudioPlayer_l() {
359 CHECK(!(mFlags & AUDIO_RUNNING));
360
361 if (mAudioSource == NULL || mAudioPlayer == NULL) {
362 return OK;
363 }
364
365 if (!(mFlags & AUDIOPLAYER_STARTED)) {
366 mFlags |= AUDIOPLAYER_STARTED;
367
368 // We've already started the MediaSource in order to enable
369 // the prefetcher to read its data.
370 status_t err = mVeAudioPlayer->start(
371 true /* sourceAlreadyStarted */);
372
373 if (err != OK) {
374 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
375 return err;
376 }
377 } else {
378 mVeAudioPlayer->resume();
379 }
380
381 mFlags |= AUDIO_RUNNING;
382
383 mWatchForAudioEOS = true;
384
385 return OK;
386}
387
James Dongc9dedc42011-05-01 12:36:22 -0700388status_t PreviewPlayer::setAudioPlayer(AudioPlayerBase *audioPlayer) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800389 Mutex::Autolock autoLock(mLock);
390 CHECK(!(mFlags & PLAYING));
391 mAudioPlayer = audioPlayer;
392
393 LOGV("SetAudioPlayer");
394 mIsChangeSourceRequired = true;
395 mVeAudioPlayer =
396 (VideoEditorAudioPlayer*)mAudioPlayer;
397
398 // check if the new and old source are dummy
399 sp<MediaSource> anAudioSource = mVeAudioPlayer->getSource();
400 if (anAudioSource == NULL) {
401 // Audio player does not have any source set.
402 LOGV("setAudioPlayer: Audio player does not have any source set");
403 return OK;
404 }
405
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800406 // If new video source is not dummy, then always change source
407 // Else audio player continues using old audio source and there are
408 // frame drops to maintain AV sync
409 sp<MetaData> meta;
410 if (mVideoSource != NULL) {
411 meta = mVideoSource->getFormat();
412 const char *pVidSrcType;
413 if (meta->findCString(kKeyDecoderComponent, &pVidSrcType)) {
414 if (strcmp(pVidSrcType, "DummyVideoSource") != 0) {
415 LOGV(" Video clip with silent audio; need to change source");
416 return OK;
417 }
418 }
419 }
420
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800421 const char *pSrcType1;
422 const char *pSrcType2;
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800423 meta = anAudioSource->getFormat();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800424
425 if (meta->findCString(kKeyDecoderComponent, &pSrcType1)) {
426 if (strcmp(pSrcType1, "DummyAudioSource") == 0) {
427 meta = mAudioSource->getFormat();
428 if (meta->findCString(kKeyDecoderComponent, &pSrcType2)) {
429 if (strcmp(pSrcType2, "DummyAudioSource") == 0) {
430 mIsChangeSourceRequired = false;
431 // Just set the new play duration for the existing source
432 MediaSource *pMediaSrc = anAudioSource.get();
433 DummyAudioSource *pDummyAudioSource = (DummyAudioSource*)pMediaSrc;
434 //Increment the duration of audio source
Raghavender Pallaebf40152011-03-14 20:15:12 -0700435 pDummyAudioSource->setDuration(
436 (int64_t)((mPlayEndTimeMsec)*1000LL));
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800437
438 // Stop the new audio source
439 // since we continue using old source
440 LOGV("setAudioPlayer: stop new audio source");
441 mAudioSource->stop();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800442 }
443 }
444 }
445 }
446
447 return OK;
448}
449
450void PreviewPlayer::onStreamDone() {
451 // Posted whenever any stream finishes playing.
452
453 Mutex::Autolock autoLock(mLock);
454 if (!mStreamDoneEventPending) {
455 return;
456 }
457 mStreamDoneEventPending = false;
458
459 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
460 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
461
462 notifyListener_l(
463 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
464
465 pause_l(true /* at eos */);
466
467 mFlags |= AT_EOS;
468 return;
469 }
470
471 const bool allDone =
472 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
473 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
474
475 if (!allDone) {
476 return;
477 }
478
479 if (mFlags & (LOOPING | AUTO_LOOPING)) {
480 seekTo_l(0);
481
482 if (mVideoSource != NULL) {
483 postVideoEvent_l();
484 }
485 } else {
486 LOGV("MEDIA_PLAYBACK_COMPLETE");
487 //pause before sending event
488 pause_l(true /* at eos */);
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700489
490 //This lock is used to syncronize onStreamDone() in PreviewPlayer and
491 //stopPreview() in PreviewController
492 Mutex::Autolock autoLock(mLockControl);
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800493 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
494
495 mFlags |= AT_EOS;
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700496 LOGV("onStreamDone end");
497 return;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800498 }
499}
500
501
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800502status_t PreviewPlayer::play_l() {
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800503
Rajneesh Chowdury8b95de22011-02-16 15:32:06 -0800504 mFlags &= ~SEEK_PREVIEW;
505
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800506 if (mFlags & PLAYING) {
507 return OK;
508 }
509 mStartNextPlayer = false;
510
511 if (!(mFlags & PREPARED)) {
512 status_t err = prepare_l();
513
514 if (err != OK) {
515 return err;
516 }
517 }
518
519 mFlags |= PLAYING;
520 mFlags |= FIRST_FRAME;
521
522 bool deferredAudioSeek = false;
523
524 if (mAudioSource != NULL) {
525 if (mAudioPlayer == NULL) {
526 if (mAudioSink != NULL) {
527
528 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800529 mVeAudioPlayer =
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800530 (VideoEditorAudioPlayer*)mAudioPlayer;
531
532 mAudioPlayer->setSource(mAudioSource);
533
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800534 mVeAudioPlayer->setAudioMixSettings(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800535 mPreviewPlayerAudioMixSettings);
536
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800537 mVeAudioPlayer->setAudioMixPCMFileHandle(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800538 mAudioMixPCMFileHandle);
539
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800540 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800541 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
542 mCurrentMediaVolumeValue);
543
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800544 mFlags |= AUDIOPLAYER_STARTED;
545 // We've already started the MediaSource in order to enable
546 // the prefetcher to read its data.
547 status_t err = mVeAudioPlayer->start(
548 true /* sourceAlreadyStarted */);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800549
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800550 if (err != OK) {
551 //delete mAudioPlayer;
552 mAudioPlayer = NULL;
553
554 mFlags &= ~(PLAYING | FIRST_FRAME);
555 return err;
556 }
557
558 mTimeSource = mVeAudioPlayer;
559 mFlags |= AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800560 deferredAudioSeek = true;
561 mWatchForAudioSeekComplete = false;
562 mWatchForAudioEOS = true;
563 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800564 } else {
565 mVeAudioPlayer = (VideoEditorAudioPlayer*)mAudioPlayer;
566 bool isAudioPlayerStarted = mVeAudioPlayer->isStarted();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800567
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800568 if (mIsChangeSourceRequired == true) {
569 LOGV("play_l: Change audio source required");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800570
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800571 if (isAudioPlayerStarted == true) {
572 mVeAudioPlayer->pause();
573 }
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800574
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800575 mVeAudioPlayer->setSource(mAudioSource);
576 mVeAudioPlayer->setObserver(this);
577
578 mVeAudioPlayer->setAudioMixSettings(
579 mPreviewPlayerAudioMixSettings);
580
581 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
582 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
583 mCurrentMediaVolumeValue);
584
585 if (isAudioPlayerStarted == true) {
586 mVeAudioPlayer->resume();
587 } else {
588 status_t err = OK;
589 err = mVeAudioPlayer->start(true);
590 if (err != OK) {
591 mAudioPlayer = NULL;
592 mVeAudioPlayer = NULL;
593
594 mFlags &= ~(PLAYING | FIRST_FRAME);
595 return err;
596 }
597 }
598 } else {
599 LOGV("play_l: No Source change required");
600 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
601 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
602 mCurrentMediaVolumeValue);
603
604 mVeAudioPlayer->resume();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800605 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800606
607 mFlags |= AUDIOPLAYER_STARTED;
608 mFlags |= AUDIO_RUNNING;
609 mTimeSource = mVeAudioPlayer;
610 deferredAudioSeek = true;
611 mWatchForAudioSeekComplete = false;
612 mWatchForAudioEOS = true;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800613 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800614 }
615
616 if (mTimeSource == NULL && mAudioPlayer == NULL) {
617 mTimeSource = &mSystemTimeSource;
618 }
619
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800620 // Set the seek option for Image source files and read.
621 // This resets the timestamping for image play
622 if (mIsVideoSourceJpg) {
623 MediaSource::ReadOptions options;
624 MediaBuffer *aLocalBuffer;
625 options.setSeekTo(mSeekTimeUs);
626 mVideoSource->read(&aLocalBuffer, &options);
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800627 aLocalBuffer->release();
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800628 }
629
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800630 if (mVideoSource != NULL) {
631 // Kick off video playback
632 postVideoEvent_l();
633 }
634
635 if (deferredAudioSeek) {
636 // If there was a seek request while we were paused
637 // and we're just starting up again, honor the request now.
638 seekAudioIfNecessary_l();
639 }
640
641 if (mFlags & AT_EOS) {
642 // Legacy behaviour, if a stream finishes playing and then
643 // is started again, we play from the start...
644 seekTo_l(0);
645 }
646
647 return OK;
648}
649
650
Santosh Madhavabfece172011-02-03 16:59:47 -0800651status_t PreviewPlayer::initRenderer_l() {
Mathias Agopian6e224292011-04-05 15:38:24 -0700652 if (mSurface != NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800653 sp<MetaData> meta = mVideoSource->getFormat();
654
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800655 const char *component;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800656 CHECK(meta->findCString(kKeyDecoderComponent, &component));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800657
658 // Must ensure that mVideoRenderer's destructor is actually executed
659 // before creating a new one.
660 IPCThreadState::self()->flushCommands();
661
662 // always use localrenderer since decoded buffers are modified
663 // by postprocessing module
664 // Other decoders are instantiated locally and as a consequence
665 // allocate their buffers in local address space.
666 if(mVideoRenderer == NULL) {
667
Chih-Chung Change048e902011-08-01 12:15:59 +0800668 mVideoRenderer = PreviewRenderer::CreatePreviewRenderer(
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +0800669 OMX_COLOR_FormatYUV420Planar,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800670 mSurface,
671 mOutputVideoWidth, mOutputVideoHeight,
Chih-Chung Change048e902011-08-01 12:15:59 +0800672 mOutputVideoWidth, mOutputVideoHeight,
673 0);
Santosh Madhavabfece172011-02-03 16:59:47 -0800674
675 if ( mVideoRenderer == NULL )
676 {
677 return UNKNOWN_ERROR;
678 }
679 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800680 }
681 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800682 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800683}
684
685
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800686status_t PreviewPlayer::seekTo(int64_t timeUs) {
687
688 if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) {
689 Mutex::Autolock autoLock(mLock);
690 return seekTo_l(timeUs);
691 }
692
693 return OK;
694}
695
696
697status_t PreviewPlayer::getVideoDimensions(
698 int32_t *width, int32_t *height) const {
699 Mutex::Autolock autoLock(mLock);
700
701 if (mVideoWidth < 0 || mVideoHeight < 0) {
702 return UNKNOWN_ERROR;
703 }
704
705 *width = mVideoWidth;
706 *height = mVideoHeight;
707
708 return OK;
709}
710
711
712status_t PreviewPlayer::initAudioDecoder() {
713 sp<MetaData> meta = mAudioTrack->getFormat();
714 const char *mime;
715 CHECK(meta->findCString(kKeyMIMEType, &mime));
716
717 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
718 mAudioSource = mAudioTrack;
719 } else {
720 sp<MediaSource> aRawSource;
721 aRawSource = OMXCodec::Create(
722 mClient.interface(), mAudioTrack->getFormat(),
723 false, // createEncoder
724 mAudioTrack);
725
726 if(aRawSource != NULL) {
727 LOGV("initAudioDecoder: new VideoEditorSRC");
728 mAudioSource = new VideoEditorSRC(aRawSource);
729 }
730 }
731
732 if (mAudioSource != NULL) {
733 int64_t durationUs;
734 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
735 Mutex::Autolock autoLock(mMiscStateLock);
736 if (mDurationUs < 0 || durationUs > mDurationUs) {
737 mDurationUs = durationUs;
738 }
739 }
740 status_t err = mAudioSource->start();
741
742 if (err != OK) {
743 mAudioSource.clear();
744 return err;
745 }
746 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
747 // For legacy reasons we're simply going to ignore the absence
748 // of an audio decoder for QCELP instead of aborting playback
749 // altogether.
750 return OK;
751 }
752
753 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
754}
755
756
757status_t PreviewPlayer::initVideoDecoder(uint32_t flags) {
758
759 mVideoSource = OMXCodec::Create(
760 mClient.interface(), mVideoTrack->getFormat(),
761 false,
762 mVideoTrack,
763 NULL, flags);
764
765 if (mVideoSource != NULL) {
766 int64_t durationUs;
767 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
768 Mutex::Autolock autoLock(mMiscStateLock);
769 if (mDurationUs < 0 || durationUs > mDurationUs) {
770 mDurationUs = durationUs;
771 }
772 }
773
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +0800774 getVideoBufferSize(mVideoTrack->getFormat(), &mVideoWidth, &mVideoHeight);
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800775 mReportedWidth = mVideoWidth;
776 mReportedHeight = mVideoHeight;
777
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800778 status_t err = mVideoSource->start();
779
780 if (err != OK) {
781 mVideoSource.clear();
782 return err;
783 }
784 }
785
786 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
787}
788
789
790void PreviewPlayer::onVideoEvent() {
791 uint32_t i=0;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800792 M4OSA_ERR err1 = M4NO_ERROR;
793 int64_t imageFrameTimeUs = 0;
794
795 Mutex::Autolock autoLock(mLock);
796 if (!mVideoEventPending) {
797 // The event has been cancelled in reset_l() but had already
798 // been scheduled for execution at that time.
799 return;
800 }
801 mVideoEventPending = false;
802
Andreas Huber9e4c36a2011-02-08 13:12:32 -0800803 if (mFlags & SEEK_PREVIEW) {
804 mFlags &= ~SEEK_PREVIEW;
805 return;
806 }
807
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800808 TimeSource *ts_st = &mSystemTimeSource;
809 int64_t timeStartUs = ts_st->getRealTimeUs();
810
Andreas Hubera5872f72011-02-24 15:25:21 -0800811 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800812
813 if(mAudioSource != NULL) {
814
815 // We're going to seek the video source first, followed by
816 // the audio source.
817 // In order to avoid jumps in the DataSource offset caused by
818 // the audio codec prefetching data from the old locations
819 // while the video codec is already reading data from the new
820 // locations, we'll "pause" the audio source, causing it to
821 // stop reading input data until a subsequent seek.
822
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800823 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800824 mAudioPlayer->pause();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800825 mFlags &= ~AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800826 }
827 mAudioSource->pause();
828 }
829 }
830
831 if (!mVideoBuffer) {
832 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -0800833 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800834 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
835 mSeekTimeUs / 1E6);
836
837 options.setSeekTo(
838 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
839 }
840 for (;;) {
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +0800841 status_t err = readYV12Buffer(mVideoSource, &mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800842 options.clearSeekTo();
843
844 if (err != OK) {
845 CHECK_EQ(mVideoBuffer, NULL);
846
847 if (err == INFO_FORMAT_CHANGED) {
848 LOGV("LV PLAYER VideoSource signalled format change");
849 notifyVideoSize_l();
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800850 sp<MetaData> meta = mVideoSource->getFormat();
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +0800851 getVideoBufferSize(meta, &mReportedWidth, &mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800852
853 if (mVideoRenderer != NULL) {
854 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -0800855 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800856 if (err != OK) {
857 postStreamDoneEvent_l(err);
858 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800859
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800860 }
861 continue;
862 }
863 // So video playback is complete, but we may still have
Santosh Madhava342f9322011-01-27 16:27:12 -0800864 // a seek request pending that needs to be applied to the audio track
Andreas Hubera5872f72011-02-24 15:25:21 -0800865 if (mSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800866 LOGV("video stream ended while seeking!");
867 }
868 finishSeekIfNecessary(-1);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800869 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
870 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800871 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800872 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800873 postStreamDoneEvent_l(err);
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800874 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -0700875 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800876 return;
877 }
878
879 if (mVideoBuffer->range_length() == 0) {
880 // Some decoders, notably the PV AVC software decoder
881 // return spurious empty buffers that we just want to ignore.
882
883 mVideoBuffer->release();
884 mVideoBuffer = NULL;
885 continue;
886 }
887
888 int64_t videoTimeUs;
889 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
890
Andreas Hubera5872f72011-02-24 15:25:21 -0800891 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800892 if (videoTimeUs < mSeekTimeUs) {
893 // buffers are before seek time
894 // ignore them
895 mVideoBuffer->release();
896 mVideoBuffer = NULL;
897 continue;
898 }
899 } else {
900 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
901 // Frames are before begin cut time
902 // Donot render
903 mVideoBuffer->release();
904 mVideoBuffer = NULL;
905 continue;
906 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800907 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800908 break;
909 }
910 }
911
912 mNumberDecVideoFrames++;
913
914 int64_t timeUs;
915 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
916
917 {
918 Mutex::Autolock autoLock(mMiscStateLock);
919 mVideoTimeUs = timeUs;
920 }
921
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800922
923 if(!mStartNextPlayer) {
Raghavender Pallaebf40152011-03-14 20:15:12 -0700924 int64_t playbackTimeRemaining = (mPlayEndTimeMsec*1000LL) - timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800925 if(playbackTimeRemaining <= 1500000) {
926 //When less than 1.5 sec of playback left
927 // send notification to start next player
928
929 mStartNextPlayer = true;
930 notifyListener_l(0xAAAAAAAA);
931 }
932 }
933
Andreas Hubera5872f72011-02-24 15:25:21 -0800934 SeekType wasSeeking = mSeeking;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800935 finishSeekIfNecessary(timeUs);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800936 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING))) {
937 status_t err = startAudioPlayer_l();
938 if (err != OK) {
939 LOGE("Starting the audio player failed w/ err %d", err);
940 return;
941 }
942 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800943
944 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
945
946 if(ts == NULL) {
947 mVideoBuffer->release();
948 mVideoBuffer = NULL;
949 return;
950 }
951
952 if(!mIsVideoSourceJpg) {
953 if (mFlags & FIRST_FRAME) {
954 mFlags &= ~FIRST_FRAME;
955
956 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
957 }
958
959 int64_t realTimeUs, mediaTimeUs;
960 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
961 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
962 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
963 }
964
965 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
966
967 int64_t latenessUs = nowUs - timeUs;
968
Andreas Hubera5872f72011-02-24 15:25:21 -0800969 if (wasSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800970 // Let's display the first frame after seeking right away.
971 latenessUs = 0;
972 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800973 LOGV("Audio time stamp = %lld and video time stamp = %lld",
974 ts->getRealTimeUs(),timeUs);
975 if (latenessUs > 40000) {
976 // We're more than 40ms late.
977
978 LOGV("LV PLAYER we're late by %lld us (%.2f secs)",
979 latenessUs, latenessUs / 1E6);
980
981 mVideoBuffer->release();
982 mVideoBuffer = NULL;
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800983 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800984 return;
985 }
986
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800987 if (latenessUs < -25000) {
988 // We're more than 25ms early.
989 LOGV("We're more than 25ms early, lateness %lld", latenessUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800990
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800991 postVideoEvent_l(25000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800992 return;
993 }
994 }
995
996 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
997 mVideoRendererIsPreview = false;
998
Santosh Madhavabfece172011-02-03 16:59:47 -0800999 status_t err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001000 if (err != OK) {
1001 postStreamDoneEvent_l(err);
1002 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001003 }
1004
1005 // If timestamp exceeds endCutTime of clip, donot render
1006 if((timeUs/1000) > mPlayEndTimeMsec) {
Chih-Chung Changcece4b32011-08-01 16:34:05 +08001007 mVideoBuffer->release();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001008 mVideoBuffer = NULL;
1009 mFlags |= VIDEO_AT_EOS;
1010 mFlags |= AUDIO_AT_EOS;
Santosh Madhavabfece172011-02-03 16:59:47 -08001011 LOGV("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS..");
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001012 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001013 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001014 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001015 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1016 return;
1017 }
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001018 // Capture the frame timestamp to be rendered
1019 mDecodedVideoTs = timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001020
1021 // Post processing to apply video effects
1022 for(i=0;i<mNumberEffects;i++) {
1023 // First check if effect starttime matches the clip being previewed
1024 if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) ||
1025 (mEffectsSettings[i].uiStartTime >=
1026 ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec)))
1027 {
1028 // This effect doesn't belong to this clip, check next one
1029 continue;
1030 }
1031 // Check if effect applies to this particular frame timestamp
1032 if((mEffectsSettings[i].uiStartTime <=
1033 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) &&
1034 ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=
1035 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec))
1036 && (mEffectsSettings[i].uiDuration != 0)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001037 setVideoPostProcessingNode(
1038 mEffectsSettings[i].VideoEffectType, TRUE);
1039 }
1040 else {
1041 setVideoPostProcessingNode(
1042 mEffectsSettings[i].VideoEffectType, FALSE);
1043 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001044 }
1045
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001046 //Provide the overlay Update indication when there is an overlay effect
Dharmaray Kundargid01ef562011-01-26 21:11:00 -08001047 if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) {
1048 mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here.
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001049 if (!mOverlayUpdateEventPosted) {
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001050 // Find the effect in effectSettings array
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001051 M4OSA_UInt32 index;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001052 for (index = 0; index < mNumberEffects; index++) {
1053 M4OSA_UInt32 timeMs = mDecodedVideoTs/1000;
1054 M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000;
1055 if(mEffectsSettings[index].VideoEffectType ==
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001056 (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001057 if (((mEffectsSettings[index].uiStartTime + 1) <=
1058 timeMs + timeOffset - mPlayBeginTimeMsec) &&
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001059 ((mEffectsSettings[index].uiStartTime - 1 +
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001060 mEffectsSettings[index].uiDuration) >=
1061 timeMs + timeOffset - mPlayBeginTimeMsec))
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001062 {
1063 break;
1064 }
1065 }
1066 }
1067 if (index < mNumberEffects) {
1068 mCurrFramingEffectIndex = index;
1069 mOverlayUpdateEventPosted = true;
1070 postOverlayUpdateEvent_l();
1071 LOGV("Framing index = %d", mCurrFramingEffectIndex);
1072 } else {
1073 LOGV("No framing effects found");
1074 }
1075 }
1076
1077 } else if (mOverlayUpdateEventPosted) {
1078 //Post the event when the overlay is no more valid
1079 LOGV("Overlay is Done");
1080 mOverlayUpdateEventPosted = false;
1081 postOverlayUpdateEvent_l();
1082 }
1083
1084
1085 if (mCurrentVideoEffect != VIDEO_EFFECT_NONE) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001086 err1 = doVideoPostProcessing();
1087 if(err1 != M4NO_ERROR) {
1088 LOGE("doVideoPostProcessing returned err");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001089 }
1090 }
1091 else {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001092 if(mRenderingMode != MEDIA_RENDERING_INVALID) {
1093 // No effects to be applied, but media rendering to be done
1094 err1 = doMediaRendering();
1095 if(err1 != M4NO_ERROR) {
1096 LOGE("doMediaRendering returned err");
1097 //Use original mVideoBuffer for rendering
1098 mVideoResizedOrCropped = false;
1099 }
1100 }
1101 }
1102
1103 if (mVideoRenderer != NULL) {
1104 LOGV("mVideoRenderer CALL render()");
Chih-Chung Change048e902011-08-01 12:15:59 +08001105 mVideoRenderer->renderYV12();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001106 }
1107
Chih-Chung Changcece4b32011-08-01 16:34:05 +08001108 mVideoBuffer->release();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001109 mVideoBuffer = NULL;
1110
1111 // Post progress callback based on callback interval set
1112 if(mNumberDecVideoFrames >= mProgressCbInterval) {
1113 postProgressCallbackEvent_l();
1114 mNumberDecVideoFrames = 0; // reset counter
1115 }
1116
1117 // if reached EndCutTime of clip, post EOS event
1118 if((timeUs/1000) >= mPlayEndTimeMsec) {
1119 LOGV("PreviewPlayer: onVideoEvent EOS.");
1120 mFlags |= VIDEO_AT_EOS;
1121 mFlags |= AUDIO_AT_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
Raghavender Pallaebf40152011-03-14 20:15:12 -07001124 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001125 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1126 }
1127 else {
Andreas Hubera5872f72011-02-24 15:25:21 -08001128 if ((wasSeeking != NO_SEEK) && (mFlags & SEEK_PREVIEW)) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001129 mFlags &= ~SEEK_PREVIEW;
1130 return;
1131 }
1132
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001133 if(!mIsVideoSourceJpg) {
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001134 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001135 }
1136 else {
1137 postVideoEvent_l(33000);
1138 }
1139 }
1140}
1141
1142status_t PreviewPlayer::prepare() {
1143 Mutex::Autolock autoLock(mLock);
1144 return prepare_l();
1145}
1146
1147status_t PreviewPlayer::prepare_l() {
1148 if (mFlags & PREPARED) {
1149 return OK;
1150 }
1151
1152 if (mFlags & PREPARING) {
1153 return UNKNOWN_ERROR;
1154 }
1155
1156 mIsAsyncPrepare = false;
1157 status_t err = prepareAsync_l();
1158
1159 if (err != OK) {
1160 return err;
1161 }
1162
1163 while (mFlags & PREPARING) {
1164 mPreparedCondition.wait(mLock);
1165 }
1166
1167 return mPrepareResult;
1168}
1169
1170status_t PreviewPlayer::prepareAsync_l() {
1171 if (mFlags & PREPARING) {
1172 return UNKNOWN_ERROR; // async prepare already pending
1173 }
1174
1175 if (!mQueueStarted) {
1176 mQueue.start();
1177 mQueueStarted = true;
1178 }
1179
1180 mFlags |= PREPARING;
1181 mAsyncPrepareEvent = new PreviewPlayerEvent(
1182 this, &PreviewPlayer::onPrepareAsyncEvent);
1183
1184 mQueue.postEvent(mAsyncPrepareEvent);
1185
1186 return OK;
1187}
1188
1189status_t PreviewPlayer::finishSetDataSource_l() {
1190 sp<DataSource> dataSource;
1191 sp<MediaExtractor> extractor;
1192
1193 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1194
1195 if (dataSource == NULL) {
1196 return UNKNOWN_ERROR;
1197 }
1198
1199 //If file type is .rgb, then no need to check for Extractor
1200 int uriLen = strlen(mUri);
1201 int startOffset = uriLen - 4;
1202 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) {
1203 extractor = NULL;
1204 }
1205 else {
1206 extractor = MediaExtractor::Create(dataSource,
1207 MEDIA_MIMETYPE_CONTAINER_MPEG4);
1208 }
1209
1210 if (extractor == NULL) {
1211 LOGV("PreviewPlayer::finishSetDataSource_l extractor == NULL");
1212 return setDataSource_l_jpg();
1213 }
1214
1215 return setDataSource_l(extractor);
1216}
1217
1218
1219// static
1220bool PreviewPlayer::ContinuePreparation(void *cookie) {
1221 PreviewPlayer *me = static_cast<PreviewPlayer *>(cookie);
1222
1223 return (me->mFlags & PREPARE_CANCELLED) == 0;
1224}
1225
1226void PreviewPlayer::onPrepareAsyncEvent() {
1227 Mutex::Autolock autoLock(mLock);
1228 LOGV("onPrepareAsyncEvent");
1229
1230 if (mFlags & PREPARE_CANCELLED) {
Santosh Madhavabfece172011-02-03 16:59:47 -08001231 LOGV("LV PLAYER prepare was cancelled before doing anything");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001232 abortPrepare(UNKNOWN_ERROR);
1233 return;
1234 }
1235
1236 if (mUri.size() > 0) {
1237 status_t err = finishSetDataSource_l();
1238
1239 if (err != OK) {
1240 abortPrepare(err);
1241 return;
1242 }
1243 }
1244
1245 if (mVideoTrack != NULL && mVideoSource == NULL) {
1246 status_t err = initVideoDecoder(OMXCodec::kHardwareCodecsOnly);
1247
1248 if (err != OK) {
1249 abortPrepare(err);
1250 return;
1251 }
1252 }
1253
1254 if (mAudioTrack != NULL && mAudioSource == NULL) {
1255 status_t err = initAudioDecoder();
1256
1257 if (err != OK) {
1258 abortPrepare(err);
1259 return;
1260 }
1261 }
1262 finishAsyncPrepare_l();
1263
1264}
1265
1266void PreviewPlayer::finishAsyncPrepare_l() {
1267 if (mIsAsyncPrepare) {
1268 if (mVideoSource == NULL) {
1269 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE 0 0 ");
1270 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1271 } else {
1272 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE");
1273 notifyVideoSize_l();
1274 }
1275 LOGV("finishAsyncPrepare_l: MEDIA_PREPARED");
1276 notifyListener_l(MEDIA_PREPARED);
1277 }
1278
1279 mPrepareResult = OK;
1280 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1281 mFlags |= PREPARED;
1282 mAsyncPrepareEvent = NULL;
1283 mPreparedCondition.broadcast();
1284}
1285
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001286void PreviewPlayer::acquireLock() {
1287 LOGV("acquireLock");
1288 mLockControl.lock();
1289}
1290
1291void PreviewPlayer::releaseLock() {
1292 LOGV("releaseLock");
1293 mLockControl.unlock();
1294}
1295
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001296status_t PreviewPlayer::loadEffectsSettings(
1297 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) {
1298 M4OSA_UInt32 i = 0, rgbSize = 0;
1299 M4VIFI_UInt8 *tmp = M4OSA_NULL;
1300
1301 mNumberEffects = nEffects;
1302 mEffectsSettings = pEffectSettings;
1303 return OK;
1304}
1305
1306status_t PreviewPlayer::loadAudioMixSettings(
1307 M4xVSS_AudioMixingSettings* pAudioMixSettings) {
1308
1309 LOGV("PreviewPlayer: loadAudioMixSettings: ");
1310 mPreviewPlayerAudioMixSettings = pAudioMixSettings;
1311 return OK;
1312}
1313
1314status_t PreviewPlayer::setAudioMixPCMFileHandle(
1315 M4OSA_Context pAudioMixPCMFileHandle) {
1316
1317 LOGV("PreviewPlayer: setAudioMixPCMFileHandle: ");
1318 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle;
1319 return OK;
1320}
1321
1322status_t PreviewPlayer::setAudioMixStoryBoardParam(
1323 M4OSA_UInt32 audioMixStoryBoardTS,
1324 M4OSA_UInt32 currentMediaBeginCutTime,
1325 M4OSA_UInt32 primaryTrackVolValue ) {
1326
1327 mAudioMixStoryBoardTS = audioMixStoryBoardTS;
1328 mCurrentMediaBeginCutTime = currentMediaBeginCutTime;
1329 mCurrentMediaVolumeValue = primaryTrackVolValue;
1330 return OK;
1331}
1332
1333status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) {
1334
1335 mPlayBeginTimeMsec = msec;
1336 return OK;
1337}
1338
1339status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) {
1340
1341 mPlayEndTimeMsec = msec;
1342 return OK;
1343}
1344
1345status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) {
1346
1347 mStoryboardStartTimeMsec = msec;
Raghavender Pallaebf40152011-03-14 20:15:12 -07001348 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001349 return OK;
1350}
1351
1352status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) {
1353
1354 mProgressCbInterval = cbInterval;
1355 return OK;
1356}
1357
1358
1359status_t PreviewPlayer::setMediaRenderingMode(
1360 M4xVSS_MediaRendering mode,
1361 M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
1362
1363 mRenderingMode = mode;
1364
1365 /* reset boolean for each clip*/
1366 mVideoResizedOrCropped = false;
1367
Hong Teng8806b702011-07-06 18:29:28 -07001368 status_t err = OK;
1369 /* get the video width and height by resolution */
1370 err = getVideoSizeByResolution(outputVideoSize,
1371 &mOutputVideoWidth, &mOutputVideoHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001372
Hong Teng8806b702011-07-06 18:29:28 -07001373 return err;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001374}
1375
1376M4OSA_ERR PreviewPlayer::doMediaRendering() {
1377 M4OSA_ERR err = M4NO_ERROR;
1378 M4VIFI_ImagePlane planeIn[3], planeOut[3];
1379 M4VIFI_UInt8 *inBuffer = M4OSA_NULL, *finalOutputBuffer = M4OSA_NULL;
1380 M4VIFI_UInt8 *tempOutputBuffer= M4OSA_NULL;
1381 size_t videoBufferSize = 0;
1382 M4OSA_UInt32 frameSize = 0, i=0, index =0, nFrameCount =0, bufferOffset =0;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001383
1384 videoBufferSize = mVideoBuffer->size();
1385 frameSize = (mVideoWidth*mVideoHeight*3) >> 1;
1386
1387 uint8_t* outBuffer;
1388 size_t outBufferStride = 0;
1389
Chih-Chung Change048e902011-08-01 12:15:59 +08001390 mVideoRenderer->getBufferYV12(&outBuffer, &outBufferStride);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001391
1392 bufferOffset = index*frameSize;
1393 inBuffer = (M4OSA_UInt8 *)mVideoBuffer->data()+
1394 mVideoBuffer->range_offset()+bufferOffset;
1395
1396
1397 /* In plane*/
1398 prepareYUV420ImagePlane(planeIn, mVideoWidth,
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001399 mVideoHeight, (M4VIFI_UInt8 *)inBuffer, mReportedWidth, mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001400
1401 // Set the output YUV420 plane to be compatible with YV12 format
1402 // W & H even
1403 // YVU instead of YUV
1404 // align buffers on 32 bits
1405
1406 //In YV12 format, sizes must be even
1407 M4OSA_UInt32 yv12PlaneWidth = ((mOutputVideoWidth +1)>>1)<<1;
1408 M4OSA_UInt32 yv12PlaneHeight = ((mOutputVideoHeight+1)>>1)<<1;
1409
1410 prepareYV12ImagePlane(planeOut, yv12PlaneWidth, yv12PlaneHeight,
1411 (M4OSA_UInt32)outBufferStride, (M4VIFI_UInt8 *)outBuffer);
1412
1413
1414 err = applyRenderingMode(planeIn, planeOut, mRenderingMode);
1415
1416 if(err != M4NO_ERROR)
1417 {
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001418 LOGE("doMediaRendering: applyRenderingMode returned err=0x%x", (int)err);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001419 return err;
1420 }
1421 mVideoResizedOrCropped = true;
1422
1423 return err;
1424}
1425
1426status_t PreviewPlayer::resetJniCallbackTimeStamp() {
1427
Raghavender Pallaebf40152011-03-14 20:15:12 -07001428 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001429 return OK;
1430}
1431
1432void PreviewPlayer::postProgressCallbackEvent_l() {
1433 if (mProgressCbEventPending) {
1434 return;
1435 }
1436 mProgressCbEventPending = true;
1437
1438 mQueue.postEvent(mProgressCbEvent);
1439}
1440
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001441
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001442void PreviewPlayer::onProgressCbEvent() {
1443 Mutex::Autolock autoLock(mLock);
1444 if (!mProgressCbEventPending) {
1445 return;
1446 }
1447 mProgressCbEventPending = false;
1448 // If playback starts from previous I-frame,
1449 // then send frame storyboard duration
1450 if((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) {
1451 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000);
1452 }
1453 else {
1454 notifyListener_l(MEDIA_INFO, 0,
1455 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec));
1456 }
1457}
1458
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001459void PreviewPlayer::postOverlayUpdateEvent_l() {
1460 if (mOverlayUpdateEventPending) {
1461 return;
1462 }
1463 mOverlayUpdateEventPending = true;
1464 mQueue.postEvent(mOverlayUpdateEvent);
1465}
1466
1467void PreviewPlayer::onUpdateOverlayEvent() {
1468 Mutex::Autolock autoLock(mLock);
1469
1470 if (!mOverlayUpdateEventPending) {
1471 return;
1472 }
1473 mOverlayUpdateEventPending = false;
1474
1475 int updateState;
1476 if (mOverlayUpdateEventPosted) {
1477 updateState = 1;
1478 } else {
1479 updateState = 0;
1480 }
1481 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex);
1482}
1483
1484
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001485void PreviewPlayer::setVideoPostProcessingNode(
1486 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
1487
1488 uint32_t effect = VIDEO_EFFECT_NONE;
1489
1490 //Map M4VSS3GPP_VideoEffectType to local enum
1491 switch(type) {
1492 case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
1493 effect = VIDEO_EFFECT_FADEFROMBLACK;
1494 break;
1495
1496 case M4VSS3GPP_kVideoEffectType_FadeToBlack:
1497 effect = VIDEO_EFFECT_FADETOBLACK;
1498 break;
1499
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001500 case M4xVSS_kVideoEffectType_BlackAndWhite:
1501 effect = VIDEO_EFFECT_BLACKANDWHITE;
1502 break;
1503
1504 case M4xVSS_kVideoEffectType_Pink:
1505 effect = VIDEO_EFFECT_PINK;
1506 break;
1507
1508 case M4xVSS_kVideoEffectType_Green:
1509 effect = VIDEO_EFFECT_GREEN;
1510 break;
1511
1512 case M4xVSS_kVideoEffectType_Sepia:
1513 effect = VIDEO_EFFECT_SEPIA;
1514 break;
1515
1516 case M4xVSS_kVideoEffectType_Negative:
1517 effect = VIDEO_EFFECT_NEGATIVE;
1518 break;
1519
1520 case M4xVSS_kVideoEffectType_Framing:
1521 effect = VIDEO_EFFECT_FRAMING;
1522 break;
1523
1524 case M4xVSS_kVideoEffectType_Fifties:
1525 effect = VIDEO_EFFECT_FIFTIES;
1526 break;
1527
1528 case M4xVSS_kVideoEffectType_ColorRGB16:
1529 effect = VIDEO_EFFECT_COLOR_RGB16;
1530 break;
1531
1532 case M4xVSS_kVideoEffectType_Gradient:
1533 effect = VIDEO_EFFECT_GRADIENT;
1534 break;
1535
1536 default:
1537 effect = VIDEO_EFFECT_NONE;
1538 break;
1539 }
1540
1541 if(enable == M4OSA_TRUE) {
1542 //If already set, then no need to set again
1543 if(!(mCurrentVideoEffect & effect)) {
1544 mCurrentVideoEffect |= effect;
1545 if(effect == VIDEO_EFFECT_FIFTIES) {
1546 mIsFiftiesEffectStarted = true;
1547 }
1548 }
1549 }
1550 else {
1551 //Reset only if already set
1552 if(mCurrentVideoEffect & effect) {
1553 mCurrentVideoEffect &= ~effect;
1554 }
1555 }
1556}
1557
1558status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) {
1559 mVideoWidth = width;
1560 mVideoHeight = height;
1561 return OK;
1562}
1563
1564
1565M4OSA_ERR PreviewPlayer::doVideoPostProcessing() {
1566 M4OSA_ERR err = M4NO_ERROR;
1567 vePostProcessParams postProcessParams;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001568
1569 postProcessParams.vidBuffer = (M4VIFI_UInt8*)mVideoBuffer->data()
1570 + mVideoBuffer->range_offset();
1571
1572 postProcessParams.videoWidth = mVideoWidth;
1573 postProcessParams.videoHeight = mVideoHeight;
1574 postProcessParams.timeMs = mDecodedVideoTs/1000;
1575 postProcessParams.timeOffset = mDecVideoTsStoryBoard/1000;
1576 postProcessParams.effectsSettings = mEffectsSettings;
1577 postProcessParams.numberEffects = mNumberEffects;
1578 postProcessParams.outVideoWidth = mOutputVideoWidth;
1579 postProcessParams.outVideoHeight = mOutputVideoHeight;
1580 postProcessParams.currentVideoEffect = mCurrentVideoEffect;
1581 postProcessParams.renderingMode = mRenderingMode;
1582 if(mIsFiftiesEffectStarted == M4OSA_TRUE) {
1583 postProcessParams.isFiftiesEffectStarted = M4OSA_TRUE;
1584 mIsFiftiesEffectStarted = M4OSA_FALSE;
1585 }
1586 else {
1587 postProcessParams.isFiftiesEffectStarted = M4OSA_FALSE;
1588 }
1589
1590 postProcessParams.overlayFrameRGBBuffer = mFrameRGBBuffer;
1591 postProcessParams.overlayFrameYUVBuffer = mFrameYUVBuffer;
Chih-Chung Change048e902011-08-01 12:15:59 +08001592 mVideoRenderer->getBufferYV12(&(postProcessParams.pOutBuffer),
1593 &(postProcessParams.outBufferStride));
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001594 err = applyEffectsAndRenderingMode(&postProcessParams, mReportedWidth, mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001595
1596 return err;
1597}
1598
1599status_t PreviewPlayer::readFirstVideoFrame() {
1600 LOGV("PreviewPlayer::readFirstVideoFrame");
1601
1602 if (!mVideoBuffer) {
1603 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -08001604 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001605 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
1606 mSeekTimeUs / 1E6);
1607
1608 options.setSeekTo(
1609 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
1610 }
1611 for (;;) {
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +08001612 status_t err = readYV12Buffer(mVideoSource, &mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001613 options.clearSeekTo();
1614
1615 if (err != OK) {
1616 CHECK_EQ(mVideoBuffer, NULL);
1617
1618 if (err == INFO_FORMAT_CHANGED) {
1619 LOGV("LV PLAYER VideoSource signalled format change");
1620 notifyVideoSize_l();
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001621 sp<MetaData> meta = mVideoSource->getFormat();
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +08001622 getVideoBufferSize(meta, &mReportedWidth, &mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001623
1624 if (mVideoRenderer != NULL) {
1625 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -08001626 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001627 if (err != OK) {
1628 postStreamDoneEvent_l(err);
1629 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001630 }
1631 continue;
1632 }
1633 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
1634 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001635 mFlags |= AUDIO_AT_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001636 postStreamDoneEvent_l(err);
1637 return OK;
1638 }
1639
1640 if (mVideoBuffer->range_length() == 0) {
1641 // Some decoders, notably the PV AVC software decoder
1642 // return spurious empty buffers that we just want to ignore.
1643
1644 mVideoBuffer->release();
1645 mVideoBuffer = NULL;
1646 continue;
1647 }
1648
1649 int64_t videoTimeUs;
1650 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
Andreas Hubera5872f72011-02-24 15:25:21 -08001651 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001652 if (videoTimeUs < mSeekTimeUs) {
1653 // buffers are before seek time
1654 // ignore them
1655 mVideoBuffer->release();
1656 mVideoBuffer = NULL;
1657 continue;
1658 }
1659 } else {
1660 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
1661 // buffers are before begin cut time
1662 // ignore them
1663 mVideoBuffer->release();
1664 mVideoBuffer = NULL;
1665 continue;
1666 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001667 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001668 break;
1669 }
1670 }
1671
1672 int64_t timeUs;
1673 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1674
1675 {
1676 Mutex::Autolock autoLock(mMiscStateLock);
1677 mVideoTimeUs = timeUs;
1678 }
1679
1680 mDecodedVideoTs = timeUs;
1681
1682 return OK;
1683
1684}
1685
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001686status_t PreviewPlayer::getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs) {
1687 *lastRenderedTimeMs = (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec);
1688 return OK;
1689}
1690
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001691} // namespace android