blob: 80eee4b611e0aaffdd5dd5bda027b0ae3afedf64 [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"
James Dong00f742c2012-01-13 17:34:42 -080039#include "DummyAudioSource.h"
40#include "DummyVideoSource.h"
41#include "VideoEditorSRC.h"
42#include "PreviewPlayer.h"
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080043
44namespace android {
45
46
James Dong00f742c2012-01-13 17:34:42 -080047void addBatteryData(uint32_t params) {
48 sp<IBinder> binder =
49 defaultServiceManager()->getService(String16("media.player"));
50 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
51 CHECK(service.get() != NULL);
52
53 service->addBatteryData(params);
54}
55
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080056struct PreviewPlayerEvent : public TimedEventQueue::Event {
57 PreviewPlayerEvent(
58 PreviewPlayer *player,
59 void (PreviewPlayer::*method)())
60 : mPlayer(player),
61 mMethod(method) {
62 }
63
64protected:
65 virtual ~PreviewPlayerEvent() {}
66
67 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
68 (mPlayer->*mMethod)();
69 }
70
71private:
72 PreviewPlayer *mPlayer;
73 void (PreviewPlayer::*mMethod)();
74
75 PreviewPlayerEvent(const PreviewPlayerEvent &);
76 PreviewPlayerEvent &operator=(const PreviewPlayerEvent &);
77};
78
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080079PreviewPlayer::PreviewPlayer(NativeWindowRenderer* renderer)
James Dong00f742c2012-01-13 17:34:42 -080080 : mQueueStarted(false),
81 mTimeSource(NULL),
82 mVideoRendererIsPreview(false),
83 mAudioPlayer(NULL),
84 mDisplayWidth(0),
85 mDisplayHeight(0),
86 mFlags(0),
87 mExtractorFlags(0),
88 mVideoBuffer(NULL),
89 mLastVideoTimeUs(-1),
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080090 mNativeWindowRenderer(renderer),
91 mCurrFramingEffectIndex(0),
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -080092 mFrameRGBBuffer(NULL),
Chih-Chung Chang43fcc392011-08-02 16:17:39 +080093 mFrameYUVBuffer(NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080094
James Dong00f742c2012-01-13 17:34:42 -080095 CHECK_EQ(mClient.connect(), (status_t)OK);
96 DataSource::RegisterDefaultSniffers();
97
98
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080099 mVideoRenderer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800100 mEffectsSettings = NULL;
James Dong727f9e12012-01-20 13:09:13 -0800101 mAudioPlayer = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800102 mAudioMixStoryBoardTS = 0;
103 mCurrentMediaBeginCutTime = 0;
104 mCurrentMediaVolumeValue = 0;
105 mNumberEffects = 0;
106 mDecodedVideoTs = 0;
107 mDecVideoTsStoryBoard = 0;
108 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
109 mProgressCbInterval = 0;
110 mNumberDecVideoFrames = 0;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800111 mOverlayUpdateEventPosted = false;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800112 mIsChangeSourceRequired = true;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800113
114 mVideoEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoEvent);
115 mVideoEventPending = false;
James Dong00f742c2012-01-13 17:34:42 -0800116 mVideoLagEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoLagUpdate);
117 mVideoEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800118 mCheckAudioStatusEvent = new PreviewPlayerEvent(
James Dong00f742c2012-01-13 17:34:42 -0800119 this, &PreviewPlayer::onCheckAudioStatus);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800120 mAudioStatusEventPending = false;
James Dong00f742c2012-01-13 17:34:42 -0800121 mStreamDoneEvent = new PreviewPlayerEvent(
122 this, &PreviewPlayer::onStreamDone);
123 mStreamDoneEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800124 mProgressCbEvent = new PreviewPlayerEvent(this,
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800125 &PreviewPlayer::onProgressCbEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800126
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800127 mOverlayUpdateEvent = new PreviewPlayerEvent(this,
128 &PreviewPlayer::onUpdateOverlayEvent);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800129 mProgressCbEventPending = false;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -0800130
131 mOverlayUpdateEventPending = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800132 mRenderingMode = (M4xVSS_MediaRendering)MEDIA_RENDERING_INVALID;
133 mIsFiftiesEffectStarted = false;
134 reset();
135}
136
137PreviewPlayer::~PreviewPlayer() {
138
139 if (mQueueStarted) {
140 mQueue.stop();
141 }
142
143 reset();
144
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800145 if (mVideoRenderer) {
146 mNativeWindowRenderer->destroyRenderInput(mVideoRenderer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800147 }
James Dong00f742c2012-01-13 17:34:42 -0800148
149 Mutex::Autolock lock(mLock);
150 clear_l();
151 mClient.disconnect();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800152}
153
James Dong00f742c2012-01-13 17:34:42 -0800154void PreviewPlayer::cancelPlayerEvents_l(bool updateProgressCb) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800155 mQueue.cancelEvent(mVideoEvent->eventID());
156 mVideoEventPending = false;
157 mQueue.cancelEvent(mStreamDoneEvent->eventID());
158 mStreamDoneEventPending = false;
159 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
160 mAudioStatusEventPending = false;
James Dong00f742c2012-01-13 17:34:42 -0800161 mQueue.cancelEvent(mVideoLagEvent->eventID());
162 mVideoLagEventPending = false;
163 if (updateProgressCb) {
164 mQueue.cancelEvent(mProgressCbEvent->eventID());
165 mProgressCbEventPending = false;
166 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800167}
168
James Dongdaeb5b32012-01-12 12:12:40 -0800169status_t PreviewPlayer::setDataSource(const char *path) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800170 Mutex::Autolock autoLock(mLock);
James Dongdaeb5b32012-01-12 12:12:40 -0800171 return setDataSource_l(path);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800172}
173
James Dongdaeb5b32012-01-12 12:12:40 -0800174status_t PreviewPlayer::setDataSource_l(const char *path) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800175 reset_l();
176
James Dongdaeb5b32012-01-12 12:12:40 -0800177 mUri = path;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800178
179 // The actual work will be done during preparation in the call to
180 // ::finishSetDataSource_l to avoid blocking the calling thread in
181 // setDataSource for any significant time.
182 return OK;
183}
184
185status_t PreviewPlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
186 bool haveAudio = false;
187 bool haveVideo = false;
188 for (size_t i = 0; i < extractor->countTracks(); ++i) {
189 sp<MetaData> meta = extractor->getTrackMetaData(i);
190
191 const char *mime;
192 CHECK(meta->findCString(kKeyMIMEType, &mime));
193
194 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
195 setVideoSource(extractor->getTrack(i));
196 haveVideo = true;
197 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
198 setAudioSource(extractor->getTrack(i));
199 haveAudio = true;
200
201 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
202 // Only do this for vorbis audio, none of the other audio
203 // formats even support this ringtone specific hack and
204 // retrieving the metadata on some extractors may turn out
205 // to be very expensive.
206 sp<MetaData> fileMeta = extractor->getMetaData();
207 int32_t loop;
208 if (fileMeta != NULL
209 && fileMeta->findInt32(kKeyAutoLoop, &loop)
210 && loop != 0) {
211 mFlags |= AUTO_LOOPING;
212 }
213 }
214 }
215
216 if (haveAudio && haveVideo) {
217 break;
218 }
219 }
220
221 /* Add the support for Dummy audio*/
222 if( !haveAudio ){
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800223 mAudioTrack = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700224 ((mPlayEndTimeMsec)*1000LL));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800225 if(mAudioTrack != NULL) {
226 haveAudio = true;
227 }
228 }
229
230 if (!haveAudio && !haveVideo) {
231 return UNKNOWN_ERROR;
232 }
233
234 mExtractorFlags = extractor->flags();
235 return OK;
236}
237
238status_t PreviewPlayer::setDataSource_l_jpg() {
James Dong00f742c2012-01-13 17:34:42 -0800239 ALOGV("setDataSource_l_jpg");
240
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800241 M4OSA_ERR err = M4NO_ERROR;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800242
243 mAudioSource = DummyAudioSource::Create(32000, 2, 20000,
Raghavender Pallaebf40152011-03-14 20:15:12 -0700244 ((mPlayEndTimeMsec)*1000LL));
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800245 if(mAudioSource != NULL) {
246 setAudioSource(mAudioSource);
247 }
248 status_t error = mAudioSource->start();
249 if (error != OK) {
James Dong00f742c2012-01-13 17:34:42 -0800250 ALOGE("Error starting dummy audio source");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800251 mAudioSource.clear();
252 return err;
253 }
254
Raghavender Pallaebf40152011-03-14 20:15:12 -0700255 mDurationUs = (mPlayEndTimeMsec - mPlayBeginTimeMsec)*1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800256
257 mVideoSource = DummyVideoSource::Create(mVideoWidth, mVideoHeight,
258 mDurationUs, mUri);
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800259
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800260 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800261 setVideoSource(mVideoSource);
262 status_t err1 = mVideoSource->start();
263 if (err1 != OK) {
264 mVideoSource.clear();
265 return err;
266 }
267
268 mIsVideoSourceJpg = true;
269 return OK;
270}
271
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800272void PreviewPlayer::reset_l() {
273
274 if (mFlags & PREPARING) {
275 mFlags |= PREPARE_CANCELLED;
276 }
277
278 while (mFlags & PREPARING) {
279 mPreparedCondition.wait(mLock);
280 }
281
James Dong00f742c2012-01-13 17:34:42 -0800282 cancelPlayerEvents_l();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800283 mAudioTrack.clear();
284 mVideoTrack.clear();
285
286 // Shutdown audio first, so that the respone to the reset request
287 // appears to happen instantaneously as far as the user is concerned
288 // If we did this later, audio would continue playing while we
289 // shutdown the video-related resources and the player appear to
290 // not be as responsive to a reset request.
291 if (mAudioPlayer == NULL && mAudioSource != NULL) {
292 // If we had an audio player, it would have effectively
293 // taken possession of the audio source and stopped it when
294 // _it_ is stopped. Otherwise this is still our responsibility.
295 mAudioSource->stop();
296 }
297 mAudioSource.clear();
298
299 mTimeSource = NULL;
300
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800301 //Single audio player instance used
302 //So donot delete it here
303 //It is deleted from PreviewController class
304 //delete mAudioPlayer;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800305 mAudioPlayer = NULL;
306
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800307 if (mVideoBuffer) {
308 mVideoBuffer->release();
309 mVideoBuffer = NULL;
310 }
311
312 if (mVideoSource != NULL) {
313 mVideoSource->stop();
314
315 // The following hack is necessary to ensure that the OMX
316 // component is completely released by the time we may try
317 // to instantiate it again.
318 wp<MediaSource> tmp = mVideoSource;
319 mVideoSource.clear();
320 while (tmp.promote() != NULL) {
321 usleep(1000);
322 }
323 IPCThreadState::self()->flushCommands();
324 }
325
326 mDurationUs = -1;
327 mFlags = 0;
328 mExtractorFlags = 0;
329 mVideoWidth = mVideoHeight = -1;
330 mTimeSourceDeltaUs = 0;
331 mVideoTimeUs = 0;
332
Andreas Hubera5872f72011-02-24 15:25:21 -0800333 mSeeking = NO_SEEK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800334 mSeekNotificationSent = false;
335 mSeekTimeUs = 0;
336
337 mUri.setTo("");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800338
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800339 mCurrentVideoEffect = VIDEO_EFFECT_NONE;
340 mIsVideoSourceJpg = false;
341 mFrameRGBBuffer = NULL;
342 if(mFrameYUVBuffer != NULL) {
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700343 free(mFrameYUVBuffer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800344 mFrameYUVBuffer = NULL;
345 }
346}
347
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800348status_t PreviewPlayer::play() {
James Dong00f742c2012-01-13 17:34:42 -0800349 ALOGV("play");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800350 Mutex::Autolock autoLock(mLock);
351
352 mFlags &= ~CACHE_UNDERRUN;
Hong Tenge0180232011-09-28 18:40:38 -0700353 mFlags &= ~INFORMED_AV_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800354 return play_l();
355}
356
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800357status_t PreviewPlayer::startAudioPlayer_l() {
James Dong00f742c2012-01-13 17:34:42 -0800358 ALOGV("startAudioPlayer_l");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800359 CHECK(!(mFlags & AUDIO_RUNNING));
360
361 if (mAudioSource == NULL || mAudioPlayer == NULL) {
362 return OK;
363 }
364
365 if (!(mFlags & AUDIOPLAYER_STARTED)) {
366 mFlags |= AUDIOPLAYER_STARTED;
367
368 // We've already started the MediaSource in order to enable
369 // the prefetcher to read its data.
James Dong727f9e12012-01-20 13:09:13 -0800370 status_t err = mAudioPlayer->start(
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800371 true /* sourceAlreadyStarted */);
372
373 if (err != OK) {
374 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
375 return err;
376 }
377 } else {
James Dong727f9e12012-01-20 13:09:13 -0800378 mAudioPlayer->resume();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800379 }
380
381 mFlags |= AUDIO_RUNNING;
382
383 mWatchForAudioEOS = true;
384
385 return OK;
386}
387
James Dong727f9e12012-01-20 13:09:13 -0800388status_t PreviewPlayer::setAudioPlayer(VideoEditorAudioPlayer *audioPlayer) {
James Dong00f742c2012-01-13 17:34:42 -0800389 ALOGV("setAudioPlayer");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800390 Mutex::Autolock autoLock(mLock);
391 CHECK(!(mFlags & PLAYING));
392 mAudioPlayer = audioPlayer;
393
Steve Block2703f232011-10-20 11:56:09 +0100394 ALOGV("SetAudioPlayer");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800395 mIsChangeSourceRequired = true;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800396
397 // check if the new and old source are dummy
James Dong727f9e12012-01-20 13:09:13 -0800398 sp<MediaSource> anAudioSource = mAudioPlayer->getSource();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800399 if (anAudioSource == NULL) {
400 // Audio player does not have any source set.
Steve Block2703f232011-10-20 11:56:09 +0100401 ALOGV("setAudioPlayer: Audio player does not have any source set");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800402 return OK;
403 }
404
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800405 // If new video source is not dummy, then always change source
406 // Else audio player continues using old audio source and there are
407 // frame drops to maintain AV sync
408 sp<MetaData> meta;
409 if (mVideoSource != NULL) {
410 meta = mVideoSource->getFormat();
411 const char *pVidSrcType;
412 if (meta->findCString(kKeyDecoderComponent, &pVidSrcType)) {
413 if (strcmp(pVidSrcType, "DummyVideoSource") != 0) {
Steve Block2703f232011-10-20 11:56:09 +0100414 ALOGV(" Video clip with silent audio; need to change source");
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800415 return OK;
416 }
417 }
418 }
419
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800420 const char *pSrcType1;
421 const char *pSrcType2;
Rajneesh Chowdury9a8c9a82011-03-11 14:02:47 -0800422 meta = anAudioSource->getFormat();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800423
424 if (meta->findCString(kKeyDecoderComponent, &pSrcType1)) {
425 if (strcmp(pSrcType1, "DummyAudioSource") == 0) {
426 meta = mAudioSource->getFormat();
427 if (meta->findCString(kKeyDecoderComponent, &pSrcType2)) {
428 if (strcmp(pSrcType2, "DummyAudioSource") == 0) {
429 mIsChangeSourceRequired = false;
430 // Just set the new play duration for the existing source
431 MediaSource *pMediaSrc = anAudioSource.get();
432 DummyAudioSource *pDummyAudioSource = (DummyAudioSource*)pMediaSrc;
433 //Increment the duration of audio source
Raghavender Pallaebf40152011-03-14 20:15:12 -0700434 pDummyAudioSource->setDuration(
435 (int64_t)((mPlayEndTimeMsec)*1000LL));
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800436
437 // Stop the new audio source
438 // since we continue using old source
Steve Block2703f232011-10-20 11:56:09 +0100439 ALOGV("setAudioPlayer: stop new audio source");
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800440 mAudioSource->stop();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800441 }
442 }
443 }
444 }
445
446 return OK;
447}
448
449void PreviewPlayer::onStreamDone() {
James Dong00f742c2012-01-13 17:34:42 -0800450 ALOGV("onStreamDone");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800451 // Posted whenever any stream finishes playing.
452
453 Mutex::Autolock autoLock(mLock);
454 if (!mStreamDoneEventPending) {
455 return;
456 }
457 mStreamDoneEventPending = false;
458
459 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
Steve Block2703f232011-10-20 11:56:09 +0100460 ALOGV("MEDIA_ERROR %d", mStreamDoneStatus);
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800461
462 notifyListener_l(
463 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
464
465 pause_l(true /* at eos */);
466
467 mFlags |= AT_EOS;
468 return;
469 }
470
471 const bool allDone =
472 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
473 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
474
475 if (!allDone) {
476 return;
477 }
478
479 if (mFlags & (LOOPING | AUTO_LOOPING)) {
480 seekTo_l(0);
481
482 if (mVideoSource != NULL) {
483 postVideoEvent_l();
484 }
485 } else {
Steve Block2703f232011-10-20 11:56:09 +0100486 ALOGV("MEDIA_PLAYBACK_COMPLETE");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800487 //pause before sending event
488 pause_l(true /* at eos */);
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700489
490 //This lock is used to syncronize onStreamDone() in PreviewPlayer and
491 //stopPreview() in PreviewController
492 Mutex::Autolock autoLock(mLockControl);
Hong Tenge0180232011-09-28 18:40:38 -0700493 /* Make sure PreviewPlayer only notifies MEDIA_PLAYBACK_COMPLETE once for each clip!
494 * It happens twice in following scenario.
495 * To make the clips in preview storyboard are played and switched smoothly,
496 * PreviewController uses two PreviewPlayer instances and one AudioPlayer.
497 * The two PreviewPlayer use the same AudioPlayer to play the audio,
498 * and change the audio source of the AudioPlayer.
499 * If the audio source of current playing clip and next clip are dummy
500 * audio source(image or video without audio), it will not change the audio source
501 * to avoid the "audio glitch", and keep using the current audio source.
502 * When the video of current clip reached the EOS, PreviewPlayer will set EOS flag
503 * for video and audio, and it will notify MEDIA_PLAYBACK_COMPLETE.
504 * But the audio(dummy audio source) is still playing(for next clip),
505 * and when it reached the EOS, and video reached EOS,
506 * PreviewPlayer will notify MEDIA_PLAYBACK_COMPLETE again. */
507 if (!(mFlags & INFORMED_AV_EOS)) {
508 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
509 mFlags |= INFORMED_AV_EOS;
510 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800511 mFlags |= AT_EOS;
Steve Block2703f232011-10-20 11:56:09 +0100512 ALOGV("onStreamDone end");
Raghavender Pallafa31daf2011-03-18 22:32:51 -0700513 return;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800514 }
515}
516
517
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800518status_t PreviewPlayer::play_l() {
James Dong00f742c2012-01-13 17:34:42 -0800519 ALOGV("play_l");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800520
Rajneesh Chowdury8b95de22011-02-16 15:32:06 -0800521 mFlags &= ~SEEK_PREVIEW;
522
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800523 if (mFlags & PLAYING) {
524 return OK;
525 }
526 mStartNextPlayer = false;
527
528 if (!(mFlags & PREPARED)) {
529 status_t err = prepare_l();
530
531 if (err != OK) {
532 return err;
533 }
534 }
535
536 mFlags |= PLAYING;
537 mFlags |= FIRST_FRAME;
538
539 bool deferredAudioSeek = false;
540
541 if (mAudioSource != NULL) {
542 if (mAudioPlayer == NULL) {
543 if (mAudioSink != NULL) {
544
545 mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800546 mAudioPlayer->setSource(mAudioSource);
547
James Dong727f9e12012-01-20 13:09:13 -0800548 mAudioPlayer->setAudioMixSettings(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800549 mPreviewPlayerAudioMixSettings);
550
James Dong727f9e12012-01-20 13:09:13 -0800551 mAudioPlayer->setAudioMixPCMFileHandle(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800552 mAudioMixPCMFileHandle);
553
James Dong727f9e12012-01-20 13:09:13 -0800554 mAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800555 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
556 mCurrentMediaVolumeValue);
557
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800558 mFlags |= AUDIOPLAYER_STARTED;
559 // We've already started the MediaSource in order to enable
560 // the prefetcher to read its data.
James Dong727f9e12012-01-20 13:09:13 -0800561 status_t err = mAudioPlayer->start(
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800562 true /* sourceAlreadyStarted */);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800563
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800564 if (err != OK) {
565 //delete mAudioPlayer;
566 mAudioPlayer = NULL;
567
568 mFlags &= ~(PLAYING | FIRST_FRAME);
569 return err;
570 }
571
James Dong727f9e12012-01-20 13:09:13 -0800572 mTimeSource = mAudioPlayer;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800573 mFlags |= AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800574 deferredAudioSeek = true;
575 mWatchForAudioSeekComplete = false;
576 mWatchForAudioEOS = true;
577 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800578 } else {
James Dong727f9e12012-01-20 13:09:13 -0800579 bool isAudioPlayerStarted = mAudioPlayer->isStarted();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800580
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800581 if (mIsChangeSourceRequired == true) {
Steve Block2703f232011-10-20 11:56:09 +0100582 ALOGV("play_l: Change audio source required");
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800583
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800584 if (isAudioPlayerStarted == true) {
James Dong727f9e12012-01-20 13:09:13 -0800585 mAudioPlayer->pause();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800586 }
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800587
James Dong727f9e12012-01-20 13:09:13 -0800588 mAudioPlayer->setSource(mAudioSource);
589 mAudioPlayer->setObserver(this);
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800590
James Dong727f9e12012-01-20 13:09:13 -0800591 mAudioPlayer->setAudioMixSettings(
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800592 mPreviewPlayerAudioMixSettings);
593
James Dong727f9e12012-01-20 13:09:13 -0800594 mAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800595 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
596 mCurrentMediaVolumeValue);
597
598 if (isAudioPlayerStarted == true) {
James Dong727f9e12012-01-20 13:09:13 -0800599 mAudioPlayer->resume();
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800600 } else {
601 status_t err = OK;
James Dong727f9e12012-01-20 13:09:13 -0800602 err = mAudioPlayer->start(true);
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800603 if (err != OK) {
604 mAudioPlayer = NULL;
James Dong727f9e12012-01-20 13:09:13 -0800605 mAudioPlayer = NULL;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800606
607 mFlags &= ~(PLAYING | FIRST_FRAME);
608 return err;
609 }
610 }
611 } else {
Steve Block2703f232011-10-20 11:56:09 +0100612 ALOGV("play_l: No Source change required");
James Dong727f9e12012-01-20 13:09:13 -0800613 mAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800614 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
615 mCurrentMediaVolumeValue);
616
James Dong727f9e12012-01-20 13:09:13 -0800617 mAudioPlayer->resume();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800618 }
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800619
620 mFlags |= AUDIOPLAYER_STARTED;
621 mFlags |= AUDIO_RUNNING;
James Dong727f9e12012-01-20 13:09:13 -0800622 mTimeSource = mAudioPlayer;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800623 deferredAudioSeek = true;
624 mWatchForAudioSeekComplete = false;
625 mWatchForAudioEOS = true;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800626 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800627 }
628
629 if (mTimeSource == NULL && mAudioPlayer == NULL) {
630 mTimeSource = &mSystemTimeSource;
631 }
632
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800633 // Set the seek option for Image source files and read.
634 // This resets the timestamping for image play
635 if (mIsVideoSourceJpg) {
636 MediaSource::ReadOptions options;
637 MediaBuffer *aLocalBuffer;
638 options.setSeekTo(mSeekTimeUs);
639 mVideoSource->read(&aLocalBuffer, &options);
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800640 aLocalBuffer->release();
Dharmaray Kundargi53c567c2011-01-29 18:52:50 -0800641 }
642
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800643 if (mVideoSource != NULL) {
644 // Kick off video playback
645 postVideoEvent_l();
646 }
647
648 if (deferredAudioSeek) {
649 // If there was a seek request while we were paused
650 // and we're just starting up again, honor the request now.
651 seekAudioIfNecessary_l();
652 }
653
654 if (mFlags & AT_EOS) {
655 // Legacy behaviour, if a stream finishes playing and then
656 // is started again, we play from the start...
657 seekTo_l(0);
658 }
659
660 return OK;
661}
662
663
Santosh Madhavabfece172011-02-03 16:59:47 -0800664status_t PreviewPlayer::initRenderer_l() {
Mathias Agopian6e224292011-04-05 15:38:24 -0700665 if (mSurface != NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800666 if(mVideoRenderer == NULL) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800667 mVideoRenderer = mNativeWindowRenderer->createRenderInput();
668 if (mVideoSource != NULL) {
669 updateSizeToRender(mVideoSource->getFormat());
Santosh Madhavabfece172011-02-03 16:59:47 -0800670 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800671 }
672 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800673 return OK;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800674}
675
676
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800677status_t PreviewPlayer::seekTo(int64_t timeUs) {
James Dong00f742c2012-01-13 17:34:42 -0800678 Mutex::Autolock autoLock(mLock);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800679 if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800680 return seekTo_l(timeUs);
681 }
682
683 return OK;
684}
685
686
687status_t PreviewPlayer::getVideoDimensions(
688 int32_t *width, int32_t *height) const {
689 Mutex::Autolock autoLock(mLock);
690
691 if (mVideoWidth < 0 || mVideoHeight < 0) {
692 return UNKNOWN_ERROR;
693 }
694
695 *width = mVideoWidth;
696 *height = mVideoHeight;
697
698 return OK;
699}
700
701
James Dong00f742c2012-01-13 17:34:42 -0800702status_t PreviewPlayer::initAudioDecoder_l() {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800703 sp<MetaData> meta = mAudioTrack->getFormat();
704 const char *mime;
705 CHECK(meta->findCString(kKeyMIMEType, &mime));
706
707 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
708 mAudioSource = mAudioTrack;
709 } else {
710 sp<MediaSource> aRawSource;
711 aRawSource = OMXCodec::Create(
712 mClient.interface(), mAudioTrack->getFormat(),
713 false, // createEncoder
714 mAudioTrack);
715
716 if(aRawSource != NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800717 mAudioSource = new VideoEditorSRC(aRawSource);
718 }
719 }
720
721 if (mAudioSource != NULL) {
722 int64_t durationUs;
723 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
James Dong00f742c2012-01-13 17:34:42 -0800724 setDuration_l(durationUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800725 }
726 status_t err = mAudioSource->start();
727
728 if (err != OK) {
729 mAudioSource.clear();
730 return err;
731 }
732 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
733 // For legacy reasons we're simply going to ignore the absence
734 // of an audio decoder for QCELP instead of aborting playback
735 // altogether.
736 return OK;
737 }
738
739 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
740}
741
James Dong00f742c2012-01-13 17:34:42 -0800742status_t PreviewPlayer::initVideoDecoder_l(uint32_t flags) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800743 initRenderer_l();
744
745 if (mVideoRenderer == NULL) {
Steve Blockf8bd29c2012-01-08 10:14:44 +0000746 ALOGE("Cannot create renderer");
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800747 return UNKNOWN_ERROR;
748 }
749
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800750 mVideoSource = OMXCodec::Create(
751 mClient.interface(), mVideoTrack->getFormat(),
752 false,
753 mVideoTrack,
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800754 NULL, flags, mVideoRenderer->getTargetWindow());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800755
756 if (mVideoSource != NULL) {
757 int64_t durationUs;
758 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
James Dong00f742c2012-01-13 17:34:42 -0800759 setDuration_l(durationUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800760 }
761
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800762 updateSizeToRender(mVideoTrack->getFormat());
Dharmaray Kundargi35cb2de2011-01-19 19:09:27 -0800763
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800764 status_t err = mVideoSource->start();
765
766 if (err != OK) {
767 mVideoSource.clear();
768 return err;
769 }
770 }
771
772 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
773}
774
775
776void PreviewPlayer::onVideoEvent() {
777 uint32_t i=0;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800778 M4OSA_ERR err1 = M4NO_ERROR;
779 int64_t imageFrameTimeUs = 0;
780
781 Mutex::Autolock autoLock(mLock);
782 if (!mVideoEventPending) {
783 // The event has been cancelled in reset_l() but had already
784 // been scheduled for execution at that time.
785 return;
786 }
787 mVideoEventPending = false;
788
Andreas Huber9e4c36a2011-02-08 13:12:32 -0800789 if (mFlags & SEEK_PREVIEW) {
790 mFlags &= ~SEEK_PREVIEW;
791 return;
792 }
793
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800794 TimeSource *ts_st = &mSystemTimeSource;
795 int64_t timeStartUs = ts_st->getRealTimeUs();
796
Andreas Hubera5872f72011-02-24 15:25:21 -0800797 if (mSeeking != NO_SEEK) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800798
799 if(mAudioSource != NULL) {
800
801 // We're going to seek the video source first, followed by
802 // the audio source.
803 // In order to avoid jumps in the DataSource offset caused by
804 // the audio codec prefetching data from the old locations
805 // while the video codec is already reading data from the new
806 // locations, we'll "pause" the audio source, causing it to
807 // stop reading input data until a subsequent seek.
808
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800809 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800810 mAudioPlayer->pause();
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800811 mFlags &= ~AUDIO_RUNNING;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800812 }
813 mAudioSource->pause();
814 }
815 }
816
817 if (!mVideoBuffer) {
818 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -0800819 if (mSeeking != NO_SEEK) {
Steve Block2703f232011-10-20 11:56:09 +0100820 ALOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800821 mSeekTimeUs / 1E6);
822
823 options.setSeekTo(
824 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
825 }
826 for (;;) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800827 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800828 options.clearSeekTo();
829
830 if (err != OK) {
James Dong00f742c2012-01-13 17:34:42 -0800831 CHECK(!mVideoBuffer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800832
833 if (err == INFO_FORMAT_CHANGED) {
Steve Block2703f232011-10-20 11:56:09 +0100834 ALOGV("LV PLAYER VideoSource signalled format change");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800835 notifyVideoSize_l();
836
837 if (mVideoRenderer != NULL) {
838 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -0800839 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800840 if (err != OK) {
841 postStreamDoneEvent_l(err);
842 }
Santosh Madhavabfece172011-02-03 16:59:47 -0800843
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800844 }
Chih-Chung Chang43fcc392011-08-02 16:17:39 +0800845
846 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800847 continue;
848 }
849 // So video playback is complete, but we may still have
Santosh Madhava342f9322011-01-27 16:27:12 -0800850 // a seek request pending that needs to be applied to the audio track
Andreas Hubera5872f72011-02-24 15:25:21 -0800851 if (mSeeking != NO_SEEK) {
Steve Block2703f232011-10-20 11:56:09 +0100852 ALOGV("video stream ended while seeking!");
Santosh Madhava342f9322011-01-27 16:27:12 -0800853 }
854 finishSeekIfNecessary(-1);
Steve Block2703f232011-10-20 11:56:09 +0100855 ALOGV("PreviewPlayer: onVideoEvent EOS reached.");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800856 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800857 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800858 mOverlayUpdateEventPosted = false;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800859 postStreamDoneEvent_l(err);
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800860 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -0700861 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800862 return;
863 }
864
865 if (mVideoBuffer->range_length() == 0) {
866 // Some decoders, notably the PV AVC software decoder
867 // return spurious empty buffers that we just want to ignore.
868
869 mVideoBuffer->release();
870 mVideoBuffer = NULL;
871 continue;
872 }
873
874 int64_t videoTimeUs;
875 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
876
Andreas Hubera5872f72011-02-24 15:25:21 -0800877 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800878 if (videoTimeUs < mSeekTimeUs) {
879 // buffers are before seek time
880 // ignore them
881 mVideoBuffer->release();
882 mVideoBuffer = NULL;
883 continue;
884 }
885 } else {
886 if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
887 // Frames are before begin cut time
888 // Donot render
889 mVideoBuffer->release();
890 mVideoBuffer = NULL;
891 continue;
892 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800893 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800894 break;
895 }
896 }
897
898 mNumberDecVideoFrames++;
899
900 int64_t timeUs;
901 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
James Dong00f742c2012-01-13 17:34:42 -0800902 setPosition_l(timeUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800903
James Dong00f742c2012-01-13 17:34:42 -0800904 if (!mStartNextPlayer) {
905 int64_t playbackTimeRemaining = (mPlayEndTimeMsec * 1000LL) - timeUs;
906 if (playbackTimeRemaining <= 1500000) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800907 //When less than 1.5 sec of playback left
908 // send notification to start next player
909
910 mStartNextPlayer = true;
911 notifyListener_l(0xAAAAAAAA);
912 }
913 }
914
Andreas Hubera5872f72011-02-24 15:25:21 -0800915 SeekType wasSeeking = mSeeking;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800916 finishSeekIfNecessary(timeUs);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800917 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING))) {
918 status_t err = startAudioPlayer_l();
919 if (err != OK) {
Steve Blockf8bd29c2012-01-08 10:14:44 +0000920 ALOGE("Starting the audio player failed w/ err %d", err);
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -0800921 return;
922 }
923 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800924
925 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
926
927 if(ts == NULL) {
928 mVideoBuffer->release();
929 mVideoBuffer = NULL;
930 return;
931 }
932
933 if(!mIsVideoSourceJpg) {
934 if (mFlags & FIRST_FRAME) {
935 mFlags &= ~FIRST_FRAME;
936
937 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
938 }
939
940 int64_t realTimeUs, mediaTimeUs;
941 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
942 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
943 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
944 }
945
946 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
947
948 int64_t latenessUs = nowUs - timeUs;
949
Andreas Hubera5872f72011-02-24 15:25:21 -0800950 if (wasSeeking != NO_SEEK) {
Santosh Madhava342f9322011-01-27 16:27:12 -0800951 // Let's display the first frame after seeking right away.
952 latenessUs = 0;
953 }
Steve Block2703f232011-10-20 11:56:09 +0100954 ALOGV("Audio time stamp = %lld and video time stamp = %lld",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800955 ts->getRealTimeUs(),timeUs);
956 if (latenessUs > 40000) {
957 // We're more than 40ms late.
958
Steve Block2703f232011-10-20 11:56:09 +0100959 ALOGV("LV PLAYER we're late by %lld us (%.2f secs)",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800960 latenessUs, latenessUs / 1E6);
961
962 mVideoBuffer->release();
963 mVideoBuffer = NULL;
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800964 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800965 return;
966 }
967
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800968 if (latenessUs < -25000) {
969 // We're more than 25ms early.
Steve Block2703f232011-10-20 11:56:09 +0100970 ALOGV("We're more than 25ms early, lateness %lld", latenessUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800971
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -0800972 postVideoEvent_l(25000);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800973 return;
974 }
975 }
976
977 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
978 mVideoRendererIsPreview = false;
979
Santosh Madhavabfece172011-02-03 16:59:47 -0800980 status_t err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -0800981 if (err != OK) {
982 postStreamDoneEvent_l(err);
983 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800984 }
985
986 // If timestamp exceeds endCutTime of clip, donot render
987 if((timeUs/1000) > mPlayEndTimeMsec) {
Chih-Chung Changcece4b32011-08-01 16:34:05 +0800988 mVideoBuffer->release();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800989 mVideoBuffer = NULL;
990 mFlags |= VIDEO_AT_EOS;
991 mFlags |= AUDIO_AT_EOS;
Steve Block2703f232011-10-20 11:56:09 +0100992 ALOGV("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS..");
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -0800993 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -0800994 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -0700995 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800996 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
997 return;
998 }
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -0800999 // Capture the frame timestamp to be rendered
1000 mDecodedVideoTs = timeUs;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001001
1002 // Post processing to apply video effects
1003 for(i=0;i<mNumberEffects;i++) {
1004 // First check if effect starttime matches the clip being previewed
1005 if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) ||
1006 (mEffectsSettings[i].uiStartTime >=
1007 ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec)))
1008 {
1009 // This effect doesn't belong to this clip, check next one
1010 continue;
1011 }
1012 // Check if effect applies to this particular frame timestamp
1013 if((mEffectsSettings[i].uiStartTime <=
1014 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) &&
1015 ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=
1016 (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec))
1017 && (mEffectsSettings[i].uiDuration != 0)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001018 setVideoPostProcessingNode(
1019 mEffectsSettings[i].VideoEffectType, TRUE);
1020 }
1021 else {
1022 setVideoPostProcessingNode(
1023 mEffectsSettings[i].VideoEffectType, FALSE);
1024 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001025 }
1026
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001027 //Provide the overlay Update indication when there is an overlay effect
Dharmaray Kundargid01ef562011-01-26 21:11:00 -08001028 if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) {
1029 mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here.
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001030 if (!mOverlayUpdateEventPosted) {
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001031 // Find the effect in effectSettings array
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001032 M4OSA_UInt32 index;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001033 for (index = 0; index < mNumberEffects; index++) {
1034 M4OSA_UInt32 timeMs = mDecodedVideoTs/1000;
1035 M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000;
1036 if(mEffectsSettings[index].VideoEffectType ==
Basavapatna Dattaguru408e25b2011-02-27 21:04:57 -08001037 (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001038 if (((mEffectsSettings[index].uiStartTime + 1) <=
1039 timeMs + timeOffset - mPlayBeginTimeMsec) &&
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001040 ((mEffectsSettings[index].uiStartTime - 1 +
Dharmaray Kundargi254c8df2011-01-28 19:28:31 -08001041 mEffectsSettings[index].uiDuration) >=
1042 timeMs + timeOffset - mPlayBeginTimeMsec))
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001043 {
1044 break;
1045 }
1046 }
1047 }
1048 if (index < mNumberEffects) {
1049 mCurrFramingEffectIndex = index;
1050 mOverlayUpdateEventPosted = true;
1051 postOverlayUpdateEvent_l();
James Dong00f742c2012-01-13 17:34:42 -08001052 ALOGV("Framing index = %ld", mCurrFramingEffectIndex);
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001053 } else {
Steve Block2703f232011-10-20 11:56:09 +01001054 ALOGV("No framing effects found");
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001055 }
1056 }
1057
1058 } else if (mOverlayUpdateEventPosted) {
1059 //Post the event when the overlay is no more valid
Steve Block2703f232011-10-20 11:56:09 +01001060 ALOGV("Overlay is Done");
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001061 mOverlayUpdateEventPosted = false;
1062 postOverlayUpdateEvent_l();
1063 }
1064
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001065 if (mVideoRenderer != NULL) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001066 mVideoRenderer->render(mVideoBuffer, mCurrentVideoEffect,
1067 mRenderingMode, mIsVideoSourceJpg);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001068 }
1069
Chih-Chung Changcece4b32011-08-01 16:34:05 +08001070 mVideoBuffer->release();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001071 mVideoBuffer = NULL;
1072
1073 // Post progress callback based on callback interval set
1074 if(mNumberDecVideoFrames >= mProgressCbInterval) {
1075 postProgressCallbackEvent_l();
1076 mNumberDecVideoFrames = 0; // reset counter
1077 }
1078
1079 // if reached EndCutTime of clip, post EOS event
1080 if((timeUs/1000) >= mPlayEndTimeMsec) {
Steve Block2703f232011-10-20 11:56:09 +01001081 ALOGV("PreviewPlayer: onVideoEvent EOS.");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001082 mFlags |= VIDEO_AT_EOS;
1083 mFlags |= AUDIO_AT_EOS;
Dheeraj Sharma4f4efef2011-02-10 16:55:37 -08001084 mOverlayUpdateEventPosted = false;
Santosh Madhavafe288aa2011-03-01 21:31:04 -08001085 // Set the last decoded timestamp to duration
Raghavender Pallaebf40152011-03-14 20:15:12 -07001086 mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001087 postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1088 }
1089 else {
Andreas Hubera5872f72011-02-24 15:25:21 -08001090 if ((wasSeeking != NO_SEEK) && (mFlags & SEEK_PREVIEW)) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001091 mFlags &= ~SEEK_PREVIEW;
1092 return;
1093 }
1094
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001095 if(!mIsVideoSourceJpg) {
Dharmaray Kundargi4f155f02011-02-01 19:16:43 -08001096 postVideoEvent_l(0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001097 }
1098 else {
1099 postVideoEvent_l(33000);
1100 }
1101 }
1102}
1103
1104status_t PreviewPlayer::prepare() {
James Dong00f742c2012-01-13 17:34:42 -08001105 ALOGV("prepare");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001106 Mutex::Autolock autoLock(mLock);
1107 return prepare_l();
1108}
1109
1110status_t PreviewPlayer::prepare_l() {
James Dong00f742c2012-01-13 17:34:42 -08001111 ALOGV("prepare_l");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001112 if (mFlags & PREPARED) {
1113 return OK;
1114 }
1115
1116 if (mFlags & PREPARING) {
1117 return UNKNOWN_ERROR;
1118 }
1119
1120 mIsAsyncPrepare = false;
1121 status_t err = prepareAsync_l();
1122
1123 if (err != OK) {
1124 return err;
1125 }
1126
1127 while (mFlags & PREPARING) {
1128 mPreparedCondition.wait(mLock);
1129 }
1130
1131 return mPrepareResult;
1132}
1133
James Dong00f742c2012-01-13 17:34:42 -08001134status_t PreviewPlayer::prepareAsync() {
1135 ALOGV("prepareAsync");
1136 Mutex::Autolock autoLock(mLock);
1137 return prepareAsync_l();
1138}
1139
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001140status_t PreviewPlayer::prepareAsync_l() {
James Dong00f742c2012-01-13 17:34:42 -08001141 ALOGV("prepareAsync_l");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001142 if (mFlags & PREPARING) {
1143 return UNKNOWN_ERROR; // async prepare already pending
1144 }
1145
1146 if (!mQueueStarted) {
1147 mQueue.start();
1148 mQueueStarted = true;
1149 }
1150
1151 mFlags |= PREPARING;
1152 mAsyncPrepareEvent = new PreviewPlayerEvent(
1153 this, &PreviewPlayer::onPrepareAsyncEvent);
1154
1155 mQueue.postEvent(mAsyncPrepareEvent);
1156
1157 return OK;
1158}
1159
1160status_t PreviewPlayer::finishSetDataSource_l() {
1161 sp<DataSource> dataSource;
1162 sp<MediaExtractor> extractor;
1163
James Dongdaeb5b32012-01-12 12:12:40 -08001164 dataSource = DataSource::CreateFromURI(mUri.string(), NULL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001165
1166 if (dataSource == NULL) {
1167 return UNKNOWN_ERROR;
1168 }
1169
1170 //If file type is .rgb, then no need to check for Extractor
1171 int uriLen = strlen(mUri);
1172 int startOffset = uriLen - 4;
1173 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) {
1174 extractor = NULL;
1175 }
1176 else {
1177 extractor = MediaExtractor::Create(dataSource,
1178 MEDIA_MIMETYPE_CONTAINER_MPEG4);
1179 }
1180
1181 if (extractor == NULL) {
James Dong00f742c2012-01-13 17:34:42 -08001182 ALOGV("finishSetDataSource_l: failed to create extractor");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001183 return setDataSource_l_jpg();
1184 }
1185
1186 return setDataSource_l(extractor);
1187}
1188
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001189void PreviewPlayer::onPrepareAsyncEvent() {
1190 Mutex::Autolock autoLock(mLock);
Steve Block2703f232011-10-20 11:56:09 +01001191 ALOGV("onPrepareAsyncEvent");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001192
1193 if (mFlags & PREPARE_CANCELLED) {
James Dong00f742c2012-01-13 17:34:42 -08001194 ALOGV("prepare was cancelled before doing anything");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001195 abortPrepare(UNKNOWN_ERROR);
1196 return;
1197 }
1198
1199 if (mUri.size() > 0) {
1200 status_t err = finishSetDataSource_l();
1201
1202 if (err != OK) {
1203 abortPrepare(err);
1204 return;
1205 }
1206 }
1207
1208 if (mVideoTrack != NULL && mVideoSource == NULL) {
James Dong00f742c2012-01-13 17:34:42 -08001209 status_t err = initVideoDecoder_l(OMXCodec::kHardwareCodecsOnly);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001210
1211 if (err != OK) {
1212 abortPrepare(err);
1213 return;
1214 }
1215 }
1216
1217 if (mAudioTrack != NULL && mAudioSource == NULL) {
James Dong00f742c2012-01-13 17:34:42 -08001218 status_t err = initAudioDecoder_l();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001219
1220 if (err != OK) {
1221 abortPrepare(err);
1222 return;
1223 }
1224 }
1225 finishAsyncPrepare_l();
1226
1227}
1228
1229void PreviewPlayer::finishAsyncPrepare_l() {
James Dong00f742c2012-01-13 17:34:42 -08001230 ALOGV("finishAsyncPrepare_l");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001231 if (mIsAsyncPrepare) {
1232 if (mVideoSource == NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001233 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1234 } else {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001235 notifyVideoSize_l();
1236 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001237 notifyListener_l(MEDIA_PREPARED);
1238 }
1239
1240 mPrepareResult = OK;
1241 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1242 mFlags |= PREPARED;
1243 mAsyncPrepareEvent = NULL;
1244 mPreparedCondition.broadcast();
1245}
1246
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001247void PreviewPlayer::acquireLock() {
Steve Block2703f232011-10-20 11:56:09 +01001248 ALOGV("acquireLock");
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001249 mLockControl.lock();
1250}
1251
1252void PreviewPlayer::releaseLock() {
Steve Block2703f232011-10-20 11:56:09 +01001253 ALOGV("releaseLock");
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001254 mLockControl.unlock();
1255}
1256
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001257status_t PreviewPlayer::loadEffectsSettings(
James Dong00f742c2012-01-13 17:34:42 -08001258 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001259
James Dong00f742c2012-01-13 17:34:42 -08001260 ALOGV("loadEffectsSettings");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001261 mNumberEffects = nEffects;
1262 mEffectsSettings = pEffectSettings;
1263 return OK;
1264}
1265
1266status_t PreviewPlayer::loadAudioMixSettings(
James Dong00f742c2012-01-13 17:34:42 -08001267 M4xVSS_AudioMixingSettings* pAudioMixSettings) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001268
James Dong00f742c2012-01-13 17:34:42 -08001269 ALOGV("loadAudioMixSettings");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001270 mPreviewPlayerAudioMixSettings = pAudioMixSettings;
1271 return OK;
1272}
1273
1274status_t PreviewPlayer::setAudioMixPCMFileHandle(
James Dong00f742c2012-01-13 17:34:42 -08001275 M4OSA_Context pAudioMixPCMFileHandle) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001276
James Dong00f742c2012-01-13 17:34:42 -08001277 ALOGV("setAudioMixPCMFileHandle");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001278 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle;
1279 return OK;
1280}
1281
1282status_t PreviewPlayer::setAudioMixStoryBoardParam(
James Dong00f742c2012-01-13 17:34:42 -08001283 M4OSA_UInt32 audioMixStoryBoardTS,
1284 M4OSA_UInt32 currentMediaBeginCutTime,
1285 M4OSA_UInt32 primaryTrackVolValue ) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001286
James Dong00f742c2012-01-13 17:34:42 -08001287 ALOGV("setAudioMixStoryBoardParam");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001288 mAudioMixStoryBoardTS = audioMixStoryBoardTS;
1289 mCurrentMediaBeginCutTime = currentMediaBeginCutTime;
1290 mCurrentMediaVolumeValue = primaryTrackVolValue;
1291 return OK;
1292}
1293
1294status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) {
1295
1296 mPlayBeginTimeMsec = msec;
1297 return OK;
1298}
1299
1300status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) {
1301
1302 mPlayEndTimeMsec = msec;
1303 return OK;
1304}
1305
1306status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) {
1307
1308 mStoryboardStartTimeMsec = msec;
James Dong00f742c2012-01-13 17:34:42 -08001309 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec * 1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001310 return OK;
1311}
1312
1313status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) {
1314
1315 mProgressCbInterval = cbInterval;
1316 return OK;
1317}
1318
1319
1320status_t PreviewPlayer::setMediaRenderingMode(
1321 M4xVSS_MediaRendering mode,
1322 M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
1323
1324 mRenderingMode = mode;
1325
Hong Teng8806b702011-07-06 18:29:28 -07001326 /* get the video width and height by resolution */
James Dong00f742c2012-01-13 17:34:42 -08001327 return getVideoSizeByResolution(
1328 outputVideoSize,
1329 &mOutputVideoWidth, &mOutputVideoHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001330
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001331}
1332
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001333status_t PreviewPlayer::resetJniCallbackTimeStamp() {
1334
James Dong00f742c2012-01-13 17:34:42 -08001335 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec * 1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001336 return OK;
1337}
1338
1339void PreviewPlayer::postProgressCallbackEvent_l() {
1340 if (mProgressCbEventPending) {
1341 return;
1342 }
1343 mProgressCbEventPending = true;
1344
1345 mQueue.postEvent(mProgressCbEvent);
1346}
1347
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001348
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001349void PreviewPlayer::onProgressCbEvent() {
1350 Mutex::Autolock autoLock(mLock);
1351 if (!mProgressCbEventPending) {
1352 return;
1353 }
1354 mProgressCbEventPending = false;
1355 // If playback starts from previous I-frame,
1356 // then send frame storyboard duration
James Dong00f742c2012-01-13 17:34:42 -08001357 if ((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001358 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000);
James Dong00f742c2012-01-13 17:34:42 -08001359 } else {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001360 notifyListener_l(MEDIA_INFO, 0,
1361 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec));
1362 }
1363}
1364
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001365void PreviewPlayer::postOverlayUpdateEvent_l() {
1366 if (mOverlayUpdateEventPending) {
1367 return;
1368 }
1369 mOverlayUpdateEventPending = true;
1370 mQueue.postEvent(mOverlayUpdateEvent);
1371}
1372
1373void PreviewPlayer::onUpdateOverlayEvent() {
1374 Mutex::Autolock autoLock(mLock);
1375
1376 if (!mOverlayUpdateEventPending) {
1377 return;
1378 }
1379 mOverlayUpdateEventPending = false;
1380
James Dong00f742c2012-01-13 17:34:42 -08001381 int updateState = mOverlayUpdateEventPosted? 1: 0;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001382 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex);
1383}
1384
1385
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001386void PreviewPlayer::setVideoPostProcessingNode(
James Dong00f742c2012-01-13 17:34:42 -08001387 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001388
1389 uint32_t effect = VIDEO_EFFECT_NONE;
1390
1391 //Map M4VSS3GPP_VideoEffectType to local enum
1392 switch(type) {
1393 case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
1394 effect = VIDEO_EFFECT_FADEFROMBLACK;
1395 break;
1396
1397 case M4VSS3GPP_kVideoEffectType_FadeToBlack:
1398 effect = VIDEO_EFFECT_FADETOBLACK;
1399 break;
1400
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001401 case M4xVSS_kVideoEffectType_BlackAndWhite:
1402 effect = VIDEO_EFFECT_BLACKANDWHITE;
1403 break;
1404
1405 case M4xVSS_kVideoEffectType_Pink:
1406 effect = VIDEO_EFFECT_PINK;
1407 break;
1408
1409 case M4xVSS_kVideoEffectType_Green:
1410 effect = VIDEO_EFFECT_GREEN;
1411 break;
1412
1413 case M4xVSS_kVideoEffectType_Sepia:
1414 effect = VIDEO_EFFECT_SEPIA;
1415 break;
1416
1417 case M4xVSS_kVideoEffectType_Negative:
1418 effect = VIDEO_EFFECT_NEGATIVE;
1419 break;
1420
1421 case M4xVSS_kVideoEffectType_Framing:
1422 effect = VIDEO_EFFECT_FRAMING;
1423 break;
1424
1425 case M4xVSS_kVideoEffectType_Fifties:
1426 effect = VIDEO_EFFECT_FIFTIES;
1427 break;
1428
1429 case M4xVSS_kVideoEffectType_ColorRGB16:
1430 effect = VIDEO_EFFECT_COLOR_RGB16;
1431 break;
1432
1433 case M4xVSS_kVideoEffectType_Gradient:
1434 effect = VIDEO_EFFECT_GRADIENT;
1435 break;
1436
1437 default:
1438 effect = VIDEO_EFFECT_NONE;
1439 break;
1440 }
1441
James Dong00f742c2012-01-13 17:34:42 -08001442 if (enable == M4OSA_TRUE) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001443 //If already set, then no need to set again
James Dong00f742c2012-01-13 17:34:42 -08001444 if (!(mCurrentVideoEffect & effect)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001445 mCurrentVideoEffect |= effect;
James Dong00f742c2012-01-13 17:34:42 -08001446 if (effect == VIDEO_EFFECT_FIFTIES) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001447 mIsFiftiesEffectStarted = true;
1448 }
1449 }
James Dong00f742c2012-01-13 17:34:42 -08001450 } else {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001451 //Reset only if already set
James Dong00f742c2012-01-13 17:34:42 -08001452 if (mCurrentVideoEffect & effect) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001453 mCurrentVideoEffect &= ~effect;
1454 }
1455 }
1456}
1457
1458status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) {
1459 mVideoWidth = width;
1460 mVideoHeight = height;
1461 return OK;
1462}
1463
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001464status_t PreviewPlayer::readFirstVideoFrame() {
James Dong00f742c2012-01-13 17:34:42 -08001465 ALOGV("readFirstVideoFrame");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001466
1467 if (!mVideoBuffer) {
1468 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -08001469 if (mSeeking != NO_SEEK) {
James Dong00f742c2012-01-13 17:34:42 -08001470 ALOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001471 mSeekTimeUs / 1E6);
1472
1473 options.setSeekTo(
1474 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
1475 }
1476 for (;;) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001477 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001478 options.clearSeekTo();
1479
1480 if (err != OK) {
James Dong00f742c2012-01-13 17:34:42 -08001481 CHECK(!mVideoBuffer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001482
1483 if (err == INFO_FORMAT_CHANGED) {
James Dong00f742c2012-01-13 17:34:42 -08001484 ALOGV("VideoSource signalled format change");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001485 notifyVideoSize_l();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001486
1487 if (mVideoRenderer != NULL) {
1488 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -08001489 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001490 if (err != OK) {
1491 postStreamDoneEvent_l(err);
1492 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001493 }
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001494
1495 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001496 continue;
1497 }
James Dong00f742c2012-01-13 17:34:42 -08001498 ALOGV("EOS reached.");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001499 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001500 mFlags |= AUDIO_AT_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001501 postStreamDoneEvent_l(err);
1502 return OK;
1503 }
1504
1505 if (mVideoBuffer->range_length() == 0) {
1506 // Some decoders, notably the PV AVC software decoder
1507 // return spurious empty buffers that we just want to ignore.
1508
1509 mVideoBuffer->release();
1510 mVideoBuffer = NULL;
1511 continue;
1512 }
1513
1514 int64_t videoTimeUs;
1515 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
Andreas Hubera5872f72011-02-24 15:25:21 -08001516 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001517 if (videoTimeUs < mSeekTimeUs) {
1518 // buffers are before seek time
1519 // ignore them
1520 mVideoBuffer->release();
1521 mVideoBuffer = NULL;
1522 continue;
1523 }
1524 } else {
James Dong00f742c2012-01-13 17:34:42 -08001525 if ((videoTimeUs/1000) < mPlayBeginTimeMsec) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001526 // buffers are before begin cut time
1527 // ignore them
1528 mVideoBuffer->release();
1529 mVideoBuffer = NULL;
1530 continue;
1531 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001532 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001533 break;
1534 }
1535 }
1536
1537 int64_t timeUs;
1538 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
James Dong00f742c2012-01-13 17:34:42 -08001539 setPosition_l(timeUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001540
1541 mDecodedVideoTs = timeUs;
1542
1543 return OK;
1544
1545}
1546
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001547status_t PreviewPlayer::getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs) {
1548 *lastRenderedTimeMs = (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec);
1549 return OK;
1550}
1551
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001552void PreviewPlayer::updateSizeToRender(sp<MetaData> meta) {
1553 if (mVideoRenderer) {
1554 mVideoRenderer->updateVideoSize(meta);
1555 }
1556}
1557
James Dong00f742c2012-01-13 17:34:42 -08001558void PreviewPlayer::setListener(const wp<MediaPlayerBase> &listener) {
1559 Mutex::Autolock autoLock(mLock);
1560 mListener = listener;
1561}
1562
1563status_t PreviewPlayer::setDataSource(const sp<IStreamSource> &source) {
1564 return INVALID_OPERATION;
1565}
1566
1567void PreviewPlayer::reset() {
1568 Mutex::Autolock autoLock(mLock);
1569 reset_l();
1570}
1571
1572void PreviewPlayer::clear_l() {
1573 mDisplayWidth = 0;
1574 mDisplayHeight = 0;
1575
1576 if (mFlags & PLAYING) {
1577 updateBatteryUsage_l();
1578 }
1579
1580 if (mFlags & PREPARING) {
1581 mFlags |= PREPARE_CANCELLED;
1582
1583 if (mFlags & PREPARING_CONNECTED) {
1584 // We are basically done preparing, we're just buffering
1585 // enough data to start playback, we can safely interrupt that.
1586 finishAsyncPrepare_l();
1587 }
1588 }
1589
1590 while (mFlags & PREPARING) {
1591 mPreparedCondition.wait(mLock);
1592 }
1593
1594 cancelPlayerEvents_l(true);
1595
1596 mAudioTrack.clear();
1597 mVideoTrack.clear();
1598
1599 // Shutdown audio first, so that the respone to the reset request
1600 // appears to happen instantaneously as far as the user is concerned
1601 // If we did this later, audio would continue playing while we
1602 // shutdown the video-related resources and the player appear to
1603 // not be as responsive to a reset request.
1604 if (mAudioPlayer == NULL && mAudioSource != NULL) {
1605 // If we had an audio player, it would have effectively
1606 // taken possession of the audio source and stopped it when
1607 // _it_ is stopped. Otherwise this is still our responsibility.
1608 mAudioSource->stop();
1609 }
1610 mAudioSource.clear();
1611
1612 mTimeSource = NULL;
1613
1614 delete mAudioPlayer;
1615 mAudioPlayer = NULL;
1616
1617 if (mVideoSource != NULL) {
1618 shutdownVideoDecoder_l();
1619 }
1620
1621 mDurationUs = -1;
1622 mFlags = 0;
1623 mExtractorFlags = 0;
1624 mTimeSourceDeltaUs = 0;
1625 mVideoTimeUs = 0;
1626
1627 mSeeking = NO_SEEK;
1628 mSeekNotificationSent = false;
1629 mSeekTimeUs = 0;
1630
1631 mUri.setTo("");
1632
1633 mBitrate = -1;
1634 mLastVideoTimeUs = -1;
1635}
1636
1637void PreviewPlayer::notifyListener_l(int msg, int ext1, int ext2) {
1638 if (mListener != NULL) {
1639 sp<MediaPlayerBase> listener = mListener.promote();
1640
1641 if (listener != NULL) {
1642 listener->sendEvent(msg, ext1, ext2);
1643 }
1644 }
1645}
1646
1647void PreviewPlayer::onVideoLagUpdate() {
1648 Mutex::Autolock autoLock(mLock);
1649 if (!mVideoLagEventPending) {
1650 return;
1651 }
1652 mVideoLagEventPending = false;
1653
1654 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
1655 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
1656
1657 if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) {
1658 ALOGV("video late by %lld ms.", videoLateByUs / 1000ll);
1659
1660 notifyListener_l(
1661 MEDIA_INFO,
1662 MEDIA_INFO_VIDEO_TRACK_LAGGING,
1663 videoLateByUs / 1000ll);
1664 }
1665
1666 postVideoLagEvent_l();
1667}
1668
1669void PreviewPlayer::notifyVideoSize_l() {
1670 sp<MetaData> meta = mVideoSource->getFormat();
1671
1672 int32_t vWidth, vHeight;
1673 int32_t cropLeft, cropTop, cropRight, cropBottom;
1674
1675 CHECK(meta->findInt32(kKeyWidth, &vWidth));
1676 CHECK(meta->findInt32(kKeyHeight, &vHeight));
1677
1678 mGivenWidth = vWidth;
1679 mGivenHeight = vHeight;
1680
1681 if (!meta->findRect(
1682 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
1683
1684 cropLeft = cropTop = 0;
1685 cropRight = vWidth - 1;
1686 cropBottom = vHeight - 1;
1687
1688 ALOGD("got dimensions only %d x %d", vWidth, vHeight);
1689 } else {
1690 ALOGD("got crop rect %d, %d, %d, %d",
1691 cropLeft, cropTop, cropRight, cropBottom);
1692 }
1693
1694 mCropRect.left = cropLeft;
1695 mCropRect.right = cropRight;
1696 mCropRect.top = cropTop;
1697 mCropRect.bottom = cropBottom;
1698
1699 int32_t displayWidth;
1700 if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
1701 ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
1702 mDisplayWidth = displayWidth;
1703 }
1704 int32_t displayHeight;
1705 if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
1706 ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
1707 mDisplayHeight = displayHeight;
1708 }
1709
1710 int32_t usableWidth = cropRight - cropLeft + 1;
1711 int32_t usableHeight = cropBottom - cropTop + 1;
1712 if (mDisplayWidth != 0) {
1713 usableWidth = mDisplayWidth;
1714 }
1715 if (mDisplayHeight != 0) {
1716 usableHeight = mDisplayHeight;
1717 }
1718
1719 int32_t rotationDegrees;
1720 if (!mVideoTrack->getFormat()->findInt32(
1721 kKeyRotation, &rotationDegrees)) {
1722 rotationDegrees = 0;
1723 }
1724
1725 if (rotationDegrees == 90 || rotationDegrees == 270) {
1726 notifyListener_l(
1727 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
1728 } else {
1729 notifyListener_l(
1730 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
1731 }
1732}
1733
1734status_t PreviewPlayer::pause() {
1735 Mutex::Autolock autoLock(mLock);
1736
1737 mFlags &= ~CACHE_UNDERRUN;
1738
1739 return pause_l();
1740}
1741
1742status_t PreviewPlayer::pause_l(bool at_eos) {
1743 if (!(mFlags & PLAYING)) {
1744 return OK;
1745 }
1746
1747 cancelPlayerEvents_l();
1748
1749 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1750 if (at_eos) {
1751 // If we played the audio stream to completion we
1752 // want to make sure that all samples remaining in the audio
1753 // track's queue are played out.
1754 mAudioPlayer->pause(true /* playPendingSamples */);
1755 } else {
1756 mAudioPlayer->pause();
1757 }
1758
1759 mFlags &= ~AUDIO_RUNNING;
1760 }
1761
1762 mFlags &= ~PLAYING;
1763 updateBatteryUsage_l();
1764
1765 return OK;
1766}
1767
1768bool PreviewPlayer::isPlaying() const {
1769 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
1770}
1771
1772void PreviewPlayer::setSurface(const sp<Surface> &surface) {
1773 Mutex::Autolock autoLock(mLock);
1774
1775 mSurface = surface;
1776 setNativeWindow_l(surface);
1777}
1778
1779void PreviewPlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
1780 Mutex::Autolock autoLock(mLock);
1781
1782 mSurface.clear();
1783 if (surfaceTexture != NULL) {
1784 setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
1785 }
1786}
1787
1788void PreviewPlayer::shutdownVideoDecoder_l() {
1789 if (mVideoBuffer) {
1790 mVideoBuffer->release();
1791 mVideoBuffer = NULL;
1792 }
1793
1794 mVideoSource->stop();
1795
1796 // The following hack is necessary to ensure that the OMX
1797 // component is completely released by the time we may try
1798 // to instantiate it again.
1799 wp<MediaSource> tmp = mVideoSource;
1800 mVideoSource.clear();
1801 while (tmp.promote() != NULL) {
1802 usleep(1000);
1803 }
1804 IPCThreadState::self()->flushCommands();
1805}
1806
1807void PreviewPlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
1808 mNativeWindow = native;
1809
1810 if (mVideoSource == NULL) {
1811 return;
1812 }
1813
1814 ALOGI("attempting to reconfigure to use new surface");
1815
1816 bool wasPlaying = (mFlags & PLAYING) != 0;
1817
1818 pause_l();
1819
1820 shutdownVideoDecoder_l();
1821
1822 CHECK_EQ(initVideoDecoder_l(), (status_t)OK);
1823
1824 if (mLastVideoTimeUs >= 0) {
1825 mSeeking = SEEK;
1826 mSeekNotificationSent = true;
1827 mSeekTimeUs = mLastVideoTimeUs;
1828 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
1829 }
1830
1831 if (wasPlaying) {
1832 play_l();
1833 }
1834}
1835
1836void PreviewPlayer::setAudioSink(
1837 const sp<MediaPlayerBase::AudioSink> &audioSink) {
1838 Mutex::Autolock autoLock(mLock);
1839
1840 mAudioSink = audioSink;
1841}
1842
1843status_t PreviewPlayer::setLooping(bool shouldLoop) {
1844 Mutex::Autolock autoLock(mLock);
1845
1846 mFlags = mFlags & ~LOOPING;
1847
1848 if (shouldLoop) {
1849 mFlags |= LOOPING;
1850 }
1851
1852 return OK;
1853}
1854
1855void PreviewPlayer::setDuration_l(int64_t durationUs) {
1856 if (mDurationUs < 0 || durationUs > mDurationUs) {
1857 mDurationUs = durationUs;
1858 }
1859}
1860
1861status_t PreviewPlayer::getDuration(int64_t *durationUs) {
1862 Mutex::Autolock autoLock(mLock);
1863 if (mDurationUs < 0) {
1864 return UNKNOWN_ERROR;
1865 }
1866
1867 *durationUs = mDurationUs;
1868 return OK;
1869}
1870
1871status_t PreviewPlayer::getPosition(int64_t *positionUs) {
1872 Mutex::Autolock autoLock(mLock);
1873
1874 if (mSeeking != NO_SEEK) {
1875 *positionUs = mSeekTimeUs;
1876 } else if (mVideoSource != NULL
1877 && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
1878 *positionUs = mVideoTimeUs;
1879 } else if (mAudioPlayer != NULL) {
1880 *positionUs = mAudioPlayer->getMediaTimeUs();
1881 } else {
1882 *positionUs = 0;
1883 }
1884
1885 return OK;
1886}
1887
1888void PreviewPlayer::setPosition_l(int64_t timeUs) {
1889 mVideoTimeUs = timeUs;
1890}
1891
1892status_t PreviewPlayer::seekTo_l(int64_t timeUs) {
1893 ALOGV("seekTo_l");
1894 if (mFlags & CACHE_UNDERRUN) {
1895 mFlags &= ~CACHE_UNDERRUN;
1896 play_l();
1897 }
1898
1899 if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
1900 // Video playback completed before, there's no pending
1901 // video event right now. In order for this new seek
1902 // to be honored, we need to post one.
1903
1904 postVideoEvent_l();
1905 }
1906
1907 mSeeking = SEEK;
1908 mSeekNotificationSent = false;
1909 mSeekTimeUs = timeUs;
1910 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
1911
1912 seekAudioIfNecessary_l();
1913
1914 if (!(mFlags & PLAYING)) {
1915 ALOGV("seeking while paused, sending SEEK_COMPLETE notification"
1916 " immediately.");
1917
1918 notifyListener_l(MEDIA_SEEK_COMPLETE);
1919 mSeekNotificationSent = true;
1920
1921 if ((mFlags & PREPARED) && mVideoSource != NULL) {
1922 mFlags |= SEEK_PREVIEW;
1923 postVideoEvent_l();
1924 }
1925 }
1926
1927 return OK;
1928}
1929
1930void PreviewPlayer::seekAudioIfNecessary_l() {
1931 if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
1932 mAudioPlayer->seekTo(mSeekTimeUs);
1933
1934 mWatchForAudioSeekComplete = true;
1935 mWatchForAudioEOS = true;
1936 }
1937}
1938
1939void PreviewPlayer::setAudioSource(const sp<MediaSource>& source) {
1940 CHECK(source != NULL);
1941 mAudioTrack = source;
1942}
1943
1944void PreviewPlayer::setVideoSource(const sp<MediaSource>& source) {
1945 CHECK(source != NULL);
1946 mVideoTrack = source;
1947}
1948
1949void PreviewPlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
1950 if (mSeeking == SEEK_VIDEO_ONLY) {
1951 mSeeking = NO_SEEK;
1952 return;
1953 }
1954
1955 if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
1956 return;
1957 }
1958
1959 if (mAudioPlayer != NULL) {
1960 ALOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
1961
1962 // If we don't have a video time, seek audio to the originally
1963 // requested seek time instead.
1964
1965 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
1966 mWatchForAudioSeekComplete = true;
1967 mWatchForAudioEOS = true;
1968 } else if (!mSeekNotificationSent) {
1969 // If we're playing video only, report seek complete now,
1970 // otherwise audio player will notify us later.
1971 notifyListener_l(MEDIA_SEEK_COMPLETE);
1972 mSeekNotificationSent = true;
1973 }
1974
1975 mFlags |= FIRST_FRAME;
1976 mSeeking = NO_SEEK;
1977}
1978
1979void PreviewPlayer::onCheckAudioStatus() {
1980 Mutex::Autolock autoLock(mLock);
1981 if (!mAudioStatusEventPending) {
1982 // Event was dispatched and while we were blocking on the mutex,
1983 // has already been cancelled.
1984 return;
1985 }
1986
1987 mAudioStatusEventPending = false;
1988
1989 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1990 mWatchForAudioSeekComplete = false;
1991
1992 if (!mSeekNotificationSent) {
1993 notifyListener_l(MEDIA_SEEK_COMPLETE);
1994 mSeekNotificationSent = true;
1995 }
1996
1997 mSeeking = NO_SEEK;
1998 }
1999
2000 status_t finalStatus;
2001 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
2002 mWatchForAudioEOS = false;
2003 mFlags |= AUDIO_AT_EOS;
2004 mFlags |= FIRST_FRAME;
2005 postStreamDoneEvent_l(finalStatus);
2006 }
2007}
2008
2009void PreviewPlayer::postVideoEvent_l(int64_t delayUs) {
2010 if (mVideoEventPending) {
2011 return;
2012 }
2013
2014 mVideoEventPending = true;
2015 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
2016}
2017
2018void PreviewPlayer::postStreamDoneEvent_l(status_t status) {
2019 if (mStreamDoneEventPending) {
2020 return;
2021 }
2022 mStreamDoneEventPending = true;
2023
2024 mStreamDoneStatus = status;
2025 mQueue.postEvent(mStreamDoneEvent);
2026}
2027
2028void PreviewPlayer::postVideoLagEvent_l() {
2029 if (mVideoLagEventPending) {
2030 return;
2031 }
2032 mVideoLagEventPending = true;
2033 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
2034}
2035
2036void PreviewPlayer::postCheckAudioStatusEvent_l(int64_t delayUs) {
2037 if (mAudioStatusEventPending) {
2038 return;
2039 }
2040 mAudioStatusEventPending = true;
2041 mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
2042}
2043
2044void PreviewPlayer::abortPrepare(status_t err) {
2045 CHECK(err != OK);
2046
2047 if (mIsAsyncPrepare) {
2048 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2049 }
2050
2051 mPrepareResult = err;
2052 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
2053 mAsyncPrepareEvent = NULL;
2054 mPreparedCondition.broadcast();
2055}
2056
2057uint32_t PreviewPlayer::getSourceSeekFlags() const {
2058 Mutex::Autolock lock(mLock);
2059 return mExtractorFlags;
2060}
2061
2062void PreviewPlayer::postAudioEOS(int64_t delayUs) {
2063 Mutex::Autolock autoLock(mLock);
2064 postCheckAudioStatusEvent_l(delayUs);
2065}
2066
2067void PreviewPlayer::postAudioSeekComplete() {
2068 Mutex::Autolock autoLock(mLock);
2069 postCheckAudioStatusEvent_l(0 /* delayUs */);
2070}
2071
2072void PreviewPlayer::updateBatteryUsage_l() {
2073 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
2074 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
2075 params |= IMediaPlayerService::kBatteryDataTrackAudio;
2076 }
2077 if (mVideoSource != NULL) {
2078 params |= IMediaPlayerService::kBatteryDataTrackVideo;
2079 }
2080 addBatteryData(params);
2081}
2082
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002083} // namespace android