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