blob: 2bd9f84ef00571abc50d40932de2eeb25534e7a1 [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
James Dong00f742c2012-01-13 17:34:42 -080018// #define LOG_NDEBUG 0
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080019#define LOG_TAG "PreviewPlayer"
20#include <utils/Log.h>
21
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080022#include <binder/IPCThreadState.h>
James Dong00f742c2012-01-13 17:34:42 -080023#include <binder/IServiceManager.h>
24#include <media/IMediaPlayerService.h>
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080025#include <media/stagefright/DataSource.h>
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080026#include <media/stagefright/MediaBuffer.h>
27#include <media/stagefright/MediaDefs.h>
28#include <media/stagefright/MediaExtractor.h>
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080029#include <media/stagefright/MediaSource.h>
30#include <media/stagefright/MetaData.h>
31#include <media/stagefright/OMXCodec.h>
James Dong00f742c2012-01-13 17:34:42 -080032#include <media/stagefright/foundation/ADebug.h>
Mathias Agopian90b61912012-02-26 00:40:08 -080033#include <gui/Surface.h>
Andy McFadden484566c2012-12-18 09:46:54 -080034#include <gui/IGraphicBufferProducer.h>
Mathias Agopianb1e7cd12013-02-14 17:11:27 -080035#include <gui/Surface.h>
James Dong00f742c2012-01-13 17:34:42 -080036
37#include "VideoEditorPreviewController.h"
James Dong00f742c2012-01-13 17:34:42 -080038#include "DummyAudioSource.h"
39#include "DummyVideoSource.h"
40#include "VideoEditorSRC.h"
41#include "PreviewPlayer.h"
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080042
43namespace android {
44
45
James Dong00f742c2012-01-13 17:34:42 -080046void addBatteryData(uint32_t params) {
47 sp<IBinder> binder =
48 defaultServiceManager()->getService(String16("media.player"));
49 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
50 CHECK(service.get() != NULL);
51
52 service->addBatteryData(params);
53}
54
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080055struct PreviewPlayerEvent : public TimedEventQueue::Event {
56 PreviewPlayerEvent(
57 PreviewPlayer *player,
58 void (PreviewPlayer::*method)())
59 : mPlayer(player),
60 mMethod(method) {
61 }
62
63protected:
64 virtual ~PreviewPlayerEvent() {}
65
66 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
67 (mPlayer->*mMethod)();
68 }
69
70private:
71 PreviewPlayer *mPlayer;
72 void (PreviewPlayer::*mMethod)();
73
74 PreviewPlayerEvent(const PreviewPlayerEvent &);
75 PreviewPlayerEvent &operator=(const PreviewPlayerEvent &);
76};
77
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080078PreviewPlayer::PreviewPlayer(NativeWindowRenderer* renderer)
James Dong00f742c2012-01-13 17:34:42 -080079 : mQueueStarted(false),
80 mTimeSource(NULL),
81 mVideoRendererIsPreview(false),
82 mAudioPlayer(NULL),
83 mDisplayWidth(0),
84 mDisplayHeight(0),
85 mFlags(0),
86 mExtractorFlags(0),
87 mVideoBuffer(NULL),
88 mLastVideoTimeUs(-1),
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080089 mNativeWindowRenderer(renderer),
90 mCurrFramingEffectIndex(0),
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -080091 mFrameRGBBuffer(NULL),
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080092 mFrameYUVBuffer(NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080093
James Dong00f742c2012-01-13 17:34:42 -080094 CHECK_EQ(mClient.connect(), (status_t)OK);
95 DataSource::RegisterDefaultSniffers();
96
97
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080098 mVideoRenderer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080099 mEffectsSettings = NULL;
James Dong727f9e12012-01-20 13:09:13 -0800100 mAudioPlayer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800101 mAudioMixStoryBoardTS = 0;
102 mCurrentMediaBeginCutTime = 0;
103 mCurrentMediaVolumeValue = 0;
104 mNumberEffects = 0;
105 mDecodedVideoTs = 0;
106 mDecVideoTsStoryBoard = 0;
107 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
108 mProgressCbInterval = 0;
109 mNumberDecVideoFrames = 0;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800110 mOverlayUpdateEventPosted = false;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800111 mIsChangeSourceRequired = true;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800112
113 mVideoEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoEvent);
114 mVideoEventPending = false;
James Dong00f742c2012-01-13 17:34:42 -0800115 mVideoLagEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoLagUpdate);
116 mVideoEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800117 mCheckAudioStatusEvent = new PreviewPlayerEvent(
James Dong00f742c2012-01-13 17:34:42 -0800118 this, &PreviewPlayer::onCheckAudioStatus);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800119 mAudioStatusEventPending = false;
James Dong00f742c2012-01-13 17:34:42 -0800120 mStreamDoneEvent = new PreviewPlayerEvent(
121 this, &PreviewPlayer::onStreamDone);
122 mStreamDoneEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800123 mProgressCbEvent = new PreviewPlayerEvent(this,
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800124 &PreviewPlayer::onProgressCbEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800125
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800126 mOverlayUpdateEvent = new PreviewPlayerEvent(this,
127 &PreviewPlayer::onUpdateOverlayEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800128 mProgressCbEventPending = false;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800129
130 mOverlayUpdateEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800131 mRenderingMode = (M4xVSS_MediaRendering)MEDIA_RENDERING_INVALID;
132 mIsFiftiesEffectStarted = false;
133 reset();
134}
135
136PreviewPlayer::~PreviewPlayer() {
137
138 if (mQueueStarted) {
139 mQueue.stop();
140 }
141
142 reset();
143
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800144 if (mVideoRenderer) {
145 mNativeWindowRenderer->destroyRenderInput(mVideoRenderer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800146 }
James Dong00f742c2012-01-13 17:34:42 -0800147
148 Mutex::Autolock lock(mLock);
149 clear_l();
150 mClient.disconnect();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800151}
152
James Dong00f742c2012-01-13 17:34:42 -0800153void PreviewPlayer::cancelPlayerEvents_l(bool updateProgressCb) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800154 mQueue.cancelEvent(mVideoEvent->eventID());
155 mVideoEventPending = false;
156 mQueue.cancelEvent(mStreamDoneEvent->eventID());
157 mStreamDoneEventPending = false;
158 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
159 mAudioStatusEventPending = false;
James Dong00f742c2012-01-13 17:34:42 -0800160 mQueue.cancelEvent(mVideoLagEvent->eventID());
161 mVideoLagEventPending = false;
162 if (updateProgressCb) {
163 mQueue.cancelEvent(mProgressCbEvent->eventID());
164 mProgressCbEventPending = false;
165 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800166}
167
James Dongdaeb5b32012-01-12 12:12:40 -0800168status_t PreviewPlayer::setDataSource(const char *path) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800169 Mutex::Autolock autoLock(mLock);
James Dongdaeb5b32012-01-12 12:12:40 -0800170 return setDataSource_l(path);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800171}
172
James Dongdaeb5b32012-01-12 12:12:40 -0800173status_t PreviewPlayer::setDataSource_l(const char *path) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800174 reset_l();
175
James Dongdaeb5b32012-01-12 12:12:40 -0800176 mUri = path;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800177
178 // The actual work will be done during preparation in the call to
179 // ::finishSetDataSource_l to avoid blocking the calling thread in
180 // setDataSource for any significant time.
181 return OK;
182}
183
184status_t PreviewPlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
185 bool haveAudio = false;
186 bool haveVideo = false;
187 for (size_t i = 0; i < extractor->countTracks(); ++i) {
188 sp<MetaData> meta = extractor->getTrackMetaData(i);
189
190 const char *mime;
191 CHECK(meta->findCString(kKeyMIMEType, &mime));
192
193 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
194 setVideoSource(extractor->getTrack(i));
195 haveVideo = true;
196 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
197 setAudioSource(extractor->getTrack(i));
198 haveAudio = true;
199
200 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
201 // Only do this for vorbis audio, none of the other audio
202 // formats even support this ringtone specific hack and
203 // retrieving the metadata on some extractors may turn out
204 // to be very expensive.
205 sp<MetaData> fileMeta = extractor->getMetaData();
206 int32_t loop;
207 if (fileMeta != NULL
208 && fileMeta->findInt32(kKeyAutoLoop, &loop)
209 && loop != 0) {
210 mFlags |= AUTO_LOOPING;
211 }
212 }
213 }
214
215 if (haveAudio && haveVideo) {
216 break;
217 }
218 }
219
220 /* Add the support for Dummy audio*/
221 if( !haveAudio ){
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800222 mAudioTrack = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700223 ((mPlayEndTimeMsec)*1000LL));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800224 if(mAudioTrack != NULL) {
225 haveAudio = true;
226 }
227 }
228
229 if (!haveAudio && !haveVideo) {
230 return UNKNOWN_ERROR;
231 }
232
233 mExtractorFlags = extractor->flags();
234 return OK;
235}
236
237status_t PreviewPlayer::setDataSource_l_jpg() {
James Dong00f742c2012-01-13 17:34:42 -0800238 ALOGV("setDataSource_l_jpg");
239
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800240 M4OSA_ERR err = M4NO_ERROR;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800241
242 mAudioSource = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700243 ((mPlayEndTimeMsec)*1000LL));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800244 if(mAudioSource != NULL) {
245 setAudioSource(mAudioSource);
246 }
247 status_t error = mAudioSource->start();
248 if (error != OK) {
James Dong00f742c2012-01-13 17:34:42 -0800249 ALOGE("Error starting dummy audio source");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800250 mAudioSource.clear();
251 return err;
252 }
253
Raghavender Pallaebf40152011-03-14 20:15:12 -0700254 mDurationUs = (mPlayEndTimeMsec - mPlayBeginTimeMsec)*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800255
256 mVideoSource = DummyVideoSource::Create(mVideoWidth, mVideoHeight,
257 mDurationUs, mUri);
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800258
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800259 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800260 setVideoSource(mVideoSource);
261 status_t err1 = mVideoSource->start();
262 if (err1 != OK) {
263 mVideoSource.clear();
264 return err;
265 }
266
267 mIsVideoSourceJpg = true;
268 return OK;
269}
270
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800271void PreviewPlayer::reset_l() {
272
273 if (mFlags & PREPARING) {
274 mFlags |= PREPARE_CANCELLED;
275 }
276
277 while (mFlags & PREPARING) {
278 mPreparedCondition.wait(mLock);
279 }
280
James Dong00f742c2012-01-13 17:34:42 -0800281 cancelPlayerEvents_l();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800282 mAudioTrack.clear();
283 mVideoTrack.clear();
284
285 // Shutdown audio first, so that the respone to the reset request
286 // appears to happen instantaneously as far as the user is concerned
287 // If we did this later, audio would continue playing while we
288 // shutdown the video-related resources and the player appear to
289 // not be as responsive to a reset request.
290 if (mAudioPlayer == NULL && mAudioSource != NULL) {
291 // If we had an audio player, it would have effectively
292 // taken possession of the audio source and stopped it when
293 // _it_ is stopped. Otherwise this is still our responsibility.
294 mAudioSource->stop();
295 }
296 mAudioSource.clear();
297
298 mTimeSource = NULL;
299
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800300 //Single audio player instance used
301 //So donot delete it here
302 //It is deleted from PreviewController class
303 //delete mAudioPlayer;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800304 mAudioPlayer = NULL;
305
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800306 if (mVideoBuffer) {
307 mVideoBuffer->release();
308 mVideoBuffer = NULL;
309 }
310
311 if (mVideoSource != NULL) {
312 mVideoSource->stop();
313
314 // The following hack is necessary to ensure that the OMX
315 // component is completely released by the time we may try
316 // to instantiate it again.
317 wp<MediaSource> tmp = mVideoSource;
318 mVideoSource.clear();
319 while (tmp.promote() != NULL) {
320 usleep(1000);
321 }
322 IPCThreadState::self()->flushCommands();
323 }
324
325 mDurationUs = -1;
326 mFlags = 0;
327 mExtractorFlags = 0;
328 mVideoWidth = mVideoHeight = -1;
329 mTimeSourceDeltaUs = 0;
330 mVideoTimeUs = 0;
331
Andreas Hubera5872f72011-02-24 15:25:21 -0800332 mSeeking = NO_SEEK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800333 mSeekNotificationSent = false;
334 mSeekTimeUs = 0;
335
336 mUri.setTo("");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800337
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800338 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
339 mIsVideoSourceJpg = false;
340 mFrameRGBBuffer = NULL;
341 if(mFrameYUVBuffer != NULL) {
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700342 free(mFrameYUVBuffer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800343 mFrameYUVBuffer = NULL;
344 }
345}
346
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800347status_t PreviewPlayer::play() {
James Dong00f742c2012-01-13 17:34:42 -0800348 ALOGV("play");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800349 Mutex::Autolock autoLock(mLock);
350
351 mFlags &= ~CACHE_UNDERRUN;
Hong Tenge0180232011-09-28 18:40:38 -0700352 mFlags &= ~INFORMED_AV_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800353 return play_l();
354}
355
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800356status_t PreviewPlayer::startAudioPlayer_l() {
James Dong00f742c2012-01-13 17:34:42 -0800357 ALOGV("startAudioPlayer_l");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800358 CHECK(!(mFlags & AUDIO_RUNNING));
359
360 if (mAudioSource == NULL || mAudioPlayer == NULL) {
361 return OK;
362 }
363
364 if (!(mFlags & AUDIOPLAYER_STARTED)) {
365 mFlags |= AUDIOPLAYER_STARTED;
366
367 // We've already started the MediaSource in order to enable
368 // the prefetcher to read its data.
James Dong727f9e12012-01-20 13:09:13 -0800369 status_t err = mAudioPlayer->start(
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800370 true /* sourceAlreadyStarted */);
371
372 if (err != OK) {
373 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
374 return err;
375 }
376 } else {
James Dong727f9e12012-01-20 13:09:13 -0800377 mAudioPlayer->resume();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800378 }
379
380 mFlags |= AUDIO_RUNNING;
381
382 mWatchForAudioEOS = true;
383
384 return OK;
385}
386
James Dong727f9e12012-01-20 13:09:13 -0800387status_t PreviewPlayer::setAudioPlayer(VideoEditorAudioPlayer *audioPlayer) {
James Dong00f742c2012-01-13 17:34:42 -0800388 ALOGV("setAudioPlayer");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800389 Mutex::Autolock autoLock(mLock);
390 CHECK(!(mFlags & PLAYING));
391 mAudioPlayer = audioPlayer;
392
Steve Block2703f232011-10-20 11:56:09 +0100393 ALOGV("SetAudioPlayer");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800394 mIsChangeSourceRequired = true;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800395
396 // check if the new and old source are dummy
James Dong727f9e12012-01-20 13:09:13 -0800397 sp<MediaSource> anAudioSource = mAudioPlayer->getSource();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800398 if (anAudioSource == NULL) {
399 // Audio player does not have any source set.
Steve Block2703f232011-10-20 11:56:09 +0100400 ALOGV("setAudioPlayer: Audio player does not have any source set");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800401 return OK;
402 }
403
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800404 // If new video source is not dummy, then always change source
405 // Else audio player continues using old audio source and there are
406 // frame drops to maintain AV sync
407 sp<MetaData> meta;
408 if (mVideoSource != NULL) {
409 meta = mVideoSource->getFormat();
410 const char *pVidSrcType;
411 if (meta->findCString(kKeyDecoderComponent, &pVidSrcType)) {
412 if (strcmp(pVidSrcType, "DummyVideoSource") != 0) {
Steve Block2703f232011-10-20 11:56:09 +0100413 ALOGV(" Video clip with silent audio; need to change source");
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800414 return OK;
415 }
416 }
417 }
418
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800419 const char *pSrcType1;
420 const char *pSrcType2;
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800421 meta = anAudioSource->getFormat();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800422
423 if (meta->findCString(kKeyDecoderComponent, &pSrcType1)) {
424 if (strcmp(pSrcType1, "DummyAudioSource") == 0) {
425 meta = mAudioSource->getFormat();
426 if (meta->findCString(kKeyDecoderComponent, &pSrcType2)) {
427 if (strcmp(pSrcType2, "DummyAudioSource") == 0) {
428 mIsChangeSourceRequired = false;
429 // Just set the new play duration for the existing source
430 MediaSource *pMediaSrc = anAudioSource.get();
431 DummyAudioSource *pDummyAudioSource = (DummyAudioSource*)pMediaSrc;
432 //Increment the duration of audio source
Raghavender Pallaebf40152011-03-14 20:15:12 -0700433 pDummyAudioSource->setDuration(
434 (int64_t)((mPlayEndTimeMsec)*1000LL));
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800435
436 // Stop the new audio source
437 // since we continue using old source
Steve Block2703f232011-10-20 11:56:09 +0100438 ALOGV("setAudioPlayer: stop new audio source");
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800439 mAudioSource->stop();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800440 }
441 }
442 }
443 }
444
445 return OK;
446}
447
448void PreviewPlayer::onStreamDone() {
James Dong00f742c2012-01-13 17:34:42 -0800449 ALOGV("onStreamDone");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800450 // Posted whenever any stream finishes playing.
451
452 Mutex::Autolock autoLock(mLock);
453 if (!mStreamDoneEventPending) {
454 return;
455 }
456 mStreamDoneEventPending = false;
457
458 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
Steve Block2703f232011-10-20 11:56:09 +0100459 ALOGV("MEDIA_ERROR %d", mStreamDoneStatus);
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800460
461 notifyListener_l(
462 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
463
464 pause_l(true /* at eos */);
465
466 mFlags |= AT_EOS;
467 return;
468 }
469
470 const bool allDone =
471 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
472 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
473
474 if (!allDone) {
475 return;
476 }
477
478 if (mFlags & (LOOPING | AUTO_LOOPING)) {
479 seekTo_l(0);
480
481 if (mVideoSource != NULL) {
482 postVideoEvent_l();
483 }
484 } else {
Steve Block2703f232011-10-20 11:56:09 +0100485 ALOGV("MEDIA_PLAYBACK_COMPLETE");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800486 //pause before sending event
487 pause_l(true /* at eos */);
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700488
489 //This lock is used to syncronize onStreamDone() in PreviewPlayer and
490 //stopPreview() in PreviewController
491 Mutex::Autolock autoLock(mLockControl);
Hong Tenge0180232011-09-28 18:40:38 -0700492 /* Make sure PreviewPlayer only notifies MEDIA_PLAYBACK_COMPLETE once for each clip!
493 * It happens twice in following scenario.
494 * To make the clips in preview storyboard are played and switched smoothly,
495 * PreviewController uses two PreviewPlayer instances and one AudioPlayer.
496 * The two PreviewPlayer use the same AudioPlayer to play the audio,
497 * and change the audio source of the AudioPlayer.
498 * If the audio source of current playing clip and next clip are dummy
499 * audio source(image or video without audio), it will not change the audio source
500 * to avoid the "audio glitch", and keep using the current audio source.
501 * When the video of current clip reached the EOS, PreviewPlayer will set EOS flag
502 * for video and audio, and it will notify MEDIA_PLAYBACK_COMPLETE.
503 * But the audio(dummy audio source) is still playing(for next clip),
504 * and when it reached the EOS, and video reached EOS,
505 * PreviewPlayer will notify MEDIA_PLAYBACK_COMPLETE again. */
506 if (!(mFlags & INFORMED_AV_EOS)) {
507 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
508 mFlags |= INFORMED_AV_EOS;
509 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800510 mFlags |= AT_EOS;
Steve Block2703f232011-10-20 11:56:09 +0100511 ALOGV("onStreamDone end");
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700512 return;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800513 }
514}
515
516
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800517status_t PreviewPlayer::play_l() {
James Dong00f742c2012-01-13 17:34:42 -0800518 ALOGV("play_l");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800519
Rajneesh Chowdury8b95de22011-02-16 15:32:06 -0800520 mFlags &= ~SEEK_PREVIEW;
521
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800522 if (mFlags & PLAYING) {
523 return OK;
524 }
525 mStartNextPlayer = false;
526
527 if (!(mFlags & PREPARED)) {
528 status_t err = prepare_l();
529
530 if (err != OK) {
531 return err;
532 }
533 }
534
535 mFlags |= PLAYING;
536 mFlags |= FIRST_FRAME;
537
538 bool deferredAudioSeek = false;
539
540 if (mAudioSource != NULL) {
541 if (mAudioPlayer == NULL) {
542 if (mAudioSink != NULL) {
543
544 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800545 mAudioPlayer->setSource(mAudioSource);
546
James Dong727f9e12012-01-20 13:09:13 -0800547 mAudioPlayer->setAudioMixSettings(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800548 mPreviewPlayerAudioMixSettings);
549
James Dong727f9e12012-01-20 13:09:13 -0800550 mAudioPlayer->setAudioMixPCMFileHandle(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800551 mAudioMixPCMFileHandle);
552
James Dong727f9e12012-01-20 13:09:13 -0800553 mAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800554 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
555 mCurrentMediaVolumeValue);
556
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800557 mFlags |= AUDIOPLAYER_STARTED;
558 // We've already started the MediaSource in order to enable
559 // the prefetcher to read its data.
James Dong727f9e12012-01-20 13:09:13 -0800560 status_t err = mAudioPlayer->start(
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800561 true /* sourceAlreadyStarted */);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800562
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800563 if (err != OK) {
564 //delete mAudioPlayer;
565 mAudioPlayer = NULL;
566
567 mFlags &= ~(PLAYING | FIRST_FRAME);
568 return err;
569 }
570
James Dong727f9e12012-01-20 13:09:13 -0800571 mTimeSource = mAudioPlayer;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800572 mFlags |= AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800573 deferredAudioSeek = true;
574 mWatchForAudioSeekComplete = false;
575 mWatchForAudioEOS = true;
576 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800577 } else {
James Dong727f9e12012-01-20 13:09:13 -0800578 bool isAudioPlayerStarted = mAudioPlayer->isStarted();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800579
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800580 if (mIsChangeSourceRequired == true) {
Steve Block2703f232011-10-20 11:56:09 +0100581 ALOGV("play_l: Change audio source required");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800582
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800583 if (isAudioPlayerStarted == true) {
James Dong727f9e12012-01-20 13:09:13 -0800584 mAudioPlayer->pause();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800585 }
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800586
James Dong727f9e12012-01-20 13:09:13 -0800587 mAudioPlayer->setSource(mAudioSource);
588 mAudioPlayer->setObserver(this);
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800589
James Dong727f9e12012-01-20 13:09:13 -0800590 mAudioPlayer->setAudioMixSettings(
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800591 mPreviewPlayerAudioMixSettings);
592
James Dong727f9e12012-01-20 13:09:13 -0800593 mAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800594 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
595 mCurrentMediaVolumeValue);
596
597 if (isAudioPlayerStarted == true) {
James Dong727f9e12012-01-20 13:09:13 -0800598 mAudioPlayer->resume();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800599 } else {
600 status_t err = OK;
James Dong727f9e12012-01-20 13:09:13 -0800601 err = mAudioPlayer->start(true);
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800602 if (err != OK) {
603 mAudioPlayer = NULL;
James Dong727f9e12012-01-20 13:09:13 -0800604 mAudioPlayer = NULL;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800605
606 mFlags &= ~(PLAYING | FIRST_FRAME);
607 return err;
608 }
609 }
610 } else {
Steve Block2703f232011-10-20 11:56:09 +0100611 ALOGV("play_l: No Source change required");
James Dong727f9e12012-01-20 13:09:13 -0800612 mAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800613 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
614 mCurrentMediaVolumeValue);
615
James Dong727f9e12012-01-20 13:09:13 -0800616 mAudioPlayer->resume();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800617 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800618
619 mFlags |= AUDIOPLAYER_STARTED;
620 mFlags |= AUDIO_RUNNING;
James Dong727f9e12012-01-20 13:09:13 -0800621 mTimeSource = mAudioPlayer;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800622 deferredAudioSeek = true;
623 mWatchForAudioSeekComplete = false;
624 mWatchForAudioEOS = true;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800625 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800626 }
627
628 if (mTimeSource == NULL && mAudioPlayer == NULL) {
629 mTimeSource = &mSystemTimeSource;
630 }
631
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800632 // Set the seek option for Image source files and read.
633 // This resets the timestamping for image play
634 if (mIsVideoSourceJpg) {
635 MediaSource::ReadOptions options;
636 MediaBuffer *aLocalBuffer;
637 options.setSeekTo(mSeekTimeUs);
638 mVideoSource->read(&aLocalBuffer, &options);
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800639 aLocalBuffer->release();
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800640 }
641
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800642 if (mVideoSource != NULL) {
643 // Kick off video playback
644 postVideoEvent_l();
645 }
646
647 if (deferredAudioSeek) {
648 // If there was a seek request while we were paused
649 // and we're just starting up again, honor the request now.
650 seekAudioIfNecessary_l();
651 }
652
653 if (mFlags & AT_EOS) {
654 // Legacy behaviour, if a stream finishes playing and then
655 // is started again, we play from the start...
656 seekTo_l(0);
657 }
658
659 return OK;
660}
661
662
Santosh Madhavabfece172011-02-03 16:59:47 -0800663status_t PreviewPlayer::initRenderer_l() {
Mathias Agopian6e224292011-04-05 15:38:24 -0700664 if (mSurface != NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800665 if(mVideoRenderer == NULL) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800666 mVideoRenderer = mNativeWindowRenderer->createRenderInput();
667 if (mVideoSource != NULL) {
668 updateSizeToRender(mVideoSource->getFormat());
Santosh Madhavabfece172011-02-03 16:59:47 -0800669 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800670 }
671 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800672 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800673}
674
675
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800676status_t PreviewPlayer::seekTo(int64_t timeUs) {
James Dong00f742c2012-01-13 17:34:42 -0800677 Mutex::Autolock autoLock(mLock);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800678 if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800679 return seekTo_l(timeUs);
680 }
681
682 return OK;
683}
684
685
686status_t PreviewPlayer::getVideoDimensions(
687 int32_t *width, int32_t *height) const {
688 Mutex::Autolock autoLock(mLock);
689
690 if (mVideoWidth < 0 || mVideoHeight < 0) {
691 return UNKNOWN_ERROR;
692 }
693
694 *width = mVideoWidth;
695 *height = mVideoHeight;
696
697 return OK;
698}
699
700
James Dong00f742c2012-01-13 17:34:42 -0800701status_t PreviewPlayer::initAudioDecoder_l() {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800702 sp<MetaData> meta = mAudioTrack->getFormat();
703 const char *mime;
704 CHECK(meta->findCString(kKeyMIMEType, &mime));
705
706 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
707 mAudioSource = mAudioTrack;
708 } else {
709 sp<MediaSource> aRawSource;
710 aRawSource = OMXCodec::Create(
711 mClient.interface(), mAudioTrack->getFormat(),
712 false, // createEncoder
713 mAudioTrack);
714
715 if(aRawSource != NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800716 mAudioSource = new VideoEditorSRC(aRawSource);
717 }
718 }
719
720 if (mAudioSource != NULL) {
721 int64_t durationUs;
722 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
James Dong00f742c2012-01-13 17:34:42 -0800723 setDuration_l(durationUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800724 }
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
James Dong00f742c2012-01-13 17:34:42 -0800741status_t PreviewPlayer::initVideoDecoder_l(uint32_t flags) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800742 initRenderer_l();
743
744 if (mVideoRenderer == NULL) {
Steve Blockf8bd29c2012-01-08 10:14:44 +0000745 ALOGE("Cannot create renderer");
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800746 return UNKNOWN_ERROR;
747 }
748
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800749 mVideoSource = OMXCodec::Create(
750 mClient.interface(), mVideoTrack->getFormat(),
751 false,
752 mVideoTrack,
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800753 NULL, flags, mVideoRenderer->getTargetWindow());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800754
755 if (mVideoSource != NULL) {
756 int64_t durationUs;
757 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
James Dong00f742c2012-01-13 17:34:42 -0800758 setDuration_l(durationUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800759 }
760
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800761 updateSizeToRender(mVideoTrack->getFormat());
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800762
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800763 status_t err = mVideoSource->start();
764
765 if (err != OK) {
766 mVideoSource.clear();
767 return err;
768 }
769 }
770
771 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
772}
773
774
775void PreviewPlayer::onVideoEvent() {
776 uint32_t i=0;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800777 M4OSA_ERR err1 = M4NO_ERROR;
778 int64_t imageFrameTimeUs = 0;
779
780 Mutex::Autolock autoLock(mLock);
781 if (!mVideoEventPending) {
782 // The event has been cancelled in reset_l() but had already
783 // been scheduled for execution at that time.
784 return;
785 }
786 mVideoEventPending = false;
787
Andreas Huber9e4c36a2011-02-08 13:12:32 -0800788 if (mFlags & SEEK_PREVIEW) {
789 mFlags &= ~SEEK_PREVIEW;
790 return;
791 }
792
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800793 TimeSource *ts_st = &mSystemTimeSource;
794 int64_t timeStartUs = ts_st->getRealTimeUs();
795
Andreas Hubera5872f72011-02-24 15:25:21 -0800796 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800797
798 if(mAudioSource != NULL) {
799
800 // We're going to seek the video source first, followed by
801 // the audio source.
802 // In order to avoid jumps in the DataSource offset caused by
803 // the audio codec prefetching data from the old locations
804 // while the video codec is already reading data from the new
805 // locations, we'll "pause" the audio source, causing it to
806 // stop reading input data until a subsequent seek.
807
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800808 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800809 mAudioPlayer->pause();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800810 mFlags &= ~AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800811 }
812 mAudioSource->pause();
813 }
814 }
815
816 if (!mVideoBuffer) {
817 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -0800818 if (mSeeking != NO_SEEK) {
Steve Block2703f232011-10-20 11:56:09 +0100819 ALOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800820 mSeekTimeUs / 1E6);
821
822 options.setSeekTo(
823 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
824 }
825 for (;;) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800826 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800827 options.clearSeekTo();
828
829 if (err != OK) {
James Dong00f742c2012-01-13 17:34:42 -0800830 CHECK(!mVideoBuffer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800831
832 if (err == INFO_FORMAT_CHANGED) {
Steve Block2703f232011-10-20 11:56:09 +0100833 ALOGV("LV PLAYER VideoSource signalled format change");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800834 notifyVideoSize_l();
835
836 if (mVideoRenderer != NULL) {
837 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -0800838 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800839 if (err != OK) {
840 postStreamDoneEvent_l(err);
841 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800842
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800843 }
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800844
845 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800846 continue;
847 }
848 // So video playback is complete, but we may still have
Santosh Madhava342f9322011-01-27 16:27:12 -0800849 // a seek request pending that needs to be applied to the audio track
Andreas Hubera5872f72011-02-24 15:25:21 -0800850 if (mSeeking != NO_SEEK) {
Steve Block2703f232011-10-20 11:56:09 +0100851 ALOGV("video stream ended while seeking!");
Santosh Madhava342f9322011-01-27 16:27:12 -0800852 }
853 finishSeekIfNecessary(-1);
Steve Block2703f232011-10-20 11:56:09 +0100854 ALOGV("PreviewPlayer: onVideoEvent EOS reached.");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800855 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800856 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800857 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800858 postStreamDoneEvent_l(err);
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800859 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -0700860 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800861 return;
862 }
863
864 if (mVideoBuffer->range_length() == 0) {
865 // Some decoders, notably the PV AVC software decoder
866 // return spurious empty buffers that we just want to ignore.
867
868 mVideoBuffer->release();
869 mVideoBuffer = NULL;
870 continue;
871 }
872
873 int64_t videoTimeUs;
874 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
875
Andreas Hubera5872f72011-02-24 15:25:21 -0800876 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800877 if (videoTimeUs < mSeekTimeUs) {
878 // buffers are before seek time
879 // ignore them
880 mVideoBuffer->release();
881 mVideoBuffer = NULL;
882 continue;
883 }
884 } else {
885 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
886 // Frames are before begin cut time
887 // Donot render
888 mVideoBuffer->release();
889 mVideoBuffer = NULL;
890 continue;
891 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800892 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800893 break;
894 }
895 }
896
897 mNumberDecVideoFrames++;
898
899 int64_t timeUs;
900 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
James Dong00f742c2012-01-13 17:34:42 -0800901 setPosition_l(timeUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800902
James Dong00f742c2012-01-13 17:34:42 -0800903 if (!mStartNextPlayer) {
904 int64_t playbackTimeRemaining = (mPlayEndTimeMsec * 1000LL) - timeUs;
905 if (playbackTimeRemaining <= 1500000) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800906 //When less than 1.5 sec of playback left
907 // send notification to start next player
908
909 mStartNextPlayer = true;
910 notifyListener_l(0xAAAAAAAA);
911 }
912 }
913
Andreas Hubera5872f72011-02-24 15:25:21 -0800914 SeekType wasSeeking = mSeeking;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800915 finishSeekIfNecessary(timeUs);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800916 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING))) {
917 status_t err = startAudioPlayer_l();
918 if (err != OK) {
Steve Blockf8bd29c2012-01-08 10:14:44 +0000919 ALOGE("Starting the audio player failed w/ err %d", err);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800920 return;
921 }
922 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800923
924 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
925
926 if(ts == NULL) {
927 mVideoBuffer->release();
928 mVideoBuffer = NULL;
929 return;
930 }
931
932 if(!mIsVideoSourceJpg) {
933 if (mFlags & FIRST_FRAME) {
934 mFlags &= ~FIRST_FRAME;
935
936 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
937 }
938
939 int64_t realTimeUs, mediaTimeUs;
940 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
941 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
942 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
943 }
944
945 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
946
947 int64_t latenessUs = nowUs - timeUs;
948
Andreas Hubera5872f72011-02-24 15:25:21 -0800949 if (wasSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800950 // Let's display the first frame after seeking right away.
951 latenessUs = 0;
952 }
Steve Block2703f232011-10-20 11:56:09 +0100953 ALOGV("Audio time stamp = %lld and video time stamp = %lld",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800954 ts->getRealTimeUs(),timeUs);
955 if (latenessUs > 40000) {
956 // We're more than 40ms late.
957
Steve Block2703f232011-10-20 11:56:09 +0100958 ALOGV("LV PLAYER we're late by %lld us (%.2f secs)",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800959 latenessUs, latenessUs / 1E6);
960
961 mVideoBuffer->release();
962 mVideoBuffer = NULL;
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800963 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800964 return;
965 }
966
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800967 if (latenessUs < -25000) {
968 // We're more than 25ms early.
Steve Block2703f232011-10-20 11:56:09 +0100969 ALOGV("We're more than 25ms early, lateness %lld", latenessUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800970
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800971 postVideoEvent_l(25000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800972 return;
973 }
974 }
975
976 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
977 mVideoRendererIsPreview = false;
978
Santosh Madhavabfece172011-02-03 16:59:47 -0800979 status_t err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800980 if (err != OK) {
981 postStreamDoneEvent_l(err);
982 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800983 }
984
985 // If timestamp exceeds endCutTime of clip, donot render
986 if((timeUs/1000) > mPlayEndTimeMsec) {
Chih-Chung Changcece4b32011-08-01 16:34:05 +0800987 mVideoBuffer->release();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800988 mVideoBuffer = NULL;
989 mFlags |= VIDEO_AT_EOS;
990 mFlags |= AUDIO_AT_EOS;
Steve Block2703f232011-10-20 11:56:09 +0100991 ALOGV("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS..");
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800992 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -0800993 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -0700994 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800995 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
996 return;
997 }
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800998 // Capture the frame timestamp to be rendered
999 mDecodedVideoTs = timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001000
1001 // Post processing to apply video effects
1002 for(i=0;i<mNumberEffects;i++) {
1003 // First check if effect starttime matches the clip being previewed
1004 if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) ||
1005 (mEffectsSettings[i].uiStartTime >=
1006 ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec)))
1007 {
1008 // This effect doesn't belong to this clip, check next one
1009 continue;
1010 }
1011 // Check if effect applies to this particular frame timestamp
1012 if((mEffectsSettings[i].uiStartTime <=
1013 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) &&
1014 ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=
1015 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec))
1016 && (mEffectsSettings[i].uiDuration != 0)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001017 setVideoPostProcessingNode(
1018 mEffectsSettings[i].VideoEffectType, TRUE);
1019 }
1020 else {
1021 setVideoPostProcessingNode(
1022 mEffectsSettings[i].VideoEffectType, FALSE);
1023 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001024 }
1025
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001026 //Provide the overlay Update indication when there is an overlay effect
Dharmaray Kundargid01ef562011-01-26 21:11:00 -08001027 if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) {
1028 mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here.
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001029 if (!mOverlayUpdateEventPosted) {
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001030 // Find the effect in effectSettings array
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001031 M4OSA_UInt32 index;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001032 for (index = 0; index < mNumberEffects; index++) {
1033 M4OSA_UInt32 timeMs = mDecodedVideoTs/1000;
1034 M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000;
1035 if(mEffectsSettings[index].VideoEffectType ==
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001036 (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001037 if (((mEffectsSettings[index].uiStartTime + 1) <=
1038 timeMs + timeOffset - mPlayBeginTimeMsec) &&
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001039 ((mEffectsSettings[index].uiStartTime - 1 +
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001040 mEffectsSettings[index].uiDuration) >=
1041 timeMs + timeOffset - mPlayBeginTimeMsec))
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001042 {
1043 break;
1044 }
1045 }
1046 }
1047 if (index < mNumberEffects) {
1048 mCurrFramingEffectIndex = index;
1049 mOverlayUpdateEventPosted = true;
1050 postOverlayUpdateEvent_l();
James Dong00f742c2012-01-13 17:34:42 -08001051 ALOGV("Framing index = %ld", mCurrFramingEffectIndex);
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001052 } else {
Steve Block2703f232011-10-20 11:56:09 +01001053 ALOGV("No framing effects found");
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001054 }
1055 }
1056
1057 } else if (mOverlayUpdateEventPosted) {
1058 //Post the event when the overlay is no more valid
Steve Block2703f232011-10-20 11:56:09 +01001059 ALOGV("Overlay is Done");
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001060 mOverlayUpdateEventPosted = false;
1061 postOverlayUpdateEvent_l();
1062 }
1063
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001064 if (mVideoRenderer != NULL) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001065 mVideoRenderer->render(mVideoBuffer, mCurrentVideoEffect,
1066 mRenderingMode, mIsVideoSourceJpg);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001067 }
1068
Chih-Chung Changcece4b32011-08-01 16:34:05 +08001069 mVideoBuffer->release();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001070 mVideoBuffer = NULL;
1071
1072 // Post progress callback based on callback interval set
1073 if(mNumberDecVideoFrames >= mProgressCbInterval) {
1074 postProgressCallbackEvent_l();
1075 mNumberDecVideoFrames = 0; // reset counter
1076 }
1077
1078 // if reached EndCutTime of clip, post EOS event
1079 if((timeUs/1000) >= mPlayEndTimeMsec) {
Steve Block2703f232011-10-20 11:56:09 +01001080 ALOGV("PreviewPlayer: onVideoEvent EOS.");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001081 mFlags |= VIDEO_AT_EOS;
1082 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001083 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001084 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001085 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001086 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1087 }
1088 else {
Andreas Hubera5872f72011-02-24 15:25:21 -08001089 if ((wasSeeking != NO_SEEK) && (mFlags & SEEK_PREVIEW)) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001090 mFlags &= ~SEEK_PREVIEW;
1091 return;
1092 }
1093
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001094 if(!mIsVideoSourceJpg) {
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001095 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001096 }
1097 else {
1098 postVideoEvent_l(33000);
1099 }
1100 }
1101}
1102
1103status_t PreviewPlayer::prepare() {
James Dong00f742c2012-01-13 17:34:42 -08001104 ALOGV("prepare");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001105 Mutex::Autolock autoLock(mLock);
1106 return prepare_l();
1107}
1108
1109status_t PreviewPlayer::prepare_l() {
James Dong00f742c2012-01-13 17:34:42 -08001110 ALOGV("prepare_l");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001111 if (mFlags & PREPARED) {
1112 return OK;
1113 }
1114
1115 if (mFlags & PREPARING) {
1116 return UNKNOWN_ERROR;
1117 }
1118
1119 mIsAsyncPrepare = false;
1120 status_t err = prepareAsync_l();
1121
1122 if (err != OK) {
1123 return err;
1124 }
1125
1126 while (mFlags & PREPARING) {
1127 mPreparedCondition.wait(mLock);
1128 }
1129
1130 return mPrepareResult;
1131}
1132
James Dong00f742c2012-01-13 17:34:42 -08001133status_t PreviewPlayer::prepareAsync() {
1134 ALOGV("prepareAsync");
1135 Mutex::Autolock autoLock(mLock);
1136 return prepareAsync_l();
1137}
1138
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001139status_t PreviewPlayer::prepareAsync_l() {
James Dong00f742c2012-01-13 17:34:42 -08001140 ALOGV("prepareAsync_l");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001141 if (mFlags & PREPARING) {
1142 return UNKNOWN_ERROR; // async prepare already pending
1143 }
1144
1145 if (!mQueueStarted) {
1146 mQueue.start();
1147 mQueueStarted = true;
1148 }
1149
1150 mFlags |= PREPARING;
1151 mAsyncPrepareEvent = new PreviewPlayerEvent(
1152 this, &PreviewPlayer::onPrepareAsyncEvent);
1153
1154 mQueue.postEvent(mAsyncPrepareEvent);
1155
1156 return OK;
1157}
1158
1159status_t PreviewPlayer::finishSetDataSource_l() {
1160 sp<DataSource> dataSource;
1161 sp<MediaExtractor> extractor;
1162
James Dongdaeb5b32012-01-12 12:12:40 -08001163 dataSource = DataSource::CreateFromURI(mUri.string(), NULL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001164
1165 if (dataSource == NULL) {
1166 return UNKNOWN_ERROR;
1167 }
1168
1169 //If file type is .rgb, then no need to check for Extractor
1170 int uriLen = strlen(mUri);
1171 int startOffset = uriLen - 4;
1172 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) {
1173 extractor = NULL;
1174 }
1175 else {
1176 extractor = MediaExtractor::Create(dataSource,
1177 MEDIA_MIMETYPE_CONTAINER_MPEG4);
1178 }
1179
1180 if (extractor == NULL) {
James Dong00f742c2012-01-13 17:34:42 -08001181 ALOGV("finishSetDataSource_l: failed to create extractor");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001182 return setDataSource_l_jpg();
1183 }
1184
1185 return setDataSource_l(extractor);
1186}
1187
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001188void PreviewPlayer::onPrepareAsyncEvent() {
1189 Mutex::Autolock autoLock(mLock);
Steve Block2703f232011-10-20 11:56:09 +01001190 ALOGV("onPrepareAsyncEvent");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001191
1192 if (mFlags & PREPARE_CANCELLED) {
James Dong00f742c2012-01-13 17:34:42 -08001193 ALOGV("prepare was cancelled before doing anything");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001194 abortPrepare(UNKNOWN_ERROR);
1195 return;
1196 }
1197
1198 if (mUri.size() > 0) {
1199 status_t err = finishSetDataSource_l();
1200
1201 if (err != OK) {
1202 abortPrepare(err);
1203 return;
1204 }
1205 }
1206
1207 if (mVideoTrack != NULL && mVideoSource == NULL) {
James Dong00f742c2012-01-13 17:34:42 -08001208 status_t err = initVideoDecoder_l(OMXCodec::kHardwareCodecsOnly);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001209
1210 if (err != OK) {
1211 abortPrepare(err);
1212 return;
1213 }
1214 }
1215
1216 if (mAudioTrack != NULL && mAudioSource == NULL) {
James Dong00f742c2012-01-13 17:34:42 -08001217 status_t err = initAudioDecoder_l();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001218
1219 if (err != OK) {
1220 abortPrepare(err);
1221 return;
1222 }
1223 }
1224 finishAsyncPrepare_l();
1225
1226}
1227
1228void PreviewPlayer::finishAsyncPrepare_l() {
James Dong00f742c2012-01-13 17:34:42 -08001229 ALOGV("finishAsyncPrepare_l");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001230 if (mIsAsyncPrepare) {
1231 if (mVideoSource == NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001232 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1233 } else {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001234 notifyVideoSize_l();
1235 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001236 notifyListener_l(MEDIA_PREPARED);
1237 }
1238
1239 mPrepareResult = OK;
1240 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1241 mFlags |= PREPARED;
1242 mAsyncPrepareEvent = NULL;
1243 mPreparedCondition.broadcast();
1244}
1245
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001246void PreviewPlayer::acquireLock() {
Steve Block2703f232011-10-20 11:56:09 +01001247 ALOGV("acquireLock");
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001248 mLockControl.lock();
1249}
1250
1251void PreviewPlayer::releaseLock() {
Steve Block2703f232011-10-20 11:56:09 +01001252 ALOGV("releaseLock");
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001253 mLockControl.unlock();
1254}
1255
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001256status_t PreviewPlayer::loadEffectsSettings(
James Dong00f742c2012-01-13 17:34:42 -08001257 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001258
James Dong00f742c2012-01-13 17:34:42 -08001259 ALOGV("loadEffectsSettings");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001260 mNumberEffects = nEffects;
1261 mEffectsSettings = pEffectSettings;
1262 return OK;
1263}
1264
1265status_t PreviewPlayer::loadAudioMixSettings(
James Dong00f742c2012-01-13 17:34:42 -08001266 M4xVSS_AudioMixingSettings* pAudioMixSettings) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001267
James Dong00f742c2012-01-13 17:34:42 -08001268 ALOGV("loadAudioMixSettings");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001269 mPreviewPlayerAudioMixSettings = pAudioMixSettings;
1270 return OK;
1271}
1272
1273status_t PreviewPlayer::setAudioMixPCMFileHandle(
James Dong00f742c2012-01-13 17:34:42 -08001274 M4OSA_Context pAudioMixPCMFileHandle) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001275
James Dong00f742c2012-01-13 17:34:42 -08001276 ALOGV("setAudioMixPCMFileHandle");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001277 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle;
1278 return OK;
1279}
1280
1281status_t PreviewPlayer::setAudioMixStoryBoardParam(
James Dong00f742c2012-01-13 17:34:42 -08001282 M4OSA_UInt32 audioMixStoryBoardTS,
1283 M4OSA_UInt32 currentMediaBeginCutTime,
1284 M4OSA_UInt32 primaryTrackVolValue ) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001285
James Dong00f742c2012-01-13 17:34:42 -08001286 ALOGV("setAudioMixStoryBoardParam");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001287 mAudioMixStoryBoardTS = audioMixStoryBoardTS;
1288 mCurrentMediaBeginCutTime = currentMediaBeginCutTime;
1289 mCurrentMediaVolumeValue = primaryTrackVolValue;
1290 return OK;
1291}
1292
1293status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) {
1294
1295 mPlayBeginTimeMsec = msec;
1296 return OK;
1297}
1298
1299status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) {
1300
1301 mPlayEndTimeMsec = msec;
1302 return OK;
1303}
1304
1305status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) {
1306
1307 mStoryboardStartTimeMsec = msec;
James Dong00f742c2012-01-13 17:34:42 -08001308 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec * 1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001309 return OK;
1310}
1311
1312status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) {
1313
1314 mProgressCbInterval = cbInterval;
1315 return OK;
1316}
1317
1318
1319status_t PreviewPlayer::setMediaRenderingMode(
1320 M4xVSS_MediaRendering mode,
1321 M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
1322
1323 mRenderingMode = mode;
1324
Hong Teng8806b702011-07-06 18:29:28 -07001325 /* get the video width and height by resolution */
James Dong00f742c2012-01-13 17:34:42 -08001326 return getVideoSizeByResolution(
1327 outputVideoSize,
1328 &mOutputVideoWidth, &mOutputVideoHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001329
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001330}
1331
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001332status_t PreviewPlayer::resetJniCallbackTimeStamp() {
1333
James Dong00f742c2012-01-13 17:34:42 -08001334 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec * 1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001335 return OK;
1336}
1337
1338void PreviewPlayer::postProgressCallbackEvent_l() {
1339 if (mProgressCbEventPending) {
1340 return;
1341 }
1342 mProgressCbEventPending = true;
1343
1344 mQueue.postEvent(mProgressCbEvent);
1345}
1346
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001347
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001348void PreviewPlayer::onProgressCbEvent() {
1349 Mutex::Autolock autoLock(mLock);
1350 if (!mProgressCbEventPending) {
1351 return;
1352 }
1353 mProgressCbEventPending = false;
1354 // If playback starts from previous I-frame,
1355 // then send frame storyboard duration
James Dong00f742c2012-01-13 17:34:42 -08001356 if ((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001357 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000);
James Dong00f742c2012-01-13 17:34:42 -08001358 } else {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001359 notifyListener_l(MEDIA_INFO, 0,
1360 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec));
1361 }
1362}
1363
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001364void PreviewPlayer::postOverlayUpdateEvent_l() {
1365 if (mOverlayUpdateEventPending) {
1366 return;
1367 }
1368 mOverlayUpdateEventPending = true;
1369 mQueue.postEvent(mOverlayUpdateEvent);
1370}
1371
1372void PreviewPlayer::onUpdateOverlayEvent() {
1373 Mutex::Autolock autoLock(mLock);
1374
1375 if (!mOverlayUpdateEventPending) {
1376 return;
1377 }
1378 mOverlayUpdateEventPending = false;
1379
James Dong00f742c2012-01-13 17:34:42 -08001380 int updateState = mOverlayUpdateEventPosted? 1: 0;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001381 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex);
1382}
1383
1384
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001385void PreviewPlayer::setVideoPostProcessingNode(
James Dong00f742c2012-01-13 17:34:42 -08001386 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001387
1388 uint32_t effect = VIDEO_EFFECT_NONE;
1389
1390 //Map M4VSS3GPP_VideoEffectType to local enum
1391 switch(type) {
1392 case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
1393 effect = VIDEO_EFFECT_FADEFROMBLACK;
1394 break;
1395
1396 case M4VSS3GPP_kVideoEffectType_FadeToBlack:
1397 effect = VIDEO_EFFECT_FADETOBLACK;
1398 break;
1399
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001400 case M4xVSS_kVideoEffectType_BlackAndWhite:
1401 effect = VIDEO_EFFECT_BLACKANDWHITE;
1402 break;
1403
1404 case M4xVSS_kVideoEffectType_Pink:
1405 effect = VIDEO_EFFECT_PINK;
1406 break;
1407
1408 case M4xVSS_kVideoEffectType_Green:
1409 effect = VIDEO_EFFECT_GREEN;
1410 break;
1411
1412 case M4xVSS_kVideoEffectType_Sepia:
1413 effect = VIDEO_EFFECT_SEPIA;
1414 break;
1415
1416 case M4xVSS_kVideoEffectType_Negative:
1417 effect = VIDEO_EFFECT_NEGATIVE;
1418 break;
1419
1420 case M4xVSS_kVideoEffectType_Framing:
1421 effect = VIDEO_EFFECT_FRAMING;
1422 break;
1423
1424 case M4xVSS_kVideoEffectType_Fifties:
1425 effect = VIDEO_EFFECT_FIFTIES;
1426 break;
1427
1428 case M4xVSS_kVideoEffectType_ColorRGB16:
1429 effect = VIDEO_EFFECT_COLOR_RGB16;
1430 break;
1431
1432 case M4xVSS_kVideoEffectType_Gradient:
1433 effect = VIDEO_EFFECT_GRADIENT;
1434 break;
1435
1436 default:
1437 effect = VIDEO_EFFECT_NONE;
1438 break;
1439 }
1440
James Dong00f742c2012-01-13 17:34:42 -08001441 if (enable == M4OSA_TRUE) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001442 //If already set, then no need to set again
James Dong00f742c2012-01-13 17:34:42 -08001443 if (!(mCurrentVideoEffect & effect)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001444 mCurrentVideoEffect |= effect;
James Dong00f742c2012-01-13 17:34:42 -08001445 if (effect == VIDEO_EFFECT_FIFTIES) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001446 mIsFiftiesEffectStarted = true;
1447 }
1448 }
James Dong00f742c2012-01-13 17:34:42 -08001449 } else {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001450 //Reset only if already set
James Dong00f742c2012-01-13 17:34:42 -08001451 if (mCurrentVideoEffect & effect) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001452 mCurrentVideoEffect &= ~effect;
1453 }
1454 }
1455}
1456
1457status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) {
1458 mVideoWidth = width;
1459 mVideoHeight = height;
1460 return OK;
1461}
1462
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001463status_t PreviewPlayer::readFirstVideoFrame() {
James Dong00f742c2012-01-13 17:34:42 -08001464 ALOGV("readFirstVideoFrame");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001465
1466 if (!mVideoBuffer) {
1467 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -08001468 if (mSeeking != NO_SEEK) {
James Dong00f742c2012-01-13 17:34:42 -08001469 ALOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001470 mSeekTimeUs / 1E6);
1471
1472 options.setSeekTo(
1473 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
1474 }
1475 for (;;) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001476 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001477 options.clearSeekTo();
1478
1479 if (err != OK) {
James Dong00f742c2012-01-13 17:34:42 -08001480 CHECK(!mVideoBuffer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001481
1482 if (err == INFO_FORMAT_CHANGED) {
James Dong00f742c2012-01-13 17:34:42 -08001483 ALOGV("VideoSource signalled format change");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001484 notifyVideoSize_l();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001485
1486 if (mVideoRenderer != NULL) {
1487 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -08001488 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001489 if (err != OK) {
1490 postStreamDoneEvent_l(err);
1491 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001492 }
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001493
1494 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001495 continue;
1496 }
James Dong00f742c2012-01-13 17:34:42 -08001497 ALOGV("EOS reached.");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001498 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001499 mFlags |= AUDIO_AT_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001500 postStreamDoneEvent_l(err);
1501 return OK;
1502 }
1503
1504 if (mVideoBuffer->range_length() == 0) {
1505 // Some decoders, notably the PV AVC software decoder
1506 // return spurious empty buffers that we just want to ignore.
1507
1508 mVideoBuffer->release();
1509 mVideoBuffer = NULL;
1510 continue;
1511 }
1512
1513 int64_t videoTimeUs;
1514 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
Andreas Hubera5872f72011-02-24 15:25:21 -08001515 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001516 if (videoTimeUs < mSeekTimeUs) {
1517 // buffers are before seek time
1518 // ignore them
1519 mVideoBuffer->release();
1520 mVideoBuffer = NULL;
1521 continue;
1522 }
1523 } else {
James Dong00f742c2012-01-13 17:34:42 -08001524 if ((videoTimeUs/1000) < mPlayBeginTimeMsec) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001525 // buffers are before begin cut time
1526 // ignore them
1527 mVideoBuffer->release();
1528 mVideoBuffer = NULL;
1529 continue;
1530 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001531 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001532 break;
1533 }
1534 }
1535
1536 int64_t timeUs;
1537 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
James Dong00f742c2012-01-13 17:34:42 -08001538 setPosition_l(timeUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001539
1540 mDecodedVideoTs = timeUs;
1541
1542 return OK;
1543
1544}
1545
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001546status_t PreviewPlayer::getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs) {
1547 *lastRenderedTimeMs = (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec);
1548 return OK;
1549}
1550
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001551void PreviewPlayer::updateSizeToRender(sp<MetaData> meta) {
1552 if (mVideoRenderer) {
1553 mVideoRenderer->updateVideoSize(meta);
1554 }
1555}
1556
James Dong00f742c2012-01-13 17:34:42 -08001557void PreviewPlayer::setListener(const wp<MediaPlayerBase> &listener) {
1558 Mutex::Autolock autoLock(mLock);
1559 mListener = listener;
1560}
1561
1562status_t PreviewPlayer::setDataSource(const sp<IStreamSource> &source) {
1563 return INVALID_OPERATION;
1564}
1565
1566void PreviewPlayer::reset() {
1567 Mutex::Autolock autoLock(mLock);
1568 reset_l();
1569}
1570
1571void PreviewPlayer::clear_l() {
1572 mDisplayWidth = 0;
1573 mDisplayHeight = 0;
1574
1575 if (mFlags & PLAYING) {
1576 updateBatteryUsage_l();
1577 }
1578
1579 if (mFlags & PREPARING) {
1580 mFlags |= PREPARE_CANCELLED;
1581
1582 if (mFlags & PREPARING_CONNECTED) {
1583 // We are basically done preparing, we're just buffering
1584 // enough data to start playback, we can safely interrupt that.
1585 finishAsyncPrepare_l();
1586 }
1587 }
1588
1589 while (mFlags & PREPARING) {
1590 mPreparedCondition.wait(mLock);
1591 }
1592
1593 cancelPlayerEvents_l(true);
1594
1595 mAudioTrack.clear();
1596 mVideoTrack.clear();
1597
1598 // Shutdown audio first, so that the respone to the reset request
1599 // appears to happen instantaneously as far as the user is concerned
1600 // If we did this later, audio would continue playing while we
1601 // shutdown the video-related resources and the player appear to
1602 // not be as responsive to a reset request.
1603 if (mAudioPlayer == NULL && mAudioSource != NULL) {
1604 // If we had an audio player, it would have effectively
1605 // taken possession of the audio source and stopped it when
1606 // _it_ is stopped. Otherwise this is still our responsibility.
1607 mAudioSource->stop();
1608 }
1609 mAudioSource.clear();
1610
1611 mTimeSource = NULL;
1612
1613 delete mAudioPlayer;
1614 mAudioPlayer = NULL;
1615
1616 if (mVideoSource != NULL) {
1617 shutdownVideoDecoder_l();
1618 }
1619
1620 mDurationUs = -1;
1621 mFlags = 0;
1622 mExtractorFlags = 0;
1623 mTimeSourceDeltaUs = 0;
1624 mVideoTimeUs = 0;
1625
1626 mSeeking = NO_SEEK;
1627 mSeekNotificationSent = false;
1628 mSeekTimeUs = 0;
1629
1630 mUri.setTo("");
1631
1632 mBitrate = -1;
1633 mLastVideoTimeUs = -1;
1634}
1635
1636void PreviewPlayer::notifyListener_l(int msg, int ext1, int ext2) {
1637 if (mListener != NULL) {
1638 sp<MediaPlayerBase> listener = mListener.promote();
1639
1640 if (listener != NULL) {
1641 listener->sendEvent(msg, ext1, ext2);
1642 }
1643 }
1644}
1645
1646void PreviewPlayer::onVideoLagUpdate() {
1647 Mutex::Autolock autoLock(mLock);
1648 if (!mVideoLagEventPending) {
1649 return;
1650 }
1651 mVideoLagEventPending = false;
1652
1653 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
1654 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
1655
1656 if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) {
1657 ALOGV("video late by %lld ms.", videoLateByUs / 1000ll);
1658
1659 notifyListener_l(
1660 MEDIA_INFO,
1661 MEDIA_INFO_VIDEO_TRACK_LAGGING,
1662 videoLateByUs / 1000ll);
1663 }
1664
1665 postVideoLagEvent_l();
1666}
1667
1668void PreviewPlayer::notifyVideoSize_l() {
1669 sp<MetaData> meta = mVideoSource->getFormat();
1670
1671 int32_t vWidth, vHeight;
1672 int32_t cropLeft, cropTop, cropRight, cropBottom;
1673
1674 CHECK(meta->findInt32(kKeyWidth, &vWidth));
1675 CHECK(meta->findInt32(kKeyHeight, &vHeight));
1676
1677 mGivenWidth = vWidth;
1678 mGivenHeight = vHeight;
1679
1680 if (!meta->findRect(
1681 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
1682
1683 cropLeft = cropTop = 0;
1684 cropRight = vWidth - 1;
1685 cropBottom = vHeight - 1;
1686
1687 ALOGD("got dimensions only %d x %d", vWidth, vHeight);
1688 } else {
1689 ALOGD("got crop rect %d, %d, %d, %d",
1690 cropLeft, cropTop, cropRight, cropBottom);
1691 }
1692
1693 mCropRect.left = cropLeft;
1694 mCropRect.right = cropRight;
1695 mCropRect.top = cropTop;
1696 mCropRect.bottom = cropBottom;
1697
1698 int32_t displayWidth;
1699 if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
1700 ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
1701 mDisplayWidth = displayWidth;
1702 }
1703 int32_t displayHeight;
1704 if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
1705 ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
1706 mDisplayHeight = displayHeight;
1707 }
1708
1709 int32_t usableWidth = cropRight - cropLeft + 1;
1710 int32_t usableHeight = cropBottom - cropTop + 1;
1711 if (mDisplayWidth != 0) {
1712 usableWidth = mDisplayWidth;
1713 }
1714 if (mDisplayHeight != 0) {
1715 usableHeight = mDisplayHeight;
1716 }
1717
1718 int32_t rotationDegrees;
1719 if (!mVideoTrack->getFormat()->findInt32(
1720 kKeyRotation, &rotationDegrees)) {
1721 rotationDegrees = 0;
1722 }
1723
1724 if (rotationDegrees == 90 || rotationDegrees == 270) {
1725 notifyListener_l(
1726 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
1727 } else {
1728 notifyListener_l(
1729 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
1730 }
1731}
1732
1733status_t PreviewPlayer::pause() {
1734 Mutex::Autolock autoLock(mLock);
1735
1736 mFlags &= ~CACHE_UNDERRUN;
1737
1738 return pause_l();
1739}
1740
1741status_t PreviewPlayer::pause_l(bool at_eos) {
1742 if (!(mFlags & PLAYING)) {
1743 return OK;
1744 }
1745
1746 cancelPlayerEvents_l();
1747
1748 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1749 if (at_eos) {
1750 // If we played the audio stream to completion we
1751 // want to make sure that all samples remaining in the audio
1752 // track's queue are played out.
1753 mAudioPlayer->pause(true /* playPendingSamples */);
1754 } else {
1755 mAudioPlayer->pause();
1756 }
1757
1758 mFlags &= ~AUDIO_RUNNING;
1759 }
1760
1761 mFlags &= ~PLAYING;
1762 updateBatteryUsage_l();
1763
1764 return OK;
1765}
1766
1767bool PreviewPlayer::isPlaying() const {
1768 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
1769}
1770
1771void PreviewPlayer::setSurface(const sp<Surface> &surface) {
1772 Mutex::Autolock autoLock(mLock);
1773
1774 mSurface = surface;
1775 setNativeWindow_l(surface);
1776}
1777
Andy McFadden484566c2012-12-18 09:46:54 -08001778void PreviewPlayer::setSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer) {
James Dong00f742c2012-01-13 17:34:42 -08001779 Mutex::Autolock autoLock(mLock);
1780
1781 mSurface.clear();
Andy McFadden484566c2012-12-18 09:46:54 -08001782 if (bufferProducer != NULL) {
Mathias Agopianb1e7cd12013-02-14 17:11:27 -08001783 setNativeWindow_l(new Surface(bufferProducer));
James Dong00f742c2012-01-13 17:34:42 -08001784 }
1785}
1786
1787void PreviewPlayer::shutdownVideoDecoder_l() {
1788 if (mVideoBuffer) {
1789 mVideoBuffer->release();
1790 mVideoBuffer = NULL;
1791 }
1792
1793 mVideoSource->stop();
1794
1795 // The following hack is necessary to ensure that the OMX
1796 // component is completely released by the time we may try
1797 // to instantiate it again.
1798 wp<MediaSource> tmp = mVideoSource;
1799 mVideoSource.clear();
1800 while (tmp.promote() != NULL) {
1801 usleep(1000);
1802 }
1803 IPCThreadState::self()->flushCommands();
1804}
1805
1806void PreviewPlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
1807 mNativeWindow = native;
1808
1809 if (mVideoSource == NULL) {
1810 return;
1811 }
1812
1813 ALOGI("attempting to reconfigure to use new surface");
1814
1815 bool wasPlaying = (mFlags & PLAYING) != 0;
1816
1817 pause_l();
1818
1819 shutdownVideoDecoder_l();
1820
1821 CHECK_EQ(initVideoDecoder_l(), (status_t)OK);
1822
1823 if (mLastVideoTimeUs >= 0) {
1824 mSeeking = SEEK;
1825 mSeekNotificationSent = true;
1826 mSeekTimeUs = mLastVideoTimeUs;
1827 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
1828 }
1829
1830 if (wasPlaying) {
1831 play_l();
1832 }
1833}
1834
1835void PreviewPlayer::setAudioSink(
1836 const sp<MediaPlayerBase::AudioSink> &audioSink) {
1837 Mutex::Autolock autoLock(mLock);
1838
1839 mAudioSink = audioSink;
1840}
1841
1842status_t PreviewPlayer::setLooping(bool shouldLoop) {
1843 Mutex::Autolock autoLock(mLock);
1844
1845 mFlags = mFlags & ~LOOPING;
1846
1847 if (shouldLoop) {
1848 mFlags |= LOOPING;
1849 }
1850
1851 return OK;
1852}
1853
1854void PreviewPlayer::setDuration_l(int64_t durationUs) {
1855 if (mDurationUs < 0 || durationUs > mDurationUs) {
1856 mDurationUs = durationUs;
1857 }
1858}
1859
1860status_t PreviewPlayer::getDuration(int64_t *durationUs) {
1861 Mutex::Autolock autoLock(mLock);
1862 if (mDurationUs < 0) {
1863 return UNKNOWN_ERROR;
1864 }
1865
1866 *durationUs = mDurationUs;
1867 return OK;
1868}
1869
1870status_t PreviewPlayer::getPosition(int64_t *positionUs) {
1871 Mutex::Autolock autoLock(mLock);
1872
1873 if (mSeeking != NO_SEEK) {
1874 *positionUs = mSeekTimeUs;
1875 } else if (mVideoSource != NULL
1876 && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
1877 *positionUs = mVideoTimeUs;
1878 } else if (mAudioPlayer != NULL) {
1879 *positionUs = mAudioPlayer->getMediaTimeUs();
1880 } else {
1881 *positionUs = 0;
1882 }
1883
1884 return OK;
1885}
1886
1887void PreviewPlayer::setPosition_l(int64_t timeUs) {
1888 mVideoTimeUs = timeUs;
1889}
1890
1891status_t PreviewPlayer::seekTo_l(int64_t timeUs) {
1892 ALOGV("seekTo_l");
1893 if (mFlags & CACHE_UNDERRUN) {
1894 mFlags &= ~CACHE_UNDERRUN;
1895 play_l();
1896 }
1897
1898 if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
1899 // Video playback completed before, there's no pending
1900 // video event right now. In order for this new seek
1901 // to be honored, we need to post one.
1902
1903 postVideoEvent_l();
1904 }
1905
1906 mSeeking = SEEK;
1907 mSeekNotificationSent = false;
1908 mSeekTimeUs = timeUs;
1909 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
1910
1911 seekAudioIfNecessary_l();
1912
1913 if (!(mFlags & PLAYING)) {
1914 ALOGV("seeking while paused, sending SEEK_COMPLETE notification"
1915 " immediately.");
1916
1917 notifyListener_l(MEDIA_SEEK_COMPLETE);
1918 mSeekNotificationSent = true;
1919
1920 if ((mFlags & PREPARED) && mVideoSource != NULL) {
1921 mFlags |= SEEK_PREVIEW;
1922 postVideoEvent_l();
1923 }
1924 }
1925
1926 return OK;
1927}
1928
1929void PreviewPlayer::seekAudioIfNecessary_l() {
1930 if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
1931 mAudioPlayer->seekTo(mSeekTimeUs);
1932
1933 mWatchForAudioSeekComplete = true;
1934 mWatchForAudioEOS = true;
1935 }
1936}
1937
1938void PreviewPlayer::setAudioSource(const sp<MediaSource>& source) {
1939 CHECK(source != NULL);
1940 mAudioTrack = source;
1941}
1942
1943void PreviewPlayer::setVideoSource(const sp<MediaSource>& source) {
1944 CHECK(source != NULL);
1945 mVideoTrack = source;
1946}
1947
1948void PreviewPlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
1949 if (mSeeking == SEEK_VIDEO_ONLY) {
1950 mSeeking = NO_SEEK;
1951 return;
1952 }
1953
1954 if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
1955 return;
1956 }
1957
1958 if (mAudioPlayer != NULL) {
1959 ALOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
1960
1961 // If we don't have a video time, seek audio to the originally
1962 // requested seek time instead.
1963
1964 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
1965 mWatchForAudioSeekComplete = true;
1966 mWatchForAudioEOS = true;
1967 } else if (!mSeekNotificationSent) {
1968 // If we're playing video only, report seek complete now,
1969 // otherwise audio player will notify us later.
1970 notifyListener_l(MEDIA_SEEK_COMPLETE);
1971 mSeekNotificationSent = true;
1972 }
1973
1974 mFlags |= FIRST_FRAME;
1975 mSeeking = NO_SEEK;
1976}
1977
1978void PreviewPlayer::onCheckAudioStatus() {
1979 Mutex::Autolock autoLock(mLock);
1980 if (!mAudioStatusEventPending) {
1981 // Event was dispatched and while we were blocking on the mutex,
1982 // has already been cancelled.
1983 return;
1984 }
1985
1986 mAudioStatusEventPending = false;
1987
1988 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1989 mWatchForAudioSeekComplete = false;
1990
1991 if (!mSeekNotificationSent) {
1992 notifyListener_l(MEDIA_SEEK_COMPLETE);
1993 mSeekNotificationSent = true;
1994 }
1995
1996 mSeeking = NO_SEEK;
1997 }
1998
1999 status_t finalStatus;
2000 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
2001 mWatchForAudioEOS = false;
2002 mFlags |= AUDIO_AT_EOS;
2003 mFlags |= FIRST_FRAME;
2004 postStreamDoneEvent_l(finalStatus);
2005 }
2006}
2007
2008void PreviewPlayer::postVideoEvent_l(int64_t delayUs) {
2009 if (mVideoEventPending) {
2010 return;
2011 }
2012
2013 mVideoEventPending = true;
2014 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
2015}
2016
2017void PreviewPlayer::postStreamDoneEvent_l(status_t status) {
2018 if (mStreamDoneEventPending) {
2019 return;
2020 }
2021 mStreamDoneEventPending = true;
2022
2023 mStreamDoneStatus = status;
2024 mQueue.postEvent(mStreamDoneEvent);
2025}
2026
2027void PreviewPlayer::postVideoLagEvent_l() {
2028 if (mVideoLagEventPending) {
2029 return;
2030 }
2031 mVideoLagEventPending = true;
2032 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
2033}
2034
2035void PreviewPlayer::postCheckAudioStatusEvent_l(int64_t delayUs) {
2036 if (mAudioStatusEventPending) {
2037 return;
2038 }
2039 mAudioStatusEventPending = true;
2040 mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
2041}
2042
2043void PreviewPlayer::abortPrepare(status_t err) {
2044 CHECK(err != OK);
2045
2046 if (mIsAsyncPrepare) {
2047 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2048 }
2049
2050 mPrepareResult = err;
2051 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
2052 mAsyncPrepareEvent = NULL;
2053 mPreparedCondition.broadcast();
2054}
2055
2056uint32_t PreviewPlayer::getSourceSeekFlags() const {
2057 Mutex::Autolock lock(mLock);
2058 return mExtractorFlags;
2059}
2060
2061void PreviewPlayer::postAudioEOS(int64_t delayUs) {
2062 Mutex::Autolock autoLock(mLock);
2063 postCheckAudioStatusEvent_l(delayUs);
2064}
2065
2066void PreviewPlayer::postAudioSeekComplete() {
2067 Mutex::Autolock autoLock(mLock);
2068 postCheckAudioStatusEvent_l(0 /* delayUs */);
2069}
2070
2071void PreviewPlayer::updateBatteryUsage_l() {
2072 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
2073 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
2074 params |= IMediaPlayerService::kBatteryDataTrackAudio;
2075 }
2076 if (mVideoSource != NULL) {
2077 params |= IMediaPlayerService::kBatteryDataTrackVideo;
2078 }
2079 addBatteryData(params);
2080}
2081
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002082} // namespace android