blob: bdb5ce46437df8db804102a3bf5fb8e5094b1a45 [file] [log] [blame]
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001/*
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Santosh Madhavabfece172011-02-03 16:59:47 -080017
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080018#define LOG_NDEBUG 1
19#define LOG_TAG "PreviewPlayer"
20#include <utils/Log.h>
21
22#include <dlfcn.h>
23
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080024#include "PreviewPlayer.h"
25#include "DummyAudioSource.h"
26#include "DummyVideoSource.h"
27#include "VideoEditorSRC.h"
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080028#include "include/NuCachedSource2.h"
29#include "include/ThrottledSource.h"
30
31
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080032#include <binder/IPCThreadState.h>
33#include <media/stagefright/DataSource.h>
34#include <media/stagefright/FileSource.h>
35#include <media/stagefright/MediaBuffer.h>
36#include <media/stagefright/MediaDefs.h>
37#include <media/stagefright/MediaExtractor.h>
38#include <media/stagefright/MediaDebug.h>
39#include <media/stagefright/MediaSource.h>
40#include <media/stagefright/MetaData.h>
41#include <media/stagefright/OMXCodec.h>
42
43#include <surfaceflinger/Surface.h>
44#include <media/stagefright/foundation/ALooper.h>
45
46namespace android {
47
48
49struct PreviewPlayerEvent : public TimedEventQueue::Event {
50 PreviewPlayerEvent(
51 PreviewPlayer *player,
52 void (PreviewPlayer::*method)())
53 : mPlayer(player),
54 mMethod(method) {
55 }
56
57protected:
58 virtual ~PreviewPlayerEvent() {}
59
60 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
61 (mPlayer->*mMethod)();
62 }
63
64private:
65 PreviewPlayer *mPlayer;
66 void (PreviewPlayer::*mMethod)();
67
68 PreviewPlayerEvent(const PreviewPlayerEvent &);
69 PreviewPlayerEvent &operator=(const PreviewPlayerEvent &);
70};
71
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080072PreviewPlayer::PreviewPlayer(NativeWindowRenderer* renderer)
James Dongc9dedc42011-05-01 12:36:22 -070073 : PreviewPlayerBase(),
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080074 mNativeWindowRenderer(renderer),
75 mCurrFramingEffectIndex(0),
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -080076 mFrameRGBBuffer(NULL),
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080077 mFrameYUVBuffer(NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080078
79 mVideoRenderer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080080 mEffectsSettings = NULL;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -080081 mVeAudioPlayer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080082 mAudioMixStoryBoardTS = 0;
83 mCurrentMediaBeginCutTime = 0;
84 mCurrentMediaVolumeValue = 0;
85 mNumberEffects = 0;
86 mDecodedVideoTs = 0;
87 mDecVideoTsStoryBoard = 0;
88 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
89 mProgressCbInterval = 0;
90 mNumberDecVideoFrames = 0;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -080091 mOverlayUpdateEventPosted = false;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -080092 mIsChangeSourceRequired = true;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080093
94 mVideoEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoEvent);
95 mVideoEventPending = false;
96 mStreamDoneEvent = new PreviewPlayerEvent(this,
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -080097 &PreviewPlayer::onStreamDone);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080098
99 mStreamDoneEventPending = false;
100
101 mCheckAudioStatusEvent = new PreviewPlayerEvent(
James Dongc9dedc42011-05-01 12:36:22 -0700102 this, &PreviewPlayerBase::onCheckAudioStatus);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800103
104 mAudioStatusEventPending = false;
105
106 mProgressCbEvent = new PreviewPlayerEvent(this,
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800107 &PreviewPlayer::onProgressCbEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800108
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800109 mOverlayUpdateEvent = new PreviewPlayerEvent(this,
110 &PreviewPlayer::onUpdateOverlayEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800111 mProgressCbEventPending = false;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800112
113 mOverlayUpdateEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800114 mRenderingMode = (M4xVSS_MediaRendering)MEDIA_RENDERING_INVALID;
115 mIsFiftiesEffectStarted = false;
116 reset();
117}
118
119PreviewPlayer::~PreviewPlayer() {
120
121 if (mQueueStarted) {
122 mQueue.stop();
123 }
124
125 reset();
126
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800127 if (mVideoRenderer) {
128 mNativeWindowRenderer->destroyRenderInput(mVideoRenderer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800129 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800130}
131
132void PreviewPlayer::cancelPlayerEvents(bool keepBufferingGoing) {
133 mQueue.cancelEvent(mVideoEvent->eventID());
134 mVideoEventPending = false;
135 mQueue.cancelEvent(mStreamDoneEvent->eventID());
136 mStreamDoneEventPending = false;
137 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
138 mAudioStatusEventPending = false;
139
140 mQueue.cancelEvent(mProgressCbEvent->eventID());
141 mProgressCbEventPending = false;
142}
143
144status_t PreviewPlayer::setDataSource(
145 const char *uri, const KeyedVector<String8, String8> *headers) {
146 Mutex::Autolock autoLock(mLock);
147 return setDataSource_l(uri, headers);
148}
149
150status_t PreviewPlayer::setDataSource_l(
151 const char *uri, const KeyedVector<String8, String8> *headers) {
152 reset_l();
153
154 mUri = uri;
155
156 if (headers) {
157 mUriHeaders = *headers;
158 }
159
160 // The actual work will be done during preparation in the call to
161 // ::finishSetDataSource_l to avoid blocking the calling thread in
162 // setDataSource for any significant time.
163 return OK;
164}
165
166status_t PreviewPlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
167 bool haveAudio = false;
168 bool haveVideo = false;
169 for (size_t i = 0; i < extractor->countTracks(); ++i) {
170 sp<MetaData> meta = extractor->getTrackMetaData(i);
171
172 const char *mime;
173 CHECK(meta->findCString(kKeyMIMEType, &mime));
174
175 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
176 setVideoSource(extractor->getTrack(i));
177 haveVideo = true;
178 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
179 setAudioSource(extractor->getTrack(i));
180 haveAudio = true;
181
182 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
183 // Only do this for vorbis audio, none of the other audio
184 // formats even support this ringtone specific hack and
185 // retrieving the metadata on some extractors may turn out
186 // to be very expensive.
187 sp<MetaData> fileMeta = extractor->getMetaData();
188 int32_t loop;
189 if (fileMeta != NULL
190 && fileMeta->findInt32(kKeyAutoLoop, &loop)
191 && loop != 0) {
192 mFlags |= AUTO_LOOPING;
193 }
194 }
195 }
196
197 if (haveAudio && haveVideo) {
198 break;
199 }
200 }
201
202 /* Add the support for Dummy audio*/
203 if( !haveAudio ){
Steve Block2703f232011-10-20 11:56:09 +0100204 ALOGV("PreviewPlayer: setDataSource_l Dummyaudiocreation started");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800205
206 mAudioTrack = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700207 ((mPlayEndTimeMsec)*1000LL));
Steve Block2703f232011-10-20 11:56:09 +0100208 ALOGV("PreviewPlayer: setDataSource_l Dummyauiosource created");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800209 if(mAudioTrack != NULL) {
210 haveAudio = true;
211 }
212 }
213
214 if (!haveAudio && !haveVideo) {
215 return UNKNOWN_ERROR;
216 }
217
218 mExtractorFlags = extractor->flags();
219 return OK;
220}
221
222status_t PreviewPlayer::setDataSource_l_jpg() {
223 M4OSA_ERR err = M4NO_ERROR;
Steve Block2703f232011-10-20 11:56:09 +0100224 ALOGV("PreviewPlayer: setDataSource_l_jpg started");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800225
226 mAudioSource = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700227 ((mPlayEndTimeMsec)*1000LL));
Steve Block2703f232011-10-20 11:56:09 +0100228 ALOGV("PreviewPlayer: setDataSource_l_jpg Dummyaudiosource created");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800229 if(mAudioSource != NULL) {
230 setAudioSource(mAudioSource);
231 }
232 status_t error = mAudioSource->start();
233 if (error != OK) {
Steve Block2703f232011-10-20 11:56:09 +0100234 ALOGV("Error starting dummy audio source");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800235 mAudioSource.clear();
236 return err;
237 }
238
Raghavender Pallaebf40152011-03-14 20:15:12 -0700239 mDurationUs = (mPlayEndTimeMsec - mPlayBeginTimeMsec)*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800240
241 mVideoSource = DummyVideoSource::Create(mVideoWidth, mVideoHeight,
242 mDurationUs, mUri);
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800243
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800244 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800245 setVideoSource(mVideoSource);
246 status_t err1 = mVideoSource->start();
247 if (err1 != OK) {
248 mVideoSource.clear();
249 return err;
250 }
251
252 mIsVideoSourceJpg = true;
253 return OK;
254}
255
256void PreviewPlayer::reset() {
257 Mutex::Autolock autoLock(mLock);
258 reset_l();
259}
260
261void PreviewPlayer::reset_l() {
262
263 if (mFlags & PREPARING) {
264 mFlags |= PREPARE_CANCELLED;
265 }
266
267 while (mFlags & PREPARING) {
268 mPreparedCondition.wait(mLock);
269 }
270
271 cancelPlayerEvents();
272 mAudioTrack.clear();
273 mVideoTrack.clear();
274
275 // Shutdown audio first, so that the respone to the reset request
276 // appears to happen instantaneously as far as the user is concerned
277 // If we did this later, audio would continue playing while we
278 // shutdown the video-related resources and the player appear to
279 // not be as responsive to a reset request.
280 if (mAudioPlayer == NULL && mAudioSource != NULL) {
281 // If we had an audio player, it would have effectively
282 // taken possession of the audio source and stopped it when
283 // _it_ is stopped. Otherwise this is still our responsibility.
284 mAudioSource->stop();
285 }
286 mAudioSource.clear();
287
288 mTimeSource = NULL;
289
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800290 //Single audio player instance used
291 //So donot delete it here
292 //It is deleted from PreviewController class
293 //delete mAudioPlayer;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800294 mAudioPlayer = NULL;
295
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800296 if (mVideoBuffer) {
297 mVideoBuffer->release();
298 mVideoBuffer = NULL;
299 }
300
301 if (mVideoSource != NULL) {
302 mVideoSource->stop();
303
304 // The following hack is necessary to ensure that the OMX
305 // component is completely released by the time we may try
306 // to instantiate it again.
307 wp<MediaSource> tmp = mVideoSource;
308 mVideoSource.clear();
309 while (tmp.promote() != NULL) {
310 usleep(1000);
311 }
312 IPCThreadState::self()->flushCommands();
313 }
314
315 mDurationUs = -1;
316 mFlags = 0;
317 mExtractorFlags = 0;
318 mVideoWidth = mVideoHeight = -1;
319 mTimeSourceDeltaUs = 0;
320 mVideoTimeUs = 0;
321
Andreas Hubera5872f72011-02-24 15:25:21 -0800322 mSeeking = NO_SEEK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800323 mSeekNotificationSent = false;
324 mSeekTimeUs = 0;
325
326 mUri.setTo("");
327 mUriHeaders.clear();
328
329 mFileSource.clear();
330
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800331 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
332 mIsVideoSourceJpg = false;
333 mFrameRGBBuffer = NULL;
334 if(mFrameYUVBuffer != NULL) {
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700335 free(mFrameYUVBuffer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800336 mFrameYUVBuffer = NULL;
337 }
338}
339
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800340status_t PreviewPlayer::play() {
341 Mutex::Autolock autoLock(mLock);
342
343 mFlags &= ~CACHE_UNDERRUN;
Hong Tenge0180232011-09-28 18:40:38 -0700344 mFlags &= ~INFORMED_AV_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800345 return play_l();
346}
347
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800348status_t PreviewPlayer::startAudioPlayer_l() {
349 CHECK(!(mFlags & AUDIO_RUNNING));
350
351 if (mAudioSource == NULL || mAudioPlayer == NULL) {
352 return OK;
353 }
354
355 if (!(mFlags & AUDIOPLAYER_STARTED)) {
356 mFlags |= AUDIOPLAYER_STARTED;
357
358 // We've already started the MediaSource in order to enable
359 // the prefetcher to read its data.
360 status_t err = mVeAudioPlayer->start(
361 true /* sourceAlreadyStarted */);
362
363 if (err != OK) {
364 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
365 return err;
366 }
367 } else {
368 mVeAudioPlayer->resume();
369 }
370
371 mFlags |= AUDIO_RUNNING;
372
373 mWatchForAudioEOS = true;
374
375 return OK;
376}
377
James Dongc9dedc42011-05-01 12:36:22 -0700378status_t PreviewPlayer::setAudioPlayer(AudioPlayerBase *audioPlayer) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800379 Mutex::Autolock autoLock(mLock);
380 CHECK(!(mFlags & PLAYING));
381 mAudioPlayer = audioPlayer;
382
Steve Block2703f232011-10-20 11:56:09 +0100383 ALOGV("SetAudioPlayer");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800384 mIsChangeSourceRequired = true;
385 mVeAudioPlayer =
386 (VideoEditorAudioPlayer*)mAudioPlayer;
387
388 // check if the new and old source are dummy
389 sp<MediaSource> anAudioSource = mVeAudioPlayer->getSource();
390 if (anAudioSource == NULL) {
391 // Audio player does not have any source set.
Steve Block2703f232011-10-20 11:56:09 +0100392 ALOGV("setAudioPlayer: Audio player does not have any source set");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800393 return OK;
394 }
395
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800396 // If new video source is not dummy, then always change source
397 // Else audio player continues using old audio source and there are
398 // frame drops to maintain AV sync
399 sp<MetaData> meta;
400 if (mVideoSource != NULL) {
401 meta = mVideoSource->getFormat();
402 const char *pVidSrcType;
403 if (meta->findCString(kKeyDecoderComponent, &pVidSrcType)) {
404 if (strcmp(pVidSrcType, "DummyVideoSource") != 0) {
Steve Block2703f232011-10-20 11:56:09 +0100405 ALOGV(" Video clip with silent audio; need to change source");
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800406 return OK;
407 }
408 }
409 }
410
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800411 const char *pSrcType1;
412 const char *pSrcType2;
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800413 meta = anAudioSource->getFormat();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800414
415 if (meta->findCString(kKeyDecoderComponent, &pSrcType1)) {
416 if (strcmp(pSrcType1, "DummyAudioSource") == 0) {
417 meta = mAudioSource->getFormat();
418 if (meta->findCString(kKeyDecoderComponent, &pSrcType2)) {
419 if (strcmp(pSrcType2, "DummyAudioSource") == 0) {
420 mIsChangeSourceRequired = false;
421 // Just set the new play duration for the existing source
422 MediaSource *pMediaSrc = anAudioSource.get();
423 DummyAudioSource *pDummyAudioSource = (DummyAudioSource*)pMediaSrc;
424 //Increment the duration of audio source
Raghavender Pallaebf40152011-03-14 20:15:12 -0700425 pDummyAudioSource->setDuration(
426 (int64_t)((mPlayEndTimeMsec)*1000LL));
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800427
428 // Stop the new audio source
429 // since we continue using old source
Steve Block2703f232011-10-20 11:56:09 +0100430 ALOGV("setAudioPlayer: stop new audio source");
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800431 mAudioSource->stop();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800432 }
433 }
434 }
435 }
436
437 return OK;
438}
439
440void PreviewPlayer::onStreamDone() {
441 // Posted whenever any stream finishes playing.
442
443 Mutex::Autolock autoLock(mLock);
444 if (!mStreamDoneEventPending) {
445 return;
446 }
447 mStreamDoneEventPending = false;
448
449 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
Steve Block2703f232011-10-20 11:56:09 +0100450 ALOGV("MEDIA_ERROR %d", mStreamDoneStatus);
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800451
452 notifyListener_l(
453 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
454
455 pause_l(true /* at eos */);
456
457 mFlags |= AT_EOS;
458 return;
459 }
460
461 const bool allDone =
462 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
463 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
464
465 if (!allDone) {
466 return;
467 }
468
469 if (mFlags & (LOOPING | AUTO_LOOPING)) {
470 seekTo_l(0);
471
472 if (mVideoSource != NULL) {
473 postVideoEvent_l();
474 }
475 } else {
Steve Block2703f232011-10-20 11:56:09 +0100476 ALOGV("MEDIA_PLAYBACK_COMPLETE");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800477 //pause before sending event
478 pause_l(true /* at eos */);
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700479
480 //This lock is used to syncronize onStreamDone() in PreviewPlayer and
481 //stopPreview() in PreviewController
482 Mutex::Autolock autoLock(mLockControl);
Hong Tenge0180232011-09-28 18:40:38 -0700483 /* Make sure PreviewPlayer only notifies MEDIA_PLAYBACK_COMPLETE once for each clip!
484 * It happens twice in following scenario.
485 * To make the clips in preview storyboard are played and switched smoothly,
486 * PreviewController uses two PreviewPlayer instances and one AudioPlayer.
487 * The two PreviewPlayer use the same AudioPlayer to play the audio,
488 * and change the audio source of the AudioPlayer.
489 * If the audio source of current playing clip and next clip are dummy
490 * audio source(image or video without audio), it will not change the audio source
491 * to avoid the "audio glitch", and keep using the current audio source.
492 * When the video of current clip reached the EOS, PreviewPlayer will set EOS flag
493 * for video and audio, and it will notify MEDIA_PLAYBACK_COMPLETE.
494 * But the audio(dummy audio source) is still playing(for next clip),
495 * and when it reached the EOS, and video reached EOS,
496 * PreviewPlayer will notify MEDIA_PLAYBACK_COMPLETE again. */
497 if (!(mFlags & INFORMED_AV_EOS)) {
498 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
499 mFlags |= INFORMED_AV_EOS;
500 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800501 mFlags |= AT_EOS;
Steve Block2703f232011-10-20 11:56:09 +0100502 ALOGV("onStreamDone end");
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700503 return;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800504 }
505}
506
507
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800508status_t PreviewPlayer::play_l() {
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800509
Rajneesh Chowdury8b95de22011-02-16 15:32:06 -0800510 mFlags &= ~SEEK_PREVIEW;
511
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800512 if (mFlags & PLAYING) {
513 return OK;
514 }
515 mStartNextPlayer = false;
516
517 if (!(mFlags & PREPARED)) {
518 status_t err = prepare_l();
519
520 if (err != OK) {
521 return err;
522 }
523 }
524
525 mFlags |= PLAYING;
526 mFlags |= FIRST_FRAME;
527
528 bool deferredAudioSeek = false;
529
530 if (mAudioSource != NULL) {
531 if (mAudioPlayer == NULL) {
532 if (mAudioSink != NULL) {
533
534 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800535 mVeAudioPlayer =
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800536 (VideoEditorAudioPlayer*)mAudioPlayer;
537
538 mAudioPlayer->setSource(mAudioSource);
539
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800540 mVeAudioPlayer->setAudioMixSettings(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800541 mPreviewPlayerAudioMixSettings);
542
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800543 mVeAudioPlayer->setAudioMixPCMFileHandle(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800544 mAudioMixPCMFileHandle);
545
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800546 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800547 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
548 mCurrentMediaVolumeValue);
549
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800550 mFlags |= AUDIOPLAYER_STARTED;
551 // We've already started the MediaSource in order to enable
552 // the prefetcher to read its data.
553 status_t err = mVeAudioPlayer->start(
554 true /* sourceAlreadyStarted */);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800555
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800556 if (err != OK) {
557 //delete mAudioPlayer;
558 mAudioPlayer = NULL;
559
560 mFlags &= ~(PLAYING | FIRST_FRAME);
561 return err;
562 }
563
564 mTimeSource = mVeAudioPlayer;
565 mFlags |= AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800566 deferredAudioSeek = true;
567 mWatchForAudioSeekComplete = false;
568 mWatchForAudioEOS = true;
569 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800570 } else {
571 mVeAudioPlayer = (VideoEditorAudioPlayer*)mAudioPlayer;
572 bool isAudioPlayerStarted = mVeAudioPlayer->isStarted();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800573
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800574 if (mIsChangeSourceRequired == true) {
Steve Block2703f232011-10-20 11:56:09 +0100575 ALOGV("play_l: Change audio source required");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800576
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800577 if (isAudioPlayerStarted == true) {
578 mVeAudioPlayer->pause();
579 }
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800580
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800581 mVeAudioPlayer->setSource(mAudioSource);
582 mVeAudioPlayer->setObserver(this);
583
584 mVeAudioPlayer->setAudioMixSettings(
585 mPreviewPlayerAudioMixSettings);
586
587 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
588 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
589 mCurrentMediaVolumeValue);
590
591 if (isAudioPlayerStarted == true) {
592 mVeAudioPlayer->resume();
593 } else {
594 status_t err = OK;
595 err = mVeAudioPlayer->start(true);
596 if (err != OK) {
597 mAudioPlayer = NULL;
598 mVeAudioPlayer = NULL;
599
600 mFlags &= ~(PLAYING | FIRST_FRAME);
601 return err;
602 }
603 }
604 } else {
Steve Block2703f232011-10-20 11:56:09 +0100605 ALOGV("play_l: No Source change required");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800606 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
607 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
608 mCurrentMediaVolumeValue);
609
610 mVeAudioPlayer->resume();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800611 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800612
613 mFlags |= AUDIOPLAYER_STARTED;
614 mFlags |= AUDIO_RUNNING;
615 mTimeSource = mVeAudioPlayer;
616 deferredAudioSeek = true;
617 mWatchForAudioSeekComplete = false;
618 mWatchForAudioEOS = true;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800619 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800620 }
621
622 if (mTimeSource == NULL && mAudioPlayer == NULL) {
623 mTimeSource = &mSystemTimeSource;
624 }
625
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800626 // Set the seek option for Image source files and read.
627 // This resets the timestamping for image play
628 if (mIsVideoSourceJpg) {
629 MediaSource::ReadOptions options;
630 MediaBuffer *aLocalBuffer;
631 options.setSeekTo(mSeekTimeUs);
632 mVideoSource->read(&aLocalBuffer, &options);
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800633 aLocalBuffer->release();
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800634 }
635
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800636 if (mVideoSource != NULL) {
637 // Kick off video playback
638 postVideoEvent_l();
639 }
640
641 if (deferredAudioSeek) {
642 // If there was a seek request while we were paused
643 // and we're just starting up again, honor the request now.
644 seekAudioIfNecessary_l();
645 }
646
647 if (mFlags & AT_EOS) {
648 // Legacy behaviour, if a stream finishes playing and then
649 // is started again, we play from the start...
650 seekTo_l(0);
651 }
652
653 return OK;
654}
655
656
Santosh Madhavabfece172011-02-03 16:59:47 -0800657status_t PreviewPlayer::initRenderer_l() {
Mathias Agopian6e224292011-04-05 15:38:24 -0700658 if (mSurface != NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800659 if(mVideoRenderer == NULL) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800660 mVideoRenderer = mNativeWindowRenderer->createRenderInput();
661 if (mVideoSource != NULL) {
662 updateSizeToRender(mVideoSource->getFormat());
Santosh Madhavabfece172011-02-03 16:59:47 -0800663 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800664 }
665 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800666 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800667}
668
669
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800670status_t PreviewPlayer::seekTo(int64_t timeUs) {
671
672 if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) {
673 Mutex::Autolock autoLock(mLock);
674 return seekTo_l(timeUs);
675 }
676
677 return OK;
678}
679
680
681status_t PreviewPlayer::getVideoDimensions(
682 int32_t *width, int32_t *height) const {
683 Mutex::Autolock autoLock(mLock);
684
685 if (mVideoWidth < 0 || mVideoHeight < 0) {
686 return UNKNOWN_ERROR;
687 }
688
689 *width = mVideoWidth;
690 *height = mVideoHeight;
691
692 return OK;
693}
694
695
696status_t PreviewPlayer::initAudioDecoder() {
697 sp<MetaData> meta = mAudioTrack->getFormat();
698 const char *mime;
699 CHECK(meta->findCString(kKeyMIMEType, &mime));
700
701 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
702 mAudioSource = mAudioTrack;
703 } else {
704 sp<MediaSource> aRawSource;
705 aRawSource = OMXCodec::Create(
706 mClient.interface(), mAudioTrack->getFormat(),
707 false, // createEncoder
708 mAudioTrack);
709
710 if(aRawSource != NULL) {
Steve Block2703f232011-10-20 11:56:09 +0100711 ALOGV("initAudioDecoder: new VideoEditorSRC");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800712 mAudioSource = new VideoEditorSRC(aRawSource);
713 }
714 }
715
716 if (mAudioSource != NULL) {
717 int64_t durationUs;
718 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
719 Mutex::Autolock autoLock(mMiscStateLock);
720 if (mDurationUs < 0 || durationUs > mDurationUs) {
721 mDurationUs = durationUs;
722 }
723 }
724 status_t err = mAudioSource->start();
725
726 if (err != OK) {
727 mAudioSource.clear();
728 return err;
729 }
730 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
731 // For legacy reasons we're simply going to ignore the absence
732 // of an audio decoder for QCELP instead of aborting playback
733 // altogether.
734 return OK;
735 }
736
737 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
738}
739
740
741status_t PreviewPlayer::initVideoDecoder(uint32_t flags) {
742
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800743 initRenderer_l();
744
745 if (mVideoRenderer == NULL) {
746 LOGE("Cannot create renderer");
747 return UNKNOWN_ERROR;
748 }
749
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800750 mVideoSource = OMXCodec::Create(
751 mClient.interface(), mVideoTrack->getFormat(),
752 false,
753 mVideoTrack,
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800754 NULL, flags, mVideoRenderer->getTargetWindow());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800755
756 if (mVideoSource != NULL) {
757 int64_t durationUs;
758 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
759 Mutex::Autolock autoLock(mMiscStateLock);
760 if (mDurationUs < 0 || durationUs > mDurationUs) {
761 mDurationUs = durationUs;
762 }
763 }
764
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800765 updateSizeToRender(mVideoTrack->getFormat());
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800766
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800767 status_t err = mVideoSource->start();
768
769 if (err != OK) {
770 mVideoSource.clear();
771 return err;
772 }
773 }
774
775 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
776}
777
778
779void PreviewPlayer::onVideoEvent() {
780 uint32_t i=0;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800781 M4OSA_ERR err1 = M4NO_ERROR;
782 int64_t imageFrameTimeUs = 0;
783
784 Mutex::Autolock autoLock(mLock);
785 if (!mVideoEventPending) {
786 // The event has been cancelled in reset_l() but had already
787 // been scheduled for execution at that time.
788 return;
789 }
790 mVideoEventPending = false;
791
Andreas Huber9e4c36a2011-02-08 13:12:32 -0800792 if (mFlags & SEEK_PREVIEW) {
793 mFlags &= ~SEEK_PREVIEW;
794 return;
795 }
796
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800797 TimeSource *ts_st = &mSystemTimeSource;
798 int64_t timeStartUs = ts_st->getRealTimeUs();
799
Andreas Hubera5872f72011-02-24 15:25:21 -0800800 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800801
802 if(mAudioSource != NULL) {
803
804 // We're going to seek the video source first, followed by
805 // the audio source.
806 // In order to avoid jumps in the DataSource offset caused by
807 // the audio codec prefetching data from the old locations
808 // while the video codec is already reading data from the new
809 // locations, we'll "pause" the audio source, causing it to
810 // stop reading input data until a subsequent seek.
811
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800812 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800813 mAudioPlayer->pause();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800814 mFlags &= ~AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800815 }
816 mAudioSource->pause();
817 }
818 }
819
820 if (!mVideoBuffer) {
821 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -0800822 if (mSeeking != NO_SEEK) {
Steve Block2703f232011-10-20 11:56:09 +0100823 ALOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800824 mSeekTimeUs / 1E6);
825
826 options.setSeekTo(
827 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
828 }
829 for (;;) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800830 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800831 options.clearSeekTo();
832
833 if (err != OK) {
834 CHECK_EQ(mVideoBuffer, NULL);
835
836 if (err == INFO_FORMAT_CHANGED) {
Steve Block2703f232011-10-20 11:56:09 +0100837 ALOGV("LV PLAYER VideoSource signalled format change");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800838 notifyVideoSize_l();
839
840 if (mVideoRenderer != NULL) {
841 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -0800842 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800843 if (err != OK) {
844 postStreamDoneEvent_l(err);
845 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800846
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800847 }
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800848
849 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800850 continue;
851 }
852 // So video playback is complete, but we may still have
Santosh Madhava342f9322011-01-27 16:27:12 -0800853 // a seek request pending that needs to be applied to the audio track
Andreas Hubera5872f72011-02-24 15:25:21 -0800854 if (mSeeking != NO_SEEK) {
Steve Block2703f232011-10-20 11:56:09 +0100855 ALOGV("video stream ended while seeking!");
Santosh Madhava342f9322011-01-27 16:27:12 -0800856 }
857 finishSeekIfNecessary(-1);
Steve Block2703f232011-10-20 11:56:09 +0100858 ALOGV("PreviewPlayer: onVideoEvent EOS reached.");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800859 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800860 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800861 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800862 postStreamDoneEvent_l(err);
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800863 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -0700864 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800865 return;
866 }
867
868 if (mVideoBuffer->range_length() == 0) {
869 // Some decoders, notably the PV AVC software decoder
870 // return spurious empty buffers that we just want to ignore.
871
872 mVideoBuffer->release();
873 mVideoBuffer = NULL;
874 continue;
875 }
876
877 int64_t videoTimeUs;
878 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
879
Andreas Hubera5872f72011-02-24 15:25:21 -0800880 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800881 if (videoTimeUs < mSeekTimeUs) {
882 // buffers are before seek time
883 // ignore them
884 mVideoBuffer->release();
885 mVideoBuffer = NULL;
886 continue;
887 }
888 } else {
889 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
890 // Frames are before begin cut time
891 // Donot render
892 mVideoBuffer->release();
893 mVideoBuffer = NULL;
894 continue;
895 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800896 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800897 break;
898 }
899 }
900
901 mNumberDecVideoFrames++;
902
903 int64_t timeUs;
904 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
905
906 {
907 Mutex::Autolock autoLock(mMiscStateLock);
908 mVideoTimeUs = timeUs;
909 }
910
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800911
912 if(!mStartNextPlayer) {
Raghavender Pallaebf40152011-03-14 20:15:12 -0700913 int64_t playbackTimeRemaining = (mPlayEndTimeMsec*1000LL) - timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800914 if(playbackTimeRemaining <= 1500000) {
915 //When less than 1.5 sec of playback left
916 // send notification to start next player
917
918 mStartNextPlayer = true;
919 notifyListener_l(0xAAAAAAAA);
920 }
921 }
922
Andreas Hubera5872f72011-02-24 15:25:21 -0800923 SeekType wasSeeking = mSeeking;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800924 finishSeekIfNecessary(timeUs);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800925 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING))) {
926 status_t err = startAudioPlayer_l();
927 if (err != OK) {
928 LOGE("Starting the audio player failed w/ err %d", err);
929 return;
930 }
931 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800932
933 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
934
935 if(ts == NULL) {
936 mVideoBuffer->release();
937 mVideoBuffer = NULL;
938 return;
939 }
940
941 if(!mIsVideoSourceJpg) {
942 if (mFlags & FIRST_FRAME) {
943 mFlags &= ~FIRST_FRAME;
944
945 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
946 }
947
948 int64_t realTimeUs, mediaTimeUs;
949 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
950 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
951 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
952 }
953
954 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
955
956 int64_t latenessUs = nowUs - timeUs;
957
Andreas Hubera5872f72011-02-24 15:25:21 -0800958 if (wasSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800959 // Let's display the first frame after seeking right away.
960 latenessUs = 0;
961 }
Steve Block2703f232011-10-20 11:56:09 +0100962 ALOGV("Audio time stamp = %lld and video time stamp = %lld",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800963 ts->getRealTimeUs(),timeUs);
964 if (latenessUs > 40000) {
965 // We're more than 40ms late.
966
Steve Block2703f232011-10-20 11:56:09 +0100967 ALOGV("LV PLAYER we're late by %lld us (%.2f secs)",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800968 latenessUs, latenessUs / 1E6);
969
970 mVideoBuffer->release();
971 mVideoBuffer = NULL;
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800972 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800973 return;
974 }
975
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800976 if (latenessUs < -25000) {
977 // We're more than 25ms early.
Steve Block2703f232011-10-20 11:56:09 +0100978 ALOGV("We're more than 25ms early, lateness %lld", latenessUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800979
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800980 postVideoEvent_l(25000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800981 return;
982 }
983 }
984
985 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
986 mVideoRendererIsPreview = false;
987
Santosh Madhavabfece172011-02-03 16:59:47 -0800988 status_t err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800989 if (err != OK) {
990 postStreamDoneEvent_l(err);
991 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800992 }
993
994 // If timestamp exceeds endCutTime of clip, donot render
995 if((timeUs/1000) > mPlayEndTimeMsec) {
Chih-Chung Changcece4b32011-08-01 16:34:05 +0800996 mVideoBuffer->release();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800997 mVideoBuffer = NULL;
998 mFlags |= VIDEO_AT_EOS;
999 mFlags |= AUDIO_AT_EOS;
Steve Block2703f232011-10-20 11:56:09 +01001000 ALOGV("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS..");
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001001 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001002 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001003 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001004 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1005 return;
1006 }
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001007 // Capture the frame timestamp to be rendered
1008 mDecodedVideoTs = timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001009
1010 // Post processing to apply video effects
1011 for(i=0;i<mNumberEffects;i++) {
1012 // First check if effect starttime matches the clip being previewed
1013 if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) ||
1014 (mEffectsSettings[i].uiStartTime >=
1015 ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec)))
1016 {
1017 // This effect doesn't belong to this clip, check next one
1018 continue;
1019 }
1020 // Check if effect applies to this particular frame timestamp
1021 if((mEffectsSettings[i].uiStartTime <=
1022 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) &&
1023 ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=
1024 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec))
1025 && (mEffectsSettings[i].uiDuration != 0)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001026 setVideoPostProcessingNode(
1027 mEffectsSettings[i].VideoEffectType, TRUE);
1028 }
1029 else {
1030 setVideoPostProcessingNode(
1031 mEffectsSettings[i].VideoEffectType, FALSE);
1032 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001033 }
1034
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001035 //Provide the overlay Update indication when there is an overlay effect
Dharmaray Kundargid01ef562011-01-26 21:11:00 -08001036 if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) {
1037 mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here.
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001038 if (!mOverlayUpdateEventPosted) {
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001039 // Find the effect in effectSettings array
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001040 M4OSA_UInt32 index;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001041 for (index = 0; index < mNumberEffects; index++) {
1042 M4OSA_UInt32 timeMs = mDecodedVideoTs/1000;
1043 M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000;
1044 if(mEffectsSettings[index].VideoEffectType ==
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001045 (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001046 if (((mEffectsSettings[index].uiStartTime + 1) <=
1047 timeMs + timeOffset - mPlayBeginTimeMsec) &&
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001048 ((mEffectsSettings[index].uiStartTime - 1 +
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001049 mEffectsSettings[index].uiDuration) >=
1050 timeMs + timeOffset - mPlayBeginTimeMsec))
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001051 {
1052 break;
1053 }
1054 }
1055 }
1056 if (index < mNumberEffects) {
1057 mCurrFramingEffectIndex = index;
1058 mOverlayUpdateEventPosted = true;
1059 postOverlayUpdateEvent_l();
Steve Block2703f232011-10-20 11:56:09 +01001060 ALOGV("Framing index = %d", mCurrFramingEffectIndex);
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001061 } else {
Steve Block2703f232011-10-20 11:56:09 +01001062 ALOGV("No framing effects found");
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001063 }
1064 }
1065
1066 } else if (mOverlayUpdateEventPosted) {
1067 //Post the event when the overlay is no more valid
Steve Block2703f232011-10-20 11:56:09 +01001068 ALOGV("Overlay is Done");
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001069 mOverlayUpdateEventPosted = false;
1070 postOverlayUpdateEvent_l();
1071 }
1072
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001073 if (mVideoRenderer != NULL) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001074 mVideoRenderer->render(mVideoBuffer, mCurrentVideoEffect,
1075 mRenderingMode, mIsVideoSourceJpg);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001076 }
1077
Chih-Chung Changcece4b32011-08-01 16:34:05 +08001078 mVideoBuffer->release();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001079 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) {
Steve Block2703f232011-10-20 11:56:09 +01001089 ALOGV("PreviewPlayer: onVideoEvent EOS.");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001090 mFlags |= VIDEO_AT_EOS;
1091 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001092 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001093 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001094 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001095 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1096 }
1097 else {
Andreas Hubera5872f72011-02-24 15:25:21 -08001098 if ((wasSeeking != NO_SEEK) && (mFlags & SEEK_PREVIEW)) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001099 mFlags &= ~SEEK_PREVIEW;
1100 return;
1101 }
1102
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001103 if(!mIsVideoSourceJpg) {
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001104 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001105 }
1106 else {
1107 postVideoEvent_l(33000);
1108 }
1109 }
1110}
1111
1112status_t PreviewPlayer::prepare() {
1113 Mutex::Autolock autoLock(mLock);
1114 return prepare_l();
1115}
1116
1117status_t PreviewPlayer::prepare_l() {
1118 if (mFlags & PREPARED) {
1119 return OK;
1120 }
1121
1122 if (mFlags & PREPARING) {
1123 return UNKNOWN_ERROR;
1124 }
1125
1126 mIsAsyncPrepare = false;
1127 status_t err = prepareAsync_l();
1128
1129 if (err != OK) {
1130 return err;
1131 }
1132
1133 while (mFlags & PREPARING) {
1134 mPreparedCondition.wait(mLock);
1135 }
1136
1137 return mPrepareResult;
1138}
1139
1140status_t PreviewPlayer::prepareAsync_l() {
1141 if (mFlags & PREPARING) {
1142 return UNKNOWN_ERROR; // async prepare already pending
1143 }
1144
1145 if (!mQueueStarted) {
1146 mQueue.start();
1147 mQueueStarted = true;
1148 }
1149
1150 mFlags |= PREPARING;
1151 mAsyncPrepareEvent = new PreviewPlayerEvent(
1152 this, &PreviewPlayer::onPrepareAsyncEvent);
1153
1154 mQueue.postEvent(mAsyncPrepareEvent);
1155
1156 return OK;
1157}
1158
1159status_t PreviewPlayer::finishSetDataSource_l() {
1160 sp<DataSource> dataSource;
1161 sp<MediaExtractor> extractor;
1162
1163 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1164
1165 if (dataSource == NULL) {
1166 return UNKNOWN_ERROR;
1167 }
1168
1169 //If file type is .rgb, then no need to check for Extractor
1170 int uriLen = strlen(mUri);
1171 int startOffset = uriLen - 4;
1172 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) {
1173 extractor = NULL;
1174 }
1175 else {
1176 extractor = MediaExtractor::Create(dataSource,
1177 MEDIA_MIMETYPE_CONTAINER_MPEG4);
1178 }
1179
1180 if (extractor == NULL) {
Steve Block2703f232011-10-20 11:56:09 +01001181 ALOGV("PreviewPlayer::finishSetDataSource_l extractor == NULL");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001182 return setDataSource_l_jpg();
1183 }
1184
1185 return setDataSource_l(extractor);
1186}
1187
1188
1189// static
1190bool PreviewPlayer::ContinuePreparation(void *cookie) {
1191 PreviewPlayer *me = static_cast<PreviewPlayer *>(cookie);
1192
1193 return (me->mFlags & PREPARE_CANCELLED) == 0;
1194}
1195
1196void PreviewPlayer::onPrepareAsyncEvent() {
1197 Mutex::Autolock autoLock(mLock);
Steve Block2703f232011-10-20 11:56:09 +01001198 ALOGV("onPrepareAsyncEvent");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001199
1200 if (mFlags & PREPARE_CANCELLED) {
Steve Block2703f232011-10-20 11:56:09 +01001201 ALOGV("LV PLAYER prepare was cancelled before doing anything");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001202 abortPrepare(UNKNOWN_ERROR);
1203 return;
1204 }
1205
1206 if (mUri.size() > 0) {
1207 status_t err = finishSetDataSource_l();
1208
1209 if (err != OK) {
1210 abortPrepare(err);
1211 return;
1212 }
1213 }
1214
1215 if (mVideoTrack != NULL && mVideoSource == NULL) {
1216 status_t err = initVideoDecoder(OMXCodec::kHardwareCodecsOnly);
1217
1218 if (err != OK) {
1219 abortPrepare(err);
1220 return;
1221 }
1222 }
1223
1224 if (mAudioTrack != NULL && mAudioSource == NULL) {
1225 status_t err = initAudioDecoder();
1226
1227 if (err != OK) {
1228 abortPrepare(err);
1229 return;
1230 }
1231 }
1232 finishAsyncPrepare_l();
1233
1234}
1235
1236void PreviewPlayer::finishAsyncPrepare_l() {
1237 if (mIsAsyncPrepare) {
1238 if (mVideoSource == NULL) {
Steve Block2703f232011-10-20 11:56:09 +01001239 ALOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE 0 0 ");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001240 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1241 } else {
Steve Block2703f232011-10-20 11:56:09 +01001242 ALOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001243 notifyVideoSize_l();
1244 }
Steve Block2703f232011-10-20 11:56:09 +01001245 ALOGV("finishAsyncPrepare_l: MEDIA_PREPARED");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001246 notifyListener_l(MEDIA_PREPARED);
1247 }
1248
1249 mPrepareResult = OK;
1250 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1251 mFlags |= PREPARED;
1252 mAsyncPrepareEvent = NULL;
1253 mPreparedCondition.broadcast();
1254}
1255
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001256void PreviewPlayer::acquireLock() {
Steve Block2703f232011-10-20 11:56:09 +01001257 ALOGV("acquireLock");
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001258 mLockControl.lock();
1259}
1260
1261void PreviewPlayer::releaseLock() {
Steve Block2703f232011-10-20 11:56:09 +01001262 ALOGV("releaseLock");
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001263 mLockControl.unlock();
1264}
1265
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001266status_t PreviewPlayer::loadEffectsSettings(
1267 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) {
1268 M4OSA_UInt32 i = 0, rgbSize = 0;
1269 M4VIFI_UInt8 *tmp = M4OSA_NULL;
1270
1271 mNumberEffects = nEffects;
1272 mEffectsSettings = pEffectSettings;
1273 return OK;
1274}
1275
1276status_t PreviewPlayer::loadAudioMixSettings(
1277 M4xVSS_AudioMixingSettings* pAudioMixSettings) {
1278
Steve Block2703f232011-10-20 11:56:09 +01001279 ALOGV("PreviewPlayer: loadAudioMixSettings: ");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001280 mPreviewPlayerAudioMixSettings = pAudioMixSettings;
1281 return OK;
1282}
1283
1284status_t PreviewPlayer::setAudioMixPCMFileHandle(
1285 M4OSA_Context pAudioMixPCMFileHandle) {
1286
Steve Block2703f232011-10-20 11:56:09 +01001287 ALOGV("PreviewPlayer: setAudioMixPCMFileHandle: ");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001288 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle;
1289 return OK;
1290}
1291
1292status_t PreviewPlayer::setAudioMixStoryBoardParam(
1293 M4OSA_UInt32 audioMixStoryBoardTS,
1294 M4OSA_UInt32 currentMediaBeginCutTime,
1295 M4OSA_UInt32 primaryTrackVolValue ) {
1296
1297 mAudioMixStoryBoardTS = audioMixStoryBoardTS;
1298 mCurrentMediaBeginCutTime = currentMediaBeginCutTime;
1299 mCurrentMediaVolumeValue = primaryTrackVolValue;
1300 return OK;
1301}
1302
1303status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) {
1304
1305 mPlayBeginTimeMsec = msec;
1306 return OK;
1307}
1308
1309status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) {
1310
1311 mPlayEndTimeMsec = msec;
1312 return OK;
1313}
1314
1315status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) {
1316
1317 mStoryboardStartTimeMsec = msec;
Raghavender Pallaebf40152011-03-14 20:15:12 -07001318 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001319 return OK;
1320}
1321
1322status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) {
1323
1324 mProgressCbInterval = cbInterval;
1325 return OK;
1326}
1327
1328
1329status_t PreviewPlayer::setMediaRenderingMode(
1330 M4xVSS_MediaRendering mode,
1331 M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
1332
1333 mRenderingMode = mode;
1334
Hong Teng8806b702011-07-06 18:29:28 -07001335 status_t err = OK;
1336 /* get the video width and height by resolution */
1337 err = getVideoSizeByResolution(outputVideoSize,
1338 &mOutputVideoWidth, &mOutputVideoHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001339
Hong Teng8806b702011-07-06 18:29:28 -07001340 return err;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001341}
1342
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001343status_t PreviewPlayer::resetJniCallbackTimeStamp() {
1344
Raghavender Pallaebf40152011-03-14 20:15:12 -07001345 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001346 return OK;
1347}
1348
1349void PreviewPlayer::postProgressCallbackEvent_l() {
1350 if (mProgressCbEventPending) {
1351 return;
1352 }
1353 mProgressCbEventPending = true;
1354
1355 mQueue.postEvent(mProgressCbEvent);
1356}
1357
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001358
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001359void PreviewPlayer::onProgressCbEvent() {
1360 Mutex::Autolock autoLock(mLock);
1361 if (!mProgressCbEventPending) {
1362 return;
1363 }
1364 mProgressCbEventPending = false;
1365 // If playback starts from previous I-frame,
1366 // then send frame storyboard duration
1367 if((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) {
1368 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000);
1369 }
1370 else {
1371 notifyListener_l(MEDIA_INFO, 0,
1372 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec));
1373 }
1374}
1375
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001376void PreviewPlayer::postOverlayUpdateEvent_l() {
1377 if (mOverlayUpdateEventPending) {
1378 return;
1379 }
1380 mOverlayUpdateEventPending = true;
1381 mQueue.postEvent(mOverlayUpdateEvent);
1382}
1383
1384void PreviewPlayer::onUpdateOverlayEvent() {
1385 Mutex::Autolock autoLock(mLock);
1386
1387 if (!mOverlayUpdateEventPending) {
1388 return;
1389 }
1390 mOverlayUpdateEventPending = false;
1391
1392 int updateState;
1393 if (mOverlayUpdateEventPosted) {
1394 updateState = 1;
1395 } else {
1396 updateState = 0;
1397 }
1398 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex);
1399}
1400
1401
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001402void PreviewPlayer::setVideoPostProcessingNode(
1403 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
1404
1405 uint32_t effect = VIDEO_EFFECT_NONE;
1406
1407 //Map M4VSS3GPP_VideoEffectType to local enum
1408 switch(type) {
1409 case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
1410 effect = VIDEO_EFFECT_FADEFROMBLACK;
1411 break;
1412
1413 case M4VSS3GPP_kVideoEffectType_FadeToBlack:
1414 effect = VIDEO_EFFECT_FADETOBLACK;
1415 break;
1416
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001417 case M4xVSS_kVideoEffectType_BlackAndWhite:
1418 effect = VIDEO_EFFECT_BLACKANDWHITE;
1419 break;
1420
1421 case M4xVSS_kVideoEffectType_Pink:
1422 effect = VIDEO_EFFECT_PINK;
1423 break;
1424
1425 case M4xVSS_kVideoEffectType_Green:
1426 effect = VIDEO_EFFECT_GREEN;
1427 break;
1428
1429 case M4xVSS_kVideoEffectType_Sepia:
1430 effect = VIDEO_EFFECT_SEPIA;
1431 break;
1432
1433 case M4xVSS_kVideoEffectType_Negative:
1434 effect = VIDEO_EFFECT_NEGATIVE;
1435 break;
1436
1437 case M4xVSS_kVideoEffectType_Framing:
1438 effect = VIDEO_EFFECT_FRAMING;
1439 break;
1440
1441 case M4xVSS_kVideoEffectType_Fifties:
1442 effect = VIDEO_EFFECT_FIFTIES;
1443 break;
1444
1445 case M4xVSS_kVideoEffectType_ColorRGB16:
1446 effect = VIDEO_EFFECT_COLOR_RGB16;
1447 break;
1448
1449 case M4xVSS_kVideoEffectType_Gradient:
1450 effect = VIDEO_EFFECT_GRADIENT;
1451 break;
1452
1453 default:
1454 effect = VIDEO_EFFECT_NONE;
1455 break;
1456 }
1457
1458 if(enable == M4OSA_TRUE) {
1459 //If already set, then no need to set again
1460 if(!(mCurrentVideoEffect & effect)) {
1461 mCurrentVideoEffect |= effect;
1462 if(effect == VIDEO_EFFECT_FIFTIES) {
1463 mIsFiftiesEffectStarted = true;
1464 }
1465 }
1466 }
1467 else {
1468 //Reset only if already set
1469 if(mCurrentVideoEffect & effect) {
1470 mCurrentVideoEffect &= ~effect;
1471 }
1472 }
1473}
1474
1475status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) {
1476 mVideoWidth = width;
1477 mVideoHeight = height;
1478 return OK;
1479}
1480
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001481status_t PreviewPlayer::readFirstVideoFrame() {
Steve Block2703f232011-10-20 11:56:09 +01001482 ALOGV("PreviewPlayer::readFirstVideoFrame");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001483
1484 if (!mVideoBuffer) {
1485 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -08001486 if (mSeeking != NO_SEEK) {
Steve Block2703f232011-10-20 11:56:09 +01001487 ALOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001488 mSeekTimeUs / 1E6);
1489
1490 options.setSeekTo(
1491 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
1492 }
1493 for (;;) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001494 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001495 options.clearSeekTo();
1496
1497 if (err != OK) {
1498 CHECK_EQ(mVideoBuffer, NULL);
1499
1500 if (err == INFO_FORMAT_CHANGED) {
Steve Block2703f232011-10-20 11:56:09 +01001501 ALOGV("LV PLAYER VideoSource signalled format change");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001502 notifyVideoSize_l();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001503
1504 if (mVideoRenderer != NULL) {
1505 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -08001506 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001507 if (err != OK) {
1508 postStreamDoneEvent_l(err);
1509 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001510 }
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001511
1512 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001513 continue;
1514 }
Steve Block2703f232011-10-20 11:56:09 +01001515 ALOGV("PreviewPlayer: onVideoEvent EOS reached.");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001516 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001517 mFlags |= AUDIO_AT_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001518 postStreamDoneEvent_l(err);
1519 return OK;
1520 }
1521
1522 if (mVideoBuffer->range_length() == 0) {
1523 // Some decoders, notably the PV AVC software decoder
1524 // return spurious empty buffers that we just want to ignore.
1525
1526 mVideoBuffer->release();
1527 mVideoBuffer = NULL;
1528 continue;
1529 }
1530
1531 int64_t videoTimeUs;
1532 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
Andreas Hubera5872f72011-02-24 15:25:21 -08001533 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001534 if (videoTimeUs < mSeekTimeUs) {
1535 // buffers are before seek time
1536 // ignore them
1537 mVideoBuffer->release();
1538 mVideoBuffer = NULL;
1539 continue;
1540 }
1541 } else {
1542 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
1543 // buffers are before begin cut time
1544 // ignore them
1545 mVideoBuffer->release();
1546 mVideoBuffer = NULL;
1547 continue;
1548 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001549 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001550 break;
1551 }
1552 }
1553
1554 int64_t timeUs;
1555 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1556
1557 {
1558 Mutex::Autolock autoLock(mMiscStateLock);
1559 mVideoTimeUs = timeUs;
1560 }
1561
1562 mDecodedVideoTs = timeUs;
1563
1564 return OK;
1565
1566}
1567
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001568status_t PreviewPlayer::getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs) {
1569 *lastRenderedTimeMs = (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec);
1570 return OK;
1571}
1572
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001573void PreviewPlayer::updateSizeToRender(sp<MetaData> meta) {
1574 if (mVideoRenderer) {
1575 mVideoRenderer->updateVideoSize(meta);
1576 }
1577}
1578
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001579} // namespace android