blob: 0f04c0ad665288dcb5382dd80b13aba746666cbb [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;
84 mLastVideoBuffer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080085 mEffectsSettings = NULL;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -080086 mVeAudioPlayer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080087 mAudioMixStoryBoardTS = 0;
88 mCurrentMediaBeginCutTime = 0;
89 mCurrentMediaVolumeValue = 0;
90 mNumberEffects = 0;
91 mDecodedVideoTs = 0;
92 mDecVideoTsStoryBoard = 0;
93 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
94 mProgressCbInterval = 0;
95 mNumberDecVideoFrames = 0;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -080096 mOverlayUpdateEventPosted = false;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -080097 mIsChangeSourceRequired = true;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080098
99 mVideoEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoEvent);
100 mVideoEventPending = false;
101 mStreamDoneEvent = new PreviewPlayerEvent(this,
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800102 &PreviewPlayer::onStreamDone);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800103
104 mStreamDoneEventPending = false;
105
106 mCheckAudioStatusEvent = new PreviewPlayerEvent(
James Dongc9dedc42011-05-01 12:36:22 -0700107 this, &PreviewPlayerBase::onCheckAudioStatus);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800108
109 mAudioStatusEventPending = false;
110
111 mProgressCbEvent = new PreviewPlayerEvent(this,
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800112 &PreviewPlayer::onProgressCbEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800113
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800114 mOverlayUpdateEvent = new PreviewPlayerEvent(this,
115 &PreviewPlayer::onUpdateOverlayEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800116 mProgressCbEventPending = false;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800117
118 mOverlayUpdateEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800119 mResizedVideoBuffer = NULL;
120 mVideoResizedOrCropped = false;
121 mRenderingMode = (M4xVSS_MediaRendering)MEDIA_RENDERING_INVALID;
122 mIsFiftiesEffectStarted = false;
123 reset();
124}
125
126PreviewPlayer::~PreviewPlayer() {
127
128 if (mQueueStarted) {
129 mQueue.stop();
130 }
131
132 reset();
133
134 if(mResizedVideoBuffer != NULL) {
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700135 free((mResizedVideoBuffer->data()));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800136 mResizedVideoBuffer = NULL;
137 }
138
Chih-Chung Change048e902011-08-01 12:15:59 +0800139 delete mVideoRenderer;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800140}
141
142void PreviewPlayer::cancelPlayerEvents(bool keepBufferingGoing) {
143 mQueue.cancelEvent(mVideoEvent->eventID());
144 mVideoEventPending = false;
145 mQueue.cancelEvent(mStreamDoneEvent->eventID());
146 mStreamDoneEventPending = false;
147 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
148 mAudioStatusEventPending = false;
149
150 mQueue.cancelEvent(mProgressCbEvent->eventID());
151 mProgressCbEventPending = false;
152}
153
154status_t PreviewPlayer::setDataSource(
155 const char *uri, const KeyedVector<String8, String8> *headers) {
156 Mutex::Autolock autoLock(mLock);
157 return setDataSource_l(uri, headers);
158}
159
160status_t PreviewPlayer::setDataSource_l(
161 const char *uri, const KeyedVector<String8, String8> *headers) {
162 reset_l();
163
164 mUri = uri;
165
166 if (headers) {
167 mUriHeaders = *headers;
168 }
169
170 // The actual work will be done during preparation in the call to
171 // ::finishSetDataSource_l to avoid blocking the calling thread in
172 // setDataSource for any significant time.
173 return OK;
174}
175
176status_t PreviewPlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
177 bool haveAudio = false;
178 bool haveVideo = false;
179 for (size_t i = 0; i < extractor->countTracks(); ++i) {
180 sp<MetaData> meta = extractor->getTrackMetaData(i);
181
182 const char *mime;
183 CHECK(meta->findCString(kKeyMIMEType, &mime));
184
185 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
186 setVideoSource(extractor->getTrack(i));
187 haveVideo = true;
188 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
189 setAudioSource(extractor->getTrack(i));
190 haveAudio = true;
191
192 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
193 // Only do this for vorbis audio, none of the other audio
194 // formats even support this ringtone specific hack and
195 // retrieving the metadata on some extractors may turn out
196 // to be very expensive.
197 sp<MetaData> fileMeta = extractor->getMetaData();
198 int32_t loop;
199 if (fileMeta != NULL
200 && fileMeta->findInt32(kKeyAutoLoop, &loop)
201 && loop != 0) {
202 mFlags |= AUTO_LOOPING;
203 }
204 }
205 }
206
207 if (haveAudio && haveVideo) {
208 break;
209 }
210 }
211
212 /* Add the support for Dummy audio*/
213 if( !haveAudio ){
214 LOGV("PreviewPlayer: setDataSource_l Dummyaudiocreation started");
215
216 mAudioTrack = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700217 ((mPlayEndTimeMsec)*1000LL));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800218 LOGV("PreviewPlayer: setDataSource_l Dummyauiosource created");
219 if(mAudioTrack != NULL) {
220 haveAudio = true;
221 }
222 }
223
224 if (!haveAudio && !haveVideo) {
225 return UNKNOWN_ERROR;
226 }
227
228 mExtractorFlags = extractor->flags();
229 return OK;
230}
231
232status_t PreviewPlayer::setDataSource_l_jpg() {
233 M4OSA_ERR err = M4NO_ERROR;
234 LOGV("PreviewPlayer: setDataSource_l_jpg started");
235
236 mAudioSource = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700237 ((mPlayEndTimeMsec)*1000LL));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800238 LOGV("PreviewPlayer: setDataSource_l_jpg Dummyaudiosource created");
239 if(mAudioSource != NULL) {
240 setAudioSource(mAudioSource);
241 }
242 status_t error = mAudioSource->start();
243 if (error != OK) {
244 LOGV("Error starting dummy audio source");
245 mAudioSource.clear();
246 return err;
247 }
248
Raghavender Pallaebf40152011-03-14 20:15:12 -0700249 mDurationUs = (mPlayEndTimeMsec - mPlayBeginTimeMsec)*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800250
251 mVideoSource = DummyVideoSource::Create(mVideoWidth, mVideoHeight,
252 mDurationUs, mUri);
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800253 mReportedWidth = mVideoWidth;
254 mReportedHeight = mVideoHeight;
255
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800256 setVideoSource(mVideoSource);
257 status_t err1 = mVideoSource->start();
258 if (err1 != OK) {
259 mVideoSource.clear();
260 return err;
261 }
262
263 mIsVideoSourceJpg = true;
264 return OK;
265}
266
267void PreviewPlayer::reset() {
268 Mutex::Autolock autoLock(mLock);
269 reset_l();
270}
271
272void PreviewPlayer::reset_l() {
273
274 if (mFlags & PREPARING) {
275 mFlags |= PREPARE_CANCELLED;
276 }
277
278 while (mFlags & PREPARING) {
279 mPreparedCondition.wait(mLock);
280 }
281
282 cancelPlayerEvents();
283 mAudioTrack.clear();
284 mVideoTrack.clear();
285
286 // Shutdown audio first, so that the respone to the reset request
287 // appears to happen instantaneously as far as the user is concerned
288 // If we did this later, audio would continue playing while we
289 // shutdown the video-related resources and the player appear to
290 // not be as responsive to a reset request.
291 if (mAudioPlayer == NULL && mAudioSource != NULL) {
292 // If we had an audio player, it would have effectively
293 // taken possession of the audio source and stopped it when
294 // _it_ is stopped. Otherwise this is still our responsibility.
295 mAudioSource->stop();
296 }
297 mAudioSource.clear();
298
299 mTimeSource = NULL;
300
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800301 //Single audio player instance used
302 //So donot delete it here
303 //It is deleted from PreviewController class
304 //delete mAudioPlayer;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800305 mAudioPlayer = NULL;
306
307 if (mLastVideoBuffer) {
308 mLastVideoBuffer->release();
309 mLastVideoBuffer = NULL;
310 }
311
312 if (mVideoBuffer) {
313 mVideoBuffer->release();
314 mVideoBuffer = NULL;
315 }
316
317 if (mVideoSource != NULL) {
318 mVideoSource->stop();
319
320 // The following hack is necessary to ensure that the OMX
321 // component is completely released by the time we may try
322 // to instantiate it again.
323 wp<MediaSource> tmp = mVideoSource;
324 mVideoSource.clear();
325 while (tmp.promote() != NULL) {
326 usleep(1000);
327 }
328 IPCThreadState::self()->flushCommands();
329 }
330
331 mDurationUs = -1;
332 mFlags = 0;
333 mExtractorFlags = 0;
334 mVideoWidth = mVideoHeight = -1;
335 mTimeSourceDeltaUs = 0;
336 mVideoTimeUs = 0;
337
Andreas Hubera5872f72011-02-24 15:25:21 -0800338 mSeeking = NO_SEEK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800339 mSeekNotificationSent = false;
340 mSeekTimeUs = 0;
341
342 mUri.setTo("");
343 mUriHeaders.clear();
344
345 mFileSource.clear();
346
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800347 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
348 mIsVideoSourceJpg = false;
349 mFrameRGBBuffer = NULL;
350 if(mFrameYUVBuffer != NULL) {
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700351 free(mFrameYUVBuffer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800352 mFrameYUVBuffer = NULL;
353 }
354}
355
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800356status_t PreviewPlayer::play() {
357 Mutex::Autolock autoLock(mLock);
358
359 mFlags &= ~CACHE_UNDERRUN;
360
361 return play_l();
362}
363
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800364status_t PreviewPlayer::startAudioPlayer_l() {
365 CHECK(!(mFlags & AUDIO_RUNNING));
366
367 if (mAudioSource == NULL || mAudioPlayer == NULL) {
368 return OK;
369 }
370
371 if (!(mFlags & AUDIOPLAYER_STARTED)) {
372 mFlags |= AUDIOPLAYER_STARTED;
373
374 // We've already started the MediaSource in order to enable
375 // the prefetcher to read its data.
376 status_t err = mVeAudioPlayer->start(
377 true /* sourceAlreadyStarted */);
378
379 if (err != OK) {
380 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
381 return err;
382 }
383 } else {
384 mVeAudioPlayer->resume();
385 }
386
387 mFlags |= AUDIO_RUNNING;
388
389 mWatchForAudioEOS = true;
390
391 return OK;
392}
393
James Dongc9dedc42011-05-01 12:36:22 -0700394status_t PreviewPlayer::setAudioPlayer(AudioPlayerBase *audioPlayer) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800395 Mutex::Autolock autoLock(mLock);
396 CHECK(!(mFlags & PLAYING));
397 mAudioPlayer = audioPlayer;
398
399 LOGV("SetAudioPlayer");
400 mIsChangeSourceRequired = true;
401 mVeAudioPlayer =
402 (VideoEditorAudioPlayer*)mAudioPlayer;
403
404 // check if the new and old source are dummy
405 sp<MediaSource> anAudioSource = mVeAudioPlayer->getSource();
406 if (anAudioSource == NULL) {
407 // Audio player does not have any source set.
408 LOGV("setAudioPlayer: Audio player does not have any source set");
409 return OK;
410 }
411
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800412 // If new video source is not dummy, then always change source
413 // Else audio player continues using old audio source and there are
414 // frame drops to maintain AV sync
415 sp<MetaData> meta;
416 if (mVideoSource != NULL) {
417 meta = mVideoSource->getFormat();
418 const char *pVidSrcType;
419 if (meta->findCString(kKeyDecoderComponent, &pVidSrcType)) {
420 if (strcmp(pVidSrcType, "DummyVideoSource") != 0) {
421 LOGV(" Video clip with silent audio; need to change source");
422 return OK;
423 }
424 }
425 }
426
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800427 const char *pSrcType1;
428 const char *pSrcType2;
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800429 meta = anAudioSource->getFormat();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800430
431 if (meta->findCString(kKeyDecoderComponent, &pSrcType1)) {
432 if (strcmp(pSrcType1, "DummyAudioSource") == 0) {
433 meta = mAudioSource->getFormat();
434 if (meta->findCString(kKeyDecoderComponent, &pSrcType2)) {
435 if (strcmp(pSrcType2, "DummyAudioSource") == 0) {
436 mIsChangeSourceRequired = false;
437 // Just set the new play duration for the existing source
438 MediaSource *pMediaSrc = anAudioSource.get();
439 DummyAudioSource *pDummyAudioSource = (DummyAudioSource*)pMediaSrc;
440 //Increment the duration of audio source
Raghavender Pallaebf40152011-03-14 20:15:12 -0700441 pDummyAudioSource->setDuration(
442 (int64_t)((mPlayEndTimeMsec)*1000LL));
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800443
444 // Stop the new audio source
445 // since we continue using old source
446 LOGV("setAudioPlayer: stop new audio source");
447 mAudioSource->stop();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800448 }
449 }
450 }
451 }
452
453 return OK;
454}
455
456void PreviewPlayer::onStreamDone() {
457 // Posted whenever any stream finishes playing.
458
459 Mutex::Autolock autoLock(mLock);
460 if (!mStreamDoneEventPending) {
461 return;
462 }
463 mStreamDoneEventPending = false;
464
465 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
466 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
467
468 notifyListener_l(
469 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
470
471 pause_l(true /* at eos */);
472
473 mFlags |= AT_EOS;
474 return;
475 }
476
477 const bool allDone =
478 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
479 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
480
481 if (!allDone) {
482 return;
483 }
484
485 if (mFlags & (LOOPING | AUTO_LOOPING)) {
486 seekTo_l(0);
487
488 if (mVideoSource != NULL) {
489 postVideoEvent_l();
490 }
491 } else {
492 LOGV("MEDIA_PLAYBACK_COMPLETE");
493 //pause before sending event
494 pause_l(true /* at eos */);
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700495
496 //This lock is used to syncronize onStreamDone() in PreviewPlayer and
497 //stopPreview() in PreviewController
498 Mutex::Autolock autoLock(mLockControl);
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800499 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
500
501 mFlags |= AT_EOS;
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700502 LOGV("onStreamDone end");
503 return;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800504 }
505}
506
507
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800508status_t PreviewPlayer::play_l() {
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800509
Rajneesh Chowdury8b95de22011-02-16 15:32:06 -0800510 mFlags &= ~SEEK_PREVIEW;
511
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800512 if (mFlags & PLAYING) {
513 return OK;
514 }
515 mStartNextPlayer = false;
516
517 if (!(mFlags & PREPARED)) {
518 status_t err = prepare_l();
519
520 if (err != OK) {
521 return err;
522 }
523 }
524
525 mFlags |= PLAYING;
526 mFlags |= FIRST_FRAME;
527
528 bool deferredAudioSeek = false;
529
530 if (mAudioSource != NULL) {
531 if (mAudioPlayer == NULL) {
532 if (mAudioSink != NULL) {
533
534 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800535 mVeAudioPlayer =
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800536 (VideoEditorAudioPlayer*)mAudioPlayer;
537
538 mAudioPlayer->setSource(mAudioSource);
539
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800540 mVeAudioPlayer->setAudioMixSettings(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800541 mPreviewPlayerAudioMixSettings);
542
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800543 mVeAudioPlayer->setAudioMixPCMFileHandle(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800544 mAudioMixPCMFileHandle);
545
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800546 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800547 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
548 mCurrentMediaVolumeValue);
549
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800550 mFlags |= AUDIOPLAYER_STARTED;
551 // We've already started the MediaSource in order to enable
552 // the prefetcher to read its data.
553 status_t err = mVeAudioPlayer->start(
554 true /* sourceAlreadyStarted */);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800555
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800556 if (err != OK) {
557 //delete mAudioPlayer;
558 mAudioPlayer = NULL;
559
560 mFlags &= ~(PLAYING | FIRST_FRAME);
561 return err;
562 }
563
564 mTimeSource = mVeAudioPlayer;
565 mFlags |= AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800566 deferredAudioSeek = true;
567 mWatchForAudioSeekComplete = false;
568 mWatchForAudioEOS = true;
569 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800570 } else {
571 mVeAudioPlayer = (VideoEditorAudioPlayer*)mAudioPlayer;
572 bool isAudioPlayerStarted = mVeAudioPlayer->isStarted();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800573
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800574 if (mIsChangeSourceRequired == true) {
575 LOGV("play_l: Change audio source required");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800576
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800577 if (isAudioPlayerStarted == true) {
578 mVeAudioPlayer->pause();
579 }
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800580
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800581 mVeAudioPlayer->setSource(mAudioSource);
582 mVeAudioPlayer->setObserver(this);
583
584 mVeAudioPlayer->setAudioMixSettings(
585 mPreviewPlayerAudioMixSettings);
586
587 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
588 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
589 mCurrentMediaVolumeValue);
590
591 if (isAudioPlayerStarted == true) {
592 mVeAudioPlayer->resume();
593 } else {
594 status_t err = OK;
595 err = mVeAudioPlayer->start(true);
596 if (err != OK) {
597 mAudioPlayer = NULL;
598 mVeAudioPlayer = NULL;
599
600 mFlags &= ~(PLAYING | FIRST_FRAME);
601 return err;
602 }
603 }
604 } else {
605 LOGV("play_l: No Source change required");
606 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
607 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
608 mCurrentMediaVolumeValue);
609
610 mVeAudioPlayer->resume();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800611 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800612
613 mFlags |= AUDIOPLAYER_STARTED;
614 mFlags |= AUDIO_RUNNING;
615 mTimeSource = mVeAudioPlayer;
616 deferredAudioSeek = true;
617 mWatchForAudioSeekComplete = false;
618 mWatchForAudioEOS = true;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800619 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800620 }
621
622 if (mTimeSource == NULL && mAudioPlayer == NULL) {
623 mTimeSource = &mSystemTimeSource;
624 }
625
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800626 // Set the seek option for Image source files and read.
627 // This resets the timestamping for image play
628 if (mIsVideoSourceJpg) {
629 MediaSource::ReadOptions options;
630 MediaBuffer *aLocalBuffer;
631 options.setSeekTo(mSeekTimeUs);
632 mVideoSource->read(&aLocalBuffer, &options);
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800633 aLocalBuffer->release();
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800634 }
635
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800636 if (mVideoSource != NULL) {
637 // Kick off video playback
638 postVideoEvent_l();
639 }
640
641 if (deferredAudioSeek) {
642 // If there was a seek request while we were paused
643 // and we're just starting up again, honor the request now.
644 seekAudioIfNecessary_l();
645 }
646
647 if (mFlags & AT_EOS) {
648 // Legacy behaviour, if a stream finishes playing and then
649 // is started again, we play from the start...
650 seekTo_l(0);
651 }
652
653 return OK;
654}
655
656
Santosh Madhavabfece172011-02-03 16:59:47 -0800657status_t PreviewPlayer::initRenderer_l() {
Mathias Agopian6e224292011-04-05 15:38:24 -0700658 if (mSurface != NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800659 sp<MetaData> meta = mVideoSource->getFormat();
660
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800661 const char *component;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800662 CHECK(meta->findCString(kKeyDecoderComponent, &component));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800663
664 // Must ensure that mVideoRenderer's destructor is actually executed
665 // before creating a new one.
666 IPCThreadState::self()->flushCommands();
667
668 // always use localrenderer since decoded buffers are modified
669 // by postprocessing module
670 // Other decoders are instantiated locally and as a consequence
671 // allocate their buffers in local address space.
672 if(mVideoRenderer == NULL) {
673
Chih-Chung Change048e902011-08-01 12:15:59 +0800674 mVideoRenderer = PreviewRenderer::CreatePreviewRenderer(
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +0800675 OMX_COLOR_FormatYUV420Planar,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800676 mSurface,
677 mOutputVideoWidth, mOutputVideoHeight,
Chih-Chung Change048e902011-08-01 12:15:59 +0800678 mOutputVideoWidth, mOutputVideoHeight,
679 0);
Santosh Madhavabfece172011-02-03 16:59:47 -0800680
681 if ( mVideoRenderer == NULL )
682 {
683 return UNKNOWN_ERROR;
684 }
685 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800686 }
687 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800688 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800689}
690
691
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800692status_t PreviewPlayer::seekTo(int64_t timeUs) {
693
694 if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) {
695 Mutex::Autolock autoLock(mLock);
696 return seekTo_l(timeUs);
697 }
698
699 return OK;
700}
701
702
703status_t PreviewPlayer::getVideoDimensions(
704 int32_t *width, int32_t *height) const {
705 Mutex::Autolock autoLock(mLock);
706
707 if (mVideoWidth < 0 || mVideoHeight < 0) {
708 return UNKNOWN_ERROR;
709 }
710
711 *width = mVideoWidth;
712 *height = mVideoHeight;
713
714 return OK;
715}
716
717
718status_t PreviewPlayer::initAudioDecoder() {
719 sp<MetaData> meta = mAudioTrack->getFormat();
720 const char *mime;
721 CHECK(meta->findCString(kKeyMIMEType, &mime));
722
723 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
724 mAudioSource = mAudioTrack;
725 } else {
726 sp<MediaSource> aRawSource;
727 aRawSource = OMXCodec::Create(
728 mClient.interface(), mAudioTrack->getFormat(),
729 false, // createEncoder
730 mAudioTrack);
731
732 if(aRawSource != NULL) {
733 LOGV("initAudioDecoder: new VideoEditorSRC");
734 mAudioSource = new VideoEditorSRC(aRawSource);
735 }
736 }
737
738 if (mAudioSource != NULL) {
739 int64_t durationUs;
740 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
741 Mutex::Autolock autoLock(mMiscStateLock);
742 if (mDurationUs < 0 || durationUs > mDurationUs) {
743 mDurationUs = durationUs;
744 }
745 }
746 status_t err = mAudioSource->start();
747
748 if (err != OK) {
749 mAudioSource.clear();
750 return err;
751 }
752 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
753 // For legacy reasons we're simply going to ignore the absence
754 // of an audio decoder for QCELP instead of aborting playback
755 // altogether.
756 return OK;
757 }
758
759 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
760}
761
762
763status_t PreviewPlayer::initVideoDecoder(uint32_t flags) {
764
765 mVideoSource = OMXCodec::Create(
766 mClient.interface(), mVideoTrack->getFormat(),
767 false,
768 mVideoTrack,
769 NULL, flags);
770
771 if (mVideoSource != NULL) {
772 int64_t durationUs;
773 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
774 Mutex::Autolock autoLock(mMiscStateLock);
775 if (mDurationUs < 0 || durationUs > mDurationUs) {
776 mDurationUs = durationUs;
777 }
778 }
779
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +0800780 getVideoBufferSize(mVideoTrack->getFormat(), &mVideoWidth, &mVideoHeight);
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800781 mReportedWidth = mVideoWidth;
782 mReportedHeight = mVideoHeight;
783
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800784 status_t err = mVideoSource->start();
785
786 if (err != OK) {
787 mVideoSource.clear();
788 return err;
789 }
790 }
791
792 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
793}
794
795
796void PreviewPlayer::onVideoEvent() {
797 uint32_t i=0;
798 bool bAppliedVideoEffect = false;
799 M4OSA_ERR err1 = M4NO_ERROR;
800 int64_t imageFrameTimeUs = 0;
801
802 Mutex::Autolock autoLock(mLock);
803 if (!mVideoEventPending) {
804 // The event has been cancelled in reset_l() but had already
805 // been scheduled for execution at that time.
806 return;
807 }
808 mVideoEventPending = false;
809
Andreas Huber9e4c36a2011-02-08 13:12:32 -0800810 if (mFlags & SEEK_PREVIEW) {
811 mFlags &= ~SEEK_PREVIEW;
812 return;
813 }
814
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800815 TimeSource *ts_st = &mSystemTimeSource;
816 int64_t timeStartUs = ts_st->getRealTimeUs();
817
Andreas Hubera5872f72011-02-24 15:25:21 -0800818 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800819 if (mLastVideoBuffer) {
820 mLastVideoBuffer->release();
821 mLastVideoBuffer = NULL;
822 }
823
824
825 if(mAudioSource != NULL) {
826
827 // We're going to seek the video source first, followed by
828 // the audio source.
829 // In order to avoid jumps in the DataSource offset caused by
830 // the audio codec prefetching data from the old locations
831 // while the video codec is already reading data from the new
832 // locations, we'll "pause" the audio source, causing it to
833 // stop reading input data until a subsequent seek.
834
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800835 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800836 mAudioPlayer->pause();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800837 mFlags &= ~AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800838 }
839 mAudioSource->pause();
840 }
841 }
842
843 if (!mVideoBuffer) {
844 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -0800845 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800846 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
847 mSeekTimeUs / 1E6);
848
849 options.setSeekTo(
850 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
851 }
852 for (;;) {
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +0800853 status_t err = readYV12Buffer(mVideoSource, &mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800854 options.clearSeekTo();
855
856 if (err != OK) {
857 CHECK_EQ(mVideoBuffer, NULL);
858
859 if (err == INFO_FORMAT_CHANGED) {
860 LOGV("LV PLAYER VideoSource signalled format change");
861 notifyVideoSize_l();
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800862 sp<MetaData> meta = mVideoSource->getFormat();
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +0800863 getVideoBufferSize(meta, &mReportedWidth, &mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800864
865 if (mVideoRenderer != NULL) {
866 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -0800867 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800868 if (err != OK) {
869 postStreamDoneEvent_l(err);
870 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800871
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800872 }
873 continue;
874 }
875 // So video playback is complete, but we may still have
Santosh Madhava342f9322011-01-27 16:27:12 -0800876 // a seek request pending that needs to be applied to the audio track
Andreas Hubera5872f72011-02-24 15:25:21 -0800877 if (mSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800878 LOGV("video stream ended while seeking!");
879 }
880 finishSeekIfNecessary(-1);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800881 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
882 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800883 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800884 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800885 postStreamDoneEvent_l(err);
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800886 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -0700887 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800888 return;
889 }
890
891 if (mVideoBuffer->range_length() == 0) {
892 // Some decoders, notably the PV AVC software decoder
893 // return spurious empty buffers that we just want to ignore.
894
895 mVideoBuffer->release();
896 mVideoBuffer = NULL;
897 continue;
898 }
899
900 int64_t videoTimeUs;
901 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
902
Andreas Hubera5872f72011-02-24 15:25:21 -0800903 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800904 if (videoTimeUs < mSeekTimeUs) {
905 // buffers are before seek time
906 // ignore them
907 mVideoBuffer->release();
908 mVideoBuffer = NULL;
909 continue;
910 }
911 } else {
912 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
913 // Frames are before begin cut time
914 // Donot render
915 mVideoBuffer->release();
916 mVideoBuffer = NULL;
917 continue;
918 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800919 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800920 break;
921 }
922 }
923
924 mNumberDecVideoFrames++;
925
926 int64_t timeUs;
927 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
928
929 {
930 Mutex::Autolock autoLock(mMiscStateLock);
931 mVideoTimeUs = timeUs;
932 }
933
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800934
935 if(!mStartNextPlayer) {
Raghavender Pallaebf40152011-03-14 20:15:12 -0700936 int64_t playbackTimeRemaining = (mPlayEndTimeMsec*1000LL) - timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800937 if(playbackTimeRemaining <= 1500000) {
938 //When less than 1.5 sec of playback left
939 // send notification to start next player
940
941 mStartNextPlayer = true;
942 notifyListener_l(0xAAAAAAAA);
943 }
944 }
945
Andreas Hubera5872f72011-02-24 15:25:21 -0800946 SeekType wasSeeking = mSeeking;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800947 finishSeekIfNecessary(timeUs);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800948 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING))) {
949 status_t err = startAudioPlayer_l();
950 if (err != OK) {
951 LOGE("Starting the audio player failed w/ err %d", err);
952 return;
953 }
954 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800955
956 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
957
958 if(ts == NULL) {
959 mVideoBuffer->release();
960 mVideoBuffer = NULL;
961 return;
962 }
963
964 if(!mIsVideoSourceJpg) {
965 if (mFlags & FIRST_FRAME) {
966 mFlags &= ~FIRST_FRAME;
967
968 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
969 }
970
971 int64_t realTimeUs, mediaTimeUs;
972 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
973 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
974 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
975 }
976
977 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
978
979 int64_t latenessUs = nowUs - timeUs;
980
Andreas Hubera5872f72011-02-24 15:25:21 -0800981 if (wasSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800982 // Let's display the first frame after seeking right away.
983 latenessUs = 0;
984 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800985 LOGV("Audio time stamp = %lld and video time stamp = %lld",
986 ts->getRealTimeUs(),timeUs);
987 if (latenessUs > 40000) {
988 // We're more than 40ms late.
989
990 LOGV("LV PLAYER we're late by %lld us (%.2f secs)",
991 latenessUs, latenessUs / 1E6);
992
993 mVideoBuffer->release();
994 mVideoBuffer = NULL;
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800995 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800996 return;
997 }
998
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800999 if (latenessUs < -25000) {
1000 // We're more than 25ms early.
1001 LOGV("We're more than 25ms early, lateness %lld", latenessUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001002
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001003 postVideoEvent_l(25000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001004 return;
1005 }
1006 }
1007
1008 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
1009 mVideoRendererIsPreview = false;
1010
Santosh Madhavabfece172011-02-03 16:59:47 -08001011 status_t err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001012 if (err != OK) {
1013 postStreamDoneEvent_l(err);
1014 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001015 }
1016
1017 // If timestamp exceeds endCutTime of clip, donot render
1018 if((timeUs/1000) > mPlayEndTimeMsec) {
1019 if (mLastVideoBuffer) {
1020 mLastVideoBuffer->release();
1021 mLastVideoBuffer = NULL;
1022 }
1023 mLastVideoBuffer = mVideoBuffer;
1024 mVideoBuffer = NULL;
1025 mFlags |= VIDEO_AT_EOS;
1026 mFlags |= AUDIO_AT_EOS;
Santosh Madhavabfece172011-02-03 16:59:47 -08001027 LOGV("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS..");
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001028 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001029 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001030 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001031 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1032 return;
1033 }
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001034 // Capture the frame timestamp to be rendered
1035 mDecodedVideoTs = timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001036
1037 // Post processing to apply video effects
1038 for(i=0;i<mNumberEffects;i++) {
1039 // First check if effect starttime matches the clip being previewed
1040 if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) ||
1041 (mEffectsSettings[i].uiStartTime >=
1042 ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec)))
1043 {
1044 // This effect doesn't belong to this clip, check next one
1045 continue;
1046 }
1047 // Check if effect applies to this particular frame timestamp
1048 if((mEffectsSettings[i].uiStartTime <=
1049 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) &&
1050 ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=
1051 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec))
1052 && (mEffectsSettings[i].uiDuration != 0)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001053 setVideoPostProcessingNode(
1054 mEffectsSettings[i].VideoEffectType, TRUE);
1055 }
1056 else {
1057 setVideoPostProcessingNode(
1058 mEffectsSettings[i].VideoEffectType, FALSE);
1059 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001060 }
1061
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001062 //Provide the overlay Update indication when there is an overlay effect
Dharmaray Kundargid01ef562011-01-26 21:11:00 -08001063 if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) {
1064 mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here.
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001065 if (!mOverlayUpdateEventPosted) {
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001066 // Find the effect in effectSettings array
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001067 M4OSA_UInt32 index;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001068 for (index = 0; index < mNumberEffects; index++) {
1069 M4OSA_UInt32 timeMs = mDecodedVideoTs/1000;
1070 M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000;
1071 if(mEffectsSettings[index].VideoEffectType ==
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001072 (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001073 if (((mEffectsSettings[index].uiStartTime + 1) <=
1074 timeMs + timeOffset - mPlayBeginTimeMsec) &&
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001075 ((mEffectsSettings[index].uiStartTime - 1 +
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001076 mEffectsSettings[index].uiDuration) >=
1077 timeMs + timeOffset - mPlayBeginTimeMsec))
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001078 {
1079 break;
1080 }
1081 }
1082 }
1083 if (index < mNumberEffects) {
1084 mCurrFramingEffectIndex = index;
1085 mOverlayUpdateEventPosted = true;
1086 postOverlayUpdateEvent_l();
1087 LOGV("Framing index = %d", mCurrFramingEffectIndex);
1088 } else {
1089 LOGV("No framing effects found");
1090 }
1091 }
1092
1093 } else if (mOverlayUpdateEventPosted) {
1094 //Post the event when the overlay is no more valid
1095 LOGV("Overlay is Done");
1096 mOverlayUpdateEventPosted = false;
1097 postOverlayUpdateEvent_l();
1098 }
1099
1100
1101 if (mCurrentVideoEffect != VIDEO_EFFECT_NONE) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001102 err1 = doVideoPostProcessing();
1103 if(err1 != M4NO_ERROR) {
1104 LOGE("doVideoPostProcessing returned err");
1105 bAppliedVideoEffect = false;
1106 }
1107 else {
1108 bAppliedVideoEffect = true;
1109 }
1110 }
1111 else {
1112 bAppliedVideoEffect = false;
1113 if(mRenderingMode != MEDIA_RENDERING_INVALID) {
1114 // No effects to be applied, but media rendering to be done
1115 err1 = doMediaRendering();
1116 if(err1 != M4NO_ERROR) {
1117 LOGE("doMediaRendering returned err");
1118 //Use original mVideoBuffer for rendering
1119 mVideoResizedOrCropped = false;
1120 }
1121 }
1122 }
1123
1124 if (mVideoRenderer != NULL) {
1125 LOGV("mVideoRenderer CALL render()");
Chih-Chung Change048e902011-08-01 12:15:59 +08001126 mVideoRenderer->renderYV12();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001127 }
1128
1129 if (mLastVideoBuffer) {
1130 mLastVideoBuffer->release();
1131 mLastVideoBuffer = NULL;
1132 }
1133
1134 mLastVideoBuffer = mVideoBuffer;
1135 mVideoBuffer = NULL;
1136
1137 // Post progress callback based on callback interval set
1138 if(mNumberDecVideoFrames >= mProgressCbInterval) {
1139 postProgressCallbackEvent_l();
1140 mNumberDecVideoFrames = 0; // reset counter
1141 }
1142
1143 // if reached EndCutTime of clip, post EOS event
1144 if((timeUs/1000) >= mPlayEndTimeMsec) {
1145 LOGV("PreviewPlayer: onVideoEvent EOS.");
1146 mFlags |= VIDEO_AT_EOS;
1147 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001148 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001149 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001150 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001151 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1152 }
1153 else {
Andreas Hubera5872f72011-02-24 15:25:21 -08001154 if ((wasSeeking != NO_SEEK) && (mFlags & SEEK_PREVIEW)) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001155 mFlags &= ~SEEK_PREVIEW;
1156 return;
1157 }
1158
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001159 if(!mIsVideoSourceJpg) {
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001160 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001161 }
1162 else {
1163 postVideoEvent_l(33000);
1164 }
1165 }
1166}
1167
1168status_t PreviewPlayer::prepare() {
1169 Mutex::Autolock autoLock(mLock);
1170 return prepare_l();
1171}
1172
1173status_t PreviewPlayer::prepare_l() {
1174 if (mFlags & PREPARED) {
1175 return OK;
1176 }
1177
1178 if (mFlags & PREPARING) {
1179 return UNKNOWN_ERROR;
1180 }
1181
1182 mIsAsyncPrepare = false;
1183 status_t err = prepareAsync_l();
1184
1185 if (err != OK) {
1186 return err;
1187 }
1188
1189 while (mFlags & PREPARING) {
1190 mPreparedCondition.wait(mLock);
1191 }
1192
1193 return mPrepareResult;
1194}
1195
1196status_t PreviewPlayer::prepareAsync_l() {
1197 if (mFlags & PREPARING) {
1198 return UNKNOWN_ERROR; // async prepare already pending
1199 }
1200
1201 if (!mQueueStarted) {
1202 mQueue.start();
1203 mQueueStarted = true;
1204 }
1205
1206 mFlags |= PREPARING;
1207 mAsyncPrepareEvent = new PreviewPlayerEvent(
1208 this, &PreviewPlayer::onPrepareAsyncEvent);
1209
1210 mQueue.postEvent(mAsyncPrepareEvent);
1211
1212 return OK;
1213}
1214
1215status_t PreviewPlayer::finishSetDataSource_l() {
1216 sp<DataSource> dataSource;
1217 sp<MediaExtractor> extractor;
1218
1219 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1220
1221 if (dataSource == NULL) {
1222 return UNKNOWN_ERROR;
1223 }
1224
1225 //If file type is .rgb, then no need to check for Extractor
1226 int uriLen = strlen(mUri);
1227 int startOffset = uriLen - 4;
1228 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) {
1229 extractor = NULL;
1230 }
1231 else {
1232 extractor = MediaExtractor::Create(dataSource,
1233 MEDIA_MIMETYPE_CONTAINER_MPEG4);
1234 }
1235
1236 if (extractor == NULL) {
1237 LOGV("PreviewPlayer::finishSetDataSource_l extractor == NULL");
1238 return setDataSource_l_jpg();
1239 }
1240
1241 return setDataSource_l(extractor);
1242}
1243
1244
1245// static
1246bool PreviewPlayer::ContinuePreparation(void *cookie) {
1247 PreviewPlayer *me = static_cast<PreviewPlayer *>(cookie);
1248
1249 return (me->mFlags & PREPARE_CANCELLED) == 0;
1250}
1251
1252void PreviewPlayer::onPrepareAsyncEvent() {
1253 Mutex::Autolock autoLock(mLock);
1254 LOGV("onPrepareAsyncEvent");
1255
1256 if (mFlags & PREPARE_CANCELLED) {
Santosh Madhavabfece172011-02-03 16:59:47 -08001257 LOGV("LV PLAYER prepare was cancelled before doing anything");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001258 abortPrepare(UNKNOWN_ERROR);
1259 return;
1260 }
1261
1262 if (mUri.size() > 0) {
1263 status_t err = finishSetDataSource_l();
1264
1265 if (err != OK) {
1266 abortPrepare(err);
1267 return;
1268 }
1269 }
1270
1271 if (mVideoTrack != NULL && mVideoSource == NULL) {
1272 status_t err = initVideoDecoder(OMXCodec::kHardwareCodecsOnly);
1273
1274 if (err != OK) {
1275 abortPrepare(err);
1276 return;
1277 }
1278 }
1279
1280 if (mAudioTrack != NULL && mAudioSource == NULL) {
1281 status_t err = initAudioDecoder();
1282
1283 if (err != OK) {
1284 abortPrepare(err);
1285 return;
1286 }
1287 }
1288 finishAsyncPrepare_l();
1289
1290}
1291
1292void PreviewPlayer::finishAsyncPrepare_l() {
1293 if (mIsAsyncPrepare) {
1294 if (mVideoSource == NULL) {
1295 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE 0 0 ");
1296 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1297 } else {
1298 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE");
1299 notifyVideoSize_l();
1300 }
1301 LOGV("finishAsyncPrepare_l: MEDIA_PREPARED");
1302 notifyListener_l(MEDIA_PREPARED);
1303 }
1304
1305 mPrepareResult = OK;
1306 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1307 mFlags |= PREPARED;
1308 mAsyncPrepareEvent = NULL;
1309 mPreparedCondition.broadcast();
1310}
1311
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001312void PreviewPlayer::acquireLock() {
1313 LOGV("acquireLock");
1314 mLockControl.lock();
1315}
1316
1317void PreviewPlayer::releaseLock() {
1318 LOGV("releaseLock");
1319 mLockControl.unlock();
1320}
1321
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001322status_t PreviewPlayer::loadEffectsSettings(
1323 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) {
1324 M4OSA_UInt32 i = 0, rgbSize = 0;
1325 M4VIFI_UInt8 *tmp = M4OSA_NULL;
1326
1327 mNumberEffects = nEffects;
1328 mEffectsSettings = pEffectSettings;
1329 return OK;
1330}
1331
1332status_t PreviewPlayer::loadAudioMixSettings(
1333 M4xVSS_AudioMixingSettings* pAudioMixSettings) {
1334
1335 LOGV("PreviewPlayer: loadAudioMixSettings: ");
1336 mPreviewPlayerAudioMixSettings = pAudioMixSettings;
1337 return OK;
1338}
1339
1340status_t PreviewPlayer::setAudioMixPCMFileHandle(
1341 M4OSA_Context pAudioMixPCMFileHandle) {
1342
1343 LOGV("PreviewPlayer: setAudioMixPCMFileHandle: ");
1344 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle;
1345 return OK;
1346}
1347
1348status_t PreviewPlayer::setAudioMixStoryBoardParam(
1349 M4OSA_UInt32 audioMixStoryBoardTS,
1350 M4OSA_UInt32 currentMediaBeginCutTime,
1351 M4OSA_UInt32 primaryTrackVolValue ) {
1352
1353 mAudioMixStoryBoardTS = audioMixStoryBoardTS;
1354 mCurrentMediaBeginCutTime = currentMediaBeginCutTime;
1355 mCurrentMediaVolumeValue = primaryTrackVolValue;
1356 return OK;
1357}
1358
1359status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) {
1360
1361 mPlayBeginTimeMsec = msec;
1362 return OK;
1363}
1364
1365status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) {
1366
1367 mPlayEndTimeMsec = msec;
1368 return OK;
1369}
1370
1371status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) {
1372
1373 mStoryboardStartTimeMsec = msec;
Raghavender Pallaebf40152011-03-14 20:15:12 -07001374 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001375 return OK;
1376}
1377
1378status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) {
1379
1380 mProgressCbInterval = cbInterval;
1381 return OK;
1382}
1383
1384
1385status_t PreviewPlayer::setMediaRenderingMode(
1386 M4xVSS_MediaRendering mode,
1387 M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
1388
1389 mRenderingMode = mode;
1390
1391 /* reset boolean for each clip*/
1392 mVideoResizedOrCropped = false;
1393
Hong Teng8806b702011-07-06 18:29:28 -07001394 status_t err = OK;
1395 /* get the video width and height by resolution */
1396 err = getVideoSizeByResolution(outputVideoSize,
1397 &mOutputVideoWidth, &mOutputVideoHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001398
Hong Teng8806b702011-07-06 18:29:28 -07001399 return err;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001400}
1401
1402M4OSA_ERR PreviewPlayer::doMediaRendering() {
1403 M4OSA_ERR err = M4NO_ERROR;
1404 M4VIFI_ImagePlane planeIn[3], planeOut[3];
1405 M4VIFI_UInt8 *inBuffer = M4OSA_NULL, *finalOutputBuffer = M4OSA_NULL;
1406 M4VIFI_UInt8 *tempOutputBuffer= M4OSA_NULL;
1407 size_t videoBufferSize = 0;
1408 M4OSA_UInt32 frameSize = 0, i=0, index =0, nFrameCount =0, bufferOffset =0;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001409
1410 videoBufferSize = mVideoBuffer->size();
1411 frameSize = (mVideoWidth*mVideoHeight*3) >> 1;
1412
1413 uint8_t* outBuffer;
1414 size_t outBufferStride = 0;
1415
Chih-Chung Change048e902011-08-01 12:15:59 +08001416 mVideoRenderer->getBufferYV12(&outBuffer, &outBufferStride);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001417
1418 bufferOffset = index*frameSize;
1419 inBuffer = (M4OSA_UInt8 *)mVideoBuffer->data()+
1420 mVideoBuffer->range_offset()+bufferOffset;
1421
1422
1423 /* In plane*/
1424 prepareYUV420ImagePlane(planeIn, mVideoWidth,
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001425 mVideoHeight, (M4VIFI_UInt8 *)inBuffer, mReportedWidth, mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001426
1427 // Set the output YUV420 plane to be compatible with YV12 format
1428 // W & H even
1429 // YVU instead of YUV
1430 // align buffers on 32 bits
1431
1432 //In YV12 format, sizes must be even
1433 M4OSA_UInt32 yv12PlaneWidth = ((mOutputVideoWidth +1)>>1)<<1;
1434 M4OSA_UInt32 yv12PlaneHeight = ((mOutputVideoHeight+1)>>1)<<1;
1435
1436 prepareYV12ImagePlane(planeOut, yv12PlaneWidth, yv12PlaneHeight,
1437 (M4OSA_UInt32)outBufferStride, (M4VIFI_UInt8 *)outBuffer);
1438
1439
1440 err = applyRenderingMode(planeIn, planeOut, mRenderingMode);
1441
1442 if(err != M4NO_ERROR)
1443 {
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001444 LOGE("doMediaRendering: applyRenderingMode returned err=0x%x", (int)err);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001445 return err;
1446 }
1447 mVideoResizedOrCropped = true;
1448
1449 return err;
1450}
1451
1452status_t PreviewPlayer::resetJniCallbackTimeStamp() {
1453
Raghavender Pallaebf40152011-03-14 20:15:12 -07001454 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001455 return OK;
1456}
1457
1458void PreviewPlayer::postProgressCallbackEvent_l() {
1459 if (mProgressCbEventPending) {
1460 return;
1461 }
1462 mProgressCbEventPending = true;
1463
1464 mQueue.postEvent(mProgressCbEvent);
1465}
1466
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001467
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001468void PreviewPlayer::onProgressCbEvent() {
1469 Mutex::Autolock autoLock(mLock);
1470 if (!mProgressCbEventPending) {
1471 return;
1472 }
1473 mProgressCbEventPending = false;
1474 // If playback starts from previous I-frame,
1475 // then send frame storyboard duration
1476 if((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) {
1477 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000);
1478 }
1479 else {
1480 notifyListener_l(MEDIA_INFO, 0,
1481 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec));
1482 }
1483}
1484
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001485void PreviewPlayer::postOverlayUpdateEvent_l() {
1486 if (mOverlayUpdateEventPending) {
1487 return;
1488 }
1489 mOverlayUpdateEventPending = true;
1490 mQueue.postEvent(mOverlayUpdateEvent);
1491}
1492
1493void PreviewPlayer::onUpdateOverlayEvent() {
1494 Mutex::Autolock autoLock(mLock);
1495
1496 if (!mOverlayUpdateEventPending) {
1497 return;
1498 }
1499 mOverlayUpdateEventPending = false;
1500
1501 int updateState;
1502 if (mOverlayUpdateEventPosted) {
1503 updateState = 1;
1504 } else {
1505 updateState = 0;
1506 }
1507 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex);
1508}
1509
1510
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001511void PreviewPlayer::setVideoPostProcessingNode(
1512 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
1513
1514 uint32_t effect = VIDEO_EFFECT_NONE;
1515
1516 //Map M4VSS3GPP_VideoEffectType to local enum
1517 switch(type) {
1518 case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
1519 effect = VIDEO_EFFECT_FADEFROMBLACK;
1520 break;
1521
1522 case M4VSS3GPP_kVideoEffectType_FadeToBlack:
1523 effect = VIDEO_EFFECT_FADETOBLACK;
1524 break;
1525
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001526 case M4xVSS_kVideoEffectType_BlackAndWhite:
1527 effect = VIDEO_EFFECT_BLACKANDWHITE;
1528 break;
1529
1530 case M4xVSS_kVideoEffectType_Pink:
1531 effect = VIDEO_EFFECT_PINK;
1532 break;
1533
1534 case M4xVSS_kVideoEffectType_Green:
1535 effect = VIDEO_EFFECT_GREEN;
1536 break;
1537
1538 case M4xVSS_kVideoEffectType_Sepia:
1539 effect = VIDEO_EFFECT_SEPIA;
1540 break;
1541
1542 case M4xVSS_kVideoEffectType_Negative:
1543 effect = VIDEO_EFFECT_NEGATIVE;
1544 break;
1545
1546 case M4xVSS_kVideoEffectType_Framing:
1547 effect = VIDEO_EFFECT_FRAMING;
1548 break;
1549
1550 case M4xVSS_kVideoEffectType_Fifties:
1551 effect = VIDEO_EFFECT_FIFTIES;
1552 break;
1553
1554 case M4xVSS_kVideoEffectType_ColorRGB16:
1555 effect = VIDEO_EFFECT_COLOR_RGB16;
1556 break;
1557
1558 case M4xVSS_kVideoEffectType_Gradient:
1559 effect = VIDEO_EFFECT_GRADIENT;
1560 break;
1561
1562 default:
1563 effect = VIDEO_EFFECT_NONE;
1564 break;
1565 }
1566
1567 if(enable == M4OSA_TRUE) {
1568 //If already set, then no need to set again
1569 if(!(mCurrentVideoEffect & effect)) {
1570 mCurrentVideoEffect |= effect;
1571 if(effect == VIDEO_EFFECT_FIFTIES) {
1572 mIsFiftiesEffectStarted = true;
1573 }
1574 }
1575 }
1576 else {
1577 //Reset only if already set
1578 if(mCurrentVideoEffect & effect) {
1579 mCurrentVideoEffect &= ~effect;
1580 }
1581 }
1582}
1583
1584status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) {
1585 mVideoWidth = width;
1586 mVideoHeight = height;
1587 return OK;
1588}
1589
1590
1591M4OSA_ERR PreviewPlayer::doVideoPostProcessing() {
1592 M4OSA_ERR err = M4NO_ERROR;
1593 vePostProcessParams postProcessParams;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001594
1595 postProcessParams.vidBuffer = (M4VIFI_UInt8*)mVideoBuffer->data()
1596 + mVideoBuffer->range_offset();
1597
1598 postProcessParams.videoWidth = mVideoWidth;
1599 postProcessParams.videoHeight = mVideoHeight;
1600 postProcessParams.timeMs = mDecodedVideoTs/1000;
1601 postProcessParams.timeOffset = mDecVideoTsStoryBoard/1000;
1602 postProcessParams.effectsSettings = mEffectsSettings;
1603 postProcessParams.numberEffects = mNumberEffects;
1604 postProcessParams.outVideoWidth = mOutputVideoWidth;
1605 postProcessParams.outVideoHeight = mOutputVideoHeight;
1606 postProcessParams.currentVideoEffect = mCurrentVideoEffect;
1607 postProcessParams.renderingMode = mRenderingMode;
1608 if(mIsFiftiesEffectStarted == M4OSA_TRUE) {
1609 postProcessParams.isFiftiesEffectStarted = M4OSA_TRUE;
1610 mIsFiftiesEffectStarted = M4OSA_FALSE;
1611 }
1612 else {
1613 postProcessParams.isFiftiesEffectStarted = M4OSA_FALSE;
1614 }
1615
1616 postProcessParams.overlayFrameRGBBuffer = mFrameRGBBuffer;
1617 postProcessParams.overlayFrameYUVBuffer = mFrameYUVBuffer;
Chih-Chung Change048e902011-08-01 12:15:59 +08001618 mVideoRenderer->getBufferYV12(&(postProcessParams.pOutBuffer),
1619 &(postProcessParams.outBufferStride));
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001620 err = applyEffectsAndRenderingMode(&postProcessParams, mReportedWidth, mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001621
1622 return err;
1623}
1624
1625status_t PreviewPlayer::readFirstVideoFrame() {
1626 LOGV("PreviewPlayer::readFirstVideoFrame");
1627
1628 if (!mVideoBuffer) {
1629 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -08001630 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001631 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
1632 mSeekTimeUs / 1E6);
1633
1634 options.setSeekTo(
1635 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
1636 }
1637 for (;;) {
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +08001638 status_t err = readYV12Buffer(mVideoSource, &mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001639 options.clearSeekTo();
1640
1641 if (err != OK) {
1642 CHECK_EQ(mVideoBuffer, NULL);
1643
1644 if (err == INFO_FORMAT_CHANGED) {
1645 LOGV("LV PLAYER VideoSource signalled format change");
1646 notifyVideoSize_l();
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001647 sp<MetaData> meta = mVideoSource->getFormat();
Chih-Chung Chang7efb8ef2011-07-22 09:01:36 +08001648 getVideoBufferSize(meta, &mReportedWidth, &mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001649
1650 if (mVideoRenderer != NULL) {
1651 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -08001652 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001653 if (err != OK) {
1654 postStreamDoneEvent_l(err);
1655 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001656 }
1657 continue;
1658 }
1659 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
1660 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001661 mFlags |= AUDIO_AT_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001662 postStreamDoneEvent_l(err);
1663 return OK;
1664 }
1665
1666 if (mVideoBuffer->range_length() == 0) {
1667 // Some decoders, notably the PV AVC software decoder
1668 // return spurious empty buffers that we just want to ignore.
1669
1670 mVideoBuffer->release();
1671 mVideoBuffer = NULL;
1672 continue;
1673 }
1674
1675 int64_t videoTimeUs;
1676 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
Andreas Hubera5872f72011-02-24 15:25:21 -08001677 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001678 if (videoTimeUs < mSeekTimeUs) {
1679 // buffers are before seek time
1680 // ignore them
1681 mVideoBuffer->release();
1682 mVideoBuffer = NULL;
1683 continue;
1684 }
1685 } else {
1686 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
1687 // buffers are before begin cut time
1688 // ignore them
1689 mVideoBuffer->release();
1690 mVideoBuffer = NULL;
1691 continue;
1692 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001693 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001694 break;
1695 }
1696 }
1697
1698 int64_t timeUs;
1699 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1700
1701 {
1702 Mutex::Autolock autoLock(mMiscStateLock);
1703 mVideoTimeUs = timeUs;
1704 }
1705
1706 mDecodedVideoTs = timeUs;
1707
1708 return OK;
1709
1710}
1711
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001712status_t PreviewPlayer::getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs) {
1713 *lastRenderedTimeMs = (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec);
1714 return OK;
1715}
1716
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001717} // namespace android