blob: b63d0d281365315eb6ae5a9d571d4bd5d93e8a49 [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;
345
346 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);
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800484 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
485
486 mFlags |= AT_EOS;
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700487 LOGV("onStreamDone end");
488 return;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800489 }
490}
491
492
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800493status_t PreviewPlayer::play_l() {
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800494
Rajneesh Chowdury8b95de22011-02-16 15:32:06 -0800495 mFlags &= ~SEEK_PREVIEW;
496
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800497 if (mFlags & PLAYING) {
498 return OK;
499 }
500 mStartNextPlayer = false;
501
502 if (!(mFlags & PREPARED)) {
503 status_t err = prepare_l();
504
505 if (err != OK) {
506 return err;
507 }
508 }
509
510 mFlags |= PLAYING;
511 mFlags |= FIRST_FRAME;
512
513 bool deferredAudioSeek = false;
514
515 if (mAudioSource != NULL) {
516 if (mAudioPlayer == NULL) {
517 if (mAudioSink != NULL) {
518
519 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800520 mVeAudioPlayer =
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800521 (VideoEditorAudioPlayer*)mAudioPlayer;
522
523 mAudioPlayer->setSource(mAudioSource);
524
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800525 mVeAudioPlayer->setAudioMixSettings(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800526 mPreviewPlayerAudioMixSettings);
527
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800528 mVeAudioPlayer->setAudioMixPCMFileHandle(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800529 mAudioMixPCMFileHandle);
530
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800531 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800532 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
533 mCurrentMediaVolumeValue);
534
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800535 mFlags |= AUDIOPLAYER_STARTED;
536 // We've already started the MediaSource in order to enable
537 // the prefetcher to read its data.
538 status_t err = mVeAudioPlayer->start(
539 true /* sourceAlreadyStarted */);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800540
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800541 if (err != OK) {
542 //delete mAudioPlayer;
543 mAudioPlayer = NULL;
544
545 mFlags &= ~(PLAYING | FIRST_FRAME);
546 return err;
547 }
548
549 mTimeSource = mVeAudioPlayer;
550 mFlags |= AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800551 deferredAudioSeek = true;
552 mWatchForAudioSeekComplete = false;
553 mWatchForAudioEOS = true;
554 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800555 } else {
556 mVeAudioPlayer = (VideoEditorAudioPlayer*)mAudioPlayer;
557 bool isAudioPlayerStarted = mVeAudioPlayer->isStarted();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800558
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800559 if (mIsChangeSourceRequired == true) {
560 LOGV("play_l: Change audio source required");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800561
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800562 if (isAudioPlayerStarted == true) {
563 mVeAudioPlayer->pause();
564 }
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800565
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800566 mVeAudioPlayer->setSource(mAudioSource);
567 mVeAudioPlayer->setObserver(this);
568
569 mVeAudioPlayer->setAudioMixSettings(
570 mPreviewPlayerAudioMixSettings);
571
572 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
573 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
574 mCurrentMediaVolumeValue);
575
576 if (isAudioPlayerStarted == true) {
577 mVeAudioPlayer->resume();
578 } else {
579 status_t err = OK;
580 err = mVeAudioPlayer->start(true);
581 if (err != OK) {
582 mAudioPlayer = NULL;
583 mVeAudioPlayer = NULL;
584
585 mFlags &= ~(PLAYING | FIRST_FRAME);
586 return err;
587 }
588 }
589 } else {
590 LOGV("play_l: No Source change required");
591 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
592 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
593 mCurrentMediaVolumeValue);
594
595 mVeAudioPlayer->resume();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800596 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800597
598 mFlags |= AUDIOPLAYER_STARTED;
599 mFlags |= AUDIO_RUNNING;
600 mTimeSource = mVeAudioPlayer;
601 deferredAudioSeek = true;
602 mWatchForAudioSeekComplete = false;
603 mWatchForAudioEOS = true;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800604 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800605 }
606
607 if (mTimeSource == NULL && mAudioPlayer == NULL) {
608 mTimeSource = &mSystemTimeSource;
609 }
610
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800611 // Set the seek option for Image source files and read.
612 // This resets the timestamping for image play
613 if (mIsVideoSourceJpg) {
614 MediaSource::ReadOptions options;
615 MediaBuffer *aLocalBuffer;
616 options.setSeekTo(mSeekTimeUs);
617 mVideoSource->read(&aLocalBuffer, &options);
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800618 aLocalBuffer->release();
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800619 }
620
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800621 if (mVideoSource != NULL) {
622 // Kick off video playback
623 postVideoEvent_l();
624 }
625
626 if (deferredAudioSeek) {
627 // If there was a seek request while we were paused
628 // and we're just starting up again, honor the request now.
629 seekAudioIfNecessary_l();
630 }
631
632 if (mFlags & AT_EOS) {
633 // Legacy behaviour, if a stream finishes playing and then
634 // is started again, we play from the start...
635 seekTo_l(0);
636 }
637
638 return OK;
639}
640
641
Santosh Madhavabfece172011-02-03 16:59:47 -0800642status_t PreviewPlayer::initRenderer_l() {
Mathias Agopian6e224292011-04-05 15:38:24 -0700643 if (mSurface != NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800644 if(mVideoRenderer == NULL) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800645 mVideoRenderer = mNativeWindowRenderer->createRenderInput();
646 if (mVideoSource != NULL) {
647 updateSizeToRender(mVideoSource->getFormat());
Santosh Madhavabfece172011-02-03 16:59:47 -0800648 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800649 }
650 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800651 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800652}
653
654
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800655status_t PreviewPlayer::seekTo(int64_t timeUs) {
656
657 if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) {
658 Mutex::Autolock autoLock(mLock);
659 return seekTo_l(timeUs);
660 }
661
662 return OK;
663}
664
665
666status_t PreviewPlayer::getVideoDimensions(
667 int32_t *width, int32_t *height) const {
668 Mutex::Autolock autoLock(mLock);
669
670 if (mVideoWidth < 0 || mVideoHeight < 0) {
671 return UNKNOWN_ERROR;
672 }
673
674 *width = mVideoWidth;
675 *height = mVideoHeight;
676
677 return OK;
678}
679
680
681status_t PreviewPlayer::initAudioDecoder() {
682 sp<MetaData> meta = mAudioTrack->getFormat();
683 const char *mime;
684 CHECK(meta->findCString(kKeyMIMEType, &mime));
685
686 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
687 mAudioSource = mAudioTrack;
688 } else {
689 sp<MediaSource> aRawSource;
690 aRawSource = OMXCodec::Create(
691 mClient.interface(), mAudioTrack->getFormat(),
692 false, // createEncoder
693 mAudioTrack);
694
695 if(aRawSource != NULL) {
696 LOGV("initAudioDecoder: new VideoEditorSRC");
697 mAudioSource = new VideoEditorSRC(aRawSource);
698 }
699 }
700
701 if (mAudioSource != NULL) {
702 int64_t durationUs;
703 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
704 Mutex::Autolock autoLock(mMiscStateLock);
705 if (mDurationUs < 0 || durationUs > mDurationUs) {
706 mDurationUs = durationUs;
707 }
708 }
709 status_t err = mAudioSource->start();
710
711 if (err != OK) {
712 mAudioSource.clear();
713 return err;
714 }
715 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
716 // For legacy reasons we're simply going to ignore the absence
717 // of an audio decoder for QCELP instead of aborting playback
718 // altogether.
719 return OK;
720 }
721
722 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
723}
724
725
726status_t PreviewPlayer::initVideoDecoder(uint32_t flags) {
727
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800728 initRenderer_l();
729
730 if (mVideoRenderer == NULL) {
731 LOGE("Cannot create renderer");
732 return UNKNOWN_ERROR;
733 }
734
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800735 mVideoSource = OMXCodec::Create(
736 mClient.interface(), mVideoTrack->getFormat(),
737 false,
738 mVideoTrack,
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800739 NULL, flags, mVideoRenderer->getTargetWindow());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800740
741 if (mVideoSource != NULL) {
742 int64_t durationUs;
743 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
744 Mutex::Autolock autoLock(mMiscStateLock);
745 if (mDurationUs < 0 || durationUs > mDurationUs) {
746 mDurationUs = durationUs;
747 }
748 }
749
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800750 updateSizeToRender(mVideoTrack->getFormat());
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800751
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800752 status_t err = mVideoSource->start();
753
754 if (err != OK) {
755 mVideoSource.clear();
756 return err;
757 }
758 }
759
760 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
761}
762
763
764void PreviewPlayer::onVideoEvent() {
765 uint32_t i=0;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800766 M4OSA_ERR err1 = M4NO_ERROR;
767 int64_t imageFrameTimeUs = 0;
768
769 Mutex::Autolock autoLock(mLock);
770 if (!mVideoEventPending) {
771 // The event has been cancelled in reset_l() but had already
772 // been scheduled for execution at that time.
773 return;
774 }
775 mVideoEventPending = false;
776
Andreas Huber9e4c36a2011-02-08 13:12:32 -0800777 if (mFlags & SEEK_PREVIEW) {
778 mFlags &= ~SEEK_PREVIEW;
779 return;
780 }
781
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800782 TimeSource *ts_st = &mSystemTimeSource;
783 int64_t timeStartUs = ts_st->getRealTimeUs();
784
Andreas Hubera5872f72011-02-24 15:25:21 -0800785 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800786
787 if(mAudioSource != NULL) {
788
789 // We're going to seek the video source first, followed by
790 // the audio source.
791 // In order to avoid jumps in the DataSource offset caused by
792 // the audio codec prefetching data from the old locations
793 // while the video codec is already reading data from the new
794 // locations, we'll "pause" the audio source, causing it to
795 // stop reading input data until a subsequent seek.
796
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800797 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800798 mAudioPlayer->pause();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800799 mFlags &= ~AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800800 }
801 mAudioSource->pause();
802 }
803 }
804
805 if (!mVideoBuffer) {
806 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -0800807 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800808 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
809 mSeekTimeUs / 1E6);
810
811 options.setSeekTo(
812 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
813 }
814 for (;;) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800815 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800816 options.clearSeekTo();
817
818 if (err != OK) {
819 CHECK_EQ(mVideoBuffer, NULL);
820
821 if (err == INFO_FORMAT_CHANGED) {
822 LOGV("LV PLAYER VideoSource signalled format change");
823 notifyVideoSize_l();
824
825 if (mVideoRenderer != NULL) {
826 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -0800827 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800828 if (err != OK) {
829 postStreamDoneEvent_l(err);
830 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800831
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800832 }
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800833
834 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800835 continue;
836 }
837 // So video playback is complete, but we may still have
Santosh Madhava342f9322011-01-27 16:27:12 -0800838 // a seek request pending that needs to be applied to the audio track
Andreas Hubera5872f72011-02-24 15:25:21 -0800839 if (mSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800840 LOGV("video stream ended while seeking!");
841 }
842 finishSeekIfNecessary(-1);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800843 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
844 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800845 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800846 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800847 postStreamDoneEvent_l(err);
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800848 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -0700849 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800850 return;
851 }
852
853 if (mVideoBuffer->range_length() == 0) {
854 // Some decoders, notably the PV AVC software decoder
855 // return spurious empty buffers that we just want to ignore.
856
857 mVideoBuffer->release();
858 mVideoBuffer = NULL;
859 continue;
860 }
861
862 int64_t videoTimeUs;
863 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
864
Andreas Hubera5872f72011-02-24 15:25:21 -0800865 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800866 if (videoTimeUs < mSeekTimeUs) {
867 // buffers are before seek time
868 // ignore them
869 mVideoBuffer->release();
870 mVideoBuffer = NULL;
871 continue;
872 }
873 } else {
874 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
875 // Frames are before begin cut time
876 // Donot render
877 mVideoBuffer->release();
878 mVideoBuffer = NULL;
879 continue;
880 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800881 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800882 break;
883 }
884 }
885
886 mNumberDecVideoFrames++;
887
888 int64_t timeUs;
889 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
890
891 {
892 Mutex::Autolock autoLock(mMiscStateLock);
893 mVideoTimeUs = timeUs;
894 }
895
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800896
897 if(!mStartNextPlayer) {
Raghavender Pallaebf40152011-03-14 20:15:12 -0700898 int64_t playbackTimeRemaining = (mPlayEndTimeMsec*1000LL) - timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800899 if(playbackTimeRemaining <= 1500000) {
900 //When less than 1.5 sec of playback left
901 // send notification to start next player
902
903 mStartNextPlayer = true;
904 notifyListener_l(0xAAAAAAAA);
905 }
906 }
907
Andreas Hubera5872f72011-02-24 15:25:21 -0800908 SeekType wasSeeking = mSeeking;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800909 finishSeekIfNecessary(timeUs);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800910 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING))) {
911 status_t err = startAudioPlayer_l();
912 if (err != OK) {
913 LOGE("Starting the audio player failed w/ err %d", err);
914 return;
915 }
916 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800917
918 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
919
920 if(ts == NULL) {
921 mVideoBuffer->release();
922 mVideoBuffer = NULL;
923 return;
924 }
925
926 if(!mIsVideoSourceJpg) {
927 if (mFlags & FIRST_FRAME) {
928 mFlags &= ~FIRST_FRAME;
929
930 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
931 }
932
933 int64_t realTimeUs, mediaTimeUs;
934 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
935 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
936 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
937 }
938
939 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
940
941 int64_t latenessUs = nowUs - timeUs;
942
Andreas Hubera5872f72011-02-24 15:25:21 -0800943 if (wasSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800944 // Let's display the first frame after seeking right away.
945 latenessUs = 0;
946 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800947 LOGV("Audio time stamp = %lld and video time stamp = %lld",
948 ts->getRealTimeUs(),timeUs);
949 if (latenessUs > 40000) {
950 // We're more than 40ms late.
951
952 LOGV("LV PLAYER we're late by %lld us (%.2f secs)",
953 latenessUs, latenessUs / 1E6);
954
955 mVideoBuffer->release();
956 mVideoBuffer = NULL;
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800957 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800958 return;
959 }
960
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800961 if (latenessUs < -25000) {
962 // We're more than 25ms early.
963 LOGV("We're more than 25ms early, lateness %lld", latenessUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800964
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800965 postVideoEvent_l(25000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800966 return;
967 }
968 }
969
970 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
971 mVideoRendererIsPreview = false;
972
Santosh Madhavabfece172011-02-03 16:59:47 -0800973 status_t err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800974 if (err != OK) {
975 postStreamDoneEvent_l(err);
976 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800977 }
978
979 // If timestamp exceeds endCutTime of clip, donot render
980 if((timeUs/1000) > mPlayEndTimeMsec) {
Chih-Chung Changcece4b32011-08-01 16:34:05 +0800981 mVideoBuffer->release();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800982 mVideoBuffer = NULL;
983 mFlags |= VIDEO_AT_EOS;
984 mFlags |= AUDIO_AT_EOS;
Santosh Madhavabfece172011-02-03 16:59:47 -0800985 LOGV("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS..");
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800986 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -0800987 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -0700988 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800989 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
990 return;
991 }
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800992 // Capture the frame timestamp to be rendered
993 mDecodedVideoTs = timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800994
995 // Post processing to apply video effects
996 for(i=0;i<mNumberEffects;i++) {
997 // First check if effect starttime matches the clip being previewed
998 if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) ||
999 (mEffectsSettings[i].uiStartTime >=
1000 ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec)))
1001 {
1002 // This effect doesn't belong to this clip, check next one
1003 continue;
1004 }
1005 // Check if effect applies to this particular frame timestamp
1006 if((mEffectsSettings[i].uiStartTime <=
1007 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) &&
1008 ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=
1009 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec))
1010 && (mEffectsSettings[i].uiDuration != 0)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001011 setVideoPostProcessingNode(
1012 mEffectsSettings[i].VideoEffectType, TRUE);
1013 }
1014 else {
1015 setVideoPostProcessingNode(
1016 mEffectsSettings[i].VideoEffectType, FALSE);
1017 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001018 }
1019
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001020 //Provide the overlay Update indication when there is an overlay effect
Dharmaray Kundargid01ef562011-01-26 21:11:00 -08001021 if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) {
1022 mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here.
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001023 if (!mOverlayUpdateEventPosted) {
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001024 // Find the effect in effectSettings array
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001025 M4OSA_UInt32 index;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001026 for (index = 0; index < mNumberEffects; index++) {
1027 M4OSA_UInt32 timeMs = mDecodedVideoTs/1000;
1028 M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000;
1029 if(mEffectsSettings[index].VideoEffectType ==
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001030 (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001031 if (((mEffectsSettings[index].uiStartTime + 1) <=
1032 timeMs + timeOffset - mPlayBeginTimeMsec) &&
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001033 ((mEffectsSettings[index].uiStartTime - 1 +
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001034 mEffectsSettings[index].uiDuration) >=
1035 timeMs + timeOffset - mPlayBeginTimeMsec))
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001036 {
1037 break;
1038 }
1039 }
1040 }
1041 if (index < mNumberEffects) {
1042 mCurrFramingEffectIndex = index;
1043 mOverlayUpdateEventPosted = true;
1044 postOverlayUpdateEvent_l();
1045 LOGV("Framing index = %d", mCurrFramingEffectIndex);
1046 } else {
1047 LOGV("No framing effects found");
1048 }
1049 }
1050
1051 } else if (mOverlayUpdateEventPosted) {
1052 //Post the event when the overlay is no more valid
1053 LOGV("Overlay is Done");
1054 mOverlayUpdateEventPosted = false;
1055 postOverlayUpdateEvent_l();
1056 }
1057
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001058 if (mVideoRenderer != NULL) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001059 mVideoRenderer->render(mVideoBuffer, mCurrentVideoEffect,
1060 mRenderingMode, mIsVideoSourceJpg);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001061 }
1062
Chih-Chung Changcece4b32011-08-01 16:34:05 +08001063 mVideoBuffer->release();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001064 mVideoBuffer = NULL;
1065
1066 // Post progress callback based on callback interval set
1067 if(mNumberDecVideoFrames >= mProgressCbInterval) {
1068 postProgressCallbackEvent_l();
1069 mNumberDecVideoFrames = 0; // reset counter
1070 }
1071
1072 // if reached EndCutTime of clip, post EOS event
1073 if((timeUs/1000) >= mPlayEndTimeMsec) {
1074 LOGV("PreviewPlayer: onVideoEvent EOS.");
1075 mFlags |= VIDEO_AT_EOS;
1076 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001077 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001078 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001079 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001080 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1081 }
1082 else {
Andreas Hubera5872f72011-02-24 15:25:21 -08001083 if ((wasSeeking != NO_SEEK) && (mFlags & SEEK_PREVIEW)) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001084 mFlags &= ~SEEK_PREVIEW;
1085 return;
1086 }
1087
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001088 if(!mIsVideoSourceJpg) {
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001089 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001090 }
1091 else {
1092 postVideoEvent_l(33000);
1093 }
1094 }
1095}
1096
1097status_t PreviewPlayer::prepare() {
1098 Mutex::Autolock autoLock(mLock);
1099 return prepare_l();
1100}
1101
1102status_t PreviewPlayer::prepare_l() {
1103 if (mFlags & PREPARED) {
1104 return OK;
1105 }
1106
1107 if (mFlags & PREPARING) {
1108 return UNKNOWN_ERROR;
1109 }
1110
1111 mIsAsyncPrepare = false;
1112 status_t err = prepareAsync_l();
1113
1114 if (err != OK) {
1115 return err;
1116 }
1117
1118 while (mFlags & PREPARING) {
1119 mPreparedCondition.wait(mLock);
1120 }
1121
1122 return mPrepareResult;
1123}
1124
1125status_t PreviewPlayer::prepareAsync_l() {
1126 if (mFlags & PREPARING) {
1127 return UNKNOWN_ERROR; // async prepare already pending
1128 }
1129
1130 if (!mQueueStarted) {
1131 mQueue.start();
1132 mQueueStarted = true;
1133 }
1134
1135 mFlags |= PREPARING;
1136 mAsyncPrepareEvent = new PreviewPlayerEvent(
1137 this, &PreviewPlayer::onPrepareAsyncEvent);
1138
1139 mQueue.postEvent(mAsyncPrepareEvent);
1140
1141 return OK;
1142}
1143
1144status_t PreviewPlayer::finishSetDataSource_l() {
1145 sp<DataSource> dataSource;
1146 sp<MediaExtractor> extractor;
1147
1148 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1149
1150 if (dataSource == NULL) {
1151 return UNKNOWN_ERROR;
1152 }
1153
1154 //If file type is .rgb, then no need to check for Extractor
1155 int uriLen = strlen(mUri);
1156 int startOffset = uriLen - 4;
1157 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) {
1158 extractor = NULL;
1159 }
1160 else {
1161 extractor = MediaExtractor::Create(dataSource,
1162 MEDIA_MIMETYPE_CONTAINER_MPEG4);
1163 }
1164
1165 if (extractor == NULL) {
1166 LOGV("PreviewPlayer::finishSetDataSource_l extractor == NULL");
1167 return setDataSource_l_jpg();
1168 }
1169
1170 return setDataSource_l(extractor);
1171}
1172
1173
1174// static
1175bool PreviewPlayer::ContinuePreparation(void *cookie) {
1176 PreviewPlayer *me = static_cast<PreviewPlayer *>(cookie);
1177
1178 return (me->mFlags & PREPARE_CANCELLED) == 0;
1179}
1180
1181void PreviewPlayer::onPrepareAsyncEvent() {
1182 Mutex::Autolock autoLock(mLock);
1183 LOGV("onPrepareAsyncEvent");
1184
1185 if (mFlags & PREPARE_CANCELLED) {
Santosh Madhavabfece172011-02-03 16:59:47 -08001186 LOGV("LV PLAYER prepare was cancelled before doing anything");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001187 abortPrepare(UNKNOWN_ERROR);
1188 return;
1189 }
1190
1191 if (mUri.size() > 0) {
1192 status_t err = finishSetDataSource_l();
1193
1194 if (err != OK) {
1195 abortPrepare(err);
1196 return;
1197 }
1198 }
1199
1200 if (mVideoTrack != NULL && mVideoSource == NULL) {
1201 status_t err = initVideoDecoder(OMXCodec::kHardwareCodecsOnly);
1202
1203 if (err != OK) {
1204 abortPrepare(err);
1205 return;
1206 }
1207 }
1208
1209 if (mAudioTrack != NULL && mAudioSource == NULL) {
1210 status_t err = initAudioDecoder();
1211
1212 if (err != OK) {
1213 abortPrepare(err);
1214 return;
1215 }
1216 }
1217 finishAsyncPrepare_l();
1218
1219}
1220
1221void PreviewPlayer::finishAsyncPrepare_l() {
1222 if (mIsAsyncPrepare) {
1223 if (mVideoSource == NULL) {
1224 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE 0 0 ");
1225 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1226 } else {
1227 LOGV("finishAsyncPrepare_l: MEDIA_SET_VIDEO_SIZE");
1228 notifyVideoSize_l();
1229 }
1230 LOGV("finishAsyncPrepare_l: MEDIA_PREPARED");
1231 notifyListener_l(MEDIA_PREPARED);
1232 }
1233
1234 mPrepareResult = OK;
1235 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1236 mFlags |= PREPARED;
1237 mAsyncPrepareEvent = NULL;
1238 mPreparedCondition.broadcast();
1239}
1240
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001241void PreviewPlayer::acquireLock() {
1242 LOGV("acquireLock");
1243 mLockControl.lock();
1244}
1245
1246void PreviewPlayer::releaseLock() {
1247 LOGV("releaseLock");
1248 mLockControl.unlock();
1249}
1250
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001251status_t PreviewPlayer::loadEffectsSettings(
1252 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) {
1253 M4OSA_UInt32 i = 0, rgbSize = 0;
1254 M4VIFI_UInt8 *tmp = M4OSA_NULL;
1255
1256 mNumberEffects = nEffects;
1257 mEffectsSettings = pEffectSettings;
1258 return OK;
1259}
1260
1261status_t PreviewPlayer::loadAudioMixSettings(
1262 M4xVSS_AudioMixingSettings* pAudioMixSettings) {
1263
1264 LOGV("PreviewPlayer: loadAudioMixSettings: ");
1265 mPreviewPlayerAudioMixSettings = pAudioMixSettings;
1266 return OK;
1267}
1268
1269status_t PreviewPlayer::setAudioMixPCMFileHandle(
1270 M4OSA_Context pAudioMixPCMFileHandle) {
1271
1272 LOGV("PreviewPlayer: setAudioMixPCMFileHandle: ");
1273 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle;
1274 return OK;
1275}
1276
1277status_t PreviewPlayer::setAudioMixStoryBoardParam(
1278 M4OSA_UInt32 audioMixStoryBoardTS,
1279 M4OSA_UInt32 currentMediaBeginCutTime,
1280 M4OSA_UInt32 primaryTrackVolValue ) {
1281
1282 mAudioMixStoryBoardTS = audioMixStoryBoardTS;
1283 mCurrentMediaBeginCutTime = currentMediaBeginCutTime;
1284 mCurrentMediaVolumeValue = primaryTrackVolValue;
1285 return OK;
1286}
1287
1288status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) {
1289
1290 mPlayBeginTimeMsec = msec;
1291 return OK;
1292}
1293
1294status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) {
1295
1296 mPlayEndTimeMsec = msec;
1297 return OK;
1298}
1299
1300status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) {
1301
1302 mStoryboardStartTimeMsec = msec;
Raghavender Pallaebf40152011-03-14 20:15:12 -07001303 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001304 return OK;
1305}
1306
1307status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) {
1308
1309 mProgressCbInterval = cbInterval;
1310 return OK;
1311}
1312
1313
1314status_t PreviewPlayer::setMediaRenderingMode(
1315 M4xVSS_MediaRendering mode,
1316 M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
1317
1318 mRenderingMode = mode;
1319
Hong Teng8806b702011-07-06 18:29:28 -07001320 status_t err = OK;
1321 /* get the video width and height by resolution */
1322 err = getVideoSizeByResolution(outputVideoSize,
1323 &mOutputVideoWidth, &mOutputVideoHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001324
Hong Teng8806b702011-07-06 18:29:28 -07001325 return err;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001326}
1327
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001328status_t PreviewPlayer::resetJniCallbackTimeStamp() {
1329
Raghavender Pallaebf40152011-03-14 20:15:12 -07001330 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001331 return OK;
1332}
1333
1334void PreviewPlayer::postProgressCallbackEvent_l() {
1335 if (mProgressCbEventPending) {
1336 return;
1337 }
1338 mProgressCbEventPending = true;
1339
1340 mQueue.postEvent(mProgressCbEvent);
1341}
1342
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001343
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001344void PreviewPlayer::onProgressCbEvent() {
1345 Mutex::Autolock autoLock(mLock);
1346 if (!mProgressCbEventPending) {
1347 return;
1348 }
1349 mProgressCbEventPending = false;
1350 // If playback starts from previous I-frame,
1351 // then send frame storyboard duration
1352 if((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) {
1353 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000);
1354 }
1355 else {
1356 notifyListener_l(MEDIA_INFO, 0,
1357 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec));
1358 }
1359}
1360
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001361void PreviewPlayer::postOverlayUpdateEvent_l() {
1362 if (mOverlayUpdateEventPending) {
1363 return;
1364 }
1365 mOverlayUpdateEventPending = true;
1366 mQueue.postEvent(mOverlayUpdateEvent);
1367}
1368
1369void PreviewPlayer::onUpdateOverlayEvent() {
1370 Mutex::Autolock autoLock(mLock);
1371
1372 if (!mOverlayUpdateEventPending) {
1373 return;
1374 }
1375 mOverlayUpdateEventPending = false;
1376
1377 int updateState;
1378 if (mOverlayUpdateEventPosted) {
1379 updateState = 1;
1380 } else {
1381 updateState = 0;
1382 }
1383 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex);
1384}
1385
1386
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001387void PreviewPlayer::setVideoPostProcessingNode(
1388 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
1389
1390 uint32_t effect = VIDEO_EFFECT_NONE;
1391
1392 //Map M4VSS3GPP_VideoEffectType to local enum
1393 switch(type) {
1394 case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
1395 effect = VIDEO_EFFECT_FADEFROMBLACK;
1396 break;
1397
1398 case M4VSS3GPP_kVideoEffectType_FadeToBlack:
1399 effect = VIDEO_EFFECT_FADETOBLACK;
1400 break;
1401
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001402 case M4xVSS_kVideoEffectType_BlackAndWhite:
1403 effect = VIDEO_EFFECT_BLACKANDWHITE;
1404 break;
1405
1406 case M4xVSS_kVideoEffectType_Pink:
1407 effect = VIDEO_EFFECT_PINK;
1408 break;
1409
1410 case M4xVSS_kVideoEffectType_Green:
1411 effect = VIDEO_EFFECT_GREEN;
1412 break;
1413
1414 case M4xVSS_kVideoEffectType_Sepia:
1415 effect = VIDEO_EFFECT_SEPIA;
1416 break;
1417
1418 case M4xVSS_kVideoEffectType_Negative:
1419 effect = VIDEO_EFFECT_NEGATIVE;
1420 break;
1421
1422 case M4xVSS_kVideoEffectType_Framing:
1423 effect = VIDEO_EFFECT_FRAMING;
1424 break;
1425
1426 case M4xVSS_kVideoEffectType_Fifties:
1427 effect = VIDEO_EFFECT_FIFTIES;
1428 break;
1429
1430 case M4xVSS_kVideoEffectType_ColorRGB16:
1431 effect = VIDEO_EFFECT_COLOR_RGB16;
1432 break;
1433
1434 case M4xVSS_kVideoEffectType_Gradient:
1435 effect = VIDEO_EFFECT_GRADIENT;
1436 break;
1437
1438 default:
1439 effect = VIDEO_EFFECT_NONE;
1440 break;
1441 }
1442
1443 if(enable == M4OSA_TRUE) {
1444 //If already set, then no need to set again
1445 if(!(mCurrentVideoEffect & effect)) {
1446 mCurrentVideoEffect |= effect;
1447 if(effect == VIDEO_EFFECT_FIFTIES) {
1448 mIsFiftiesEffectStarted = true;
1449 }
1450 }
1451 }
1452 else {
1453 //Reset only if already set
1454 if(mCurrentVideoEffect & effect) {
1455 mCurrentVideoEffect &= ~effect;
1456 }
1457 }
1458}
1459
1460status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) {
1461 mVideoWidth = width;
1462 mVideoHeight = height;
1463 return OK;
1464}
1465
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001466status_t PreviewPlayer::readFirstVideoFrame() {
1467 LOGV("PreviewPlayer::readFirstVideoFrame");
1468
1469 if (!mVideoBuffer) {
1470 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -08001471 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001472 LOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
1473 mSeekTimeUs / 1E6);
1474
1475 options.setSeekTo(
1476 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
1477 }
1478 for (;;) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001479 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001480 options.clearSeekTo();
1481
1482 if (err != OK) {
1483 CHECK_EQ(mVideoBuffer, NULL);
1484
1485 if (err == INFO_FORMAT_CHANGED) {
1486 LOGV("LV PLAYER VideoSource signalled format change");
1487 notifyVideoSize_l();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001488
1489 if (mVideoRenderer != NULL) {
1490 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -08001491 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001492 if (err != OK) {
1493 postStreamDoneEvent_l(err);
1494 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001495 }
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001496
1497 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001498 continue;
1499 }
1500 LOGV("PreviewPlayer: onVideoEvent EOS reached.");
1501 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001502 mFlags |= AUDIO_AT_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001503 postStreamDoneEvent_l(err);
1504 return OK;
1505 }
1506
1507 if (mVideoBuffer->range_length() == 0) {
1508 // Some decoders, notably the PV AVC software decoder
1509 // return spurious empty buffers that we just want to ignore.
1510
1511 mVideoBuffer->release();
1512 mVideoBuffer = NULL;
1513 continue;
1514 }
1515
1516 int64_t videoTimeUs;
1517 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
Andreas Hubera5872f72011-02-24 15:25:21 -08001518 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001519 if (videoTimeUs < mSeekTimeUs) {
1520 // buffers are before seek time
1521 // ignore them
1522 mVideoBuffer->release();
1523 mVideoBuffer = NULL;
1524 continue;
1525 }
1526 } else {
1527 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
1528 // buffers are before begin cut time
1529 // ignore them
1530 mVideoBuffer->release();
1531 mVideoBuffer = NULL;
1532 continue;
1533 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001534 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001535 break;
1536 }
1537 }
1538
1539 int64_t timeUs;
1540 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1541
1542 {
1543 Mutex::Autolock autoLock(mMiscStateLock);
1544 mVideoTimeUs = timeUs;
1545 }
1546
1547 mDecodedVideoTs = timeUs;
1548
1549 return OK;
1550
1551}
1552
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001553status_t PreviewPlayer::getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs) {
1554 *lastRenderedTimeMs = (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec);
1555 return OK;
1556}
1557
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001558void PreviewPlayer::updateSizeToRender(sp<MetaData> meta) {
1559 if (mVideoRenderer) {
1560 mVideoRenderer->updateVideoSize(meta);
1561 }
1562}
1563
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001564} // namespace android