blob: 9d2154aa2d3c6161a49e1cae1e9f01d1312cd3cd [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>
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080034#include <media/stagefright/MediaBuffer.h>
35#include <media/stagefright/MediaDefs.h>
36#include <media/stagefright/MediaExtractor.h>
37#include <media/stagefright/MediaDebug.h>
38#include <media/stagefright/MediaSource.h>
39#include <media/stagefright/MetaData.h>
40#include <media/stagefright/OMXCodec.h>
41
42#include <surfaceflinger/Surface.h>
43#include <media/stagefright/foundation/ALooper.h>
44
45namespace android {
46
47
48struct PreviewPlayerEvent : public TimedEventQueue::Event {
49 PreviewPlayerEvent(
50 PreviewPlayer *player,
51 void (PreviewPlayer::*method)())
52 : mPlayer(player),
53 mMethod(method) {
54 }
55
56protected:
57 virtual ~PreviewPlayerEvent() {}
58
59 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
60 (mPlayer->*mMethod)();
61 }
62
63private:
64 PreviewPlayer *mPlayer;
65 void (PreviewPlayer::*mMethod)();
66
67 PreviewPlayerEvent(const PreviewPlayerEvent &);
68 PreviewPlayerEvent &operator=(const PreviewPlayerEvent &);
69};
70
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080071PreviewPlayer::PreviewPlayer(NativeWindowRenderer* renderer)
James Dongc9dedc42011-05-01 12:36:22 -070072 : PreviewPlayerBase(),
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080073 mNativeWindowRenderer(renderer),
74 mCurrFramingEffectIndex(0),
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -080075 mFrameRGBBuffer(NULL),
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080076 mFrameYUVBuffer(NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080077
78 mVideoRenderer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080079 mEffectsSettings = NULL;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -080080 mVeAudioPlayer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080081 mAudioMixStoryBoardTS = 0;
82 mCurrentMediaBeginCutTime = 0;
83 mCurrentMediaVolumeValue = 0;
84 mNumberEffects = 0;
85 mDecodedVideoTs = 0;
86 mDecVideoTsStoryBoard = 0;
87 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
88 mProgressCbInterval = 0;
89 mNumberDecVideoFrames = 0;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -080090 mOverlayUpdateEventPosted = false;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -080091 mIsChangeSourceRequired = true;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080092
93 mVideoEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoEvent);
94 mVideoEventPending = false;
95 mStreamDoneEvent = new PreviewPlayerEvent(this,
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -080096 &PreviewPlayer::onStreamDone);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080097
98 mStreamDoneEventPending = false;
99
100 mCheckAudioStatusEvent = new PreviewPlayerEvent(
James Dongc9dedc42011-05-01 12:36:22 -0700101 this, &PreviewPlayerBase::onCheckAudioStatus);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800102
103 mAudioStatusEventPending = false;
104
105 mProgressCbEvent = new PreviewPlayerEvent(this,
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800106 &PreviewPlayer::onProgressCbEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800107
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800108 mOverlayUpdateEvent = new PreviewPlayerEvent(this,
109 &PreviewPlayer::onUpdateOverlayEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800110 mProgressCbEventPending = false;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800111
112 mOverlayUpdateEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800113 mRenderingMode = (M4xVSS_MediaRendering)MEDIA_RENDERING_INVALID;
114 mIsFiftiesEffectStarted = false;
115 reset();
116}
117
118PreviewPlayer::~PreviewPlayer() {
119
120 if (mQueueStarted) {
121 mQueue.stop();
122 }
123
124 reset();
125
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800126 if (mVideoRenderer) {
127 mNativeWindowRenderer->destroyRenderInput(mVideoRenderer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800128 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800129}
130
James Dongdaeb5b32012-01-12 12:12:40 -0800131void PreviewPlayer::cancelPlayerEvents() {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800132 mQueue.cancelEvent(mVideoEvent->eventID());
133 mVideoEventPending = false;
134 mQueue.cancelEvent(mStreamDoneEvent->eventID());
135 mStreamDoneEventPending = false;
136 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
137 mAudioStatusEventPending = false;
138
139 mQueue.cancelEvent(mProgressCbEvent->eventID());
140 mProgressCbEventPending = false;
141}
142
James Dongdaeb5b32012-01-12 12:12:40 -0800143status_t PreviewPlayer::setDataSource(const char *path) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800144 Mutex::Autolock autoLock(mLock);
James Dongdaeb5b32012-01-12 12:12:40 -0800145 return setDataSource_l(path);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800146}
147
James Dongdaeb5b32012-01-12 12:12:40 -0800148status_t PreviewPlayer::setDataSource_l(const char *path) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800149 reset_l();
150
James Dongdaeb5b32012-01-12 12:12:40 -0800151 mUri = path;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800152
153 // The actual work will be done during preparation in the call to
154 // ::finishSetDataSource_l to avoid blocking the calling thread in
155 // setDataSource for any significant time.
156 return OK;
157}
158
159status_t PreviewPlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
160 bool haveAudio = false;
161 bool haveVideo = false;
162 for (size_t i = 0; i < extractor->countTracks(); ++i) {
163 sp<MetaData> meta = extractor->getTrackMetaData(i);
164
165 const char *mime;
166 CHECK(meta->findCString(kKeyMIMEType, &mime));
167
168 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
169 setVideoSource(extractor->getTrack(i));
170 haveVideo = true;
171 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
172 setAudioSource(extractor->getTrack(i));
173 haveAudio = true;
174
175 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
176 // Only do this for vorbis audio, none of the other audio
177 // formats even support this ringtone specific hack and
178 // retrieving the metadata on some extractors may turn out
179 // to be very expensive.
180 sp<MetaData> fileMeta = extractor->getMetaData();
181 int32_t loop;
182 if (fileMeta != NULL
183 && fileMeta->findInt32(kKeyAutoLoop, &loop)
184 && loop != 0) {
185 mFlags |= AUTO_LOOPING;
186 }
187 }
188 }
189
190 if (haveAudio && haveVideo) {
191 break;
192 }
193 }
194
195 /* Add the support for Dummy audio*/
196 if( !haveAudio ){
Steve Block2703f232011-10-20 11:56:09 +0100197 ALOGV("PreviewPlayer: setDataSource_l Dummyaudiocreation started");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800198
199 mAudioTrack = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700200 ((mPlayEndTimeMsec)*1000LL));
Steve Block2703f232011-10-20 11:56:09 +0100201 ALOGV("PreviewPlayer: setDataSource_l Dummyauiosource created");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800202 if(mAudioTrack != NULL) {
203 haveAudio = true;
204 }
205 }
206
207 if (!haveAudio && !haveVideo) {
208 return UNKNOWN_ERROR;
209 }
210
211 mExtractorFlags = extractor->flags();
212 return OK;
213}
214
215status_t PreviewPlayer::setDataSource_l_jpg() {
216 M4OSA_ERR err = M4NO_ERROR;
Steve Block2703f232011-10-20 11:56:09 +0100217 ALOGV("PreviewPlayer: setDataSource_l_jpg started");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800218
219 mAudioSource = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700220 ((mPlayEndTimeMsec)*1000LL));
Steve Block2703f232011-10-20 11:56:09 +0100221 ALOGV("PreviewPlayer: setDataSource_l_jpg Dummyaudiosource created");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800222 if(mAudioSource != NULL) {
223 setAudioSource(mAudioSource);
224 }
225 status_t error = mAudioSource->start();
226 if (error != OK) {
Steve Block2703f232011-10-20 11:56:09 +0100227 ALOGV("Error starting dummy audio source");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800228 mAudioSource.clear();
229 return err;
230 }
231
Raghavender Pallaebf40152011-03-14 20:15:12 -0700232 mDurationUs = (mPlayEndTimeMsec - mPlayBeginTimeMsec)*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800233
234 mVideoSource = DummyVideoSource::Create(mVideoWidth, mVideoHeight,
235 mDurationUs, mUri);
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800236
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800237 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800238 setVideoSource(mVideoSource);
239 status_t err1 = mVideoSource->start();
240 if (err1 != OK) {
241 mVideoSource.clear();
242 return err;
243 }
244
245 mIsVideoSourceJpg = true;
246 return OK;
247}
248
249void PreviewPlayer::reset() {
250 Mutex::Autolock autoLock(mLock);
251 reset_l();
252}
253
254void PreviewPlayer::reset_l() {
255
256 if (mFlags & PREPARING) {
257 mFlags |= PREPARE_CANCELLED;
258 }
259
260 while (mFlags & PREPARING) {
261 mPreparedCondition.wait(mLock);
262 }
263
264 cancelPlayerEvents();
265 mAudioTrack.clear();
266 mVideoTrack.clear();
267
268 // Shutdown audio first, so that the respone to the reset request
269 // appears to happen instantaneously as far as the user is concerned
270 // If we did this later, audio would continue playing while we
271 // shutdown the video-related resources and the player appear to
272 // not be as responsive to a reset request.
273 if (mAudioPlayer == NULL && mAudioSource != NULL) {
274 // If we had an audio player, it would have effectively
275 // taken possession of the audio source and stopped it when
276 // _it_ is stopped. Otherwise this is still our responsibility.
277 mAudioSource->stop();
278 }
279 mAudioSource.clear();
280
281 mTimeSource = NULL;
282
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800283 //Single audio player instance used
284 //So donot delete it here
285 //It is deleted from PreviewController class
286 //delete mAudioPlayer;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800287 mAudioPlayer = NULL;
288
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800289 if (mVideoBuffer) {
290 mVideoBuffer->release();
291 mVideoBuffer = NULL;
292 }
293
294 if (mVideoSource != NULL) {
295 mVideoSource->stop();
296
297 // The following hack is necessary to ensure that the OMX
298 // component is completely released by the time we may try
299 // to instantiate it again.
300 wp<MediaSource> tmp = mVideoSource;
301 mVideoSource.clear();
302 while (tmp.promote() != NULL) {
303 usleep(1000);
304 }
305 IPCThreadState::self()->flushCommands();
306 }
307
308 mDurationUs = -1;
309 mFlags = 0;
310 mExtractorFlags = 0;
311 mVideoWidth = mVideoHeight = -1;
312 mTimeSourceDeltaUs = 0;
313 mVideoTimeUs = 0;
314
Andreas Hubera5872f72011-02-24 15:25:21 -0800315 mSeeking = NO_SEEK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800316 mSeekNotificationSent = false;
317 mSeekTimeUs = 0;
318
319 mUri.setTo("");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800320
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800321 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
322 mIsVideoSourceJpg = false;
323 mFrameRGBBuffer = NULL;
324 if(mFrameYUVBuffer != NULL) {
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700325 free(mFrameYUVBuffer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800326 mFrameYUVBuffer = NULL;
327 }
328}
329
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800330status_t PreviewPlayer::play() {
331 Mutex::Autolock autoLock(mLock);
332
333 mFlags &= ~CACHE_UNDERRUN;
Hong Tenge0180232011-09-28 18:40:38 -0700334 mFlags &= ~INFORMED_AV_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800335 return play_l();
336}
337
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800338status_t PreviewPlayer::startAudioPlayer_l() {
339 CHECK(!(mFlags & AUDIO_RUNNING));
340
341 if (mAudioSource == NULL || mAudioPlayer == NULL) {
342 return OK;
343 }
344
345 if (!(mFlags & AUDIOPLAYER_STARTED)) {
346 mFlags |= AUDIOPLAYER_STARTED;
347
348 // We've already started the MediaSource in order to enable
349 // the prefetcher to read its data.
350 status_t err = mVeAudioPlayer->start(
351 true /* sourceAlreadyStarted */);
352
353 if (err != OK) {
354 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
355 return err;
356 }
357 } else {
358 mVeAudioPlayer->resume();
359 }
360
361 mFlags |= AUDIO_RUNNING;
362
363 mWatchForAudioEOS = true;
364
365 return OK;
366}
367
James Dongc9dedc42011-05-01 12:36:22 -0700368status_t PreviewPlayer::setAudioPlayer(AudioPlayerBase *audioPlayer) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800369 Mutex::Autolock autoLock(mLock);
370 CHECK(!(mFlags & PLAYING));
371 mAudioPlayer = audioPlayer;
372
Steve Block2703f232011-10-20 11:56:09 +0100373 ALOGV("SetAudioPlayer");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800374 mIsChangeSourceRequired = true;
375 mVeAudioPlayer =
376 (VideoEditorAudioPlayer*)mAudioPlayer;
377
378 // check if the new and old source are dummy
379 sp<MediaSource> anAudioSource = mVeAudioPlayer->getSource();
380 if (anAudioSource == NULL) {
381 // Audio player does not have any source set.
Steve Block2703f232011-10-20 11:56:09 +0100382 ALOGV("setAudioPlayer: Audio player does not have any source set");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800383 return OK;
384 }
385
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800386 // If new video source is not dummy, then always change source
387 // Else audio player continues using old audio source and there are
388 // frame drops to maintain AV sync
389 sp<MetaData> meta;
390 if (mVideoSource != NULL) {
391 meta = mVideoSource->getFormat();
392 const char *pVidSrcType;
393 if (meta->findCString(kKeyDecoderComponent, &pVidSrcType)) {
394 if (strcmp(pVidSrcType, "DummyVideoSource") != 0) {
Steve Block2703f232011-10-20 11:56:09 +0100395 ALOGV(" Video clip with silent audio; need to change source");
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800396 return OK;
397 }
398 }
399 }
400
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800401 const char *pSrcType1;
402 const char *pSrcType2;
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800403 meta = anAudioSource->getFormat();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800404
405 if (meta->findCString(kKeyDecoderComponent, &pSrcType1)) {
406 if (strcmp(pSrcType1, "DummyAudioSource") == 0) {
407 meta = mAudioSource->getFormat();
408 if (meta->findCString(kKeyDecoderComponent, &pSrcType2)) {
409 if (strcmp(pSrcType2, "DummyAudioSource") == 0) {
410 mIsChangeSourceRequired = false;
411 // Just set the new play duration for the existing source
412 MediaSource *pMediaSrc = anAudioSource.get();
413 DummyAudioSource *pDummyAudioSource = (DummyAudioSource*)pMediaSrc;
414 //Increment the duration of audio source
Raghavender Pallaebf40152011-03-14 20:15:12 -0700415 pDummyAudioSource->setDuration(
416 (int64_t)((mPlayEndTimeMsec)*1000LL));
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800417
418 // Stop the new audio source
419 // since we continue using old source
Steve Block2703f232011-10-20 11:56:09 +0100420 ALOGV("setAudioPlayer: stop new audio source");
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800421 mAudioSource->stop();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800422 }
423 }
424 }
425 }
426
427 return OK;
428}
429
430void PreviewPlayer::onStreamDone() {
431 // Posted whenever any stream finishes playing.
432
433 Mutex::Autolock autoLock(mLock);
434 if (!mStreamDoneEventPending) {
435 return;
436 }
437 mStreamDoneEventPending = false;
438
439 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
Steve Block2703f232011-10-20 11:56:09 +0100440 ALOGV("MEDIA_ERROR %d", mStreamDoneStatus);
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800441
442 notifyListener_l(
443 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
444
445 pause_l(true /* at eos */);
446
447 mFlags |= AT_EOS;
448 return;
449 }
450
451 const bool allDone =
452 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
453 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
454
455 if (!allDone) {
456 return;
457 }
458
459 if (mFlags & (LOOPING | AUTO_LOOPING)) {
460 seekTo_l(0);
461
462 if (mVideoSource != NULL) {
463 postVideoEvent_l();
464 }
465 } else {
Steve Block2703f232011-10-20 11:56:09 +0100466 ALOGV("MEDIA_PLAYBACK_COMPLETE");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800467 //pause before sending event
468 pause_l(true /* at eos */);
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700469
470 //This lock is used to syncronize onStreamDone() in PreviewPlayer and
471 //stopPreview() in PreviewController
472 Mutex::Autolock autoLock(mLockControl);
Hong Tenge0180232011-09-28 18:40:38 -0700473 /* Make sure PreviewPlayer only notifies MEDIA_PLAYBACK_COMPLETE once for each clip!
474 * It happens twice in following scenario.
475 * To make the clips in preview storyboard are played and switched smoothly,
476 * PreviewController uses two PreviewPlayer instances and one AudioPlayer.
477 * The two PreviewPlayer use the same AudioPlayer to play the audio,
478 * and change the audio source of the AudioPlayer.
479 * If the audio source of current playing clip and next clip are dummy
480 * audio source(image or video without audio), it will not change the audio source
481 * to avoid the "audio glitch", and keep using the current audio source.
482 * When the video of current clip reached the EOS, PreviewPlayer will set EOS flag
483 * for video and audio, and it will notify MEDIA_PLAYBACK_COMPLETE.
484 * But the audio(dummy audio source) is still playing(for next clip),
485 * and when it reached the EOS, and video reached EOS,
486 * PreviewPlayer will notify MEDIA_PLAYBACK_COMPLETE again. */
487 if (!(mFlags & INFORMED_AV_EOS)) {
488 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
489 mFlags |= INFORMED_AV_EOS;
490 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800491 mFlags |= AT_EOS;
Steve Block2703f232011-10-20 11:56:09 +0100492 ALOGV("onStreamDone end");
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700493 return;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800494 }
495}
496
497
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800498status_t PreviewPlayer::play_l() {
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800499
Rajneesh Chowdury8b95de22011-02-16 15:32:06 -0800500 mFlags &= ~SEEK_PREVIEW;
501
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800502 if (mFlags & PLAYING) {
503 return OK;
504 }
505 mStartNextPlayer = false;
506
507 if (!(mFlags & PREPARED)) {
508 status_t err = prepare_l();
509
510 if (err != OK) {
511 return err;
512 }
513 }
514
515 mFlags |= PLAYING;
516 mFlags |= FIRST_FRAME;
517
518 bool deferredAudioSeek = false;
519
520 if (mAudioSource != NULL) {
521 if (mAudioPlayer == NULL) {
522 if (mAudioSink != NULL) {
523
524 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800525 mVeAudioPlayer =
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800526 (VideoEditorAudioPlayer*)mAudioPlayer;
527
528 mAudioPlayer->setSource(mAudioSource);
529
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800530 mVeAudioPlayer->setAudioMixSettings(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800531 mPreviewPlayerAudioMixSettings);
532
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800533 mVeAudioPlayer->setAudioMixPCMFileHandle(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800534 mAudioMixPCMFileHandle);
535
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800536 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800537 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
538 mCurrentMediaVolumeValue);
539
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800540 mFlags |= AUDIOPLAYER_STARTED;
541 // We've already started the MediaSource in order to enable
542 // the prefetcher to read its data.
543 status_t err = mVeAudioPlayer->start(
544 true /* sourceAlreadyStarted */);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800545
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800546 if (err != OK) {
547 //delete mAudioPlayer;
548 mAudioPlayer = NULL;
549
550 mFlags &= ~(PLAYING | FIRST_FRAME);
551 return err;
552 }
553
554 mTimeSource = mVeAudioPlayer;
555 mFlags |= AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800556 deferredAudioSeek = true;
557 mWatchForAudioSeekComplete = false;
558 mWatchForAudioEOS = true;
559 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800560 } else {
561 mVeAudioPlayer = (VideoEditorAudioPlayer*)mAudioPlayer;
562 bool isAudioPlayerStarted = mVeAudioPlayer->isStarted();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800563
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800564 if (mIsChangeSourceRequired == true) {
Steve Block2703f232011-10-20 11:56:09 +0100565 ALOGV("play_l: Change audio source required");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800566
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800567 if (isAudioPlayerStarted == true) {
568 mVeAudioPlayer->pause();
569 }
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800570
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800571 mVeAudioPlayer->setSource(mAudioSource);
572 mVeAudioPlayer->setObserver(this);
573
574 mVeAudioPlayer->setAudioMixSettings(
575 mPreviewPlayerAudioMixSettings);
576
577 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
578 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
579 mCurrentMediaVolumeValue);
580
581 if (isAudioPlayerStarted == true) {
582 mVeAudioPlayer->resume();
583 } else {
584 status_t err = OK;
585 err = mVeAudioPlayer->start(true);
586 if (err != OK) {
587 mAudioPlayer = NULL;
588 mVeAudioPlayer = NULL;
589
590 mFlags &= ~(PLAYING | FIRST_FRAME);
591 return err;
592 }
593 }
594 } else {
Steve Block2703f232011-10-20 11:56:09 +0100595 ALOGV("play_l: No Source change required");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800596 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
597 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
598 mCurrentMediaVolumeValue);
599
600 mVeAudioPlayer->resume();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800601 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800602
603 mFlags |= AUDIOPLAYER_STARTED;
604 mFlags |= AUDIO_RUNNING;
605 mTimeSource = mVeAudioPlayer;
606 deferredAudioSeek = true;
607 mWatchForAudioSeekComplete = false;
608 mWatchForAudioEOS = true;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800609 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800610 }
611
612 if (mTimeSource == NULL && mAudioPlayer == NULL) {
613 mTimeSource = &mSystemTimeSource;
614 }
615
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800616 // Set the seek option for Image source files and read.
617 // This resets the timestamping for image play
618 if (mIsVideoSourceJpg) {
619 MediaSource::ReadOptions options;
620 MediaBuffer *aLocalBuffer;
621 options.setSeekTo(mSeekTimeUs);
622 mVideoSource->read(&aLocalBuffer, &options);
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800623 aLocalBuffer->release();
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800624 }
625
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800626 if (mVideoSource != NULL) {
627 // Kick off video playback
628 postVideoEvent_l();
629 }
630
631 if (deferredAudioSeek) {
632 // If there was a seek request while we were paused
633 // and we're just starting up again, honor the request now.
634 seekAudioIfNecessary_l();
635 }
636
637 if (mFlags & AT_EOS) {
638 // Legacy behaviour, if a stream finishes playing and then
639 // is started again, we play from the start...
640 seekTo_l(0);
641 }
642
643 return OK;
644}
645
646
Santosh Madhavabfece172011-02-03 16:59:47 -0800647status_t PreviewPlayer::initRenderer_l() {
Mathias Agopian6e224292011-04-05 15:38:24 -0700648 if (mSurface != NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800649 if(mVideoRenderer == NULL) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800650 mVideoRenderer = mNativeWindowRenderer->createRenderInput();
651 if (mVideoSource != NULL) {
652 updateSizeToRender(mVideoSource->getFormat());
Santosh Madhavabfece172011-02-03 16:59:47 -0800653 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800654 }
655 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800656 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800657}
658
659
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800660status_t PreviewPlayer::seekTo(int64_t timeUs) {
661
662 if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) {
663 Mutex::Autolock autoLock(mLock);
664 return seekTo_l(timeUs);
665 }
666
667 return OK;
668}
669
670
671status_t PreviewPlayer::getVideoDimensions(
672 int32_t *width, int32_t *height) const {
673 Mutex::Autolock autoLock(mLock);
674
675 if (mVideoWidth < 0 || mVideoHeight < 0) {
676 return UNKNOWN_ERROR;
677 }
678
679 *width = mVideoWidth;
680 *height = mVideoHeight;
681
682 return OK;
683}
684
685
686status_t PreviewPlayer::initAudioDecoder() {
687 sp<MetaData> meta = mAudioTrack->getFormat();
688 const char *mime;
689 CHECK(meta->findCString(kKeyMIMEType, &mime));
690
691 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
692 mAudioSource = mAudioTrack;
693 } else {
694 sp<MediaSource> aRawSource;
695 aRawSource = OMXCodec::Create(
696 mClient.interface(), mAudioTrack->getFormat(),
697 false, // createEncoder
698 mAudioTrack);
699
700 if(aRawSource != NULL) {
Steve Block2703f232011-10-20 11:56:09 +0100701 ALOGV("initAudioDecoder: new VideoEditorSRC");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800702 mAudioSource = new VideoEditorSRC(aRawSource);
703 }
704 }
705
706 if (mAudioSource != NULL) {
707 int64_t durationUs;
708 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
709 Mutex::Autolock autoLock(mMiscStateLock);
710 if (mDurationUs < 0 || durationUs > mDurationUs) {
711 mDurationUs = durationUs;
712 }
713 }
714 status_t err = mAudioSource->start();
715
716 if (err != OK) {
717 mAudioSource.clear();
718 return err;
719 }
720 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
721 // For legacy reasons we're simply going to ignore the absence
722 // of an audio decoder for QCELP instead of aborting playback
723 // altogether.
724 return OK;
725 }
726
727 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
728}
729
730
731status_t PreviewPlayer::initVideoDecoder(uint32_t flags) {
732
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800733 initRenderer_l();
734
735 if (mVideoRenderer == NULL) {
Steve Blockf8bd29c2012-01-08 10:14:44 +0000736 ALOGE("Cannot create renderer");
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800737 return UNKNOWN_ERROR;
738 }
739
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800740 mVideoSource = OMXCodec::Create(
741 mClient.interface(), mVideoTrack->getFormat(),
742 false,
743 mVideoTrack,
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800744 NULL, flags, mVideoRenderer->getTargetWindow());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800745
746 if (mVideoSource != NULL) {
747 int64_t durationUs;
748 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
749 Mutex::Autolock autoLock(mMiscStateLock);
750 if (mDurationUs < 0 || durationUs > mDurationUs) {
751 mDurationUs = durationUs;
752 }
753 }
754
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800755 updateSizeToRender(mVideoTrack->getFormat());
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800756
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800757 status_t err = mVideoSource->start();
758
759 if (err != OK) {
760 mVideoSource.clear();
761 return err;
762 }
763 }
764
765 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
766}
767
768
769void PreviewPlayer::onVideoEvent() {
770 uint32_t i=0;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800771 M4OSA_ERR err1 = M4NO_ERROR;
772 int64_t imageFrameTimeUs = 0;
773
774 Mutex::Autolock autoLock(mLock);
775 if (!mVideoEventPending) {
776 // The event has been cancelled in reset_l() but had already
777 // been scheduled for execution at that time.
778 return;
779 }
780 mVideoEventPending = false;
781
Andreas Huber9e4c36a2011-02-08 13:12:32 -0800782 if (mFlags & SEEK_PREVIEW) {
783 mFlags &= ~SEEK_PREVIEW;
784 return;
785 }
786
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800787 TimeSource *ts_st = &mSystemTimeSource;
788 int64_t timeStartUs = ts_st->getRealTimeUs();
789
Andreas Hubera5872f72011-02-24 15:25:21 -0800790 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800791
792 if(mAudioSource != NULL) {
793
794 // We're going to seek the video source first, followed by
795 // the audio source.
796 // In order to avoid jumps in the DataSource offset caused by
797 // the audio codec prefetching data from the old locations
798 // while the video codec is already reading data from the new
799 // locations, we'll "pause" the audio source, causing it to
800 // stop reading input data until a subsequent seek.
801
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800802 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800803 mAudioPlayer->pause();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800804 mFlags &= ~AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800805 }
806 mAudioSource->pause();
807 }
808 }
809
810 if (!mVideoBuffer) {
811 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -0800812 if (mSeeking != NO_SEEK) {
Steve Block2703f232011-10-20 11:56:09 +0100813 ALOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800814 mSeekTimeUs / 1E6);
815
816 options.setSeekTo(
817 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
818 }
819 for (;;) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800820 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800821 options.clearSeekTo();
822
823 if (err != OK) {
824 CHECK_EQ(mVideoBuffer, NULL);
825
826 if (err == INFO_FORMAT_CHANGED) {
Steve Block2703f232011-10-20 11:56:09 +0100827 ALOGV("LV PLAYER VideoSource signalled format change");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800828 notifyVideoSize_l();
829
830 if (mVideoRenderer != NULL) {
831 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -0800832 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800833 if (err != OK) {
834 postStreamDoneEvent_l(err);
835 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800836
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800837 }
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800838
839 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800840 continue;
841 }
842 // So video playback is complete, but we may still have
Santosh Madhava342f9322011-01-27 16:27:12 -0800843 // a seek request pending that needs to be applied to the audio track
Andreas Hubera5872f72011-02-24 15:25:21 -0800844 if (mSeeking != NO_SEEK) {
Steve Block2703f232011-10-20 11:56:09 +0100845 ALOGV("video stream ended while seeking!");
Santosh Madhava342f9322011-01-27 16:27:12 -0800846 }
847 finishSeekIfNecessary(-1);
Steve Block2703f232011-10-20 11:56:09 +0100848 ALOGV("PreviewPlayer: onVideoEvent EOS reached.");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800849 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800850 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800851 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800852 postStreamDoneEvent_l(err);
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800853 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -0700854 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800855 return;
856 }
857
858 if (mVideoBuffer->range_length() == 0) {
859 // Some decoders, notably the PV AVC software decoder
860 // return spurious empty buffers that we just want to ignore.
861
862 mVideoBuffer->release();
863 mVideoBuffer = NULL;
864 continue;
865 }
866
867 int64_t videoTimeUs;
868 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
869
Andreas Hubera5872f72011-02-24 15:25:21 -0800870 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800871 if (videoTimeUs < mSeekTimeUs) {
872 // buffers are before seek time
873 // ignore them
874 mVideoBuffer->release();
875 mVideoBuffer = NULL;
876 continue;
877 }
878 } else {
879 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
880 // Frames are before begin cut time
881 // Donot render
882 mVideoBuffer->release();
883 mVideoBuffer = NULL;
884 continue;
885 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800886 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800887 break;
888 }
889 }
890
891 mNumberDecVideoFrames++;
892
893 int64_t timeUs;
894 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
895
896 {
897 Mutex::Autolock autoLock(mMiscStateLock);
898 mVideoTimeUs = timeUs;
899 }
900
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800901
902 if(!mStartNextPlayer) {
Raghavender Pallaebf40152011-03-14 20:15:12 -0700903 int64_t playbackTimeRemaining = (mPlayEndTimeMsec*1000LL) - timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800904 if(playbackTimeRemaining <= 1500000) {
905 //When less than 1.5 sec of playback left
906 // send notification to start next player
907
908 mStartNextPlayer = true;
909 notifyListener_l(0xAAAAAAAA);
910 }
911 }
912
Andreas Hubera5872f72011-02-24 15:25:21 -0800913 SeekType wasSeeking = mSeeking;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800914 finishSeekIfNecessary(timeUs);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800915 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING))) {
916 status_t err = startAudioPlayer_l();
917 if (err != OK) {
Steve Blockf8bd29c2012-01-08 10:14:44 +0000918 ALOGE("Starting the audio player failed w/ err %d", err);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800919 return;
920 }
921 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800922
923 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
924
925 if(ts == NULL) {
926 mVideoBuffer->release();
927 mVideoBuffer = NULL;
928 return;
929 }
930
931 if(!mIsVideoSourceJpg) {
932 if (mFlags & FIRST_FRAME) {
933 mFlags &= ~FIRST_FRAME;
934
935 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
936 }
937
938 int64_t realTimeUs, mediaTimeUs;
939 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
940 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
941 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
942 }
943
944 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
945
946 int64_t latenessUs = nowUs - timeUs;
947
Andreas Hubera5872f72011-02-24 15:25:21 -0800948 if (wasSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800949 // Let's display the first frame after seeking right away.
950 latenessUs = 0;
951 }
Steve Block2703f232011-10-20 11:56:09 +0100952 ALOGV("Audio time stamp = %lld and video time stamp = %lld",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800953 ts->getRealTimeUs(),timeUs);
954 if (latenessUs > 40000) {
955 // We're more than 40ms late.
956
Steve Block2703f232011-10-20 11:56:09 +0100957 ALOGV("LV PLAYER we're late by %lld us (%.2f secs)",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800958 latenessUs, latenessUs / 1E6);
959
960 mVideoBuffer->release();
961 mVideoBuffer = NULL;
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800962 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800963 return;
964 }
965
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800966 if (latenessUs < -25000) {
967 // We're more than 25ms early.
Steve Block2703f232011-10-20 11:56:09 +0100968 ALOGV("We're more than 25ms early, lateness %lld", latenessUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800969
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800970 postVideoEvent_l(25000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800971 return;
972 }
973 }
974
975 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
976 mVideoRendererIsPreview = false;
977
Santosh Madhavabfece172011-02-03 16:59:47 -0800978 status_t err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800979 if (err != OK) {
980 postStreamDoneEvent_l(err);
981 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800982 }
983
984 // If timestamp exceeds endCutTime of clip, donot render
985 if((timeUs/1000) > mPlayEndTimeMsec) {
Chih-Chung Changcece4b32011-08-01 16:34:05 +0800986 mVideoBuffer->release();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800987 mVideoBuffer = NULL;
988 mFlags |= VIDEO_AT_EOS;
989 mFlags |= AUDIO_AT_EOS;
Steve Block2703f232011-10-20 11:56:09 +0100990 ALOGV("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS..");
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800991 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -0800992 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -0700993 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800994 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
995 return;
996 }
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800997 // Capture the frame timestamp to be rendered
998 mDecodedVideoTs = timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800999
1000 // Post processing to apply video effects
1001 for(i=0;i<mNumberEffects;i++) {
1002 // First check if effect starttime matches the clip being previewed
1003 if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) ||
1004 (mEffectsSettings[i].uiStartTime >=
1005 ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec)))
1006 {
1007 // This effect doesn't belong to this clip, check next one
1008 continue;
1009 }
1010 // Check if effect applies to this particular frame timestamp
1011 if((mEffectsSettings[i].uiStartTime <=
1012 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) &&
1013 ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=
1014 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec))
1015 && (mEffectsSettings[i].uiDuration != 0)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001016 setVideoPostProcessingNode(
1017 mEffectsSettings[i].VideoEffectType, TRUE);
1018 }
1019 else {
1020 setVideoPostProcessingNode(
1021 mEffectsSettings[i].VideoEffectType, FALSE);
1022 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001023 }
1024
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001025 //Provide the overlay Update indication when there is an overlay effect
Dharmaray Kundargid01ef562011-01-26 21:11:00 -08001026 if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) {
1027 mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here.
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001028 if (!mOverlayUpdateEventPosted) {
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001029 // Find the effect in effectSettings array
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001030 M4OSA_UInt32 index;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001031 for (index = 0; index < mNumberEffects; index++) {
1032 M4OSA_UInt32 timeMs = mDecodedVideoTs/1000;
1033 M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000;
1034 if(mEffectsSettings[index].VideoEffectType ==
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001035 (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001036 if (((mEffectsSettings[index].uiStartTime + 1) <=
1037 timeMs + timeOffset - mPlayBeginTimeMsec) &&
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001038 ((mEffectsSettings[index].uiStartTime - 1 +
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001039 mEffectsSettings[index].uiDuration) >=
1040 timeMs + timeOffset - mPlayBeginTimeMsec))
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001041 {
1042 break;
1043 }
1044 }
1045 }
1046 if (index < mNumberEffects) {
1047 mCurrFramingEffectIndex = index;
1048 mOverlayUpdateEventPosted = true;
1049 postOverlayUpdateEvent_l();
Steve Block2703f232011-10-20 11:56:09 +01001050 ALOGV("Framing index = %d", mCurrFramingEffectIndex);
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001051 } else {
Steve Block2703f232011-10-20 11:56:09 +01001052 ALOGV("No framing effects found");
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001053 }
1054 }
1055
1056 } else if (mOverlayUpdateEventPosted) {
1057 //Post the event when the overlay is no more valid
Steve Block2703f232011-10-20 11:56:09 +01001058 ALOGV("Overlay is Done");
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001059 mOverlayUpdateEventPosted = false;
1060 postOverlayUpdateEvent_l();
1061 }
1062
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001063 if (mVideoRenderer != NULL) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001064 mVideoRenderer->render(mVideoBuffer, mCurrentVideoEffect,
1065 mRenderingMode, mIsVideoSourceJpg);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001066 }
1067
Chih-Chung Changcece4b32011-08-01 16:34:05 +08001068 mVideoBuffer->release();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001069 mVideoBuffer = NULL;
1070
1071 // Post progress callback based on callback interval set
1072 if(mNumberDecVideoFrames >= mProgressCbInterval) {
1073 postProgressCallbackEvent_l();
1074 mNumberDecVideoFrames = 0; // reset counter
1075 }
1076
1077 // if reached EndCutTime of clip, post EOS event
1078 if((timeUs/1000) >= mPlayEndTimeMsec) {
Steve Block2703f232011-10-20 11:56:09 +01001079 ALOGV("PreviewPlayer: onVideoEvent EOS.");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001080 mFlags |= VIDEO_AT_EOS;
1081 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001082 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001083 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001084 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001085 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1086 }
1087 else {
Andreas Hubera5872f72011-02-24 15:25:21 -08001088 if ((wasSeeking != NO_SEEK) && (mFlags & SEEK_PREVIEW)) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001089 mFlags &= ~SEEK_PREVIEW;
1090 return;
1091 }
1092
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001093 if(!mIsVideoSourceJpg) {
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001094 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001095 }
1096 else {
1097 postVideoEvent_l(33000);
1098 }
1099 }
1100}
1101
1102status_t PreviewPlayer::prepare() {
1103 Mutex::Autolock autoLock(mLock);
1104 return prepare_l();
1105}
1106
1107status_t PreviewPlayer::prepare_l() {
1108 if (mFlags & PREPARED) {
1109 return OK;
1110 }
1111
1112 if (mFlags & PREPARING) {
1113 return UNKNOWN_ERROR;
1114 }
1115
1116 mIsAsyncPrepare = false;
1117 status_t err = prepareAsync_l();
1118
1119 if (err != OK) {
1120 return err;
1121 }
1122
1123 while (mFlags & PREPARING) {
1124 mPreparedCondition.wait(mLock);
1125 }
1126
1127 return mPrepareResult;
1128}
1129
1130status_t PreviewPlayer::prepareAsync_l() {
1131 if (mFlags & PREPARING) {
1132 return UNKNOWN_ERROR; // async prepare already pending
1133 }
1134
1135 if (!mQueueStarted) {
1136 mQueue.start();
1137 mQueueStarted = true;
1138 }
1139
1140 mFlags |= PREPARING;
1141 mAsyncPrepareEvent = new PreviewPlayerEvent(
1142 this, &PreviewPlayer::onPrepareAsyncEvent);
1143
1144 mQueue.postEvent(mAsyncPrepareEvent);
1145
1146 return OK;
1147}
1148
1149status_t PreviewPlayer::finishSetDataSource_l() {
1150 sp<DataSource> dataSource;
1151 sp<MediaExtractor> extractor;
1152
James Dongdaeb5b32012-01-12 12:12:40 -08001153 dataSource = DataSource::CreateFromURI(mUri.string(), NULL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001154
1155 if (dataSource == NULL) {
1156 return UNKNOWN_ERROR;
1157 }
1158
1159 //If file type is .rgb, then no need to check for Extractor
1160 int uriLen = strlen(mUri);
1161 int startOffset = uriLen - 4;
1162 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) {
1163 extractor = NULL;
1164 }
1165 else {
1166 extractor = MediaExtractor::Create(dataSource,
1167 MEDIA_MIMETYPE_CONTAINER_MPEG4);
1168 }
1169
1170 if (extractor == NULL) {
Steve Block2703f232011-10-20 11:56:09 +01001171 ALOGV("PreviewPlayer::finishSetDataSource_l extractor == NULL");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001172 return setDataSource_l_jpg();
1173 }
1174
1175 return setDataSource_l(extractor);
1176}
1177
1178
1179// static
1180bool PreviewPlayer::ContinuePreparation(void *cookie) {
1181 PreviewPlayer *me = static_cast<PreviewPlayer *>(cookie);
1182
1183 return (me->mFlags & PREPARE_CANCELLED) == 0;
1184}
1185
1186void PreviewPlayer::onPrepareAsyncEvent() {
1187 Mutex::Autolock autoLock(mLock);
Steve Block2703f232011-10-20 11:56:09 +01001188 ALOGV("onPrepareAsyncEvent");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001189
1190 if (mFlags & PREPARE_CANCELLED) {
Steve Block2703f232011-10-20 11:56:09 +01001191 ALOGV("LV PLAYER prepare was cancelled before doing anything");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001192 abortPrepare(UNKNOWN_ERROR);
1193 return;
1194 }
1195
1196 if (mUri.size() > 0) {
1197 status_t err = finishSetDataSource_l();
1198
1199 if (err != OK) {
1200 abortPrepare(err);
1201 return;
1202 }
1203 }
1204
1205 if (mVideoTrack != NULL && mVideoSource == NULL) {
1206 status_t err = initVideoDecoder(OMXCodec::kHardwareCodecsOnly);
1207
1208 if (err != OK) {
1209 abortPrepare(err);
1210 return;
1211 }
1212 }
1213
1214 if (mAudioTrack != NULL && mAudioSource == NULL) {
1215 status_t err = initAudioDecoder();
1216
1217 if (err != OK) {
1218 abortPrepare(err);
1219 return;
1220 }
1221 }
1222 finishAsyncPrepare_l();
1223
1224}
1225
1226void PreviewPlayer::finishAsyncPrepare_l() {
1227 if (mIsAsyncPrepare) {
1228 if (mVideoSource == NULL) {
Steve Block2703f232011-10-20 11:56:09 +01001229 ALOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE 0 0 ");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001230 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1231 } else {
Steve Block2703f232011-10-20 11:56:09 +01001232 ALOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001233 notifyVideoSize_l();
1234 }
Steve Block2703f232011-10-20 11:56:09 +01001235 ALOGV("finishAsyncPrepare_l: MEDIA_PREPARED");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001236 notifyListener_l(MEDIA_PREPARED);
1237 }
1238
1239 mPrepareResult = OK;
1240 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1241 mFlags |= PREPARED;
1242 mAsyncPrepareEvent = NULL;
1243 mPreparedCondition.broadcast();
1244}
1245
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001246void PreviewPlayer::acquireLock() {
Steve Block2703f232011-10-20 11:56:09 +01001247 ALOGV("acquireLock");
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001248 mLockControl.lock();
1249}
1250
1251void PreviewPlayer::releaseLock() {
Steve Block2703f232011-10-20 11:56:09 +01001252 ALOGV("releaseLock");
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001253 mLockControl.unlock();
1254}
1255
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001256status_t PreviewPlayer::loadEffectsSettings(
1257 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) {
1258 M4OSA_UInt32 i = 0, rgbSize = 0;
1259 M4VIFI_UInt8 *tmp = M4OSA_NULL;
1260
1261 mNumberEffects = nEffects;
1262 mEffectsSettings = pEffectSettings;
1263 return OK;
1264}
1265
1266status_t PreviewPlayer::loadAudioMixSettings(
1267 M4xVSS_AudioMixingSettings* pAudioMixSettings) {
1268
Steve Block2703f232011-10-20 11:56:09 +01001269 ALOGV("PreviewPlayer: loadAudioMixSettings: ");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001270 mPreviewPlayerAudioMixSettings = pAudioMixSettings;
1271 return OK;
1272}
1273
1274status_t PreviewPlayer::setAudioMixPCMFileHandle(
1275 M4OSA_Context pAudioMixPCMFileHandle) {
1276
Steve Block2703f232011-10-20 11:56:09 +01001277 ALOGV("PreviewPlayer: setAudioMixPCMFileHandle: ");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001278 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle;
1279 return OK;
1280}
1281
1282status_t PreviewPlayer::setAudioMixStoryBoardParam(
1283 M4OSA_UInt32 audioMixStoryBoardTS,
1284 M4OSA_UInt32 currentMediaBeginCutTime,
1285 M4OSA_UInt32 primaryTrackVolValue ) {
1286
1287 mAudioMixStoryBoardTS = audioMixStoryBoardTS;
1288 mCurrentMediaBeginCutTime = currentMediaBeginCutTime;
1289 mCurrentMediaVolumeValue = primaryTrackVolValue;
1290 return OK;
1291}
1292
1293status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) {
1294
1295 mPlayBeginTimeMsec = msec;
1296 return OK;
1297}
1298
1299status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) {
1300
1301 mPlayEndTimeMsec = msec;
1302 return OK;
1303}
1304
1305status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) {
1306
1307 mStoryboardStartTimeMsec = msec;
Raghavender Pallaebf40152011-03-14 20:15:12 -07001308 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001309 return OK;
1310}
1311
1312status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) {
1313
1314 mProgressCbInterval = cbInterval;
1315 return OK;
1316}
1317
1318
1319status_t PreviewPlayer::setMediaRenderingMode(
1320 M4xVSS_MediaRendering mode,
1321 M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
1322
1323 mRenderingMode = mode;
1324
Hong Teng8806b702011-07-06 18:29:28 -07001325 status_t err = OK;
1326 /* get the video width and height by resolution */
1327 err = getVideoSizeByResolution(outputVideoSize,
1328 &mOutputVideoWidth, &mOutputVideoHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001329
Hong Teng8806b702011-07-06 18:29:28 -07001330 return err;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001331}
1332
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001333status_t PreviewPlayer::resetJniCallbackTimeStamp() {
1334
Raghavender Pallaebf40152011-03-14 20:15:12 -07001335 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001336 return OK;
1337}
1338
1339void PreviewPlayer::postProgressCallbackEvent_l() {
1340 if (mProgressCbEventPending) {
1341 return;
1342 }
1343 mProgressCbEventPending = true;
1344
1345 mQueue.postEvent(mProgressCbEvent);
1346}
1347
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001348
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001349void PreviewPlayer::onProgressCbEvent() {
1350 Mutex::Autolock autoLock(mLock);
1351 if (!mProgressCbEventPending) {
1352 return;
1353 }
1354 mProgressCbEventPending = false;
1355 // If playback starts from previous I-frame,
1356 // then send frame storyboard duration
1357 if((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) {
1358 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000);
1359 }
1360 else {
1361 notifyListener_l(MEDIA_INFO, 0,
1362 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec));
1363 }
1364}
1365
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001366void PreviewPlayer::postOverlayUpdateEvent_l() {
1367 if (mOverlayUpdateEventPending) {
1368 return;
1369 }
1370 mOverlayUpdateEventPending = true;
1371 mQueue.postEvent(mOverlayUpdateEvent);
1372}
1373
1374void PreviewPlayer::onUpdateOverlayEvent() {
1375 Mutex::Autolock autoLock(mLock);
1376
1377 if (!mOverlayUpdateEventPending) {
1378 return;
1379 }
1380 mOverlayUpdateEventPending = false;
1381
1382 int updateState;
1383 if (mOverlayUpdateEventPosted) {
1384 updateState = 1;
1385 } else {
1386 updateState = 0;
1387 }
1388 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex);
1389}
1390
1391
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001392void PreviewPlayer::setVideoPostProcessingNode(
1393 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
1394
1395 uint32_t effect = VIDEO_EFFECT_NONE;
1396
1397 //Map M4VSS3GPP_VideoEffectType to local enum
1398 switch(type) {
1399 case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
1400 effect = VIDEO_EFFECT_FADEFROMBLACK;
1401 break;
1402
1403 case M4VSS3GPP_kVideoEffectType_FadeToBlack:
1404 effect = VIDEO_EFFECT_FADETOBLACK;
1405 break;
1406
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001407 case M4xVSS_kVideoEffectType_BlackAndWhite:
1408 effect = VIDEO_EFFECT_BLACKANDWHITE;
1409 break;
1410
1411 case M4xVSS_kVideoEffectType_Pink:
1412 effect = VIDEO_EFFECT_PINK;
1413 break;
1414
1415 case M4xVSS_kVideoEffectType_Green:
1416 effect = VIDEO_EFFECT_GREEN;
1417 break;
1418
1419 case M4xVSS_kVideoEffectType_Sepia:
1420 effect = VIDEO_EFFECT_SEPIA;
1421 break;
1422
1423 case M4xVSS_kVideoEffectType_Negative:
1424 effect = VIDEO_EFFECT_NEGATIVE;
1425 break;
1426
1427 case M4xVSS_kVideoEffectType_Framing:
1428 effect = VIDEO_EFFECT_FRAMING;
1429 break;
1430
1431 case M4xVSS_kVideoEffectType_Fifties:
1432 effect = VIDEO_EFFECT_FIFTIES;
1433 break;
1434
1435 case M4xVSS_kVideoEffectType_ColorRGB16:
1436 effect = VIDEO_EFFECT_COLOR_RGB16;
1437 break;
1438
1439 case M4xVSS_kVideoEffectType_Gradient:
1440 effect = VIDEO_EFFECT_GRADIENT;
1441 break;
1442
1443 default:
1444 effect = VIDEO_EFFECT_NONE;
1445 break;
1446 }
1447
1448 if(enable == M4OSA_TRUE) {
1449 //If already set, then no need to set again
1450 if(!(mCurrentVideoEffect & effect)) {
1451 mCurrentVideoEffect |= effect;
1452 if(effect == VIDEO_EFFECT_FIFTIES) {
1453 mIsFiftiesEffectStarted = true;
1454 }
1455 }
1456 }
1457 else {
1458 //Reset only if already set
1459 if(mCurrentVideoEffect & effect) {
1460 mCurrentVideoEffect &= ~effect;
1461 }
1462 }
1463}
1464
1465status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) {
1466 mVideoWidth = width;
1467 mVideoHeight = height;
1468 return OK;
1469}
1470
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001471status_t PreviewPlayer::readFirstVideoFrame() {
Steve Block2703f232011-10-20 11:56:09 +01001472 ALOGV("PreviewPlayer::readFirstVideoFrame");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001473
1474 if (!mVideoBuffer) {
1475 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -08001476 if (mSeeking != NO_SEEK) {
Steve Block2703f232011-10-20 11:56:09 +01001477 ALOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001478 mSeekTimeUs / 1E6);
1479
1480 options.setSeekTo(
1481 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
1482 }
1483 for (;;) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001484 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001485 options.clearSeekTo();
1486
1487 if (err != OK) {
1488 CHECK_EQ(mVideoBuffer, NULL);
1489
1490 if (err == INFO_FORMAT_CHANGED) {
Steve Block2703f232011-10-20 11:56:09 +01001491 ALOGV("LV PLAYER VideoSource signalled format change");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001492 notifyVideoSize_l();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001493
1494 if (mVideoRenderer != NULL) {
1495 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -08001496 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001497 if (err != OK) {
1498 postStreamDoneEvent_l(err);
1499 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001500 }
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001501
1502 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001503 continue;
1504 }
Steve Block2703f232011-10-20 11:56:09 +01001505 ALOGV("PreviewPlayer: onVideoEvent EOS reached.");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001506 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001507 mFlags |= AUDIO_AT_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001508 postStreamDoneEvent_l(err);
1509 return OK;
1510 }
1511
1512 if (mVideoBuffer->range_length() == 0) {
1513 // Some decoders, notably the PV AVC software decoder
1514 // return spurious empty buffers that we just want to ignore.
1515
1516 mVideoBuffer->release();
1517 mVideoBuffer = NULL;
1518 continue;
1519 }
1520
1521 int64_t videoTimeUs;
1522 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
Andreas Hubera5872f72011-02-24 15:25:21 -08001523 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001524 if (videoTimeUs < mSeekTimeUs) {
1525 // buffers are before seek time
1526 // ignore them
1527 mVideoBuffer->release();
1528 mVideoBuffer = NULL;
1529 continue;
1530 }
1531 } else {
1532 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
1533 // buffers are before begin cut time
1534 // ignore them
1535 mVideoBuffer->release();
1536 mVideoBuffer = NULL;
1537 continue;
1538 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001539 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001540 break;
1541 }
1542 }
1543
1544 int64_t timeUs;
1545 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1546
1547 {
1548 Mutex::Autolock autoLock(mMiscStateLock);
1549 mVideoTimeUs = timeUs;
1550 }
1551
1552 mDecodedVideoTs = timeUs;
1553
1554 return OK;
1555
1556}
1557
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001558status_t PreviewPlayer::getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs) {
1559 *lastRenderedTimeMs = (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec);
1560 return OK;
1561}
1562
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001563void PreviewPlayer::updateSizeToRender(sp<MetaData> meta) {
1564 if (mVideoRenderer) {
1565 mVideoRenderer->updateVideoSize(meta);
1566 }
1567}
1568
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001569} // namespace android