blob: 1330c7fa4fbf70171aad79f4bd474ae520fb6fe8 [file] [log] [blame]
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001/*
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Santosh Madhavabfece172011-02-03 16:59:47 -080017
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080018#define LOG_NDEBUG 1
19#define LOG_TAG "PreviewPlayer"
20#include <utils/Log.h>
21
22#include <dlfcn.h>
23
24#include "include/ARTSPController.h"
25#include "PreviewPlayer.h"
26#include "DummyAudioSource.h"
27#include "DummyVideoSource.h"
28#include "VideoEditorSRC.h"
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080029#include "include/NuCachedSource2.h"
30#include "include/ThrottledSource.h"
31
32
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080033#include <binder/IPCThreadState.h>
34#include <media/stagefright/DataSource.h>
35#include <media/stagefright/FileSource.h>
36#include <media/stagefright/MediaBuffer.h>
37#include <media/stagefright/MediaDefs.h>
38#include <media/stagefright/MediaExtractor.h>
39#include <media/stagefright/MediaDebug.h>
40#include <media/stagefright/MediaSource.h>
41#include <media/stagefright/MetaData.h>
42#include <media/stagefright/OMXCodec.h>
43
44#include <surfaceflinger/Surface.h>
45#include <media/stagefright/foundation/ALooper.h>
46
47namespace android {
48
49
50struct PreviewPlayerEvent : public TimedEventQueue::Event {
51 PreviewPlayerEvent(
52 PreviewPlayer *player,
53 void (PreviewPlayer::*method)())
54 : mPlayer(player),
55 mMethod(method) {
56 }
57
58protected:
59 virtual ~PreviewPlayerEvent() {}
60
61 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
62 (mPlayer->*mMethod)();
63 }
64
65private:
66 PreviewPlayer *mPlayer;
67 void (PreviewPlayer::*mMethod)();
68
69 PreviewPlayerEvent(const PreviewPlayerEvent &);
70 PreviewPlayerEvent &operator=(const PreviewPlayerEvent &);
71};
72
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080073PreviewPlayer::PreviewPlayer(NativeWindowRenderer* renderer)
James Dongc9dedc42011-05-01 12:36:22 -070074 : PreviewPlayerBase(),
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080075 mNativeWindowRenderer(renderer),
76 mCurrFramingEffectIndex(0),
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -080077 mFrameRGBBuffer(NULL),
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080078 mFrameYUVBuffer(NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080079
80 mVideoRenderer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080081 mEffectsSettings = NULL;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -080082 mVeAudioPlayer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080083 mAudioMixStoryBoardTS = 0;
84 mCurrentMediaBeginCutTime = 0;
85 mCurrentMediaVolumeValue = 0;
86 mNumberEffects = 0;
87 mDecodedVideoTs = 0;
88 mDecVideoTsStoryBoard = 0;
89 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
90 mProgressCbInterval = 0;
91 mNumberDecVideoFrames = 0;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -080092 mOverlayUpdateEventPosted = false;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -080093 mIsChangeSourceRequired = true;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080094
95 mVideoEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoEvent);
96 mVideoEventPending = false;
97 mStreamDoneEvent = new PreviewPlayerEvent(this,
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -080098 &PreviewPlayer::onStreamDone);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080099
100 mStreamDoneEventPending = false;
101
102 mCheckAudioStatusEvent = new PreviewPlayerEvent(
James Dongc9dedc42011-05-01 12:36:22 -0700103 this, &PreviewPlayerBase::onCheckAudioStatus);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800104
105 mAudioStatusEventPending = false;
106
107 mProgressCbEvent = new PreviewPlayerEvent(this,
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800108 &PreviewPlayer::onProgressCbEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800109
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800110 mOverlayUpdateEvent = new PreviewPlayerEvent(this,
111 &PreviewPlayer::onUpdateOverlayEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800112 mProgressCbEventPending = false;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800113
114 mOverlayUpdateEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800115 mRenderingMode = (M4xVSS_MediaRendering)MEDIA_RENDERING_INVALID;
116 mIsFiftiesEffectStarted = false;
117 reset();
118}
119
120PreviewPlayer::~PreviewPlayer() {
121
122 if (mQueueStarted) {
123 mQueue.stop();
124 }
125
126 reset();
127
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800128 if (mVideoRenderer) {
129 mNativeWindowRenderer->destroyRenderInput(mVideoRenderer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800130 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800131}
132
133void PreviewPlayer::cancelPlayerEvents(bool keepBufferingGoing) {
134 mQueue.cancelEvent(mVideoEvent->eventID());
135 mVideoEventPending = false;
136 mQueue.cancelEvent(mStreamDoneEvent->eventID());
137 mStreamDoneEventPending = false;
138 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
139 mAudioStatusEventPending = false;
140
141 mQueue.cancelEvent(mProgressCbEvent->eventID());
142 mProgressCbEventPending = false;
143}
144
145status_t PreviewPlayer::setDataSource(
146 const char *uri, const KeyedVector<String8, String8> *headers) {
147 Mutex::Autolock autoLock(mLock);
148 return setDataSource_l(uri, headers);
149}
150
151status_t PreviewPlayer::setDataSource_l(
152 const char *uri, const KeyedVector<String8, String8> *headers) {
153 reset_l();
154
155 mUri = uri;
156
157 if (headers) {
158 mUriHeaders = *headers;
159 }
160
161 // The actual work will be done during preparation in the call to
162 // ::finishSetDataSource_l to avoid blocking the calling thread in
163 // setDataSource for any significant time.
164 return OK;
165}
166
167status_t PreviewPlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
168 bool haveAudio = false;
169 bool haveVideo = false;
170 for (size_t i = 0; i < extractor->countTracks(); ++i) {
171 sp<MetaData> meta = extractor->getTrackMetaData(i);
172
173 const char *mime;
174 CHECK(meta->findCString(kKeyMIMEType, &mime));
175
176 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
177 setVideoSource(extractor->getTrack(i));
178 haveVideo = true;
179 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
180 setAudioSource(extractor->getTrack(i));
181 haveAudio = true;
182
183 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
184 // Only do this for vorbis audio, none of the other audio
185 // formats even support this ringtone specific hack and
186 // retrieving the metadata on some extractors may turn out
187 // to be very expensive.
188 sp<MetaData> fileMeta = extractor->getMetaData();
189 int32_t loop;
190 if (fileMeta != NULL
191 && fileMeta->findInt32(kKeyAutoLoop, &loop)
192 && loop != 0) {
193 mFlags |= AUTO_LOOPING;
194 }
195 }
196 }
197
198 if (haveAudio && haveVideo) {
199 break;
200 }
201 }
202
203 /* Add the support for Dummy audio*/
204 if( !haveAudio ){
205 LOGV("PreviewPlayer: setDataSource_l Dummyaudiocreation started");
206
207 mAudioTrack = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700208 ((mPlayEndTimeMsec)*1000LL));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800209 LOGV("PreviewPlayer: setDataSource_l Dummyauiosource created");
210 if(mAudioTrack != NULL) {
211 haveAudio = true;
212 }
213 }
214
215 if (!haveAudio && !haveVideo) {
216 return UNKNOWN_ERROR;
217 }
218
219 mExtractorFlags = extractor->flags();
220 return OK;
221}
222
223status_t PreviewPlayer::setDataSource_l_jpg() {
224 M4OSA_ERR err = M4NO_ERROR;
225 LOGV("PreviewPlayer: setDataSource_l_jpg started");
226
227 mAudioSource = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700228 ((mPlayEndTimeMsec)*1000LL));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800229 LOGV("PreviewPlayer: setDataSource_l_jpg Dummyaudiosource created");
230 if(mAudioSource != NULL) {
231 setAudioSource(mAudioSource);
232 }
233 status_t error = mAudioSource->start();
234 if (error != OK) {
235 LOGV("Error starting dummy audio source");
236 mAudioSource.clear();
237 return err;
238 }
239
Raghavender Pallaebf40152011-03-14 20:15:12 -0700240 mDurationUs = (mPlayEndTimeMsec - mPlayBeginTimeMsec)*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800241
242 mVideoSource = DummyVideoSource::Create(mVideoWidth, mVideoHeight,
243 mDurationUs, mUri);
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800244
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800245 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800246 setVideoSource(mVideoSource);
247 status_t err1 = mVideoSource->start();
248 if (err1 != OK) {
249 mVideoSource.clear();
250 return err;
251 }
252
253 mIsVideoSourceJpg = true;
254 return OK;
255}
256
257void PreviewPlayer::reset() {
258 Mutex::Autolock autoLock(mLock);
259 reset_l();
260}
261
262void PreviewPlayer::reset_l() {
263
264 if (mFlags & PREPARING) {
265 mFlags |= PREPARE_CANCELLED;
266 }
267
268 while (mFlags & PREPARING) {
269 mPreparedCondition.wait(mLock);
270 }
271
272 cancelPlayerEvents();
273 mAudioTrack.clear();
274 mVideoTrack.clear();
275
276 // Shutdown audio first, so that the respone to the reset request
277 // appears to happen instantaneously as far as the user is concerned
278 // If we did this later, audio would continue playing while we
279 // shutdown the video-related resources and the player appear to
280 // not be as responsive to a reset request.
281 if (mAudioPlayer == NULL && mAudioSource != NULL) {
282 // If we had an audio player, it would have effectively
283 // taken possession of the audio source and stopped it when
284 // _it_ is stopped. Otherwise this is still our responsibility.
285 mAudioSource->stop();
286 }
287 mAudioSource.clear();
288
289 mTimeSource = NULL;
290
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800291 //Single audio player instance used
292 //So donot delete it here
293 //It is deleted from PreviewController class
294 //delete mAudioPlayer;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800295 mAudioPlayer = NULL;
296
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800297 if (mVideoBuffer) {
298 mVideoBuffer->release();
299 mVideoBuffer = NULL;
300 }
301
302 if (mVideoSource != NULL) {
303 mVideoSource->stop();
304
305 // The following hack is necessary to ensure that the OMX
306 // component is completely released by the time we may try
307 // to instantiate it again.
308 wp<MediaSource> tmp = mVideoSource;
309 mVideoSource.clear();
310 while (tmp.promote() != NULL) {
311 usleep(1000);
312 }
313 IPCThreadState::self()->flushCommands();
314 }
315
316 mDurationUs = -1;
317 mFlags = 0;
318 mExtractorFlags = 0;
319 mVideoWidth = mVideoHeight = -1;
320 mTimeSourceDeltaUs = 0;
321 mVideoTimeUs = 0;
322
Andreas Hubera5872f72011-02-24 15:25:21 -0800323 mSeeking = NO_SEEK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800324 mSeekNotificationSent = false;
325 mSeekTimeUs = 0;
326
327 mUri.setTo("");
328 mUriHeaders.clear();
329
330 mFileSource.clear();
331
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800332 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
333 mIsVideoSourceJpg = false;
334 mFrameRGBBuffer = NULL;
335 if(mFrameYUVBuffer != NULL) {
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700336 free(mFrameYUVBuffer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800337 mFrameYUVBuffer = NULL;
338 }
339}
340
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800341status_t PreviewPlayer::play() {
342 Mutex::Autolock autoLock(mLock);
343
344 mFlags &= ~CACHE_UNDERRUN;
Hong Tenge0180232011-09-28 18:40:38 -0700345 mFlags &= ~INFORMED_AV_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800346 return play_l();
347}
348
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800349status_t PreviewPlayer::startAudioPlayer_l() {
350 CHECK(!(mFlags & AUDIO_RUNNING));
351
352 if (mAudioSource == NULL || mAudioPlayer == NULL) {
353 return OK;
354 }
355
356 if (!(mFlags & AUDIOPLAYER_STARTED)) {
357 mFlags |= AUDIOPLAYER_STARTED;
358
359 // We've already started the MediaSource in order to enable
360 // the prefetcher to read its data.
361 status_t err = mVeAudioPlayer->start(
362 true /* sourceAlreadyStarted */);
363
364 if (err != OK) {
365 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
366 return err;
367 }
368 } else {
369 mVeAudioPlayer->resume();
370 }
371
372 mFlags |= AUDIO_RUNNING;
373
374 mWatchForAudioEOS = true;
375
376 return OK;
377}
378
James Dongc9dedc42011-05-01 12:36:22 -0700379status_t PreviewPlayer::setAudioPlayer(AudioPlayerBase *audioPlayer) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800380 Mutex::Autolock autoLock(mLock);
381 CHECK(!(mFlags & PLAYING));
382 mAudioPlayer = audioPlayer;
383
384 LOGV("SetAudioPlayer");
385 mIsChangeSourceRequired = true;
386 mVeAudioPlayer =
387 (VideoEditorAudioPlayer*)mAudioPlayer;
388
389 // check if the new and old source are dummy
390 sp<MediaSource> anAudioSource = mVeAudioPlayer->getSource();
391 if (anAudioSource == NULL) {
392 // Audio player does not have any source set.
393 LOGV("setAudioPlayer: Audio player does not have any source set");
394 return OK;
395 }
396
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800397 // If new video source is not dummy, then always change source
398 // Else audio player continues using old audio source and there are
399 // frame drops to maintain AV sync
400 sp<MetaData> meta;
401 if (mVideoSource != NULL) {
402 meta = mVideoSource->getFormat();
403 const char *pVidSrcType;
404 if (meta->findCString(kKeyDecoderComponent, &pVidSrcType)) {
405 if (strcmp(pVidSrcType, "DummyVideoSource") != 0) {
406 LOGV(" Video clip with silent audio; need to change source");
407 return OK;
408 }
409 }
410 }
411
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800412 const char *pSrcType1;
413 const char *pSrcType2;
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800414 meta = anAudioSource->getFormat();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800415
416 if (meta->findCString(kKeyDecoderComponent, &pSrcType1)) {
417 if (strcmp(pSrcType1, "DummyAudioSource") == 0) {
418 meta = mAudioSource->getFormat();
419 if (meta->findCString(kKeyDecoderComponent, &pSrcType2)) {
420 if (strcmp(pSrcType2, "DummyAudioSource") == 0) {
421 mIsChangeSourceRequired = false;
422 // Just set the new play duration for the existing source
423 MediaSource *pMediaSrc = anAudioSource.get();
424 DummyAudioSource *pDummyAudioSource = (DummyAudioSource*)pMediaSrc;
425 //Increment the duration of audio source
Raghavender Pallaebf40152011-03-14 20:15:12 -0700426 pDummyAudioSource->setDuration(
427 (int64_t)((mPlayEndTimeMsec)*1000LL));
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800428
429 // Stop the new audio source
430 // since we continue using old source
431 LOGV("setAudioPlayer: stop new audio source");
432 mAudioSource->stop();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800433 }
434 }
435 }
436 }
437
438 return OK;
439}
440
441void PreviewPlayer::onStreamDone() {
442 // Posted whenever any stream finishes playing.
443
444 Mutex::Autolock autoLock(mLock);
445 if (!mStreamDoneEventPending) {
446 return;
447 }
448 mStreamDoneEventPending = false;
449
450 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
451 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
452
453 notifyListener_l(
454 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
455
456 pause_l(true /* at eos */);
457
458 mFlags |= AT_EOS;
459 return;
460 }
461
462 const bool allDone =
463 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
464 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
465
466 if (!allDone) {
467 return;
468 }
469
470 if (mFlags & (LOOPING | AUTO_LOOPING)) {
471 seekTo_l(0);
472
473 if (mVideoSource != NULL) {
474 postVideoEvent_l();
475 }
476 } else {
477 LOGV("MEDIA_PLAYBACK_COMPLETE");
478 //pause before sending event
479 pause_l(true /* at eos */);
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700480
481 //This lock is used to syncronize onStreamDone() in PreviewPlayer and
482 //stopPreview() in PreviewController
483 Mutex::Autolock autoLock(mLockControl);
Hong Tenge0180232011-09-28 18:40:38 -0700484 /* Make sure PreviewPlayer only notifies MEDIA_PLAYBACK_COMPLETE once for each clip!
485 * It happens twice in following scenario.
486 * To make the clips in preview storyboard are played and switched smoothly,
487 * PreviewController uses two PreviewPlayer instances and one AudioPlayer.
488 * The two PreviewPlayer use the same AudioPlayer to play the audio,
489 * and change the audio source of the AudioPlayer.
490 * If the audio source of current playing clip and next clip are dummy
491 * audio source(image or video without audio), it will not change the audio source
492 * to avoid the "audio glitch", and keep using the current audio source.
493 * When the video of current clip reached the EOS, PreviewPlayer will set EOS flag
494 * for video and audio, and it will notify MEDIA_PLAYBACK_COMPLETE.
495 * But the audio(dummy audio source) is still playing(for next clip),
496 * and when it reached the EOS, and video reached EOS,
497 * PreviewPlayer will notify MEDIA_PLAYBACK_COMPLETE again. */
498 if (!(mFlags & INFORMED_AV_EOS)) {
499 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
500 mFlags |= INFORMED_AV_EOS;
501 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800502 mFlags |= AT_EOS;
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700503 LOGV("onStreamDone end");
504 return;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800505 }
506}
507
508
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800509status_t PreviewPlayer::play_l() {
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800510
Rajneesh Chowdury8b95de22011-02-16 15:32:06 -0800511 mFlags &= ~SEEK_PREVIEW;
512
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800513 if (mFlags & PLAYING) {
514 return OK;
515 }
516 mStartNextPlayer = false;
517
518 if (!(mFlags & PREPARED)) {
519 status_t err = prepare_l();
520
521 if (err != OK) {
522 return err;
523 }
524 }
525
526 mFlags |= PLAYING;
527 mFlags |= FIRST_FRAME;
528
529 bool deferredAudioSeek = false;
530
531 if (mAudioSource != NULL) {
532 if (mAudioPlayer == NULL) {
533 if (mAudioSink != NULL) {
534
535 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800536 mVeAudioPlayer =
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800537 (VideoEditorAudioPlayer*)mAudioPlayer;
538
539 mAudioPlayer->setSource(mAudioSource);
540
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800541 mVeAudioPlayer->setAudioMixSettings(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800542 mPreviewPlayerAudioMixSettings);
543
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800544 mVeAudioPlayer->setAudioMixPCMFileHandle(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800545 mAudioMixPCMFileHandle);
546
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800547 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800548 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
549 mCurrentMediaVolumeValue);
550
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800551 mFlags |= AUDIOPLAYER_STARTED;
552 // We've already started the MediaSource in order to enable
553 // the prefetcher to read its data.
554 status_t err = mVeAudioPlayer->start(
555 true /* sourceAlreadyStarted */);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800556
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800557 if (err != OK) {
558 //delete mAudioPlayer;
559 mAudioPlayer = NULL;
560
561 mFlags &= ~(PLAYING | FIRST_FRAME);
562 return err;
563 }
564
565 mTimeSource = mVeAudioPlayer;
566 mFlags |= AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800567 deferredAudioSeek = true;
568 mWatchForAudioSeekComplete = false;
569 mWatchForAudioEOS = true;
570 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800571 } else {
572 mVeAudioPlayer = (VideoEditorAudioPlayer*)mAudioPlayer;
573 bool isAudioPlayerStarted = mVeAudioPlayer->isStarted();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800574
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800575 if (mIsChangeSourceRequired == true) {
576 LOGV("play_l: Change audio source required");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800577
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800578 if (isAudioPlayerStarted == true) {
579 mVeAudioPlayer->pause();
580 }
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800581
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800582 mVeAudioPlayer->setSource(mAudioSource);
583 mVeAudioPlayer->setObserver(this);
584
585 mVeAudioPlayer->setAudioMixSettings(
586 mPreviewPlayerAudioMixSettings);
587
588 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
589 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
590 mCurrentMediaVolumeValue);
591
592 if (isAudioPlayerStarted == true) {
593 mVeAudioPlayer->resume();
594 } else {
595 status_t err = OK;
596 err = mVeAudioPlayer->start(true);
597 if (err != OK) {
598 mAudioPlayer = NULL;
599 mVeAudioPlayer = NULL;
600
601 mFlags &= ~(PLAYING | FIRST_FRAME);
602 return err;
603 }
604 }
605 } else {
606 LOGV("play_l: No Source change required");
607 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
608 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
609 mCurrentMediaVolumeValue);
610
611 mVeAudioPlayer->resume();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800612 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800613
614 mFlags |= AUDIOPLAYER_STARTED;
615 mFlags |= AUDIO_RUNNING;
616 mTimeSource = mVeAudioPlayer;
617 deferredAudioSeek = true;
618 mWatchForAudioSeekComplete = false;
619 mWatchForAudioEOS = true;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800620 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800621 }
622
623 if (mTimeSource == NULL && mAudioPlayer == NULL) {
624 mTimeSource = &mSystemTimeSource;
625 }
626
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800627 // Set the seek option for Image source files and read.
628 // This resets the timestamping for image play
629 if (mIsVideoSourceJpg) {
630 MediaSource::ReadOptions options;
631 MediaBuffer *aLocalBuffer;
632 options.setSeekTo(mSeekTimeUs);
633 mVideoSource->read(&aLocalBuffer, &options);
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800634 aLocalBuffer->release();
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800635 }
636
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800637 if (mVideoSource != NULL) {
638 // Kick off video playback
639 postVideoEvent_l();
640 }
641
642 if (deferredAudioSeek) {
643 // If there was a seek request while we were paused
644 // and we're just starting up again, honor the request now.
645 seekAudioIfNecessary_l();
646 }
647
648 if (mFlags & AT_EOS) {
649 // Legacy behaviour, if a stream finishes playing and then
650 // is started again, we play from the start...
651 seekTo_l(0);
652 }
653
654 return OK;
655}
656
657
Santosh Madhavabfece172011-02-03 16:59:47 -0800658status_t PreviewPlayer::initRenderer_l() {
Mathias Agopian6e224292011-04-05 15:38:24 -0700659 if (mSurface != NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800660 if(mVideoRenderer == NULL) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800661 mVideoRenderer = mNativeWindowRenderer->createRenderInput();
662 if (mVideoSource != NULL) {
663 updateSizeToRender(mVideoSource->getFormat());
Santosh Madhavabfece172011-02-03 16:59:47 -0800664 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800665 }
666 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800667 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800668}
669
670
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800671status_t PreviewPlayer::seekTo(int64_t timeUs) {
672
673 if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) {
674 Mutex::Autolock autoLock(mLock);
675 return seekTo_l(timeUs);
676 }
677
678 return OK;
679}
680
681
682status_t PreviewPlayer::getVideoDimensions(
683 int32_t *width, int32_t *height) const {
684 Mutex::Autolock autoLock(mLock);
685
686 if (mVideoWidth < 0 || mVideoHeight < 0) {
687 return UNKNOWN_ERROR;
688 }
689
690 *width = mVideoWidth;
691 *height = mVideoHeight;
692
693 return OK;
694}
695
696
697status_t PreviewPlayer::initAudioDecoder() {
698 sp<MetaData> meta = mAudioTrack->getFormat();
699 const char *mime;
700 CHECK(meta->findCString(kKeyMIMEType, &mime));
701
702 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
703 mAudioSource = mAudioTrack;
704 } else {
705 sp<MediaSource> aRawSource;
706 aRawSource = OMXCodec::Create(
707 mClient.interface(), mAudioTrack->getFormat(),
708 false, // createEncoder
709 mAudioTrack);
710
711 if(aRawSource != NULL) {
712 LOGV("initAudioDecoder: new VideoEditorSRC");
713 mAudioSource = new VideoEditorSRC(aRawSource);
714 }
715 }
716
717 if (mAudioSource != NULL) {
718 int64_t durationUs;
719 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
720 Mutex::Autolock autoLock(mMiscStateLock);
721 if (mDurationUs < 0 || durationUs > mDurationUs) {
722 mDurationUs = durationUs;
723 }
724 }
725 status_t err = mAudioSource->start();
726
727 if (err != OK) {
728 mAudioSource.clear();
729 return err;
730 }
731 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
732 // For legacy reasons we're simply going to ignore the absence
733 // of an audio decoder for QCELP instead of aborting playback
734 // altogether.
735 return OK;
736 }
737
738 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
739}
740
741
742status_t PreviewPlayer::initVideoDecoder(uint32_t flags) {
743
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800744 initRenderer_l();
745
746 if (mVideoRenderer == NULL) {
747 LOGE("Cannot create renderer");
748 return UNKNOWN_ERROR;
749 }
750
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800751 mVideoSource = OMXCodec::Create(
752 mClient.interface(), mVideoTrack->getFormat(),
753 false,
754 mVideoTrack,
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800755 NULL, flags, mVideoRenderer->getTargetWindow());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800756
757 if (mVideoSource != NULL) {
758 int64_t durationUs;
759 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
760 Mutex::Autolock autoLock(mMiscStateLock);
761 if (mDurationUs < 0 || durationUs > mDurationUs) {
762 mDurationUs = durationUs;
763 }
764 }
765
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800766 updateSizeToRender(mVideoTrack->getFormat());
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800767
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800768 status_t err = mVideoSource->start();
769
770 if (err != OK) {
771 mVideoSource.clear();
772 return err;
773 }
774 }
775
776 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
777}
778
779
780void PreviewPlayer::onVideoEvent() {
781 uint32_t i=0;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800782 M4OSA_ERR err1 = M4NO_ERROR;
783 int64_t imageFrameTimeUs = 0;
784
785 Mutex::Autolock autoLock(mLock);
786 if (!mVideoEventPending) {
787 // The event has been cancelled in reset_l() but had already
788 // been scheduled for execution at that time.
789 return;
790 }
791 mVideoEventPending = false;
792
Andreas Huber9e4c36a2011-02-08 13:12:32 -0800793 if (mFlags & SEEK_PREVIEW) {
794 mFlags &= ~SEEK_PREVIEW;
795 return;
796 }
797
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800798 TimeSource *ts_st = &mSystemTimeSource;
799 int64_t timeStartUs = ts_st->getRealTimeUs();
800
Andreas Hubera5872f72011-02-24 15:25:21 -0800801 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800802
803 if(mAudioSource != NULL) {
804
805 // We're going to seek the video source first, followed by
806 // the audio source.
807 // In order to avoid jumps in the DataSource offset caused by
808 // the audio codec prefetching data from the old locations
809 // while the video codec is already reading data from the new
810 // locations, we'll "pause" the audio source, causing it to
811 // stop reading input data until a subsequent seek.
812
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800813 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800814 mAudioPlayer->pause();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800815 mFlags &= ~AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800816 }
817 mAudioSource->pause();
818 }
819 }
820
821 if (!mVideoBuffer) {
822 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -0800823 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800824 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
825 mSeekTimeUs / 1E6);
826
827 options.setSeekTo(
828 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
829 }
830 for (;;) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800831 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800832 options.clearSeekTo();
833
834 if (err != OK) {
835 CHECK_EQ(mVideoBuffer, NULL);
836
837 if (err == INFO_FORMAT_CHANGED) {
838 LOGV("LV PLAYER VideoSource signalled format change");
839 notifyVideoSize_l();
840
841 if (mVideoRenderer != NULL) {
842 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -0800843 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800844 if (err != OK) {
845 postStreamDoneEvent_l(err);
846 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800847
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800848 }
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800849
850 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800851 continue;
852 }
853 // So video playback is complete, but we may still have
Santosh Madhava342f9322011-01-27 16:27:12 -0800854 // a seek request pending that needs to be applied to the audio track
Andreas Hubera5872f72011-02-24 15:25:21 -0800855 if (mSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800856 LOGV("video stream ended while seeking!");
857 }
858 finishSeekIfNecessary(-1);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800859 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
860 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800861 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800862 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800863 postStreamDoneEvent_l(err);
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800864 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -0700865 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800866 return;
867 }
868
869 if (mVideoBuffer->range_length() == 0) {
870 // Some decoders, notably the PV AVC software decoder
871 // return spurious empty buffers that we just want to ignore.
872
873 mVideoBuffer->release();
874 mVideoBuffer = NULL;
875 continue;
876 }
877
878 int64_t videoTimeUs;
879 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
880
Andreas Hubera5872f72011-02-24 15:25:21 -0800881 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800882 if (videoTimeUs < mSeekTimeUs) {
883 // buffers are before seek time
884 // ignore them
885 mVideoBuffer->release();
886 mVideoBuffer = NULL;
887 continue;
888 }
889 } else {
890 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
891 // Frames are before begin cut time
892 // Donot render
893 mVideoBuffer->release();
894 mVideoBuffer = NULL;
895 continue;
896 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800897 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800898 break;
899 }
900 }
901
902 mNumberDecVideoFrames++;
903
904 int64_t timeUs;
905 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
906
907 {
908 Mutex::Autolock autoLock(mMiscStateLock);
909 mVideoTimeUs = timeUs;
910 }
911
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800912
913 if(!mStartNextPlayer) {
Raghavender Pallaebf40152011-03-14 20:15:12 -0700914 int64_t playbackTimeRemaining = (mPlayEndTimeMsec*1000LL) - timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800915 if(playbackTimeRemaining <= 1500000) {
916 //When less than 1.5 sec of playback left
917 // send notification to start next player
918
919 mStartNextPlayer = true;
920 notifyListener_l(0xAAAAAAAA);
921 }
922 }
923
Andreas Hubera5872f72011-02-24 15:25:21 -0800924 SeekType wasSeeking = mSeeking;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800925 finishSeekIfNecessary(timeUs);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800926 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING))) {
927 status_t err = startAudioPlayer_l();
928 if (err != OK) {
929 LOGE("Starting the audio player failed w/ err %d", err);
930 return;
931 }
932 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800933
934 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
935
936 if(ts == NULL) {
937 mVideoBuffer->release();
938 mVideoBuffer = NULL;
939 return;
940 }
941
942 if(!mIsVideoSourceJpg) {
943 if (mFlags & FIRST_FRAME) {
944 mFlags &= ~FIRST_FRAME;
945
946 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
947 }
948
949 int64_t realTimeUs, mediaTimeUs;
950 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
951 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
952 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
953 }
954
955 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
956
957 int64_t latenessUs = nowUs - timeUs;
958
Andreas Hubera5872f72011-02-24 15:25:21 -0800959 if (wasSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800960 // Let's display the first frame after seeking right away.
961 latenessUs = 0;
962 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800963 LOGV("Audio time stamp = %lld and video time stamp = %lld",
964 ts->getRealTimeUs(),timeUs);
965 if (latenessUs > 40000) {
966 // We're more than 40ms late.
967
968 LOGV("LV PLAYER we're late by %lld us (%.2f secs)",
969 latenessUs, latenessUs / 1E6);
970
971 mVideoBuffer->release();
972 mVideoBuffer = NULL;
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800973 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800974 return;
975 }
976
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800977 if (latenessUs < -25000) {
978 // We're more than 25ms early.
979 LOGV("We're more than 25ms early, lateness %lld", latenessUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800980
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800981 postVideoEvent_l(25000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800982 return;
983 }
984 }
985
986 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
987 mVideoRendererIsPreview = false;
988
Santosh Madhavabfece172011-02-03 16:59:47 -0800989 status_t err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800990 if (err != OK) {
991 postStreamDoneEvent_l(err);
992 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800993 }
994
995 // If timestamp exceeds endCutTime of clip, donot render
996 if((timeUs/1000) > mPlayEndTimeMsec) {
Chih-Chung Changcece4b32011-08-01 16:34:05 +0800997 mVideoBuffer->release();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800998 mVideoBuffer = NULL;
999 mFlags |= VIDEO_AT_EOS;
1000 mFlags |= AUDIO_AT_EOS;
Santosh Madhavabfece172011-02-03 16:59:47 -08001001 LOGV("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS..");
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001002 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001003 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001004 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001005 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1006 return;
1007 }
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001008 // Capture the frame timestamp to be rendered
1009 mDecodedVideoTs = timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001010
1011 // Post processing to apply video effects
1012 for(i=0;i<mNumberEffects;i++) {
1013 // First check if effect starttime matches the clip being previewed
1014 if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) ||
1015 (mEffectsSettings[i].uiStartTime >=
1016 ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec)))
1017 {
1018 // This effect doesn't belong to this clip, check next one
1019 continue;
1020 }
1021 // Check if effect applies to this particular frame timestamp
1022 if((mEffectsSettings[i].uiStartTime <=
1023 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) &&
1024 ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=
1025 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec))
1026 && (mEffectsSettings[i].uiDuration != 0)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001027 setVideoPostProcessingNode(
1028 mEffectsSettings[i].VideoEffectType, TRUE);
1029 }
1030 else {
1031 setVideoPostProcessingNode(
1032 mEffectsSettings[i].VideoEffectType, FALSE);
1033 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001034 }
1035
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001036 //Provide the overlay Update indication when there is an overlay effect
Dharmaray Kundargid01ef562011-01-26 21:11:00 -08001037 if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) {
1038 mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here.
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001039 if (!mOverlayUpdateEventPosted) {
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001040 // Find the effect in effectSettings array
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001041 M4OSA_UInt32 index;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001042 for (index = 0; index < mNumberEffects; index++) {
1043 M4OSA_UInt32 timeMs = mDecodedVideoTs/1000;
1044 M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000;
1045 if(mEffectsSettings[index].VideoEffectType ==
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001046 (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001047 if (((mEffectsSettings[index].uiStartTime + 1) <=
1048 timeMs + timeOffset - mPlayBeginTimeMsec) &&
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001049 ((mEffectsSettings[index].uiStartTime - 1 +
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001050 mEffectsSettings[index].uiDuration) >=
1051 timeMs + timeOffset - mPlayBeginTimeMsec))
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001052 {
1053 break;
1054 }
1055 }
1056 }
1057 if (index < mNumberEffects) {
1058 mCurrFramingEffectIndex = index;
1059 mOverlayUpdateEventPosted = true;
1060 postOverlayUpdateEvent_l();
1061 LOGV("Framing index = %d", mCurrFramingEffectIndex);
1062 } else {
1063 LOGV("No framing effects found");
1064 }
1065 }
1066
1067 } else if (mOverlayUpdateEventPosted) {
1068 //Post the event when the overlay is no more valid
1069 LOGV("Overlay is Done");
1070 mOverlayUpdateEventPosted = false;
1071 postOverlayUpdateEvent_l();
1072 }
1073
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001074 if (mVideoRenderer != NULL) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001075 mVideoRenderer->render(mVideoBuffer, mCurrentVideoEffect,
1076 mRenderingMode, mIsVideoSourceJpg);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001077 }
1078
Chih-Chung Changcece4b32011-08-01 16:34:05 +08001079 mVideoBuffer->release();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001080 mVideoBuffer = NULL;
1081
1082 // Post progress callback based on callback interval set
1083 if(mNumberDecVideoFrames >= mProgressCbInterval) {
1084 postProgressCallbackEvent_l();
1085 mNumberDecVideoFrames = 0; // reset counter
1086 }
1087
1088 // if reached EndCutTime of clip, post EOS event
1089 if((timeUs/1000) >= mPlayEndTimeMsec) {
1090 LOGV("PreviewPlayer: onVideoEvent EOS.");
1091 mFlags |= VIDEO_AT_EOS;
1092 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001093 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001094 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001095 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001096 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1097 }
1098 else {
Andreas Hubera5872f72011-02-24 15:25:21 -08001099 if ((wasSeeking != NO_SEEK) && (mFlags & SEEK_PREVIEW)) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001100 mFlags &= ~SEEK_PREVIEW;
1101 return;
1102 }
1103
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001104 if(!mIsVideoSourceJpg) {
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001105 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001106 }
1107 else {
1108 postVideoEvent_l(33000);
1109 }
1110 }
1111}
1112
1113status_t PreviewPlayer::prepare() {
1114 Mutex::Autolock autoLock(mLock);
1115 return prepare_l();
1116}
1117
1118status_t PreviewPlayer::prepare_l() {
1119 if (mFlags & PREPARED) {
1120 return OK;
1121 }
1122
1123 if (mFlags & PREPARING) {
1124 return UNKNOWN_ERROR;
1125 }
1126
1127 mIsAsyncPrepare = false;
1128 status_t err = prepareAsync_l();
1129
1130 if (err != OK) {
1131 return err;
1132 }
1133
1134 while (mFlags & PREPARING) {
1135 mPreparedCondition.wait(mLock);
1136 }
1137
1138 return mPrepareResult;
1139}
1140
1141status_t PreviewPlayer::prepareAsync_l() {
1142 if (mFlags & PREPARING) {
1143 return UNKNOWN_ERROR; // async prepare already pending
1144 }
1145
1146 if (!mQueueStarted) {
1147 mQueue.start();
1148 mQueueStarted = true;
1149 }
1150
1151 mFlags |= PREPARING;
1152 mAsyncPrepareEvent = new PreviewPlayerEvent(
1153 this, &PreviewPlayer::onPrepareAsyncEvent);
1154
1155 mQueue.postEvent(mAsyncPrepareEvent);
1156
1157 return OK;
1158}
1159
1160status_t PreviewPlayer::finishSetDataSource_l() {
1161 sp<DataSource> dataSource;
1162 sp<MediaExtractor> extractor;
1163
1164 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1165
1166 if (dataSource == NULL) {
1167 return UNKNOWN_ERROR;
1168 }
1169
1170 //If file type is .rgb, then no need to check for Extractor
1171 int uriLen = strlen(mUri);
1172 int startOffset = uriLen - 4;
1173 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) {
1174 extractor = NULL;
1175 }
1176 else {
1177 extractor = MediaExtractor::Create(dataSource,
1178 MEDIA_MIMETYPE_CONTAINER_MPEG4);
1179 }
1180
1181 if (extractor == NULL) {
1182 LOGV("PreviewPlayer::finishSetDataSource_l extractor == NULL");
1183 return setDataSource_l_jpg();
1184 }
1185
1186 return setDataSource_l(extractor);
1187}
1188
1189
1190// static
1191bool PreviewPlayer::ContinuePreparation(void *cookie) {
1192 PreviewPlayer *me = static_cast<PreviewPlayer *>(cookie);
1193
1194 return (me->mFlags & PREPARE_CANCELLED) == 0;
1195}
1196
1197void PreviewPlayer::onPrepareAsyncEvent() {
1198 Mutex::Autolock autoLock(mLock);
1199 LOGV("onPrepareAsyncEvent");
1200
1201 if (mFlags & PREPARE_CANCELLED) {
Santosh Madhavabfece172011-02-03 16:59:47 -08001202 LOGV("LV PLAYER prepare was cancelled before doing anything");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001203 abortPrepare(UNKNOWN_ERROR);
1204 return;
1205 }
1206
1207 if (mUri.size() > 0) {
1208 status_t err = finishSetDataSource_l();
1209
1210 if (err != OK) {
1211 abortPrepare(err);
1212 return;
1213 }
1214 }
1215
1216 if (mVideoTrack != NULL && mVideoSource == NULL) {
1217 status_t err = initVideoDecoder(OMXCodec::kHardwareCodecsOnly);
1218
1219 if (err != OK) {
1220 abortPrepare(err);
1221 return;
1222 }
1223 }
1224
1225 if (mAudioTrack != NULL && mAudioSource == NULL) {
1226 status_t err = initAudioDecoder();
1227
1228 if (err != OK) {
1229 abortPrepare(err);
1230 return;
1231 }
1232 }
1233 finishAsyncPrepare_l();
1234
1235}
1236
1237void PreviewPlayer::finishAsyncPrepare_l() {
1238 if (mIsAsyncPrepare) {
1239 if (mVideoSource == NULL) {
1240 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE 0 0 ");
1241 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1242 } else {
1243 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE");
1244 notifyVideoSize_l();
1245 }
1246 LOGV("finishAsyncPrepare_l: MEDIA_PREPARED");
1247 notifyListener_l(MEDIA_PREPARED);
1248 }
1249
1250 mPrepareResult = OK;
1251 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1252 mFlags |= PREPARED;
1253 mAsyncPrepareEvent = NULL;
1254 mPreparedCondition.broadcast();
1255}
1256
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001257void PreviewPlayer::acquireLock() {
1258 LOGV("acquireLock");
1259 mLockControl.lock();
1260}
1261
1262void PreviewPlayer::releaseLock() {
1263 LOGV("releaseLock");
1264 mLockControl.unlock();
1265}
1266
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001267status_t PreviewPlayer::loadEffectsSettings(
1268 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) {
1269 M4OSA_UInt32 i = 0, rgbSize = 0;
1270 M4VIFI_UInt8 *tmp = M4OSA_NULL;
1271
1272 mNumberEffects = nEffects;
1273 mEffectsSettings = pEffectSettings;
1274 return OK;
1275}
1276
1277status_t PreviewPlayer::loadAudioMixSettings(
1278 M4xVSS_AudioMixingSettings* pAudioMixSettings) {
1279
1280 LOGV("PreviewPlayer: loadAudioMixSettings: ");
1281 mPreviewPlayerAudioMixSettings = pAudioMixSettings;
1282 return OK;
1283}
1284
1285status_t PreviewPlayer::setAudioMixPCMFileHandle(
1286 M4OSA_Context pAudioMixPCMFileHandle) {
1287
1288 LOGV("PreviewPlayer: setAudioMixPCMFileHandle: ");
1289 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle;
1290 return OK;
1291}
1292
1293status_t PreviewPlayer::setAudioMixStoryBoardParam(
1294 M4OSA_UInt32 audioMixStoryBoardTS,
1295 M4OSA_UInt32 currentMediaBeginCutTime,
1296 M4OSA_UInt32 primaryTrackVolValue ) {
1297
1298 mAudioMixStoryBoardTS = audioMixStoryBoardTS;
1299 mCurrentMediaBeginCutTime = currentMediaBeginCutTime;
1300 mCurrentMediaVolumeValue = primaryTrackVolValue;
1301 return OK;
1302}
1303
1304status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) {
1305
1306 mPlayBeginTimeMsec = msec;
1307 return OK;
1308}
1309
1310status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) {
1311
1312 mPlayEndTimeMsec = msec;
1313 return OK;
1314}
1315
1316status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) {
1317
1318 mStoryboardStartTimeMsec = msec;
Raghavender Pallaebf40152011-03-14 20:15:12 -07001319 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001320 return OK;
1321}
1322
1323status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) {
1324
1325 mProgressCbInterval = cbInterval;
1326 return OK;
1327}
1328
1329
1330status_t PreviewPlayer::setMediaRenderingMode(
1331 M4xVSS_MediaRendering mode,
1332 M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
1333
1334 mRenderingMode = mode;
1335
Hong Teng8806b702011-07-06 18:29:28 -07001336 status_t err = OK;
1337 /* get the video width and height by resolution */
1338 err = getVideoSizeByResolution(outputVideoSize,
1339 &mOutputVideoWidth, &mOutputVideoHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001340
Hong Teng8806b702011-07-06 18:29:28 -07001341 return err;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001342}
1343
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001344status_t PreviewPlayer::resetJniCallbackTimeStamp() {
1345
Raghavender Pallaebf40152011-03-14 20:15:12 -07001346 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001347 return OK;
1348}
1349
1350void PreviewPlayer::postProgressCallbackEvent_l() {
1351 if (mProgressCbEventPending) {
1352 return;
1353 }
1354 mProgressCbEventPending = true;
1355
1356 mQueue.postEvent(mProgressCbEvent);
1357}
1358
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001359
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001360void PreviewPlayer::onProgressCbEvent() {
1361 Mutex::Autolock autoLock(mLock);
1362 if (!mProgressCbEventPending) {
1363 return;
1364 }
1365 mProgressCbEventPending = false;
1366 // If playback starts from previous I-frame,
1367 // then send frame storyboard duration
1368 if((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) {
1369 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000);
1370 }
1371 else {
1372 notifyListener_l(MEDIA_INFO, 0,
1373 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec));
1374 }
1375}
1376
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001377void PreviewPlayer::postOverlayUpdateEvent_l() {
1378 if (mOverlayUpdateEventPending) {
1379 return;
1380 }
1381 mOverlayUpdateEventPending = true;
1382 mQueue.postEvent(mOverlayUpdateEvent);
1383}
1384
1385void PreviewPlayer::onUpdateOverlayEvent() {
1386 Mutex::Autolock autoLock(mLock);
1387
1388 if (!mOverlayUpdateEventPending) {
1389 return;
1390 }
1391 mOverlayUpdateEventPending = false;
1392
1393 int updateState;
1394 if (mOverlayUpdateEventPosted) {
1395 updateState = 1;
1396 } else {
1397 updateState = 0;
1398 }
1399 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex);
1400}
1401
1402
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001403void PreviewPlayer::setVideoPostProcessingNode(
1404 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
1405
1406 uint32_t effect = VIDEO_EFFECT_NONE;
1407
1408 //Map M4VSS3GPP_VideoEffectType to local enum
1409 switch(type) {
1410 case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
1411 effect = VIDEO_EFFECT_FADEFROMBLACK;
1412 break;
1413
1414 case M4VSS3GPP_kVideoEffectType_FadeToBlack:
1415 effect = VIDEO_EFFECT_FADETOBLACK;
1416 break;
1417
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001418 case M4xVSS_kVideoEffectType_BlackAndWhite:
1419 effect = VIDEO_EFFECT_BLACKANDWHITE;
1420 break;
1421
1422 case M4xVSS_kVideoEffectType_Pink:
1423 effect = VIDEO_EFFECT_PINK;
1424 break;
1425
1426 case M4xVSS_kVideoEffectType_Green:
1427 effect = VIDEO_EFFECT_GREEN;
1428 break;
1429
1430 case M4xVSS_kVideoEffectType_Sepia:
1431 effect = VIDEO_EFFECT_SEPIA;
1432 break;
1433
1434 case M4xVSS_kVideoEffectType_Negative:
1435 effect = VIDEO_EFFECT_NEGATIVE;
1436 break;
1437
1438 case M4xVSS_kVideoEffectType_Framing:
1439 effect = VIDEO_EFFECT_FRAMING;
1440 break;
1441
1442 case M4xVSS_kVideoEffectType_Fifties:
1443 effect = VIDEO_EFFECT_FIFTIES;
1444 break;
1445
1446 case M4xVSS_kVideoEffectType_ColorRGB16:
1447 effect = VIDEO_EFFECT_COLOR_RGB16;
1448 break;
1449
1450 case M4xVSS_kVideoEffectType_Gradient:
1451 effect = VIDEO_EFFECT_GRADIENT;
1452 break;
1453
1454 default:
1455 effect = VIDEO_EFFECT_NONE;
1456 break;
1457 }
1458
1459 if(enable == M4OSA_TRUE) {
1460 //If already set, then no need to set again
1461 if(!(mCurrentVideoEffect & effect)) {
1462 mCurrentVideoEffect |= effect;
1463 if(effect == VIDEO_EFFECT_FIFTIES) {
1464 mIsFiftiesEffectStarted = true;
1465 }
1466 }
1467 }
1468 else {
1469 //Reset only if already set
1470 if(mCurrentVideoEffect & effect) {
1471 mCurrentVideoEffect &= ~effect;
1472 }
1473 }
1474}
1475
1476status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) {
1477 mVideoWidth = width;
1478 mVideoHeight = height;
1479 return OK;
1480}
1481
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001482status_t PreviewPlayer::readFirstVideoFrame() {
1483 LOGV("PreviewPlayer::readFirstVideoFrame");
1484
1485 if (!mVideoBuffer) {
1486 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -08001487 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001488 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
1489 mSeekTimeUs / 1E6);
1490
1491 options.setSeekTo(
1492 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
1493 }
1494 for (;;) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001495 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001496 options.clearSeekTo();
1497
1498 if (err != OK) {
1499 CHECK_EQ(mVideoBuffer, NULL);
1500
1501 if (err == INFO_FORMAT_CHANGED) {
1502 LOGV("LV PLAYER VideoSource signalled format change");
1503 notifyVideoSize_l();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001504
1505 if (mVideoRenderer != NULL) {
1506 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -08001507 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001508 if (err != OK) {
1509 postStreamDoneEvent_l(err);
1510 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001511 }
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001512
1513 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001514 continue;
1515 }
1516 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
1517 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001518 mFlags |= AUDIO_AT_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001519 postStreamDoneEvent_l(err);
1520 return OK;
1521 }
1522
1523 if (mVideoBuffer->range_length() == 0) {
1524 // Some decoders, notably the PV AVC software decoder
1525 // return spurious empty buffers that we just want to ignore.
1526
1527 mVideoBuffer->release();
1528 mVideoBuffer = NULL;
1529 continue;
1530 }
1531
1532 int64_t videoTimeUs;
1533 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
Andreas Hubera5872f72011-02-24 15:25:21 -08001534 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001535 if (videoTimeUs < mSeekTimeUs) {
1536 // buffers are before seek time
1537 // ignore them
1538 mVideoBuffer->release();
1539 mVideoBuffer = NULL;
1540 continue;
1541 }
1542 } else {
1543 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
1544 // buffers are before begin cut time
1545 // ignore them
1546 mVideoBuffer->release();
1547 mVideoBuffer = NULL;
1548 continue;
1549 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001550 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001551 break;
1552 }
1553 }
1554
1555 int64_t timeUs;
1556 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1557
1558 {
1559 Mutex::Autolock autoLock(mMiscStateLock);
1560 mVideoTimeUs = timeUs;
1561 }
1562
1563 mDecodedVideoTs = timeUs;
1564
1565 return OK;
1566
1567}
1568
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001569status_t PreviewPlayer::getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs) {
1570 *lastRenderedTimeMs = (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec);
1571 return OK;
1572}
1573
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001574void PreviewPlayer::updateSizeToRender(sp<MetaData> meta) {
1575 if (mVideoRenderer) {
1576 mVideoRenderer->updateVideoSize(meta);
1577 }
1578}
1579
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001580} // namespace android