blob: 77c70a5be5c400b272c6c5f24afd3edea304f34f [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>
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080033#include <surfaceflinger/Surface.h>
James Dong00f742c2012-01-13 17:34:42 -080034#include <gui/ISurfaceTexture.h>
35#include <gui/SurfaceTextureClient.h>
36#include <surfaceflinger/ISurfaceComposer.h>
37
38#include "VideoEditorPreviewController.h"
39#include "AudioPlayerBase.h"
40#include "DummyAudioSource.h"
41#include "DummyVideoSource.h"
42#include "VideoEditorSRC.h"
43#include "PreviewPlayer.h"
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080044
45namespace android {
46
47
James Dong00f742c2012-01-13 17:34:42 -080048void addBatteryData(uint32_t params) {
49 sp<IBinder> binder =
50 defaultServiceManager()->getService(String16("media.player"));
51 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
52 CHECK(service.get() != NULL);
53
54 service->addBatteryData(params);
55}
56
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080057struct PreviewPlayerEvent : public TimedEventQueue::Event {
58 PreviewPlayerEvent(
59 PreviewPlayer *player,
60 void (PreviewPlayer::*method)())
61 : mPlayer(player),
62 mMethod(method) {
63 }
64
65protected:
66 virtual ~PreviewPlayerEvent() {}
67
68 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
69 (mPlayer->*mMethod)();
70 }
71
72private:
73 PreviewPlayer *mPlayer;
74 void (PreviewPlayer::*mMethod)();
75
76 PreviewPlayerEvent(const PreviewPlayerEvent &);
77 PreviewPlayerEvent &operator=(const PreviewPlayerEvent &);
78};
79
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080080PreviewPlayer::PreviewPlayer(NativeWindowRenderer* renderer)
James Dong00f742c2012-01-13 17:34:42 -080081 : mQueueStarted(false),
82 mTimeSource(NULL),
83 mVideoRendererIsPreview(false),
84 mAudioPlayer(NULL),
85 mDisplayWidth(0),
86 mDisplayHeight(0),
87 mFlags(0),
88 mExtractorFlags(0),
89 mVideoBuffer(NULL),
90 mLastVideoTimeUs(-1),
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080091 mNativeWindowRenderer(renderer),
92 mCurrFramingEffectIndex(0),
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -080093 mFrameRGBBuffer(NULL),
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080094 mFrameYUVBuffer(NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080095
James Dong00f742c2012-01-13 17:34:42 -080096 CHECK_EQ(mClient.connect(), (status_t)OK);
97 DataSource::RegisterDefaultSniffers();
98
99
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800100 mVideoRenderer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800101 mEffectsSettings = NULL;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800102 mVeAudioPlayer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800103 mAudioMixStoryBoardTS = 0;
104 mCurrentMediaBeginCutTime = 0;
105 mCurrentMediaVolumeValue = 0;
106 mNumberEffects = 0;
107 mDecodedVideoTs = 0;
108 mDecVideoTsStoryBoard = 0;
109 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
110 mProgressCbInterval = 0;
111 mNumberDecVideoFrames = 0;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800112 mOverlayUpdateEventPosted = false;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800113 mIsChangeSourceRequired = true;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800114
115 mVideoEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoEvent);
116 mVideoEventPending = false;
James Dong00f742c2012-01-13 17:34:42 -0800117 mVideoLagEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoLagUpdate);
118 mVideoEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800119 mCheckAudioStatusEvent = new PreviewPlayerEvent(
James Dong00f742c2012-01-13 17:34:42 -0800120 this, &PreviewPlayer::onCheckAudioStatus);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800121 mAudioStatusEventPending = false;
James Dong00f742c2012-01-13 17:34:42 -0800122 mStreamDoneEvent = new PreviewPlayerEvent(
123 this, &PreviewPlayer::onStreamDone);
124 mStreamDoneEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800125 mProgressCbEvent = new PreviewPlayerEvent(this,
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800126 &PreviewPlayer::onProgressCbEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800127
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800128 mOverlayUpdateEvent = new PreviewPlayerEvent(this,
129 &PreviewPlayer::onUpdateOverlayEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800130 mProgressCbEventPending = false;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800131
132 mOverlayUpdateEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800133 mRenderingMode = (M4xVSS_MediaRendering)MEDIA_RENDERING_INVALID;
134 mIsFiftiesEffectStarted = false;
135 reset();
136}
137
138PreviewPlayer::~PreviewPlayer() {
139
140 if (mQueueStarted) {
141 mQueue.stop();
142 }
143
144 reset();
145
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800146 if (mVideoRenderer) {
147 mNativeWindowRenderer->destroyRenderInput(mVideoRenderer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800148 }
James Dong00f742c2012-01-13 17:34:42 -0800149
150 Mutex::Autolock lock(mLock);
151 clear_l();
152 mClient.disconnect();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800153}
154
James Dong00f742c2012-01-13 17:34:42 -0800155void PreviewPlayer::cancelPlayerEvents_l(bool updateProgressCb) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800156 mQueue.cancelEvent(mVideoEvent->eventID());
157 mVideoEventPending = false;
158 mQueue.cancelEvent(mStreamDoneEvent->eventID());
159 mStreamDoneEventPending = false;
160 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
161 mAudioStatusEventPending = false;
James Dong00f742c2012-01-13 17:34:42 -0800162 mQueue.cancelEvent(mVideoLagEvent->eventID());
163 mVideoLagEventPending = false;
164 if (updateProgressCb) {
165 mQueue.cancelEvent(mProgressCbEvent->eventID());
166 mProgressCbEventPending = false;
167 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800168}
169
James Dongdaeb5b32012-01-12 12:12:40 -0800170status_t PreviewPlayer::setDataSource(const char *path) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800171 Mutex::Autolock autoLock(mLock);
James Dongdaeb5b32012-01-12 12:12:40 -0800172 return setDataSource_l(path);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800173}
174
James Dongdaeb5b32012-01-12 12:12:40 -0800175status_t PreviewPlayer::setDataSource_l(const char *path) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800176 reset_l();
177
James Dongdaeb5b32012-01-12 12:12:40 -0800178 mUri = path;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800179
180 // The actual work will be done during preparation in the call to
181 // ::finishSetDataSource_l to avoid blocking the calling thread in
182 // setDataSource for any significant time.
183 return OK;
184}
185
186status_t PreviewPlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
187 bool haveAudio = false;
188 bool haveVideo = false;
189 for (size_t i = 0; i < extractor->countTracks(); ++i) {
190 sp<MetaData> meta = extractor->getTrackMetaData(i);
191
192 const char *mime;
193 CHECK(meta->findCString(kKeyMIMEType, &mime));
194
195 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
196 setVideoSource(extractor->getTrack(i));
197 haveVideo = true;
198 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
199 setAudioSource(extractor->getTrack(i));
200 haveAudio = true;
201
202 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
203 // Only do this for vorbis audio, none of the other audio
204 // formats even support this ringtone specific hack and
205 // retrieving the metadata on some extractors may turn out
206 // to be very expensive.
207 sp<MetaData> fileMeta = extractor->getMetaData();
208 int32_t loop;
209 if (fileMeta != NULL
210 && fileMeta->findInt32(kKeyAutoLoop, &loop)
211 && loop != 0) {
212 mFlags |= AUTO_LOOPING;
213 }
214 }
215 }
216
217 if (haveAudio && haveVideo) {
218 break;
219 }
220 }
221
222 /* Add the support for Dummy audio*/
223 if( !haveAudio ){
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800224 mAudioTrack = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700225 ((mPlayEndTimeMsec)*1000LL));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800226 if(mAudioTrack != NULL) {
227 haveAudio = true;
228 }
229 }
230
231 if (!haveAudio && !haveVideo) {
232 return UNKNOWN_ERROR;
233 }
234
235 mExtractorFlags = extractor->flags();
236 return OK;
237}
238
239status_t PreviewPlayer::setDataSource_l_jpg() {
James Dong00f742c2012-01-13 17:34:42 -0800240 ALOGV("setDataSource_l_jpg");
241
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800242 M4OSA_ERR err = M4NO_ERROR;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800243
244 mAudioSource = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700245 ((mPlayEndTimeMsec)*1000LL));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800246 if(mAudioSource != NULL) {
247 setAudioSource(mAudioSource);
248 }
249 status_t error = mAudioSource->start();
250 if (error != OK) {
James Dong00f742c2012-01-13 17:34:42 -0800251 ALOGE("Error starting dummy audio source");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800252 mAudioSource.clear();
253 return err;
254 }
255
Raghavender Pallaebf40152011-03-14 20:15:12 -0700256 mDurationUs = (mPlayEndTimeMsec - mPlayBeginTimeMsec)*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800257
258 mVideoSource = DummyVideoSource::Create(mVideoWidth, mVideoHeight,
259 mDurationUs, mUri);
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800260
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800261 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800262 setVideoSource(mVideoSource);
263 status_t err1 = mVideoSource->start();
264 if (err1 != OK) {
265 mVideoSource.clear();
266 return err;
267 }
268
269 mIsVideoSourceJpg = true;
270 return OK;
271}
272
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800273void PreviewPlayer::reset_l() {
274
275 if (mFlags & PREPARING) {
276 mFlags |= PREPARE_CANCELLED;
277 }
278
279 while (mFlags & PREPARING) {
280 mPreparedCondition.wait(mLock);
281 }
282
James Dong00f742c2012-01-13 17:34:42 -0800283 cancelPlayerEvents_l();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800284 mAudioTrack.clear();
285 mVideoTrack.clear();
286
287 // Shutdown audio first, so that the respone to the reset request
288 // appears to happen instantaneously as far as the user is concerned
289 // If we did this later, audio would continue playing while we
290 // shutdown the video-related resources and the player appear to
291 // not be as responsive to a reset request.
292 if (mAudioPlayer == NULL && mAudioSource != NULL) {
293 // If we had an audio player, it would have effectively
294 // taken possession of the audio source and stopped it when
295 // _it_ is stopped. Otherwise this is still our responsibility.
296 mAudioSource->stop();
297 }
298 mAudioSource.clear();
299
300 mTimeSource = NULL;
301
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800302 //Single audio player instance used
303 //So donot delete it here
304 //It is deleted from PreviewController class
305 //delete mAudioPlayer;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800306 mAudioPlayer = NULL;
307
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800308 if (mVideoBuffer) {
309 mVideoBuffer->release();
310 mVideoBuffer = NULL;
311 }
312
313 if (mVideoSource != NULL) {
314 mVideoSource->stop();
315
316 // The following hack is necessary to ensure that the OMX
317 // component is completely released by the time we may try
318 // to instantiate it again.
319 wp<MediaSource> tmp = mVideoSource;
320 mVideoSource.clear();
321 while (tmp.promote() != NULL) {
322 usleep(1000);
323 }
324 IPCThreadState::self()->flushCommands();
325 }
326
327 mDurationUs = -1;
328 mFlags = 0;
329 mExtractorFlags = 0;
330 mVideoWidth = mVideoHeight = -1;
331 mTimeSourceDeltaUs = 0;
332 mVideoTimeUs = 0;
333
Andreas Hubera5872f72011-02-24 15:25:21 -0800334 mSeeking = NO_SEEK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800335 mSeekNotificationSent = false;
336 mSeekTimeUs = 0;
337
338 mUri.setTo("");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800339
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800340 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
341 mIsVideoSourceJpg = false;
342 mFrameRGBBuffer = NULL;
343 if(mFrameYUVBuffer != NULL) {
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700344 free(mFrameYUVBuffer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800345 mFrameYUVBuffer = NULL;
346 }
347}
348
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800349status_t PreviewPlayer::play() {
James Dong00f742c2012-01-13 17:34:42 -0800350 ALOGV("play");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800351 Mutex::Autolock autoLock(mLock);
352
353 mFlags &= ~CACHE_UNDERRUN;
Hong Tenge0180232011-09-28 18:40:38 -0700354 mFlags &= ~INFORMED_AV_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800355 return play_l();
356}
357
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800358status_t PreviewPlayer::startAudioPlayer_l() {
James Dong00f742c2012-01-13 17:34:42 -0800359 ALOGV("startAudioPlayer_l");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800360 CHECK(!(mFlags & AUDIO_RUNNING));
361
362 if (mAudioSource == NULL || mAudioPlayer == NULL) {
363 return OK;
364 }
365
366 if (!(mFlags & AUDIOPLAYER_STARTED)) {
367 mFlags |= AUDIOPLAYER_STARTED;
368
369 // We've already started the MediaSource in order to enable
370 // the prefetcher to read its data.
371 status_t err = mVeAudioPlayer->start(
372 true /* sourceAlreadyStarted */);
373
374 if (err != OK) {
375 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
376 return err;
377 }
378 } else {
379 mVeAudioPlayer->resume();
380 }
381
382 mFlags |= AUDIO_RUNNING;
383
384 mWatchForAudioEOS = true;
385
386 return OK;
387}
388
James Dongc9dedc42011-05-01 12:36:22 -0700389status_t PreviewPlayer::setAudioPlayer(AudioPlayerBase *audioPlayer) {
James Dong00f742c2012-01-13 17:34:42 -0800390 ALOGV("setAudioPlayer");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800391 Mutex::Autolock autoLock(mLock);
392 CHECK(!(mFlags & PLAYING));
393 mAudioPlayer = audioPlayer;
394
Steve Block2703f232011-10-20 11:56:09 +0100395 ALOGV("SetAudioPlayer");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800396 mIsChangeSourceRequired = true;
397 mVeAudioPlayer =
398 (VideoEditorAudioPlayer*)mAudioPlayer;
399
400 // check if the new and old source are dummy
401 sp<MediaSource> anAudioSource = mVeAudioPlayer->getSource();
402 if (anAudioSource == NULL) {
403 // Audio player does not have any source set.
Steve Block2703f232011-10-20 11:56:09 +0100404 ALOGV("setAudioPlayer: Audio player does not have any source set");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800405 return OK;
406 }
407
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800408 // If new video source is not dummy, then always change source
409 // Else audio player continues using old audio source and there are
410 // frame drops to maintain AV sync
411 sp<MetaData> meta;
412 if (mVideoSource != NULL) {
413 meta = mVideoSource->getFormat();
414 const char *pVidSrcType;
415 if (meta->findCString(kKeyDecoderComponent, &pVidSrcType)) {
416 if (strcmp(pVidSrcType, "DummyVideoSource") != 0) {
Steve Block2703f232011-10-20 11:56:09 +0100417 ALOGV(" Video clip with silent audio; need to change source");
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800418 return OK;
419 }
420 }
421 }
422
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800423 const char *pSrcType1;
424 const char *pSrcType2;
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800425 meta = anAudioSource->getFormat();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800426
427 if (meta->findCString(kKeyDecoderComponent, &pSrcType1)) {
428 if (strcmp(pSrcType1, "DummyAudioSource") == 0) {
429 meta = mAudioSource->getFormat();
430 if (meta->findCString(kKeyDecoderComponent, &pSrcType2)) {
431 if (strcmp(pSrcType2, "DummyAudioSource") == 0) {
432 mIsChangeSourceRequired = false;
433 // Just set the new play duration for the existing source
434 MediaSource *pMediaSrc = anAudioSource.get();
435 DummyAudioSource *pDummyAudioSource = (DummyAudioSource*)pMediaSrc;
436 //Increment the duration of audio source
Raghavender Pallaebf40152011-03-14 20:15:12 -0700437 pDummyAudioSource->setDuration(
438 (int64_t)((mPlayEndTimeMsec)*1000LL));
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800439
440 // Stop the new audio source
441 // since we continue using old source
Steve Block2703f232011-10-20 11:56:09 +0100442 ALOGV("setAudioPlayer: stop new audio source");
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800443 mAudioSource->stop();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800444 }
445 }
446 }
447 }
448
449 return OK;
450}
451
452void PreviewPlayer::onStreamDone() {
James Dong00f742c2012-01-13 17:34:42 -0800453 ALOGV("onStreamDone");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800454 // Posted whenever any stream finishes playing.
455
456 Mutex::Autolock autoLock(mLock);
457 if (!mStreamDoneEventPending) {
458 return;
459 }
460 mStreamDoneEventPending = false;
461
462 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
Steve Block2703f232011-10-20 11:56:09 +0100463 ALOGV("MEDIA_ERROR %d", mStreamDoneStatus);
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800464
465 notifyListener_l(
466 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
467
468 pause_l(true /* at eos */);
469
470 mFlags |= AT_EOS;
471 return;
472 }
473
474 const bool allDone =
475 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
476 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
477
478 if (!allDone) {
479 return;
480 }
481
482 if (mFlags & (LOOPING | AUTO_LOOPING)) {
483 seekTo_l(0);
484
485 if (mVideoSource != NULL) {
486 postVideoEvent_l();
487 }
488 } else {
Steve Block2703f232011-10-20 11:56:09 +0100489 ALOGV("MEDIA_PLAYBACK_COMPLETE");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800490 //pause before sending event
491 pause_l(true /* at eos */);
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700492
493 //This lock is used to syncronize onStreamDone() in PreviewPlayer and
494 //stopPreview() in PreviewController
495 Mutex::Autolock autoLock(mLockControl);
Hong Tenge0180232011-09-28 18:40:38 -0700496 /* Make sure PreviewPlayer only notifies MEDIA_PLAYBACK_COMPLETE once for each clip!
497 * It happens twice in following scenario.
498 * To make the clips in preview storyboard are played and switched smoothly,
499 * PreviewController uses two PreviewPlayer instances and one AudioPlayer.
500 * The two PreviewPlayer use the same AudioPlayer to play the audio,
501 * and change the audio source of the AudioPlayer.
502 * If the audio source of current playing clip and next clip are dummy
503 * audio source(image or video without audio), it will not change the audio source
504 * to avoid the "audio glitch", and keep using the current audio source.
505 * When the video of current clip reached the EOS, PreviewPlayer will set EOS flag
506 * for video and audio, and it will notify MEDIA_PLAYBACK_COMPLETE.
507 * But the audio(dummy audio source) is still playing(for next clip),
508 * and when it reached the EOS, and video reached EOS,
509 * PreviewPlayer will notify MEDIA_PLAYBACK_COMPLETE again. */
510 if (!(mFlags & INFORMED_AV_EOS)) {
511 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
512 mFlags |= INFORMED_AV_EOS;
513 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800514 mFlags |= AT_EOS;
Steve Block2703f232011-10-20 11:56:09 +0100515 ALOGV("onStreamDone end");
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700516 return;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800517 }
518}
519
520
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800521status_t PreviewPlayer::play_l() {
James Dong00f742c2012-01-13 17:34:42 -0800522 ALOGV("play_l");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800523
Rajneesh Chowdury8b95de22011-02-16 15:32:06 -0800524 mFlags &= ~SEEK_PREVIEW;
525
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800526 if (mFlags & PLAYING) {
527 return OK;
528 }
529 mStartNextPlayer = false;
530
531 if (!(mFlags & PREPARED)) {
532 status_t err = prepare_l();
533
534 if (err != OK) {
535 return err;
536 }
537 }
538
539 mFlags |= PLAYING;
540 mFlags |= FIRST_FRAME;
541
542 bool deferredAudioSeek = false;
543
544 if (mAudioSource != NULL) {
545 if (mAudioPlayer == NULL) {
546 if (mAudioSink != NULL) {
547
548 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800549 mVeAudioPlayer =
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800550 (VideoEditorAudioPlayer*)mAudioPlayer;
551
552 mAudioPlayer->setSource(mAudioSource);
553
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800554 mVeAudioPlayer->setAudioMixSettings(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800555 mPreviewPlayerAudioMixSettings);
556
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800557 mVeAudioPlayer->setAudioMixPCMFileHandle(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800558 mAudioMixPCMFileHandle);
559
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800560 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800561 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
562 mCurrentMediaVolumeValue);
563
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800564 mFlags |= AUDIOPLAYER_STARTED;
565 // We've already started the MediaSource in order to enable
566 // the prefetcher to read its data.
567 status_t err = mVeAudioPlayer->start(
568 true /* sourceAlreadyStarted */);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800569
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800570 if (err != OK) {
571 //delete mAudioPlayer;
572 mAudioPlayer = NULL;
573
574 mFlags &= ~(PLAYING | FIRST_FRAME);
575 return err;
576 }
577
578 mTimeSource = mVeAudioPlayer;
579 mFlags |= AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800580 deferredAudioSeek = true;
581 mWatchForAudioSeekComplete = false;
582 mWatchForAudioEOS = true;
583 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800584 } else {
585 mVeAudioPlayer = (VideoEditorAudioPlayer*)mAudioPlayer;
586 bool isAudioPlayerStarted = mVeAudioPlayer->isStarted();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800587
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800588 if (mIsChangeSourceRequired == true) {
Steve Block2703f232011-10-20 11:56:09 +0100589 ALOGV("play_l: Change audio source required");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800590
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800591 if (isAudioPlayerStarted == true) {
592 mVeAudioPlayer->pause();
593 }
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800594
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800595 mVeAudioPlayer->setSource(mAudioSource);
596 mVeAudioPlayer->setObserver(this);
597
598 mVeAudioPlayer->setAudioMixSettings(
599 mPreviewPlayerAudioMixSettings);
600
601 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
602 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
603 mCurrentMediaVolumeValue);
604
605 if (isAudioPlayerStarted == true) {
606 mVeAudioPlayer->resume();
607 } else {
608 status_t err = OK;
609 err = mVeAudioPlayer->start(true);
610 if (err != OK) {
611 mAudioPlayer = NULL;
612 mVeAudioPlayer = NULL;
613
614 mFlags &= ~(PLAYING | FIRST_FRAME);
615 return err;
616 }
617 }
618 } else {
Steve Block2703f232011-10-20 11:56:09 +0100619 ALOGV("play_l: No Source change required");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800620 mVeAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
621 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
622 mCurrentMediaVolumeValue);
623
624 mVeAudioPlayer->resume();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800625 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800626
627 mFlags |= AUDIOPLAYER_STARTED;
628 mFlags |= AUDIO_RUNNING;
629 mTimeSource = mVeAudioPlayer;
630 deferredAudioSeek = true;
631 mWatchForAudioSeekComplete = false;
632 mWatchForAudioEOS = true;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800633 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800634 }
635
636 if (mTimeSource == NULL && mAudioPlayer == NULL) {
637 mTimeSource = &mSystemTimeSource;
638 }
639
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800640 // Set the seek option for Image source files and read.
641 // This resets the timestamping for image play
642 if (mIsVideoSourceJpg) {
643 MediaSource::ReadOptions options;
644 MediaBuffer *aLocalBuffer;
645 options.setSeekTo(mSeekTimeUs);
646 mVideoSource->read(&aLocalBuffer, &options);
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800647 aLocalBuffer->release();
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800648 }
649
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800650 if (mVideoSource != NULL) {
651 // Kick off video playback
652 postVideoEvent_l();
653 }
654
655 if (deferredAudioSeek) {
656 // If there was a seek request while we were paused
657 // and we're just starting up again, honor the request now.
658 seekAudioIfNecessary_l();
659 }
660
661 if (mFlags & AT_EOS) {
662 // Legacy behaviour, if a stream finishes playing and then
663 // is started again, we play from the start...
664 seekTo_l(0);
665 }
666
667 return OK;
668}
669
670
Santosh Madhavabfece172011-02-03 16:59:47 -0800671status_t PreviewPlayer::initRenderer_l() {
Mathias Agopian6e224292011-04-05 15:38:24 -0700672 if (mSurface != NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800673 if(mVideoRenderer == NULL) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800674 mVideoRenderer = mNativeWindowRenderer->createRenderInput();
675 if (mVideoSource != NULL) {
676 updateSizeToRender(mVideoSource->getFormat());
Santosh Madhavabfece172011-02-03 16:59:47 -0800677 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800678 }
679 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800680 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800681}
682
683
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800684status_t PreviewPlayer::seekTo(int64_t timeUs) {
James Dong00f742c2012-01-13 17:34:42 -0800685 Mutex::Autolock autoLock(mLock);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800686 if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800687 return seekTo_l(timeUs);
688 }
689
690 return OK;
691}
692
693
694status_t PreviewPlayer::getVideoDimensions(
695 int32_t *width, int32_t *height) const {
696 Mutex::Autolock autoLock(mLock);
697
698 if (mVideoWidth < 0 || mVideoHeight < 0) {
699 return UNKNOWN_ERROR;
700 }
701
702 *width = mVideoWidth;
703 *height = mVideoHeight;
704
705 return OK;
706}
707
708
James Dong00f742c2012-01-13 17:34:42 -0800709status_t PreviewPlayer::initAudioDecoder_l() {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800710 sp<MetaData> meta = mAudioTrack->getFormat();
711 const char *mime;
712 CHECK(meta->findCString(kKeyMIMEType, &mime));
713
714 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
715 mAudioSource = mAudioTrack;
716 } else {
717 sp<MediaSource> aRawSource;
718 aRawSource = OMXCodec::Create(
719 mClient.interface(), mAudioTrack->getFormat(),
720 false, // createEncoder
721 mAudioTrack);
722
723 if(aRawSource != NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800724 mAudioSource = new VideoEditorSRC(aRawSource);
725 }
726 }
727
728 if (mAudioSource != NULL) {
729 int64_t durationUs;
730 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
James Dong00f742c2012-01-13 17:34:42 -0800731 setDuration_l(durationUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800732 }
733 status_t err = mAudioSource->start();
734
735 if (err != OK) {
736 mAudioSource.clear();
737 return err;
738 }
739 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
740 // For legacy reasons we're simply going to ignore the absence
741 // of an audio decoder for QCELP instead of aborting playback
742 // altogether.
743 return OK;
744 }
745
746 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
747}
748
James Dong00f742c2012-01-13 17:34:42 -0800749status_t PreviewPlayer::initVideoDecoder_l(uint32_t flags) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800750 initRenderer_l();
751
752 if (mVideoRenderer == NULL) {
Steve Blockf8bd29c2012-01-08 10:14:44 +0000753 ALOGE("Cannot create renderer");
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800754 return UNKNOWN_ERROR;
755 }
756
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800757 mVideoSource = OMXCodec::Create(
758 mClient.interface(), mVideoTrack->getFormat(),
759 false,
760 mVideoTrack,
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800761 NULL, flags, mVideoRenderer->getTargetWindow());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800762
763 if (mVideoSource != NULL) {
764 int64_t durationUs;
765 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
James Dong00f742c2012-01-13 17:34:42 -0800766 setDuration_l(durationUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800767 }
768
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800769 updateSizeToRender(mVideoTrack->getFormat());
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800770
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800771 status_t err = mVideoSource->start();
772
773 if (err != OK) {
774 mVideoSource.clear();
775 return err;
776 }
777 }
778
779 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
780}
781
782
783void PreviewPlayer::onVideoEvent() {
784 uint32_t i=0;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800785 M4OSA_ERR err1 = M4NO_ERROR;
786 int64_t imageFrameTimeUs = 0;
787
788 Mutex::Autolock autoLock(mLock);
789 if (!mVideoEventPending) {
790 // The event has been cancelled in reset_l() but had already
791 // been scheduled for execution at that time.
792 return;
793 }
794 mVideoEventPending = false;
795
Andreas Huber9e4c36a2011-02-08 13:12:32 -0800796 if (mFlags & SEEK_PREVIEW) {
797 mFlags &= ~SEEK_PREVIEW;
798 return;
799 }
800
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800801 TimeSource *ts_st = &mSystemTimeSource;
802 int64_t timeStartUs = ts_st->getRealTimeUs();
803
Andreas Hubera5872f72011-02-24 15:25:21 -0800804 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800805
806 if(mAudioSource != NULL) {
807
808 // We're going to seek the video source first, followed by
809 // the audio source.
810 // In order to avoid jumps in the DataSource offset caused by
811 // the audio codec prefetching data from the old locations
812 // while the video codec is already reading data from the new
813 // locations, we'll "pause" the audio source, causing it to
814 // stop reading input data until a subsequent seek.
815
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800816 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800817 mAudioPlayer->pause();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800818 mFlags &= ~AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800819 }
820 mAudioSource->pause();
821 }
822 }
823
824 if (!mVideoBuffer) {
825 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -0800826 if (mSeeking != NO_SEEK) {
Steve Block2703f232011-10-20 11:56:09 +0100827 ALOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800828 mSeekTimeUs / 1E6);
829
830 options.setSeekTo(
831 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
832 }
833 for (;;) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800834 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800835 options.clearSeekTo();
836
837 if (err != OK) {
James Dong00f742c2012-01-13 17:34:42 -0800838 CHECK(!mVideoBuffer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800839
840 if (err == INFO_FORMAT_CHANGED) {
Steve Block2703f232011-10-20 11:56:09 +0100841 ALOGV("LV PLAYER VideoSource signalled format change");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800842 notifyVideoSize_l();
843
844 if (mVideoRenderer != NULL) {
845 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -0800846 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800847 if (err != OK) {
848 postStreamDoneEvent_l(err);
849 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800850
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800851 }
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800852
853 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800854 continue;
855 }
856 // So video playback is complete, but we may still have
Santosh Madhava342f9322011-01-27 16:27:12 -0800857 // a seek request pending that needs to be applied to the audio track
Andreas Hubera5872f72011-02-24 15:25:21 -0800858 if (mSeeking != NO_SEEK) {
Steve Block2703f232011-10-20 11:56:09 +0100859 ALOGV("video stream ended while seeking!");
Santosh Madhava342f9322011-01-27 16:27:12 -0800860 }
861 finishSeekIfNecessary(-1);
Steve Block2703f232011-10-20 11:56:09 +0100862 ALOGV("PreviewPlayer: onVideoEvent EOS reached.");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800863 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800864 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800865 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800866 postStreamDoneEvent_l(err);
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800867 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -0700868 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800869 return;
870 }
871
872 if (mVideoBuffer->range_length() == 0) {
873 // Some decoders, notably the PV AVC software decoder
874 // return spurious empty buffers that we just want to ignore.
875
876 mVideoBuffer->release();
877 mVideoBuffer = NULL;
878 continue;
879 }
880
881 int64_t videoTimeUs;
882 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
883
Andreas Hubera5872f72011-02-24 15:25:21 -0800884 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800885 if (videoTimeUs < mSeekTimeUs) {
886 // buffers are before seek time
887 // ignore them
888 mVideoBuffer->release();
889 mVideoBuffer = NULL;
890 continue;
891 }
892 } else {
893 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
894 // Frames are before begin cut time
895 // Donot render
896 mVideoBuffer->release();
897 mVideoBuffer = NULL;
898 continue;
899 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800900 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800901 break;
902 }
903 }
904
905 mNumberDecVideoFrames++;
906
907 int64_t timeUs;
908 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
James Dong00f742c2012-01-13 17:34:42 -0800909 setPosition_l(timeUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800910
James Dong00f742c2012-01-13 17:34:42 -0800911 if (!mStartNextPlayer) {
912 int64_t playbackTimeRemaining = (mPlayEndTimeMsec * 1000LL) - timeUs;
913 if (playbackTimeRemaining <= 1500000) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800914 //When less than 1.5 sec of playback left
915 // send notification to start next player
916
917 mStartNextPlayer = true;
918 notifyListener_l(0xAAAAAAAA);
919 }
920 }
921
Andreas Hubera5872f72011-02-24 15:25:21 -0800922 SeekType wasSeeking = mSeeking;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800923 finishSeekIfNecessary(timeUs);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800924 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING))) {
925 status_t err = startAudioPlayer_l();
926 if (err != OK) {
Steve Blockf8bd29c2012-01-08 10:14:44 +0000927 ALOGE("Starting the audio player failed w/ err %d", err);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800928 return;
929 }
930 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800931
932 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
933
934 if(ts == NULL) {
935 mVideoBuffer->release();
936 mVideoBuffer = NULL;
937 return;
938 }
939
940 if(!mIsVideoSourceJpg) {
941 if (mFlags & FIRST_FRAME) {
942 mFlags &= ~FIRST_FRAME;
943
944 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
945 }
946
947 int64_t realTimeUs, mediaTimeUs;
948 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
949 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
950 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
951 }
952
953 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
954
955 int64_t latenessUs = nowUs - timeUs;
956
Andreas Hubera5872f72011-02-24 15:25:21 -0800957 if (wasSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800958 // Let's display the first frame after seeking right away.
959 latenessUs = 0;
960 }
Steve Block2703f232011-10-20 11:56:09 +0100961 ALOGV("Audio time stamp = %lld and video time stamp = %lld",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800962 ts->getRealTimeUs(),timeUs);
963 if (latenessUs > 40000) {
964 // We're more than 40ms late.
965
Steve Block2703f232011-10-20 11:56:09 +0100966 ALOGV("LV PLAYER we're late by %lld us (%.2f secs)",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800967 latenessUs, latenessUs / 1E6);
968
969 mVideoBuffer->release();
970 mVideoBuffer = NULL;
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800971 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800972 return;
973 }
974
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800975 if (latenessUs < -25000) {
976 // We're more than 25ms early.
Steve Block2703f232011-10-20 11:56:09 +0100977 ALOGV("We're more than 25ms early, lateness %lld", latenessUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800978
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800979 postVideoEvent_l(25000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800980 return;
981 }
982 }
983
984 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
985 mVideoRendererIsPreview = false;
986
Santosh Madhavabfece172011-02-03 16:59:47 -0800987 status_t err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800988 if (err != OK) {
989 postStreamDoneEvent_l(err);
990 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800991 }
992
993 // If timestamp exceeds endCutTime of clip, donot render
994 if((timeUs/1000) > mPlayEndTimeMsec) {
Chih-Chung Changcece4b32011-08-01 16:34:05 +0800995 mVideoBuffer->release();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800996 mVideoBuffer = NULL;
997 mFlags |= VIDEO_AT_EOS;
998 mFlags |= AUDIO_AT_EOS;
Steve Block2703f232011-10-20 11:56:09 +0100999 ALOGV("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS..");
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001000 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001001 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001002 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001003 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1004 return;
1005 }
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001006 // Capture the frame timestamp to be rendered
1007 mDecodedVideoTs = timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001008
1009 // Post processing to apply video effects
1010 for(i=0;i<mNumberEffects;i++) {
1011 // First check if effect starttime matches the clip being previewed
1012 if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) ||
1013 (mEffectsSettings[i].uiStartTime >=
1014 ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec)))
1015 {
1016 // This effect doesn't belong to this clip, check next one
1017 continue;
1018 }
1019 // Check if effect applies to this particular frame timestamp
1020 if((mEffectsSettings[i].uiStartTime <=
1021 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) &&
1022 ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=
1023 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec))
1024 && (mEffectsSettings[i].uiDuration != 0)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001025 setVideoPostProcessingNode(
1026 mEffectsSettings[i].VideoEffectType, TRUE);
1027 }
1028 else {
1029 setVideoPostProcessingNode(
1030 mEffectsSettings[i].VideoEffectType, FALSE);
1031 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001032 }
1033
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001034 //Provide the overlay Update indication when there is an overlay effect
Dharmaray Kundargid01ef562011-01-26 21:11:00 -08001035 if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) {
1036 mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here.
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001037 if (!mOverlayUpdateEventPosted) {
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001038 // Find the effect in effectSettings array
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001039 M4OSA_UInt32 index;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001040 for (index = 0; index < mNumberEffects; index++) {
1041 M4OSA_UInt32 timeMs = mDecodedVideoTs/1000;
1042 M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000;
1043 if(mEffectsSettings[index].VideoEffectType ==
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001044 (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001045 if (((mEffectsSettings[index].uiStartTime + 1) <=
1046 timeMs + timeOffset - mPlayBeginTimeMsec) &&
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001047 ((mEffectsSettings[index].uiStartTime - 1 +
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001048 mEffectsSettings[index].uiDuration) >=
1049 timeMs + timeOffset - mPlayBeginTimeMsec))
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001050 {
1051 break;
1052 }
1053 }
1054 }
1055 if (index < mNumberEffects) {
1056 mCurrFramingEffectIndex = index;
1057 mOverlayUpdateEventPosted = true;
1058 postOverlayUpdateEvent_l();
James Dong00f742c2012-01-13 17:34:42 -08001059 ALOGV("Framing index = %ld", mCurrFramingEffectIndex);
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001060 } else {
Steve Block2703f232011-10-20 11:56:09 +01001061 ALOGV("No framing effects found");
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001062 }
1063 }
1064
1065 } else if (mOverlayUpdateEventPosted) {
1066 //Post the event when the overlay is no more valid
Steve Block2703f232011-10-20 11:56:09 +01001067 ALOGV("Overlay is Done");
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001068 mOverlayUpdateEventPosted = false;
1069 postOverlayUpdateEvent_l();
1070 }
1071
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001072 if (mVideoRenderer != NULL) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001073 mVideoRenderer->render(mVideoBuffer, mCurrentVideoEffect,
1074 mRenderingMode, mIsVideoSourceJpg);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001075 }
1076
Chih-Chung Changcece4b32011-08-01 16:34:05 +08001077 mVideoBuffer->release();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001078 mVideoBuffer = NULL;
1079
1080 // Post progress callback based on callback interval set
1081 if(mNumberDecVideoFrames >= mProgressCbInterval) {
1082 postProgressCallbackEvent_l();
1083 mNumberDecVideoFrames = 0; // reset counter
1084 }
1085
1086 // if reached EndCutTime of clip, post EOS event
1087 if((timeUs/1000) >= mPlayEndTimeMsec) {
Steve Block2703f232011-10-20 11:56:09 +01001088 ALOGV("PreviewPlayer: onVideoEvent EOS.");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001089 mFlags |= VIDEO_AT_EOS;
1090 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001091 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001092 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001093 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001094 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1095 }
1096 else {
Andreas Hubera5872f72011-02-24 15:25:21 -08001097 if ((wasSeeking != NO_SEEK) && (mFlags & SEEK_PREVIEW)) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001098 mFlags &= ~SEEK_PREVIEW;
1099 return;
1100 }
1101
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001102 if(!mIsVideoSourceJpg) {
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001103 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001104 }
1105 else {
1106 postVideoEvent_l(33000);
1107 }
1108 }
1109}
1110
1111status_t PreviewPlayer::prepare() {
James Dong00f742c2012-01-13 17:34:42 -08001112 ALOGV("prepare");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001113 Mutex::Autolock autoLock(mLock);
1114 return prepare_l();
1115}
1116
1117status_t PreviewPlayer::prepare_l() {
James Dong00f742c2012-01-13 17:34:42 -08001118 ALOGV("prepare_l");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001119 if (mFlags & PREPARED) {
1120 return OK;
1121 }
1122
1123 if (mFlags & PREPARING) {
1124 return UNKNOWN_ERROR;
1125 }
1126
1127 mIsAsyncPrepare = false;
1128 status_t err = prepareAsync_l();
1129
1130 if (err != OK) {
1131 return err;
1132 }
1133
1134 while (mFlags & PREPARING) {
1135 mPreparedCondition.wait(mLock);
1136 }
1137
1138 return mPrepareResult;
1139}
1140
James Dong00f742c2012-01-13 17:34:42 -08001141status_t PreviewPlayer::prepareAsync() {
1142 ALOGV("prepareAsync");
1143 Mutex::Autolock autoLock(mLock);
1144 return prepareAsync_l();
1145}
1146
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001147status_t PreviewPlayer::prepareAsync_l() {
James Dong00f742c2012-01-13 17:34:42 -08001148 ALOGV("prepareAsync_l");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001149 if (mFlags & PREPARING) {
1150 return UNKNOWN_ERROR; // async prepare already pending
1151 }
1152
1153 if (!mQueueStarted) {
1154 mQueue.start();
1155 mQueueStarted = true;
1156 }
1157
1158 mFlags |= PREPARING;
1159 mAsyncPrepareEvent = new PreviewPlayerEvent(
1160 this, &PreviewPlayer::onPrepareAsyncEvent);
1161
1162 mQueue.postEvent(mAsyncPrepareEvent);
1163
1164 return OK;
1165}
1166
1167status_t PreviewPlayer::finishSetDataSource_l() {
1168 sp<DataSource> dataSource;
1169 sp<MediaExtractor> extractor;
1170
James Dongdaeb5b32012-01-12 12:12:40 -08001171 dataSource = DataSource::CreateFromURI(mUri.string(), NULL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001172
1173 if (dataSource == NULL) {
1174 return UNKNOWN_ERROR;
1175 }
1176
1177 //If file type is .rgb, then no need to check for Extractor
1178 int uriLen = strlen(mUri);
1179 int startOffset = uriLen - 4;
1180 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) {
1181 extractor = NULL;
1182 }
1183 else {
1184 extractor = MediaExtractor::Create(dataSource,
1185 MEDIA_MIMETYPE_CONTAINER_MPEG4);
1186 }
1187
1188 if (extractor == NULL) {
James Dong00f742c2012-01-13 17:34:42 -08001189 ALOGV("finishSetDataSource_l: failed to create extractor");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001190 return setDataSource_l_jpg();
1191 }
1192
1193 return setDataSource_l(extractor);
1194}
1195
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001196void PreviewPlayer::onPrepareAsyncEvent() {
1197 Mutex::Autolock autoLock(mLock);
Steve Block2703f232011-10-20 11:56:09 +01001198 ALOGV("onPrepareAsyncEvent");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001199
1200 if (mFlags & PREPARE_CANCELLED) {
James Dong00f742c2012-01-13 17:34:42 -08001201 ALOGV("prepare was cancelled before doing anything");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001202 abortPrepare(UNKNOWN_ERROR);
1203 return;
1204 }
1205
1206 if (mUri.size() > 0) {
1207 status_t err = finishSetDataSource_l();
1208
1209 if (err != OK) {
1210 abortPrepare(err);
1211 return;
1212 }
1213 }
1214
1215 if (mVideoTrack != NULL && mVideoSource == NULL) {
James Dong00f742c2012-01-13 17:34:42 -08001216 status_t err = initVideoDecoder_l(OMXCodec::kHardwareCodecsOnly);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001217
1218 if (err != OK) {
1219 abortPrepare(err);
1220 return;
1221 }
1222 }
1223
1224 if (mAudioTrack != NULL && mAudioSource == NULL) {
James Dong00f742c2012-01-13 17:34:42 -08001225 status_t err = initAudioDecoder_l();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001226
1227 if (err != OK) {
1228 abortPrepare(err);
1229 return;
1230 }
1231 }
1232 finishAsyncPrepare_l();
1233
1234}
1235
1236void PreviewPlayer::finishAsyncPrepare_l() {
James Dong00f742c2012-01-13 17:34:42 -08001237 ALOGV("finishAsyncPrepare_l");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001238 if (mIsAsyncPrepare) {
1239 if (mVideoSource == NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001240 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1241 } else {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001242 notifyVideoSize_l();
1243 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001244 notifyListener_l(MEDIA_PREPARED);
1245 }
1246
1247 mPrepareResult = OK;
1248 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1249 mFlags |= PREPARED;
1250 mAsyncPrepareEvent = NULL;
1251 mPreparedCondition.broadcast();
1252}
1253
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001254void PreviewPlayer::acquireLock() {
Steve Block2703f232011-10-20 11:56:09 +01001255 ALOGV("acquireLock");
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001256 mLockControl.lock();
1257}
1258
1259void PreviewPlayer::releaseLock() {
Steve Block2703f232011-10-20 11:56:09 +01001260 ALOGV("releaseLock");
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001261 mLockControl.unlock();
1262}
1263
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001264status_t PreviewPlayer::loadEffectsSettings(
James Dong00f742c2012-01-13 17:34:42 -08001265 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001266
James Dong00f742c2012-01-13 17:34:42 -08001267 ALOGV("loadEffectsSettings");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001268 mNumberEffects = nEffects;
1269 mEffectsSettings = pEffectSettings;
1270 return OK;
1271}
1272
1273status_t PreviewPlayer::loadAudioMixSettings(
James Dong00f742c2012-01-13 17:34:42 -08001274 M4xVSS_AudioMixingSettings* pAudioMixSettings) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001275
James Dong00f742c2012-01-13 17:34:42 -08001276 ALOGV("loadAudioMixSettings");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001277 mPreviewPlayerAudioMixSettings = pAudioMixSettings;
1278 return OK;
1279}
1280
1281status_t PreviewPlayer::setAudioMixPCMFileHandle(
James Dong00f742c2012-01-13 17:34:42 -08001282 M4OSA_Context pAudioMixPCMFileHandle) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001283
James Dong00f742c2012-01-13 17:34:42 -08001284 ALOGV("setAudioMixPCMFileHandle");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001285 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle;
1286 return OK;
1287}
1288
1289status_t PreviewPlayer::setAudioMixStoryBoardParam(
James Dong00f742c2012-01-13 17:34:42 -08001290 M4OSA_UInt32 audioMixStoryBoardTS,
1291 M4OSA_UInt32 currentMediaBeginCutTime,
1292 M4OSA_UInt32 primaryTrackVolValue ) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001293
James Dong00f742c2012-01-13 17:34:42 -08001294 ALOGV("setAudioMixStoryBoardParam");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001295 mAudioMixStoryBoardTS = audioMixStoryBoardTS;
1296 mCurrentMediaBeginCutTime = currentMediaBeginCutTime;
1297 mCurrentMediaVolumeValue = primaryTrackVolValue;
1298 return OK;
1299}
1300
1301status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) {
1302
1303 mPlayBeginTimeMsec = msec;
1304 return OK;
1305}
1306
1307status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) {
1308
1309 mPlayEndTimeMsec = msec;
1310 return OK;
1311}
1312
1313status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) {
1314
1315 mStoryboardStartTimeMsec = msec;
James Dong00f742c2012-01-13 17:34:42 -08001316 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec * 1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001317 return OK;
1318}
1319
1320status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) {
1321
1322 mProgressCbInterval = cbInterval;
1323 return OK;
1324}
1325
1326
1327status_t PreviewPlayer::setMediaRenderingMode(
1328 M4xVSS_MediaRendering mode,
1329 M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
1330
1331 mRenderingMode = mode;
1332
Hong Teng8806b702011-07-06 18:29:28 -07001333 /* get the video width and height by resolution */
James Dong00f742c2012-01-13 17:34:42 -08001334 return getVideoSizeByResolution(
1335 outputVideoSize,
1336 &mOutputVideoWidth, &mOutputVideoHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001337
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001338}
1339
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001340status_t PreviewPlayer::resetJniCallbackTimeStamp() {
1341
James Dong00f742c2012-01-13 17:34:42 -08001342 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec * 1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001343 return OK;
1344}
1345
1346void PreviewPlayer::postProgressCallbackEvent_l() {
1347 if (mProgressCbEventPending) {
1348 return;
1349 }
1350 mProgressCbEventPending = true;
1351
1352 mQueue.postEvent(mProgressCbEvent);
1353}
1354
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001355
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001356void PreviewPlayer::onProgressCbEvent() {
1357 Mutex::Autolock autoLock(mLock);
1358 if (!mProgressCbEventPending) {
1359 return;
1360 }
1361 mProgressCbEventPending = false;
1362 // If playback starts from previous I-frame,
1363 // then send frame storyboard duration
James Dong00f742c2012-01-13 17:34:42 -08001364 if ((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001365 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000);
James Dong00f742c2012-01-13 17:34:42 -08001366 } else {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001367 notifyListener_l(MEDIA_INFO, 0,
1368 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec));
1369 }
1370}
1371
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001372void PreviewPlayer::postOverlayUpdateEvent_l() {
1373 if (mOverlayUpdateEventPending) {
1374 return;
1375 }
1376 mOverlayUpdateEventPending = true;
1377 mQueue.postEvent(mOverlayUpdateEvent);
1378}
1379
1380void PreviewPlayer::onUpdateOverlayEvent() {
1381 Mutex::Autolock autoLock(mLock);
1382
1383 if (!mOverlayUpdateEventPending) {
1384 return;
1385 }
1386 mOverlayUpdateEventPending = false;
1387
James Dong00f742c2012-01-13 17:34:42 -08001388 int updateState = mOverlayUpdateEventPosted? 1: 0;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001389 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex);
1390}
1391
1392
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001393void PreviewPlayer::setVideoPostProcessingNode(
James Dong00f742c2012-01-13 17:34:42 -08001394 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001395
1396 uint32_t effect = VIDEO_EFFECT_NONE;
1397
1398 //Map M4VSS3GPP_VideoEffectType to local enum
1399 switch(type) {
1400 case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
1401 effect = VIDEO_EFFECT_FADEFROMBLACK;
1402 break;
1403
1404 case M4VSS3GPP_kVideoEffectType_FadeToBlack:
1405 effect = VIDEO_EFFECT_FADETOBLACK;
1406 break;
1407
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001408 case M4xVSS_kVideoEffectType_BlackAndWhite:
1409 effect = VIDEO_EFFECT_BLACKANDWHITE;
1410 break;
1411
1412 case M4xVSS_kVideoEffectType_Pink:
1413 effect = VIDEO_EFFECT_PINK;
1414 break;
1415
1416 case M4xVSS_kVideoEffectType_Green:
1417 effect = VIDEO_EFFECT_GREEN;
1418 break;
1419
1420 case M4xVSS_kVideoEffectType_Sepia:
1421 effect = VIDEO_EFFECT_SEPIA;
1422 break;
1423
1424 case M4xVSS_kVideoEffectType_Negative:
1425 effect = VIDEO_EFFECT_NEGATIVE;
1426 break;
1427
1428 case M4xVSS_kVideoEffectType_Framing:
1429 effect = VIDEO_EFFECT_FRAMING;
1430 break;
1431
1432 case M4xVSS_kVideoEffectType_Fifties:
1433 effect = VIDEO_EFFECT_FIFTIES;
1434 break;
1435
1436 case M4xVSS_kVideoEffectType_ColorRGB16:
1437 effect = VIDEO_EFFECT_COLOR_RGB16;
1438 break;
1439
1440 case M4xVSS_kVideoEffectType_Gradient:
1441 effect = VIDEO_EFFECT_GRADIENT;
1442 break;
1443
1444 default:
1445 effect = VIDEO_EFFECT_NONE;
1446 break;
1447 }
1448
James Dong00f742c2012-01-13 17:34:42 -08001449 if (enable == M4OSA_TRUE) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001450 //If already set, then no need to set again
James Dong00f742c2012-01-13 17:34:42 -08001451 if (!(mCurrentVideoEffect & effect)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001452 mCurrentVideoEffect |= effect;
James Dong00f742c2012-01-13 17:34:42 -08001453 if (effect == VIDEO_EFFECT_FIFTIES) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001454 mIsFiftiesEffectStarted = true;
1455 }
1456 }
James Dong00f742c2012-01-13 17:34:42 -08001457 } else {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001458 //Reset only if already set
James Dong00f742c2012-01-13 17:34:42 -08001459 if (mCurrentVideoEffect & effect) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001460 mCurrentVideoEffect &= ~effect;
1461 }
1462 }
1463}
1464
1465status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) {
1466 mVideoWidth = width;
1467 mVideoHeight = height;
1468 return OK;
1469}
1470
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001471status_t PreviewPlayer::readFirstVideoFrame() {
James Dong00f742c2012-01-13 17:34:42 -08001472 ALOGV("readFirstVideoFrame");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001473
1474 if (!mVideoBuffer) {
1475 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -08001476 if (mSeeking != NO_SEEK) {
James Dong00f742c2012-01-13 17:34:42 -08001477 ALOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001478 mSeekTimeUs / 1E6);
1479
1480 options.setSeekTo(
1481 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
1482 }
1483 for (;;) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001484 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001485 options.clearSeekTo();
1486
1487 if (err != OK) {
James Dong00f742c2012-01-13 17:34:42 -08001488 CHECK(!mVideoBuffer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001489
1490 if (err == INFO_FORMAT_CHANGED) {
James Dong00f742c2012-01-13 17:34:42 -08001491 ALOGV("VideoSource signalled format change");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001492 notifyVideoSize_l();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001493
1494 if (mVideoRenderer != NULL) {
1495 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -08001496 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001497 if (err != OK) {
1498 postStreamDoneEvent_l(err);
1499 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001500 }
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001501
1502 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001503 continue;
1504 }
James Dong00f742c2012-01-13 17:34:42 -08001505 ALOGV("EOS reached.");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001506 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001507 mFlags |= AUDIO_AT_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001508 postStreamDoneEvent_l(err);
1509 return OK;
1510 }
1511
1512 if (mVideoBuffer->range_length() == 0) {
1513 // Some decoders, notably the PV AVC software decoder
1514 // return spurious empty buffers that we just want to ignore.
1515
1516 mVideoBuffer->release();
1517 mVideoBuffer = NULL;
1518 continue;
1519 }
1520
1521 int64_t videoTimeUs;
1522 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
Andreas Hubera5872f72011-02-24 15:25:21 -08001523 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001524 if (videoTimeUs < mSeekTimeUs) {
1525 // buffers are before seek time
1526 // ignore them
1527 mVideoBuffer->release();
1528 mVideoBuffer = NULL;
1529 continue;
1530 }
1531 } else {
James Dong00f742c2012-01-13 17:34:42 -08001532 if ((videoTimeUs/1000) < mPlayBeginTimeMsec) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001533 // buffers are before begin cut time
1534 // ignore them
1535 mVideoBuffer->release();
1536 mVideoBuffer = NULL;
1537 continue;
1538 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001539 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001540 break;
1541 }
1542 }
1543
1544 int64_t timeUs;
1545 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
James Dong00f742c2012-01-13 17:34:42 -08001546 setPosition_l(timeUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001547
1548 mDecodedVideoTs = timeUs;
1549
1550 return OK;
1551
1552}
1553
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001554status_t PreviewPlayer::getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs) {
1555 *lastRenderedTimeMs = (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec);
1556 return OK;
1557}
1558
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001559void PreviewPlayer::updateSizeToRender(sp<MetaData> meta) {
1560 if (mVideoRenderer) {
1561 mVideoRenderer->updateVideoSize(meta);
1562 }
1563}
1564
James Dong00f742c2012-01-13 17:34:42 -08001565void PreviewPlayer::setListener(const wp<MediaPlayerBase> &listener) {
1566 Mutex::Autolock autoLock(mLock);
1567 mListener = listener;
1568}
1569
1570status_t PreviewPlayer::setDataSource(const sp<IStreamSource> &source) {
1571 return INVALID_OPERATION;
1572}
1573
1574void PreviewPlayer::reset() {
1575 Mutex::Autolock autoLock(mLock);
1576 reset_l();
1577}
1578
1579void PreviewPlayer::clear_l() {
1580 mDisplayWidth = 0;
1581 mDisplayHeight = 0;
1582
1583 if (mFlags & PLAYING) {
1584 updateBatteryUsage_l();
1585 }
1586
1587 if (mFlags & PREPARING) {
1588 mFlags |= PREPARE_CANCELLED;
1589
1590 if (mFlags & PREPARING_CONNECTED) {
1591 // We are basically done preparing, we're just buffering
1592 // enough data to start playback, we can safely interrupt that.
1593 finishAsyncPrepare_l();
1594 }
1595 }
1596
1597 while (mFlags & PREPARING) {
1598 mPreparedCondition.wait(mLock);
1599 }
1600
1601 cancelPlayerEvents_l(true);
1602
1603 mAudioTrack.clear();
1604 mVideoTrack.clear();
1605
1606 // Shutdown audio first, so that the respone to the reset request
1607 // appears to happen instantaneously as far as the user is concerned
1608 // If we did this later, audio would continue playing while we
1609 // shutdown the video-related resources and the player appear to
1610 // not be as responsive to a reset request.
1611 if (mAudioPlayer == NULL && mAudioSource != NULL) {
1612 // If we had an audio player, it would have effectively
1613 // taken possession of the audio source and stopped it when
1614 // _it_ is stopped. Otherwise this is still our responsibility.
1615 mAudioSource->stop();
1616 }
1617 mAudioSource.clear();
1618
1619 mTimeSource = NULL;
1620
1621 delete mAudioPlayer;
1622 mAudioPlayer = NULL;
1623
1624 if (mVideoSource != NULL) {
1625 shutdownVideoDecoder_l();
1626 }
1627
1628 mDurationUs = -1;
1629 mFlags = 0;
1630 mExtractorFlags = 0;
1631 mTimeSourceDeltaUs = 0;
1632 mVideoTimeUs = 0;
1633
1634 mSeeking = NO_SEEK;
1635 mSeekNotificationSent = false;
1636 mSeekTimeUs = 0;
1637
1638 mUri.setTo("");
1639
1640 mBitrate = -1;
1641 mLastVideoTimeUs = -1;
1642}
1643
1644void PreviewPlayer::notifyListener_l(int msg, int ext1, int ext2) {
1645 if (mListener != NULL) {
1646 sp<MediaPlayerBase> listener = mListener.promote();
1647
1648 if (listener != NULL) {
1649 listener->sendEvent(msg, ext1, ext2);
1650 }
1651 }
1652}
1653
1654void PreviewPlayer::onVideoLagUpdate() {
1655 Mutex::Autolock autoLock(mLock);
1656 if (!mVideoLagEventPending) {
1657 return;
1658 }
1659 mVideoLagEventPending = false;
1660
1661 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
1662 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
1663
1664 if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) {
1665 ALOGV("video late by %lld ms.", videoLateByUs / 1000ll);
1666
1667 notifyListener_l(
1668 MEDIA_INFO,
1669 MEDIA_INFO_VIDEO_TRACK_LAGGING,
1670 videoLateByUs / 1000ll);
1671 }
1672
1673 postVideoLagEvent_l();
1674}
1675
1676void PreviewPlayer::notifyVideoSize_l() {
1677 sp<MetaData> meta = mVideoSource->getFormat();
1678
1679 int32_t vWidth, vHeight;
1680 int32_t cropLeft, cropTop, cropRight, cropBottom;
1681
1682 CHECK(meta->findInt32(kKeyWidth, &vWidth));
1683 CHECK(meta->findInt32(kKeyHeight, &vHeight));
1684
1685 mGivenWidth = vWidth;
1686 mGivenHeight = vHeight;
1687
1688 if (!meta->findRect(
1689 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
1690
1691 cropLeft = cropTop = 0;
1692 cropRight = vWidth - 1;
1693 cropBottom = vHeight - 1;
1694
1695 ALOGD("got dimensions only %d x %d", vWidth, vHeight);
1696 } else {
1697 ALOGD("got crop rect %d, %d, %d, %d",
1698 cropLeft, cropTop, cropRight, cropBottom);
1699 }
1700
1701 mCropRect.left = cropLeft;
1702 mCropRect.right = cropRight;
1703 mCropRect.top = cropTop;
1704 mCropRect.bottom = cropBottom;
1705
1706 int32_t displayWidth;
1707 if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
1708 ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
1709 mDisplayWidth = displayWidth;
1710 }
1711 int32_t displayHeight;
1712 if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
1713 ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
1714 mDisplayHeight = displayHeight;
1715 }
1716
1717 int32_t usableWidth = cropRight - cropLeft + 1;
1718 int32_t usableHeight = cropBottom - cropTop + 1;
1719 if (mDisplayWidth != 0) {
1720 usableWidth = mDisplayWidth;
1721 }
1722 if (mDisplayHeight != 0) {
1723 usableHeight = mDisplayHeight;
1724 }
1725
1726 int32_t rotationDegrees;
1727 if (!mVideoTrack->getFormat()->findInt32(
1728 kKeyRotation, &rotationDegrees)) {
1729 rotationDegrees = 0;
1730 }
1731
1732 if (rotationDegrees == 90 || rotationDegrees == 270) {
1733 notifyListener_l(
1734 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
1735 } else {
1736 notifyListener_l(
1737 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
1738 }
1739}
1740
1741status_t PreviewPlayer::pause() {
1742 Mutex::Autolock autoLock(mLock);
1743
1744 mFlags &= ~CACHE_UNDERRUN;
1745
1746 return pause_l();
1747}
1748
1749status_t PreviewPlayer::pause_l(bool at_eos) {
1750 if (!(mFlags & PLAYING)) {
1751 return OK;
1752 }
1753
1754 cancelPlayerEvents_l();
1755
1756 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1757 if (at_eos) {
1758 // If we played the audio stream to completion we
1759 // want to make sure that all samples remaining in the audio
1760 // track's queue are played out.
1761 mAudioPlayer->pause(true /* playPendingSamples */);
1762 } else {
1763 mAudioPlayer->pause();
1764 }
1765
1766 mFlags &= ~AUDIO_RUNNING;
1767 }
1768
1769 mFlags &= ~PLAYING;
1770 updateBatteryUsage_l();
1771
1772 return OK;
1773}
1774
1775bool PreviewPlayer::isPlaying() const {
1776 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
1777}
1778
1779void PreviewPlayer::setSurface(const sp<Surface> &surface) {
1780 Mutex::Autolock autoLock(mLock);
1781
1782 mSurface = surface;
1783 setNativeWindow_l(surface);
1784}
1785
1786void PreviewPlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
1787 Mutex::Autolock autoLock(mLock);
1788
1789 mSurface.clear();
1790 if (surfaceTexture != NULL) {
1791 setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
1792 }
1793}
1794
1795void PreviewPlayer::shutdownVideoDecoder_l() {
1796 if (mVideoBuffer) {
1797 mVideoBuffer->release();
1798 mVideoBuffer = NULL;
1799 }
1800
1801 mVideoSource->stop();
1802
1803 // The following hack is necessary to ensure that the OMX
1804 // component is completely released by the time we may try
1805 // to instantiate it again.
1806 wp<MediaSource> tmp = mVideoSource;
1807 mVideoSource.clear();
1808 while (tmp.promote() != NULL) {
1809 usleep(1000);
1810 }
1811 IPCThreadState::self()->flushCommands();
1812}
1813
1814void PreviewPlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
1815 mNativeWindow = native;
1816
1817 if (mVideoSource == NULL) {
1818 return;
1819 }
1820
1821 ALOGI("attempting to reconfigure to use new surface");
1822
1823 bool wasPlaying = (mFlags & PLAYING) != 0;
1824
1825 pause_l();
1826
1827 shutdownVideoDecoder_l();
1828
1829 CHECK_EQ(initVideoDecoder_l(), (status_t)OK);
1830
1831 if (mLastVideoTimeUs >= 0) {
1832 mSeeking = SEEK;
1833 mSeekNotificationSent = true;
1834 mSeekTimeUs = mLastVideoTimeUs;
1835 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
1836 }
1837
1838 if (wasPlaying) {
1839 play_l();
1840 }
1841}
1842
1843void PreviewPlayer::setAudioSink(
1844 const sp<MediaPlayerBase::AudioSink> &audioSink) {
1845 Mutex::Autolock autoLock(mLock);
1846
1847 mAudioSink = audioSink;
1848}
1849
1850status_t PreviewPlayer::setLooping(bool shouldLoop) {
1851 Mutex::Autolock autoLock(mLock);
1852
1853 mFlags = mFlags & ~LOOPING;
1854
1855 if (shouldLoop) {
1856 mFlags |= LOOPING;
1857 }
1858
1859 return OK;
1860}
1861
1862void PreviewPlayer::setDuration_l(int64_t durationUs) {
1863 if (mDurationUs < 0 || durationUs > mDurationUs) {
1864 mDurationUs = durationUs;
1865 }
1866}
1867
1868status_t PreviewPlayer::getDuration(int64_t *durationUs) {
1869 Mutex::Autolock autoLock(mLock);
1870 if (mDurationUs < 0) {
1871 return UNKNOWN_ERROR;
1872 }
1873
1874 *durationUs = mDurationUs;
1875 return OK;
1876}
1877
1878status_t PreviewPlayer::getPosition(int64_t *positionUs) {
1879 Mutex::Autolock autoLock(mLock);
1880
1881 if (mSeeking != NO_SEEK) {
1882 *positionUs = mSeekTimeUs;
1883 } else if (mVideoSource != NULL
1884 && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
1885 *positionUs = mVideoTimeUs;
1886 } else if (mAudioPlayer != NULL) {
1887 *positionUs = mAudioPlayer->getMediaTimeUs();
1888 } else {
1889 *positionUs = 0;
1890 }
1891
1892 return OK;
1893}
1894
1895void PreviewPlayer::setPosition_l(int64_t timeUs) {
1896 mVideoTimeUs = timeUs;
1897}
1898
1899status_t PreviewPlayer::seekTo_l(int64_t timeUs) {
1900 ALOGV("seekTo_l");
1901 if (mFlags & CACHE_UNDERRUN) {
1902 mFlags &= ~CACHE_UNDERRUN;
1903 play_l();
1904 }
1905
1906 if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
1907 // Video playback completed before, there's no pending
1908 // video event right now. In order for this new seek
1909 // to be honored, we need to post one.
1910
1911 postVideoEvent_l();
1912 }
1913
1914 mSeeking = SEEK;
1915 mSeekNotificationSent = false;
1916 mSeekTimeUs = timeUs;
1917 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
1918
1919 seekAudioIfNecessary_l();
1920
1921 if (!(mFlags & PLAYING)) {
1922 ALOGV("seeking while paused, sending SEEK_COMPLETE notification"
1923 " immediately.");
1924
1925 notifyListener_l(MEDIA_SEEK_COMPLETE);
1926 mSeekNotificationSent = true;
1927
1928 if ((mFlags & PREPARED) && mVideoSource != NULL) {
1929 mFlags |= SEEK_PREVIEW;
1930 postVideoEvent_l();
1931 }
1932 }
1933
1934 return OK;
1935}
1936
1937void PreviewPlayer::seekAudioIfNecessary_l() {
1938 if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
1939 mAudioPlayer->seekTo(mSeekTimeUs);
1940
1941 mWatchForAudioSeekComplete = true;
1942 mWatchForAudioEOS = true;
1943 }
1944}
1945
1946void PreviewPlayer::setAudioSource(const sp<MediaSource>& source) {
1947 CHECK(source != NULL);
1948 mAudioTrack = source;
1949}
1950
1951void PreviewPlayer::setVideoSource(const sp<MediaSource>& source) {
1952 CHECK(source != NULL);
1953 mVideoTrack = source;
1954}
1955
1956void PreviewPlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
1957 if (mSeeking == SEEK_VIDEO_ONLY) {
1958 mSeeking = NO_SEEK;
1959 return;
1960 }
1961
1962 if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
1963 return;
1964 }
1965
1966 if (mAudioPlayer != NULL) {
1967 ALOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
1968
1969 // If we don't have a video time, seek audio to the originally
1970 // requested seek time instead.
1971
1972 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
1973 mWatchForAudioSeekComplete = true;
1974 mWatchForAudioEOS = true;
1975 } else if (!mSeekNotificationSent) {
1976 // If we're playing video only, report seek complete now,
1977 // otherwise audio player will notify us later.
1978 notifyListener_l(MEDIA_SEEK_COMPLETE);
1979 mSeekNotificationSent = true;
1980 }
1981
1982 mFlags |= FIRST_FRAME;
1983 mSeeking = NO_SEEK;
1984}
1985
1986void PreviewPlayer::onCheckAudioStatus() {
1987 Mutex::Autolock autoLock(mLock);
1988 if (!mAudioStatusEventPending) {
1989 // Event was dispatched and while we were blocking on the mutex,
1990 // has already been cancelled.
1991 return;
1992 }
1993
1994 mAudioStatusEventPending = false;
1995
1996 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1997 mWatchForAudioSeekComplete = false;
1998
1999 if (!mSeekNotificationSent) {
2000 notifyListener_l(MEDIA_SEEK_COMPLETE);
2001 mSeekNotificationSent = true;
2002 }
2003
2004 mSeeking = NO_SEEK;
2005 }
2006
2007 status_t finalStatus;
2008 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
2009 mWatchForAudioEOS = false;
2010 mFlags |= AUDIO_AT_EOS;
2011 mFlags |= FIRST_FRAME;
2012 postStreamDoneEvent_l(finalStatus);
2013 }
2014}
2015
2016void PreviewPlayer::postVideoEvent_l(int64_t delayUs) {
2017 if (mVideoEventPending) {
2018 return;
2019 }
2020
2021 mVideoEventPending = true;
2022 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
2023}
2024
2025void PreviewPlayer::postStreamDoneEvent_l(status_t status) {
2026 if (mStreamDoneEventPending) {
2027 return;
2028 }
2029 mStreamDoneEventPending = true;
2030
2031 mStreamDoneStatus = status;
2032 mQueue.postEvent(mStreamDoneEvent);
2033}
2034
2035void PreviewPlayer::postVideoLagEvent_l() {
2036 if (mVideoLagEventPending) {
2037 return;
2038 }
2039 mVideoLagEventPending = true;
2040 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
2041}
2042
2043void PreviewPlayer::postCheckAudioStatusEvent_l(int64_t delayUs) {
2044 if (mAudioStatusEventPending) {
2045 return;
2046 }
2047 mAudioStatusEventPending = true;
2048 mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
2049}
2050
2051void PreviewPlayer::abortPrepare(status_t err) {
2052 CHECK(err != OK);
2053
2054 if (mIsAsyncPrepare) {
2055 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2056 }
2057
2058 mPrepareResult = err;
2059 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
2060 mAsyncPrepareEvent = NULL;
2061 mPreparedCondition.broadcast();
2062}
2063
2064uint32_t PreviewPlayer::getSourceSeekFlags() const {
2065 Mutex::Autolock lock(mLock);
2066 return mExtractorFlags;
2067}
2068
2069void PreviewPlayer::postAudioEOS(int64_t delayUs) {
2070 Mutex::Autolock autoLock(mLock);
2071 postCheckAudioStatusEvent_l(delayUs);
2072}
2073
2074void PreviewPlayer::postAudioSeekComplete() {
2075 Mutex::Autolock autoLock(mLock);
2076 postCheckAudioStatusEvent_l(0 /* delayUs */);
2077}
2078
2079void PreviewPlayer::updateBatteryUsage_l() {
2080 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
2081 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
2082 params |= IMediaPlayerService::kBatteryDataTrackAudio;
2083 }
2084 if (mVideoSource != NULL) {
2085 params |= IMediaPlayerService::kBatteryDataTrackVideo;
2086 }
2087 addBatteryData(params);
2088}
2089
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002090} // namespace android