blob: 7d08a9f5f213fcfa8eb53500016ba9643bd2e130 [file] [log] [blame]
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001/*
2 * Copyright (C) 2011 NXP Software
3 * Copyright (C) 2011 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Santosh Madhavabfece172011-02-03 16:59:47 -080018
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080019#define LOG_NDEBUG 1
20#define LOG_TAG "PreviewPlayer"
21#include <utils/Log.h>
22
23#include <dlfcn.h>
24
25#include "include/ARTSPController.h"
26#include "PreviewPlayer.h"
27#include "DummyAudioSource.h"
28#include "DummyVideoSource.h"
29#include "VideoEditorSRC.h"
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080030#include "include/NuCachedSource2.h"
31#include "include/ThrottledSource.h"
32
33
34#include "PreviewRenderer.h"
35
36#include <binder/IPCThreadState.h>
37#include <media/stagefright/DataSource.h>
38#include <media/stagefright/FileSource.h>
39#include <media/stagefright/MediaBuffer.h>
40#include <media/stagefright/MediaDefs.h>
41#include <media/stagefright/MediaExtractor.h>
42#include <media/stagefright/MediaDebug.h>
43#include <media/stagefright/MediaSource.h>
44#include <media/stagefright/MetaData.h>
45#include <media/stagefright/OMXCodec.h>
46
47#include <surfaceflinger/Surface.h>
48#include <media/stagefright/foundation/ALooper.h>
49
50namespace android {
51
52
53struct PreviewPlayerEvent : public TimedEventQueue::Event {
54 PreviewPlayerEvent(
55 PreviewPlayer *player,
56 void (PreviewPlayer::*method)())
57 : mPlayer(player),
58 mMethod(method) {
59 }
60
61protected:
62 virtual ~PreviewPlayerEvent() {}
63
64 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
65 (mPlayer->*mMethod)();
66 }
67
68private:
69 PreviewPlayer *mPlayer;
70 void (PreviewPlayer::*mMethod)();
71
72 PreviewPlayerEvent(const PreviewPlayerEvent &);
73 PreviewPlayerEvent &operator=(const PreviewPlayerEvent &);
74};
75
76
77struct PreviewLocalRenderer : public PreviewPlayerRenderer {
Santosh Madhavabfece172011-02-03 16:59:47 -080078
79 static PreviewLocalRenderer* initPreviewLocalRenderer (
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080080 bool previewOnly,
81 OMX_COLOR_FORMATTYPE colorFormat,
82 const sp<Surface> &surface,
83 size_t displayWidth, size_t displayHeight,
84 size_t decodedWidth, size_t decodedHeight,
85 int32_t rotationDegrees = 0)
Santosh Madhavabfece172011-02-03 16:59:47 -080086 {
87 PreviewLocalRenderer* mLocalRenderer = new
88 PreviewLocalRenderer(
89 previewOnly,
90 colorFormat,
91 surface,
92 displayWidth, displayHeight,
93 decodedWidth, decodedHeight,
94 rotationDegrees);
95
96 if ( mLocalRenderer->init(previewOnly,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080097 colorFormat, surface,
98 displayWidth, displayHeight,
99 decodedWidth, decodedHeight,
Santosh Madhavabfece172011-02-03 16:59:47 -0800100 rotationDegrees) != OK )
101 {
102 delete mLocalRenderer;
103 return NULL;
104 }
105 return mLocalRenderer;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800106 }
107
108 virtual void render(MediaBuffer *buffer) {
109 render((const uint8_t *)buffer->data() + buffer->range_offset(),
110 buffer->range_length());
111 }
112
113 void render(const void *data, size_t size) {
114 mTarget->render(data, size, NULL);
115 }
116 void render() {
117 mTarget->renderYV12();
118 }
119 void getBuffer(uint8_t **data, size_t *stride) {
120 mTarget->getBufferYV12(data, stride);
121 }
122
123protected:
124 virtual ~PreviewLocalRenderer() {
125 delete mTarget;
126 mTarget = NULL;
127 }
128
129private:
130 PreviewRenderer *mTarget;
131
Santosh Madhavabfece172011-02-03 16:59:47 -0800132 PreviewLocalRenderer(
133 bool previewOnly,
134 OMX_COLOR_FORMATTYPE colorFormat,
135 const sp<Surface> &surface,
136 size_t displayWidth, size_t displayHeight,
137 size_t decodedWidth, size_t decodedHeight,
138 int32_t rotationDegrees = 0)
139 : mTarget(NULL) {
140 }
141
142
143 int init(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800144 bool previewOnly,
145 OMX_COLOR_FORMATTYPE colorFormat,
146 const sp<Surface> &surface,
147 size_t displayWidth, size_t displayHeight,
148 size_t decodedWidth, size_t decodedHeight,
149 int32_t rotationDegrees = 0);
150
151 PreviewLocalRenderer(const PreviewLocalRenderer &);
152 PreviewLocalRenderer &operator=(const PreviewLocalRenderer &);;
153};
154
Santosh Madhavabfece172011-02-03 16:59:47 -0800155int PreviewLocalRenderer::init(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800156 bool previewOnly,
157 OMX_COLOR_FORMATTYPE colorFormat,
158 const sp<Surface> &surface,
159 size_t displayWidth, size_t displayHeight,
160 size_t decodedWidth, size_t decodedHeight,
161 int32_t rotationDegrees) {
Santosh Madhavabfece172011-02-03 16:59:47 -0800162
163 mTarget = PreviewRenderer::CreatePreviewRenderer (
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800164 colorFormat, surface, displayWidth, displayHeight,
165 decodedWidth, decodedHeight, rotationDegrees);
Santosh Madhavabfece172011-02-03 16:59:47 -0800166 if (mTarget == M4OSA_NULL) {
167 return UNKNOWN_ERROR;
168 }
169 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800170}
171
172PreviewPlayer::PreviewPlayer()
173 : AwesomePlayer(),
174 mFrameRGBBuffer(NULL),
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800175 mFrameYUVBuffer(NULL),
176 mReportedWidth(0),
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800177 mReportedHeight(0),
178 mCurrFramingEffectIndex(0) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800179
180 mVideoRenderer = NULL;
181 mLastVideoBuffer = NULL;
182 mSuspensionState = NULL;
183 mEffectsSettings = NULL;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800184 mVeAudioPlayer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800185 mAudioMixStoryBoardTS = 0;
186 mCurrentMediaBeginCutTime = 0;
187 mCurrentMediaVolumeValue = 0;
188 mNumberEffects = 0;
189 mDecodedVideoTs = 0;
190 mDecVideoTsStoryBoard = 0;
191 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
192 mProgressCbInterval = 0;
193 mNumberDecVideoFrames = 0;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800194 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800195
196 mVideoEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoEvent);
197 mVideoEventPending = false;
198 mStreamDoneEvent = new PreviewPlayerEvent(this,
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800199 &AwesomePlayer::onStreamDone);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800200
201 mStreamDoneEventPending = false;
202
203 mCheckAudioStatusEvent = new PreviewPlayerEvent(
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800204 this, &AwesomePlayer::onCheckAudioStatus);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800205
206 mAudioStatusEventPending = false;
207
208 mProgressCbEvent = new PreviewPlayerEvent(this,
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800209 &PreviewPlayer::onProgressCbEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800210
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800211 mOverlayUpdateEvent = new PreviewPlayerEvent(this,
212 &PreviewPlayer::onUpdateOverlayEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800213 mProgressCbEventPending = false;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800214
215 mOverlayUpdateEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800216 mResizedVideoBuffer = NULL;
217 mVideoResizedOrCropped = false;
218 mRenderingMode = (M4xVSS_MediaRendering)MEDIA_RENDERING_INVALID;
219 mIsFiftiesEffectStarted = false;
220 reset();
221}
222
223PreviewPlayer::~PreviewPlayer() {
224
225 if (mQueueStarted) {
226 mQueue.stop();
227 }
228
229 reset();
230
231 if(mResizedVideoBuffer != NULL) {
232 M4OSA_free((M4OSA_MemAddr32)(mResizedVideoBuffer->data()));
233 mResizedVideoBuffer = NULL;
234 }
235
236 mVideoRenderer.clear();
237 mVideoRenderer = NULL;
238}
239
240void PreviewPlayer::cancelPlayerEvents(bool keepBufferingGoing) {
241 mQueue.cancelEvent(mVideoEvent->eventID());
242 mVideoEventPending = false;
243 mQueue.cancelEvent(mStreamDoneEvent->eventID());
244 mStreamDoneEventPending = false;
245 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
246 mAudioStatusEventPending = false;
247
248 mQueue.cancelEvent(mProgressCbEvent->eventID());
249 mProgressCbEventPending = false;
250}
251
252status_t PreviewPlayer::setDataSource(
253 const char *uri, const KeyedVector<String8, String8> *headers) {
254 Mutex::Autolock autoLock(mLock);
255 return setDataSource_l(uri, headers);
256}
257
258status_t PreviewPlayer::setDataSource_l(
259 const char *uri, const KeyedVector<String8, String8> *headers) {
260 reset_l();
261
262 mUri = uri;
263
264 if (headers) {
265 mUriHeaders = *headers;
266 }
267
268 // The actual work will be done during preparation in the call to
269 // ::finishSetDataSource_l to avoid blocking the calling thread in
270 // setDataSource for any significant time.
271 return OK;
272}
273
274status_t PreviewPlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
275 bool haveAudio = false;
276 bool haveVideo = false;
277 for (size_t i = 0; i < extractor->countTracks(); ++i) {
278 sp<MetaData> meta = extractor->getTrackMetaData(i);
279
280 const char *mime;
281 CHECK(meta->findCString(kKeyMIMEType, &mime));
282
283 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
284 setVideoSource(extractor->getTrack(i));
285 haveVideo = true;
286 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
287 setAudioSource(extractor->getTrack(i));
288 haveAudio = true;
289
290 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
291 // Only do this for vorbis audio, none of the other audio
292 // formats even support this ringtone specific hack and
293 // retrieving the metadata on some extractors may turn out
294 // to be very expensive.
295 sp<MetaData> fileMeta = extractor->getMetaData();
296 int32_t loop;
297 if (fileMeta != NULL
298 && fileMeta->findInt32(kKeyAutoLoop, &loop)
299 && loop != 0) {
300 mFlags |= AUTO_LOOPING;
301 }
302 }
303 }
304
305 if (haveAudio && haveVideo) {
306 break;
307 }
308 }
309
310 /* Add the support for Dummy audio*/
311 if( !haveAudio ){
312 LOGV("PreviewPlayer: setDataSource_l Dummyaudiocreation started");
313
314 mAudioTrack = DummyAudioSource::Create(32000, 2, 20000,
315 ((mPlayEndTimeMsec)*1000));
316 LOGV("PreviewPlayer: setDataSource_l Dummyauiosource created");
317 if(mAudioTrack != NULL) {
318 haveAudio = true;
319 }
320 }
321
322 if (!haveAudio && !haveVideo) {
323 return UNKNOWN_ERROR;
324 }
325
326 mExtractorFlags = extractor->flags();
327 return OK;
328}
329
330status_t PreviewPlayer::setDataSource_l_jpg() {
331 M4OSA_ERR err = M4NO_ERROR;
332 LOGV("PreviewPlayer: setDataSource_l_jpg started");
333
334 mAudioSource = DummyAudioSource::Create(32000, 2, 20000,
335 ((mPlayEndTimeMsec)*1000));
336 LOGV("PreviewPlayer: setDataSource_l_jpg Dummyaudiosource created");
337 if(mAudioSource != NULL) {
338 setAudioSource(mAudioSource);
339 }
340 status_t error = mAudioSource->start();
341 if (error != OK) {
342 LOGV("Error starting dummy audio source");
343 mAudioSource.clear();
344 return err;
345 }
346
347 mDurationUs = (mPlayEndTimeMsec - mPlayBeginTimeMsec)*1000;
348
349 mVideoSource = DummyVideoSource::Create(mVideoWidth, mVideoHeight,
350 mDurationUs, mUri);
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800351 mReportedWidth = mVideoWidth;
352 mReportedHeight = mVideoHeight;
353
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800354 setVideoSource(mVideoSource);
355 status_t err1 = mVideoSource->start();
356 if (err1 != OK) {
357 mVideoSource.clear();
358 return err;
359 }
360
361 mIsVideoSourceJpg = true;
362 return OK;
363}
364
365void PreviewPlayer::reset() {
366 Mutex::Autolock autoLock(mLock);
367 reset_l();
368}
369
370void PreviewPlayer::reset_l() {
371
372 if (mFlags & PREPARING) {
373 mFlags |= PREPARE_CANCELLED;
374 }
375
376 while (mFlags & PREPARING) {
377 mPreparedCondition.wait(mLock);
378 }
379
380 cancelPlayerEvents();
381 mAudioTrack.clear();
382 mVideoTrack.clear();
383
384 // Shutdown audio first, so that the respone to the reset request
385 // appears to happen instantaneously as far as the user is concerned
386 // If we did this later, audio would continue playing while we
387 // shutdown the video-related resources and the player appear to
388 // not be as responsive to a reset request.
389 if (mAudioPlayer == NULL && mAudioSource != NULL) {
390 // If we had an audio player, it would have effectively
391 // taken possession of the audio source and stopped it when
392 // _it_ is stopped. Otherwise this is still our responsibility.
393 mAudioSource->stop();
394 }
395 mAudioSource.clear();
396
397 mTimeSource = NULL;
398
399 delete mAudioPlayer;
400 mAudioPlayer = NULL;
401
402 if (mLastVideoBuffer) {
403 mLastVideoBuffer->release();
404 mLastVideoBuffer = NULL;
405 }
406
407 if (mVideoBuffer) {
408 mVideoBuffer->release();
409 mVideoBuffer = NULL;
410 }
411
412 if (mVideoSource != NULL) {
413 mVideoSource->stop();
414
415 // The following hack is necessary to ensure that the OMX
416 // component is completely released by the time we may try
417 // to instantiate it again.
418 wp<MediaSource> tmp = mVideoSource;
419 mVideoSource.clear();
420 while (tmp.promote() != NULL) {
421 usleep(1000);
422 }
423 IPCThreadState::self()->flushCommands();
424 }
425
426 mDurationUs = -1;
427 mFlags = 0;
428 mExtractorFlags = 0;
429 mVideoWidth = mVideoHeight = -1;
430 mTimeSourceDeltaUs = 0;
431 mVideoTimeUs = 0;
432
433 mSeeking = false;
434 mSeekNotificationSent = false;
435 mSeekTimeUs = 0;
436
437 mUri.setTo("");
438 mUriHeaders.clear();
439
440 mFileSource.clear();
441
442 delete mSuspensionState;
443 mSuspensionState = NULL;
444
445 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
446 mIsVideoSourceJpg = false;
447 mFrameRGBBuffer = NULL;
448 if(mFrameYUVBuffer != NULL) {
449 M4OSA_free((M4OSA_MemAddr32)mFrameYUVBuffer);
450 mFrameYUVBuffer = NULL;
451 }
452}
453
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800454status_t PreviewPlayer::play() {
455 Mutex::Autolock autoLock(mLock);
456
457 mFlags &= ~CACHE_UNDERRUN;
458
459 return play_l();
460}
461
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800462status_t PreviewPlayer::startAudioPlayer_l() {
463 CHECK(!(mFlags & AUDIO_RUNNING));
464
465 if (mAudioSource == NULL || mAudioPlayer == NULL) {
466 return OK;
467 }
468
469 if (!(mFlags & AUDIOPLAYER_STARTED)) {
470 mFlags |= AUDIOPLAYER_STARTED;
471
472 // We've already started the MediaSource in order to enable
473 // the prefetcher to read its data.
474 status_t err = mVeAudioPlayer->start(
475 true /* sourceAlreadyStarted */);
476
477 if (err != OK) {
478 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
479 return err;
480 }
481 } else {
482 mVeAudioPlayer->resume();
483 }
484
485 mFlags |= AUDIO_RUNNING;
486
487 mWatchForAudioEOS = true;
488
489 return OK;
490}
491
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800492status_t PreviewPlayer::play_l() {
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800493
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800494 if (mFlags & PLAYING) {
495 return OK;
496 }
497 mStartNextPlayer = false;
498
499 if (!(mFlags & PREPARED)) {
500 status_t err = prepare_l();
501
502 if (err != OK) {
503 return err;
504 }
505 }
506
507 mFlags |= PLAYING;
508 mFlags |= FIRST_FRAME;
509
510 bool deferredAudioSeek = false;
511
512 if (mAudioSource != NULL) {
513 if (mAudioPlayer == NULL) {
514 if (mAudioSink != NULL) {
515
516 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800517 mVeAudioPlayer =
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800518 (VideoEditorAudioPlayer*)mAudioPlayer;
519
520 mAudioPlayer->setSource(mAudioSource);
521
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800522 mVeAudioPlayer->setAudioMixSettings(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800523 mPreviewPlayerAudioMixSettings);
524
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800525 mVeAudioPlayer->setAudioMixPCMFileHandle(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800526 mAudioMixPCMFileHandle);
527
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800528 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800529 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
530 mCurrentMediaVolumeValue);
531
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800532 mTimeSource = mVeAudioPlayer; //mAudioPlayer;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800533
534 deferredAudioSeek = true;
535 mWatchForAudioSeekComplete = false;
536 mWatchForAudioEOS = true;
537 }
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800538 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800539
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800540 CHECK(!(mFlags & AUDIO_RUNNING));
541
542 if (mVideoSource == NULL) {
543 status_t err = startAudioPlayer_l();
544
545 if (err != OK) {
546 delete mAudioPlayer;
547 mAudioPlayer = NULL;
548 mFlags &= ~(PLAYING | FIRST_FRAME);
549 return err;
550 }
551 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800552 }
553
554 if (mTimeSource == NULL && mAudioPlayer == NULL) {
555 mTimeSource = &mSystemTimeSource;
556 }
557
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800558 // Set the seek option for Image source files and read.
559 // This resets the timestamping for image play
560 if (mIsVideoSourceJpg) {
561 MediaSource::ReadOptions options;
562 MediaBuffer *aLocalBuffer;
563 options.setSeekTo(mSeekTimeUs);
564 mVideoSource->read(&aLocalBuffer, &options);
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800565 aLocalBuffer->release();
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800566 }
567
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800568 if (mVideoSource != NULL) {
569 // Kick off video playback
570 postVideoEvent_l();
571 }
572
573 if (deferredAudioSeek) {
574 // If there was a seek request while we were paused
575 // and we're just starting up again, honor the request now.
576 seekAudioIfNecessary_l();
577 }
578
579 if (mFlags & AT_EOS) {
580 // Legacy behaviour, if a stream finishes playing and then
581 // is started again, we play from the start...
582 seekTo_l(0);
583 }
584
585 return OK;
586}
587
588
Santosh Madhavabfece172011-02-03 16:59:47 -0800589status_t PreviewPlayer::initRenderer_l() {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800590 if (mSurface != NULL || mISurface != NULL) {
591 sp<MetaData> meta = mVideoSource->getFormat();
592
593 int32_t format;
594 const char *component;
595 int32_t decodedWidth, decodedHeight;
596 CHECK(meta->findInt32(kKeyColorFormat, &format));
597 CHECK(meta->findCString(kKeyDecoderComponent, &component));
598 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
599 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
600
601 // Must ensure that mVideoRenderer's destructor is actually executed
602 // before creating a new one.
603 IPCThreadState::self()->flushCommands();
604
605 // always use localrenderer since decoded buffers are modified
606 // by postprocessing module
607 // Other decoders are instantiated locally and as a consequence
608 // allocate their buffers in local address space.
609 if(mVideoRenderer == NULL) {
610
Santosh Madhavabfece172011-02-03 16:59:47 -0800611 mVideoRenderer = PreviewLocalRenderer:: initPreviewLocalRenderer (
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800612 false, // previewOnly
613 (OMX_COLOR_FORMATTYPE)format,
614 mSurface,
615 mOutputVideoWidth, mOutputVideoHeight,
616 mOutputVideoWidth, mOutputVideoHeight);
Santosh Madhavabfece172011-02-03 16:59:47 -0800617
618 if ( mVideoRenderer == NULL )
619 {
620 return UNKNOWN_ERROR;
621 }
622 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800623 }
624 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800625 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800626}
627
628
629void PreviewPlayer::setISurface(const sp<ISurface> &isurface) {
630 Mutex::Autolock autoLock(mLock);
631 mISurface = isurface;
632}
633
634
635status_t PreviewPlayer::seekTo(int64_t timeUs) {
636
637 if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) {
638 Mutex::Autolock autoLock(mLock);
639 return seekTo_l(timeUs);
640 }
641
642 return OK;
643}
644
645
646status_t PreviewPlayer::getVideoDimensions(
647 int32_t *width, int32_t *height) const {
648 Mutex::Autolock autoLock(mLock);
649
650 if (mVideoWidth < 0 || mVideoHeight < 0) {
651 return UNKNOWN_ERROR;
652 }
653
654 *width = mVideoWidth;
655 *height = mVideoHeight;
656
657 return OK;
658}
659
660
661status_t PreviewPlayer::initAudioDecoder() {
662 sp<MetaData> meta = mAudioTrack->getFormat();
663 const char *mime;
664 CHECK(meta->findCString(kKeyMIMEType, &mime));
665
666 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
667 mAudioSource = mAudioTrack;
668 } else {
669 sp<MediaSource> aRawSource;
670 aRawSource = OMXCodec::Create(
671 mClient.interface(), mAudioTrack->getFormat(),
672 false, // createEncoder
673 mAudioTrack);
674
675 if(aRawSource != NULL) {
676 LOGV("initAudioDecoder: new VideoEditorSRC");
677 mAudioSource = new VideoEditorSRC(aRawSource);
678 }
679 }
680
681 if (mAudioSource != NULL) {
682 int64_t durationUs;
683 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
684 Mutex::Autolock autoLock(mMiscStateLock);
685 if (mDurationUs < 0 || durationUs > mDurationUs) {
686 mDurationUs = durationUs;
687 }
688 }
689 status_t err = mAudioSource->start();
690
691 if (err != OK) {
692 mAudioSource.clear();
693 return err;
694 }
695 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
696 // For legacy reasons we're simply going to ignore the absence
697 // of an audio decoder for QCELP instead of aborting playback
698 // altogether.
699 return OK;
700 }
701
702 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
703}
704
705
706status_t PreviewPlayer::initVideoDecoder(uint32_t flags) {
707
708 mVideoSource = OMXCodec::Create(
709 mClient.interface(), mVideoTrack->getFormat(),
710 false,
711 mVideoTrack,
712 NULL, flags);
713
714 if (mVideoSource != NULL) {
715 int64_t durationUs;
716 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
717 Mutex::Autolock autoLock(mMiscStateLock);
718 if (mDurationUs < 0 || durationUs > mDurationUs) {
719 mDurationUs = durationUs;
720 }
721 }
722
723 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
724 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
725
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800726 mReportedWidth = mVideoWidth;
727 mReportedHeight = mVideoHeight;
728
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800729 status_t err = mVideoSource->start();
730
731 if (err != OK) {
732 mVideoSource.clear();
733 return err;
734 }
735 }
736
737 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
738}
739
740
741void PreviewPlayer::onVideoEvent() {
742 uint32_t i=0;
743 bool bAppliedVideoEffect = false;
744 M4OSA_ERR err1 = M4NO_ERROR;
745 int64_t imageFrameTimeUs = 0;
746
747 Mutex::Autolock autoLock(mLock);
748 if (!mVideoEventPending) {
749 // The event has been cancelled in reset_l() but had already
750 // been scheduled for execution at that time.
751 return;
752 }
753 mVideoEventPending = false;
754
Andreas Huber9e4c36a2011-02-08 13:12:32 -0800755 if (mFlags & SEEK_PREVIEW) {
756 mFlags &= ~SEEK_PREVIEW;
757 return;
758 }
759
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800760 TimeSource *ts_st = &mSystemTimeSource;
761 int64_t timeStartUs = ts_st->getRealTimeUs();
762
763 if (mSeeking) {
764 if (mLastVideoBuffer) {
765 mLastVideoBuffer->release();
766 mLastVideoBuffer = NULL;
767 }
768
769
770 if(mAudioSource != NULL) {
771
772 // We're going to seek the video source first, followed by
773 // the audio source.
774 // In order to avoid jumps in the DataSource offset caused by
775 // the audio codec prefetching data from the old locations
776 // while the video codec is already reading data from the new
777 // locations, we'll "pause" the audio source, causing it to
778 // stop reading input data until a subsequent seek.
779
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800780 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800781 mAudioPlayer->pause();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800782 mFlags &= ~AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800783 }
784 mAudioSource->pause();
785 }
786 }
787
788 if (!mVideoBuffer) {
789 MediaSource::ReadOptions options;
790 if (mSeeking) {
791 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
792 mSeekTimeUs / 1E6);
793
794 options.setSeekTo(
795 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
796 }
797 for (;;) {
798 status_t err = mVideoSource->read(&mVideoBuffer, &options);
799 options.clearSeekTo();
800
801 if (err != OK) {
802 CHECK_EQ(mVideoBuffer, NULL);
803
804 if (err == INFO_FORMAT_CHANGED) {
805 LOGV("LV PLAYER VideoSource signalled format change");
806 notifyVideoSize_l();
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800807 sp<MetaData> meta = mVideoSource->getFormat();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800808
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800809 CHECK(meta->findInt32(kKeyWidth, &mReportedWidth));
810 CHECK(meta->findInt32(kKeyHeight, &mReportedHeight));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800811 if (mVideoRenderer != NULL) {
812 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -0800813 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800814 if (err != OK) {
815 postStreamDoneEvent_l(err);
816 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800817
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800818 }
819 continue;
820 }
821 // So video playback is complete, but we may still have
Santosh Madhava342f9322011-01-27 16:27:12 -0800822 // a seek request pending that needs to be applied to the audio track
823 if (mSeeking) {
824 LOGV("video stream ended while seeking!");
825 }
826 finishSeekIfNecessary(-1);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800827 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
828 mFlags |= VIDEO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800829 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800830 postStreamDoneEvent_l(err);
831 return;
832 }
833
834 if (mVideoBuffer->range_length() == 0) {
835 // Some decoders, notably the PV AVC software decoder
836 // return spurious empty buffers that we just want to ignore.
837
838 mVideoBuffer->release();
839 mVideoBuffer = NULL;
840 continue;
841 }
842
843 int64_t videoTimeUs;
844 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
845
846 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
847 // Frames are before begin cut time
848 // Donot render
849 mVideoBuffer->release();
850 mVideoBuffer = NULL;
851 continue;
852 }
853
854 break;
855 }
856 }
857
858 mNumberDecVideoFrames++;
859
860 int64_t timeUs;
861 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
862
863 {
864 Mutex::Autolock autoLock(mMiscStateLock);
865 mVideoTimeUs = timeUs;
866 }
867
868 mDecodedVideoTs = timeUs;
869
870 if(!mStartNextPlayer) {
871 int64_t playbackTimeRemaining = (mPlayEndTimeMsec*1000) - timeUs;
872 if(playbackTimeRemaining <= 1500000) {
873 //When less than 1.5 sec of playback left
874 // send notification to start next player
875
876 mStartNextPlayer = true;
877 notifyListener_l(0xAAAAAAAA);
878 }
879 }
880
881 bool wasSeeking = mSeeking;
882 finishSeekIfNecessary(timeUs);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800883 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING))) {
884 status_t err = startAudioPlayer_l();
885 if (err != OK) {
886 LOGE("Starting the audio player failed w/ err %d", err);
887 return;
888 }
889 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800890
891 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
892
893 if(ts == NULL) {
894 mVideoBuffer->release();
895 mVideoBuffer = NULL;
896 return;
897 }
898
899 if(!mIsVideoSourceJpg) {
900 if (mFlags & FIRST_FRAME) {
901 mFlags &= ~FIRST_FRAME;
902
903 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
904 }
905
906 int64_t realTimeUs, mediaTimeUs;
907 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
908 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
909 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
910 }
911
912 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
913
914 int64_t latenessUs = nowUs - timeUs;
915
916 if (wasSeeking) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800917 // Let's display the first frame after seeking right away.
918 latenessUs = 0;
919 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800920 LOGV("Audio time stamp = %lld and video time stamp = %lld",
921 ts->getRealTimeUs(),timeUs);
922 if (latenessUs > 40000) {
923 // We're more than 40ms late.
924
925 LOGV("LV PLAYER we're late by %lld us (%.2f secs)",
926 latenessUs, latenessUs / 1E6);
927
928 mVideoBuffer->release();
929 mVideoBuffer = NULL;
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800930 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800931 return;
932 }
933
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800934 if (latenessUs < -25000) {
935 // We're more than 25ms early.
936 LOGV("We're more than 25ms early, lateness %lld", latenessUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800937
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800938 postVideoEvent_l(25000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800939 return;
940 }
941 }
942
943 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
944 mVideoRendererIsPreview = false;
945
Santosh Madhavabfece172011-02-03 16:59:47 -0800946 status_t err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800947 if (err != OK) {
948 postStreamDoneEvent_l(err);
949 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800950 }
951
952 // If timestamp exceeds endCutTime of clip, donot render
953 if((timeUs/1000) > mPlayEndTimeMsec) {
954 if (mLastVideoBuffer) {
955 mLastVideoBuffer->release();
956 mLastVideoBuffer = NULL;
957 }
958 mLastVideoBuffer = mVideoBuffer;
959 mVideoBuffer = NULL;
960 mFlags |= VIDEO_AT_EOS;
961 mFlags |= AUDIO_AT_EOS;
Santosh Madhavabfece172011-02-03 16:59:47 -0800962 LOGV("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS..");
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800963 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800964 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
965 return;
966 }
967
968 // Post processing to apply video effects
969 for(i=0;i<mNumberEffects;i++) {
970 // First check if effect starttime matches the clip being previewed
971 if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) ||
972 (mEffectsSettings[i].uiStartTime >=
973 ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec)))
974 {
975 // This effect doesn't belong to this clip, check next one
976 continue;
977 }
978 // Check if effect applies to this particular frame timestamp
979 if((mEffectsSettings[i].uiStartTime <=
980 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) &&
981 ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=
982 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec))
983 && (mEffectsSettings[i].uiDuration != 0)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800984 setVideoPostProcessingNode(
985 mEffectsSettings[i].VideoEffectType, TRUE);
986 }
987 else {
988 setVideoPostProcessingNode(
989 mEffectsSettings[i].VideoEffectType, FALSE);
990 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800991 }
992
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800993 //Provide the overlay Update indication when there is an overlay effect
Dharmaray Kundargid01ef562011-01-26 21:11:00 -0800994 if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) {
995 mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here.
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800996 if (!mOverlayUpdateEventPosted) {
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800997 // Find the effect in effectSettings array
998 int index;
999 for (index = 0; index < mNumberEffects; index++) {
1000 M4OSA_UInt32 timeMs = mDecodedVideoTs/1000;
1001 M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000;
1002 if(mEffectsSettings[index].VideoEffectType ==
1003 M4xVSS_kVideoEffectType_Framing) {
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001004 if (((mEffectsSettings[index].uiStartTime + 1) <=
1005 timeMs + timeOffset - mPlayBeginTimeMsec) &&
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001006 ((mEffectsSettings[index].uiStartTime - 1 +
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001007 mEffectsSettings[index].uiDuration) >=
1008 timeMs + timeOffset - mPlayBeginTimeMsec))
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001009 {
1010 break;
1011 }
1012 }
1013 }
1014 if (index < mNumberEffects) {
1015 mCurrFramingEffectIndex = index;
1016 mOverlayUpdateEventPosted = true;
1017 postOverlayUpdateEvent_l();
1018 LOGV("Framing index = %d", mCurrFramingEffectIndex);
1019 } else {
1020 LOGV("No framing effects found");
1021 }
1022 }
1023
1024 } else if (mOverlayUpdateEventPosted) {
1025 //Post the event when the overlay is no more valid
1026 LOGV("Overlay is Done");
1027 mOverlayUpdateEventPosted = false;
1028 postOverlayUpdateEvent_l();
1029 }
1030
1031
1032 if (mCurrentVideoEffect != VIDEO_EFFECT_NONE) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001033 err1 = doVideoPostProcessing();
1034 if(err1 != M4NO_ERROR) {
1035 LOGE("doVideoPostProcessing returned err");
1036 bAppliedVideoEffect = false;
1037 }
1038 else {
1039 bAppliedVideoEffect = true;
1040 }
1041 }
1042 else {
1043 bAppliedVideoEffect = false;
1044 if(mRenderingMode != MEDIA_RENDERING_INVALID) {
1045 // No effects to be applied, but media rendering to be done
1046 err1 = doMediaRendering();
1047 if(err1 != M4NO_ERROR) {
1048 LOGE("doMediaRendering returned err");
1049 //Use original mVideoBuffer for rendering
1050 mVideoResizedOrCropped = false;
1051 }
1052 }
1053 }
1054
1055 if (mVideoRenderer != NULL) {
1056 LOGV("mVideoRenderer CALL render()");
1057 mVideoRenderer->render();
1058 }
1059
1060 if (mLastVideoBuffer) {
1061 mLastVideoBuffer->release();
1062 mLastVideoBuffer = NULL;
1063 }
1064
1065 mLastVideoBuffer = mVideoBuffer;
1066 mVideoBuffer = NULL;
1067
1068 // Post progress callback based on callback interval set
1069 if(mNumberDecVideoFrames >= mProgressCbInterval) {
1070 postProgressCallbackEvent_l();
1071 mNumberDecVideoFrames = 0; // reset counter
1072 }
1073
1074 // if reached EndCutTime of clip, post EOS event
1075 if((timeUs/1000) >= mPlayEndTimeMsec) {
1076 LOGV("PreviewPlayer: onVideoEvent EOS.");
1077 mFlags |= VIDEO_AT_EOS;
1078 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001079 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001080 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1081 }
1082 else {
1083 if(!mIsVideoSourceJpg) {
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001084 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001085 }
1086 else {
1087 postVideoEvent_l(33000);
1088 }
1089 }
1090}
1091
1092status_t PreviewPlayer::prepare() {
1093 Mutex::Autolock autoLock(mLock);
1094 return prepare_l();
1095}
1096
1097status_t PreviewPlayer::prepare_l() {
1098 if (mFlags & PREPARED) {
1099 return OK;
1100 }
1101
1102 if (mFlags & PREPARING) {
1103 return UNKNOWN_ERROR;
1104 }
1105
1106 mIsAsyncPrepare = false;
1107 status_t err = prepareAsync_l();
1108
1109 if (err != OK) {
1110 return err;
1111 }
1112
1113 while (mFlags & PREPARING) {
1114 mPreparedCondition.wait(mLock);
1115 }
1116
1117 return mPrepareResult;
1118}
1119
1120status_t PreviewPlayer::prepareAsync_l() {
1121 if (mFlags & PREPARING) {
1122 return UNKNOWN_ERROR; // async prepare already pending
1123 }
1124
1125 if (!mQueueStarted) {
1126 mQueue.start();
1127 mQueueStarted = true;
1128 }
1129
1130 mFlags |= PREPARING;
1131 mAsyncPrepareEvent = new PreviewPlayerEvent(
1132 this, &PreviewPlayer::onPrepareAsyncEvent);
1133
1134 mQueue.postEvent(mAsyncPrepareEvent);
1135
1136 return OK;
1137}
1138
1139status_t PreviewPlayer::finishSetDataSource_l() {
1140 sp<DataSource> dataSource;
1141 sp<MediaExtractor> extractor;
1142
1143 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1144
1145 if (dataSource == NULL) {
1146 return UNKNOWN_ERROR;
1147 }
1148
1149 //If file type is .rgb, then no need to check for Extractor
1150 int uriLen = strlen(mUri);
1151 int startOffset = uriLen - 4;
1152 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) {
1153 extractor = NULL;
1154 }
1155 else {
1156 extractor = MediaExtractor::Create(dataSource,
1157 MEDIA_MIMETYPE_CONTAINER_MPEG4);
1158 }
1159
1160 if (extractor == NULL) {
1161 LOGV("PreviewPlayer::finishSetDataSource_l extractor == NULL");
1162 return setDataSource_l_jpg();
1163 }
1164
1165 return setDataSource_l(extractor);
1166}
1167
1168
1169// static
1170bool PreviewPlayer::ContinuePreparation(void *cookie) {
1171 PreviewPlayer *me = static_cast<PreviewPlayer *>(cookie);
1172
1173 return (me->mFlags & PREPARE_CANCELLED) == 0;
1174}
1175
1176void PreviewPlayer::onPrepareAsyncEvent() {
1177 Mutex::Autolock autoLock(mLock);
1178 LOGV("onPrepareAsyncEvent");
1179
1180 if (mFlags & PREPARE_CANCELLED) {
Santosh Madhavabfece172011-02-03 16:59:47 -08001181 LOGV("LV PLAYER prepare was cancelled before doing anything");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001182 abortPrepare(UNKNOWN_ERROR);
1183 return;
1184 }
1185
1186 if (mUri.size() > 0) {
1187 status_t err = finishSetDataSource_l();
1188
1189 if (err != OK) {
1190 abortPrepare(err);
1191 return;
1192 }
1193 }
1194
1195 if (mVideoTrack != NULL && mVideoSource == NULL) {
1196 status_t err = initVideoDecoder(OMXCodec::kHardwareCodecsOnly);
1197
1198 if (err != OK) {
1199 abortPrepare(err);
1200 return;
1201 }
1202 }
1203
1204 if (mAudioTrack != NULL && mAudioSource == NULL) {
1205 status_t err = initAudioDecoder();
1206
1207 if (err != OK) {
1208 abortPrepare(err);
1209 return;
1210 }
1211 }
1212 finishAsyncPrepare_l();
1213
1214}
1215
1216void PreviewPlayer::finishAsyncPrepare_l() {
1217 if (mIsAsyncPrepare) {
1218 if (mVideoSource == NULL) {
1219 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE 0 0 ");
1220 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1221 } else {
1222 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE");
1223 notifyVideoSize_l();
1224 }
1225 LOGV("finishAsyncPrepare_l: MEDIA_PREPARED");
1226 notifyListener_l(MEDIA_PREPARED);
1227 }
1228
1229 mPrepareResult = OK;
1230 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1231 mFlags |= PREPARED;
1232 mAsyncPrepareEvent = NULL;
1233 mPreparedCondition.broadcast();
1234}
1235
1236status_t PreviewPlayer::suspend() {
1237 LOGV("suspend");
1238 Mutex::Autolock autoLock(mLock);
1239
1240 if (mSuspensionState != NULL) {
1241 if (mLastVideoBuffer == NULL) {
1242 //go into here if video is suspended again
1243 //after resuming without being played between
1244 //them
1245 SuspensionState *state = mSuspensionState;
1246 mSuspensionState = NULL;
1247 reset_l();
1248 mSuspensionState = state;
1249 return OK;
1250 }
1251
1252 delete mSuspensionState;
1253 mSuspensionState = NULL;
1254 }
1255
1256 if (mFlags & PREPARING) {
1257 mFlags |= PREPARE_CANCELLED;
1258 }
1259
1260 while (mFlags & PREPARING) {
1261 mPreparedCondition.wait(mLock);
1262 }
1263
1264 SuspensionState *state = new SuspensionState;
1265 state->mUri = mUri;
1266 state->mUriHeaders = mUriHeaders;
1267 state->mFileSource = mFileSource;
1268
1269 state->mFlags = mFlags & (PLAYING | AUTO_LOOPING | LOOPING | AT_EOS);
1270 getPosition(&state->mPositionUs);
1271
1272 if (mLastVideoBuffer) {
1273 size_t size = mLastVideoBuffer->range_length();
1274 if (size) {
1275 int32_t unreadable;
1276 if (!mLastVideoBuffer->meta_data()->findInt32(
1277 kKeyIsUnreadable, &unreadable)
1278 || unreadable == 0) {
1279 state->mLastVideoFrameSize = size;
1280 state->mLastVideoFrame = malloc(size);
1281 memcpy(state->mLastVideoFrame,
1282 (const uint8_t *)mLastVideoBuffer->data()
1283 + mLastVideoBuffer->range_offset(),
1284 size);
1285
1286 state->mVideoWidth = mVideoWidth;
1287 state->mVideoHeight = mVideoHeight;
1288
1289 sp<MetaData> meta = mVideoSource->getFormat();
1290 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1291 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1292 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1293 } else {
1294 LOGV("Unable to save last video frame, we have no access to "
1295 "the decoded video data.");
1296 }
1297 }
1298 }
1299
1300 reset_l();
1301
1302 mSuspensionState = state;
1303
1304 return OK;
1305}
1306
1307status_t PreviewPlayer::resume() {
1308 LOGV("resume");
1309 Mutex::Autolock autoLock(mLock);
1310
1311 if (mSuspensionState == NULL) {
1312 return INVALID_OPERATION;
1313 }
1314
1315 SuspensionState *state = mSuspensionState;
1316 mSuspensionState = NULL;
1317
1318 status_t err;
1319 if (state->mFileSource != NULL) {
1320 err = AwesomePlayer::setDataSource_l(state->mFileSource);
1321
1322 if (err == OK) {
1323 mFileSource = state->mFileSource;
1324 }
1325 } else {
1326 err = AwesomePlayer::setDataSource_l(state->mUri, &state->mUriHeaders);
1327 }
1328
1329 if (err != OK) {
1330 delete state;
1331 state = NULL;
1332
1333 return err;
1334 }
1335
1336 seekTo_l(state->mPositionUs);
1337
1338 mFlags = state->mFlags & (AUTO_LOOPING | LOOPING | AT_EOS);
1339
1340 if (state->mLastVideoFrame && (mSurface != NULL || mISurface != NULL)) {
1341 mVideoRenderer =
Santosh Madhavabfece172011-02-03 16:59:47 -08001342 PreviewLocalRenderer::initPreviewLocalRenderer(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001343 true, // previewOnly
1344 (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1345 mSurface,
1346 state->mVideoWidth,
1347 state->mVideoHeight,
1348 state->mDecodedWidth,
1349 state->mDecodedHeight);
1350
1351 mVideoRendererIsPreview = true;
1352
1353 ((PreviewLocalRenderer *)mVideoRenderer.get())->render(
1354 state->mLastVideoFrame, state->mLastVideoFrameSize);
1355 }
1356
1357 if (state->mFlags & PLAYING) {
1358 play_l();
1359 }
1360
1361 mSuspensionState = state;
1362 state = NULL;
1363
1364 return OK;
1365}
1366
1367
1368status_t PreviewPlayer::loadEffectsSettings(
1369 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) {
1370 M4OSA_UInt32 i = 0, rgbSize = 0;
1371 M4VIFI_UInt8 *tmp = M4OSA_NULL;
1372
1373 mNumberEffects = nEffects;
1374 mEffectsSettings = pEffectSettings;
1375 return OK;
1376}
1377
1378status_t PreviewPlayer::loadAudioMixSettings(
1379 M4xVSS_AudioMixingSettings* pAudioMixSettings) {
1380
1381 LOGV("PreviewPlayer: loadAudioMixSettings: ");
1382 mPreviewPlayerAudioMixSettings = pAudioMixSettings;
1383 return OK;
1384}
1385
1386status_t PreviewPlayer::setAudioMixPCMFileHandle(
1387 M4OSA_Context pAudioMixPCMFileHandle) {
1388
1389 LOGV("PreviewPlayer: setAudioMixPCMFileHandle: ");
1390 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle;
1391 return OK;
1392}
1393
1394status_t PreviewPlayer::setAudioMixStoryBoardParam(
1395 M4OSA_UInt32 audioMixStoryBoardTS,
1396 M4OSA_UInt32 currentMediaBeginCutTime,
1397 M4OSA_UInt32 primaryTrackVolValue ) {
1398
1399 mAudioMixStoryBoardTS = audioMixStoryBoardTS;
1400 mCurrentMediaBeginCutTime = currentMediaBeginCutTime;
1401 mCurrentMediaVolumeValue = primaryTrackVolValue;
1402 return OK;
1403}
1404
1405status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) {
1406
1407 mPlayBeginTimeMsec = msec;
1408 return OK;
1409}
1410
1411status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) {
1412
1413 mPlayEndTimeMsec = msec;
1414 return OK;
1415}
1416
1417status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) {
1418
1419 mStoryboardStartTimeMsec = msec;
1420 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000;
1421 return OK;
1422}
1423
1424status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) {
1425
1426 mProgressCbInterval = cbInterval;
1427 return OK;
1428}
1429
1430
1431status_t PreviewPlayer::setMediaRenderingMode(
1432 M4xVSS_MediaRendering mode,
1433 M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
1434
1435 mRenderingMode = mode;
1436
1437 /* reset boolean for each clip*/
1438 mVideoResizedOrCropped = false;
1439
1440 switch(outputVideoSize) {
1441 case M4VIDEOEDITING_kSQCIF:
1442 mOutputVideoWidth = 128;
1443 mOutputVideoHeight = 96;
1444 break;
1445
1446 case M4VIDEOEDITING_kQQVGA:
1447 mOutputVideoWidth = 160;
1448 mOutputVideoHeight = 120;
1449 break;
1450
1451 case M4VIDEOEDITING_kQCIF:
1452 mOutputVideoWidth = 176;
1453 mOutputVideoHeight = 144;
1454 break;
1455
1456 case M4VIDEOEDITING_kQVGA:
1457 mOutputVideoWidth = 320;
1458 mOutputVideoHeight = 240;
1459 break;
1460
1461 case M4VIDEOEDITING_kCIF:
1462 mOutputVideoWidth = 352;
1463 mOutputVideoHeight = 288;
1464 break;
1465
1466 case M4VIDEOEDITING_kVGA:
1467 mOutputVideoWidth = 640;
1468 mOutputVideoHeight = 480;
1469 break;
1470
1471 case M4VIDEOEDITING_kWVGA:
1472 mOutputVideoWidth = 800;
1473 mOutputVideoHeight = 480;
1474 break;
1475
1476 case M4VIDEOEDITING_kNTSC:
1477 mOutputVideoWidth = 720;
1478 mOutputVideoHeight = 480;
1479 break;
1480
1481 case M4VIDEOEDITING_k640_360:
1482 mOutputVideoWidth = 640;
1483 mOutputVideoHeight = 360;
1484 break;
1485
1486 case M4VIDEOEDITING_k854_480:
1487 mOutputVideoWidth = 854;
1488 mOutputVideoHeight = 480;
1489 break;
1490
1491 case M4VIDEOEDITING_kHD1280:
1492 mOutputVideoWidth = 1280;
1493 mOutputVideoHeight = 720;
1494 break;
1495
1496 case M4VIDEOEDITING_kHD1080:
1497 mOutputVideoWidth = 1080;
1498 mOutputVideoHeight = 720;
1499 break;
1500
1501 case M4VIDEOEDITING_kHD960:
1502 mOutputVideoWidth = 960;
1503 mOutputVideoHeight = 720;
1504 break;
1505
1506 default:
1507 LOGE("unsupported output video size set");
1508 return BAD_VALUE;
1509 }
1510
1511 return OK;
1512}
1513
1514M4OSA_ERR PreviewPlayer::doMediaRendering() {
1515 M4OSA_ERR err = M4NO_ERROR;
1516 M4VIFI_ImagePlane planeIn[3], planeOut[3];
1517 M4VIFI_UInt8 *inBuffer = M4OSA_NULL, *finalOutputBuffer = M4OSA_NULL;
1518 M4VIFI_UInt8 *tempOutputBuffer= M4OSA_NULL;
1519 size_t videoBufferSize = 0;
1520 M4OSA_UInt32 frameSize = 0, i=0, index =0, nFrameCount =0, bufferOffset =0;
1521 int32_t colorFormat = 0;
1522
1523 if(!mIsVideoSourceJpg) {
1524 sp<MetaData> meta = mVideoSource->getFormat();
1525 CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
1526 }
1527 else {
1528 colorFormat = OMX_COLOR_FormatYUV420Planar;
1529 }
1530
1531 videoBufferSize = mVideoBuffer->size();
1532 frameSize = (mVideoWidth*mVideoHeight*3) >> 1;
1533
1534 uint8_t* outBuffer;
1535 size_t outBufferStride = 0;
1536
1537 mVideoRenderer->getBuffer(&outBuffer, &outBufferStride);
1538
1539 bufferOffset = index*frameSize;
1540 inBuffer = (M4OSA_UInt8 *)mVideoBuffer->data()+
1541 mVideoBuffer->range_offset()+bufferOffset;
1542
1543
1544 /* In plane*/
1545 prepareYUV420ImagePlane(planeIn, mVideoWidth,
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001546 mVideoHeight, (M4VIFI_UInt8 *)inBuffer, mReportedWidth, mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001547
1548 // Set the output YUV420 plane to be compatible with YV12 format
1549 // W & H even
1550 // YVU instead of YUV
1551 // align buffers on 32 bits
1552
1553 //In YV12 format, sizes must be even
1554 M4OSA_UInt32 yv12PlaneWidth = ((mOutputVideoWidth +1)>>1)<<1;
1555 M4OSA_UInt32 yv12PlaneHeight = ((mOutputVideoHeight+1)>>1)<<1;
1556
1557 prepareYV12ImagePlane(planeOut, yv12PlaneWidth, yv12PlaneHeight,
1558 (M4OSA_UInt32)outBufferStride, (M4VIFI_UInt8 *)outBuffer);
1559
1560
1561 err = applyRenderingMode(planeIn, planeOut, mRenderingMode);
1562
1563 if(err != M4NO_ERROR)
1564 {
1565 LOGE("doMediaRendering: applyRenderingMode returned err=0x%x", err);
1566 return err;
1567 }
1568 mVideoResizedOrCropped = true;
1569
1570 return err;
1571}
1572
1573status_t PreviewPlayer::resetJniCallbackTimeStamp() {
1574
1575 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000;
1576 return OK;
1577}
1578
1579void PreviewPlayer::postProgressCallbackEvent_l() {
1580 if (mProgressCbEventPending) {
1581 return;
1582 }
1583 mProgressCbEventPending = true;
1584
1585 mQueue.postEvent(mProgressCbEvent);
1586}
1587
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001588
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001589void PreviewPlayer::onProgressCbEvent() {
1590 Mutex::Autolock autoLock(mLock);
1591 if (!mProgressCbEventPending) {
1592 return;
1593 }
1594 mProgressCbEventPending = false;
1595 // If playback starts from previous I-frame,
1596 // then send frame storyboard duration
1597 if((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) {
1598 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000);
1599 }
1600 else {
1601 notifyListener_l(MEDIA_INFO, 0,
1602 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec));
1603 }
1604}
1605
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001606void PreviewPlayer::postOverlayUpdateEvent_l() {
1607 if (mOverlayUpdateEventPending) {
1608 return;
1609 }
1610 mOverlayUpdateEventPending = true;
1611 mQueue.postEvent(mOverlayUpdateEvent);
1612}
1613
1614void PreviewPlayer::onUpdateOverlayEvent() {
1615 Mutex::Autolock autoLock(mLock);
1616
1617 if (!mOverlayUpdateEventPending) {
1618 return;
1619 }
1620 mOverlayUpdateEventPending = false;
1621
1622 int updateState;
1623 if (mOverlayUpdateEventPosted) {
1624 updateState = 1;
1625 } else {
1626 updateState = 0;
1627 }
1628 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex);
1629}
1630
1631
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001632void PreviewPlayer::setVideoPostProcessingNode(
1633 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
1634
1635 uint32_t effect = VIDEO_EFFECT_NONE;
1636
1637 //Map M4VSS3GPP_VideoEffectType to local enum
1638 switch(type) {
1639 case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
1640 effect = VIDEO_EFFECT_FADEFROMBLACK;
1641 break;
1642
1643 case M4VSS3GPP_kVideoEffectType_FadeToBlack:
1644 effect = VIDEO_EFFECT_FADETOBLACK;
1645 break;
1646
1647 case M4VSS3GPP_kVideoEffectType_CurtainOpening:
1648 effect = VIDEO_EFFECT_CURTAINOPEN;
1649 break;
1650
1651 case M4VSS3GPP_kVideoEffectType_CurtainClosing:
1652 effect = VIDEO_EFFECT_CURTAINCLOSE;
1653 break;
1654
1655 case M4xVSS_kVideoEffectType_BlackAndWhite:
1656 effect = VIDEO_EFFECT_BLACKANDWHITE;
1657 break;
1658
1659 case M4xVSS_kVideoEffectType_Pink:
1660 effect = VIDEO_EFFECT_PINK;
1661 break;
1662
1663 case M4xVSS_kVideoEffectType_Green:
1664 effect = VIDEO_EFFECT_GREEN;
1665 break;
1666
1667 case M4xVSS_kVideoEffectType_Sepia:
1668 effect = VIDEO_EFFECT_SEPIA;
1669 break;
1670
1671 case M4xVSS_kVideoEffectType_Negative:
1672 effect = VIDEO_EFFECT_NEGATIVE;
1673 break;
1674
1675 case M4xVSS_kVideoEffectType_Framing:
1676 effect = VIDEO_EFFECT_FRAMING;
1677 break;
1678
1679 case M4xVSS_kVideoEffectType_Fifties:
1680 effect = VIDEO_EFFECT_FIFTIES;
1681 break;
1682
1683 case M4xVSS_kVideoEffectType_ColorRGB16:
1684 effect = VIDEO_EFFECT_COLOR_RGB16;
1685 break;
1686
1687 case M4xVSS_kVideoEffectType_Gradient:
1688 effect = VIDEO_EFFECT_GRADIENT;
1689 break;
1690
1691 default:
1692 effect = VIDEO_EFFECT_NONE;
1693 break;
1694 }
1695
1696 if(enable == M4OSA_TRUE) {
1697 //If already set, then no need to set again
1698 if(!(mCurrentVideoEffect & effect)) {
1699 mCurrentVideoEffect |= effect;
1700 if(effect == VIDEO_EFFECT_FIFTIES) {
1701 mIsFiftiesEffectStarted = true;
1702 }
1703 }
1704 }
1705 else {
1706 //Reset only if already set
1707 if(mCurrentVideoEffect & effect) {
1708 mCurrentVideoEffect &= ~effect;
1709 }
1710 }
1711}
1712
1713status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) {
1714 mVideoWidth = width;
1715 mVideoHeight = height;
1716 return OK;
1717}
1718
1719
1720M4OSA_ERR PreviewPlayer::doVideoPostProcessing() {
1721 M4OSA_ERR err = M4NO_ERROR;
1722 vePostProcessParams postProcessParams;
1723 int32_t colorFormat = 0;
1724
1725
1726 if(!mIsVideoSourceJpg) {
1727 sp<MetaData> meta = mVideoSource->getFormat();
1728 CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
1729 }
1730 else {
1731 colorFormat = OMX_COLOR_FormatYUV420Planar;
1732 }
1733
1734 if((colorFormat == OMX_COLOR_FormatYUV420SemiPlanar) ||
1735 (colorFormat == 0x7FA30C00)) {
1736 LOGE("doVideoPostProcessing: colorFormat YUV420Sp not supported");
1737 return M4ERR_UNSUPPORTED_MEDIA_TYPE;
1738 }
1739
1740 postProcessParams.vidBuffer = (M4VIFI_UInt8*)mVideoBuffer->data()
1741 + mVideoBuffer->range_offset();
1742
1743 postProcessParams.videoWidth = mVideoWidth;
1744 postProcessParams.videoHeight = mVideoHeight;
1745 postProcessParams.timeMs = mDecodedVideoTs/1000;
1746 postProcessParams.timeOffset = mDecVideoTsStoryBoard/1000;
1747 postProcessParams.effectsSettings = mEffectsSettings;
1748 postProcessParams.numberEffects = mNumberEffects;
1749 postProcessParams.outVideoWidth = mOutputVideoWidth;
1750 postProcessParams.outVideoHeight = mOutputVideoHeight;
1751 postProcessParams.currentVideoEffect = mCurrentVideoEffect;
1752 postProcessParams.renderingMode = mRenderingMode;
1753 if(mIsFiftiesEffectStarted == M4OSA_TRUE) {
1754 postProcessParams.isFiftiesEffectStarted = M4OSA_TRUE;
1755 mIsFiftiesEffectStarted = M4OSA_FALSE;
1756 }
1757 else {
1758 postProcessParams.isFiftiesEffectStarted = M4OSA_FALSE;
1759 }
1760
1761 postProcessParams.overlayFrameRGBBuffer = mFrameRGBBuffer;
1762 postProcessParams.overlayFrameYUVBuffer = mFrameYUVBuffer;
1763 mVideoRenderer->getBuffer(&(postProcessParams.pOutBuffer), &(postProcessParams.outBufferStride));
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001764 err = applyEffectsAndRenderingMode(&postProcessParams, mReportedWidth, mReportedHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001765
1766 return err;
1767}
1768
1769status_t PreviewPlayer::readFirstVideoFrame() {
1770 LOGV("PreviewPlayer::readFirstVideoFrame");
1771
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -08001772 if (mFlags & SEEK_PREVIEW) {
1773 mFlags &= ~SEEK_PREVIEW;
1774 return OK;
1775 }
1776
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001777 if (!mVideoBuffer) {
1778 MediaSource::ReadOptions options;
1779 if (mSeeking) {
1780 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
1781 mSeekTimeUs / 1E6);
1782
1783 options.setSeekTo(
1784 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
1785 }
1786 for (;;) {
1787 status_t err = mVideoSource->read(&mVideoBuffer, &options);
1788 options.clearSeekTo();
1789
1790 if (err != OK) {
1791 CHECK_EQ(mVideoBuffer, NULL);
1792
1793 if (err == INFO_FORMAT_CHANGED) {
1794 LOGV("LV PLAYER VideoSource signalled format change");
1795 notifyVideoSize_l();
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -08001796 sp<MetaData> meta = mVideoSource->getFormat();
1797
1798 CHECK(meta->findInt32(kKeyWidth, &mReportedWidth));
1799 CHECK(meta->findInt32(kKeyHeight, &mReportedHeight));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001800
1801 if (mVideoRenderer != NULL) {
1802 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -08001803 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001804 if (err != OK) {
1805 postStreamDoneEvent_l(err);
1806 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001807 }
1808 continue;
1809 }
1810 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
1811 mFlags |= VIDEO_AT_EOS;
1812 postStreamDoneEvent_l(err);
1813 return OK;
1814 }
1815
1816 if (mVideoBuffer->range_length() == 0) {
1817 // Some decoders, notably the PV AVC software decoder
1818 // return spurious empty buffers that we just want to ignore.
1819
1820 mVideoBuffer->release();
1821 mVideoBuffer = NULL;
1822 continue;
1823 }
1824
1825 int64_t videoTimeUs;
1826 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
1827
1828 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
1829 // buffers are before begin cut time
1830 // ignore them
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001831 mVideoBuffer->release();
1832 mVideoBuffer = NULL;
1833 continue;
1834 }
1835
1836 break;
1837 }
1838 }
1839
1840 int64_t timeUs;
1841 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1842
1843 {
1844 Mutex::Autolock autoLock(mMiscStateLock);
1845 mVideoTimeUs = timeUs;
1846 }
1847
1848 mDecodedVideoTs = timeUs;
1849
1850 return OK;
1851
1852}
1853
1854} // namespace android