blob: b36fe0a3a4badb4140fd346bf6fea61a6bd65ec7 [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>
Andreas Huber1b86fe02014-01-29 11:13:26 -080024#include <media/IMediaHTTPService.h>
James Dong00f742c2012-01-13 17:34:42 -080025#include <media/IMediaPlayerService.h>
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080026#include <media/stagefright/DataSource.h>
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080027#include <media/stagefright/MediaBuffer.h>
28#include <media/stagefright/MediaDefs.h>
29#include <media/stagefright/MediaExtractor.h>
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080030#include <media/stagefright/MediaSource.h>
31#include <media/stagefright/MetaData.h>
32#include <media/stagefright/OMXCodec.h>
James Dong00f742c2012-01-13 17:34:42 -080033#include <media/stagefright/foundation/ADebug.h>
Mathias Agopian90b61912012-02-26 00:40:08 -080034#include <gui/Surface.h>
Andy McFadden8ba01022012-12-18 09:46:54 -080035#include <gui/IGraphicBufferProducer.h>
Mathias Agopian1a2952a2013-02-14 17:11:27 -080036#include <gui/Surface.h>
James Dong00f742c2012-01-13 17:34:42 -080037
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
Andreas Huber1b86fe02014-01-29 11:13:26 -08001164 dataSource = DataSource::CreateFromURI(
1165 NULL /* httpService */, mUri.string(), NULL);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001166
1167 if (dataSource == NULL) {
1168 return UNKNOWN_ERROR;
1169 }
1170
1171 //If file type is .rgb, then no need to check for Extractor
1172 int uriLen = strlen(mUri);
1173 int startOffset = uriLen - 4;
1174 if(!strncasecmp(mUri+startOffset, ".rgb", 4)) {
1175 extractor = NULL;
1176 }
1177 else {
1178 extractor = MediaExtractor::Create(dataSource,
1179 MEDIA_MIMETYPE_CONTAINER_MPEG4);
1180 }
1181
1182 if (extractor == NULL) {
James Dong00f742c2012-01-13 17:34:42 -08001183 ALOGV("finishSetDataSource_l: failed to create extractor");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001184 return setDataSource_l_jpg();
1185 }
1186
1187 return setDataSource_l(extractor);
1188}
1189
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001190void PreviewPlayer::onPrepareAsyncEvent() {
1191 Mutex::Autolock autoLock(mLock);
Steve Block2703f232011-10-20 11:56:09 +01001192 ALOGV("onPrepareAsyncEvent");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001193
1194 if (mFlags & PREPARE_CANCELLED) {
James Dong00f742c2012-01-13 17:34:42 -08001195 ALOGV("prepare was cancelled before doing anything");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001196 abortPrepare(UNKNOWN_ERROR);
1197 return;
1198 }
1199
1200 if (mUri.size() > 0) {
1201 status_t err = finishSetDataSource_l();
1202
1203 if (err != OK) {
1204 abortPrepare(err);
1205 return;
1206 }
1207 }
1208
1209 if (mVideoTrack != NULL && mVideoSource == NULL) {
James Dong00f742c2012-01-13 17:34:42 -08001210 status_t err = initVideoDecoder_l(OMXCodec::kHardwareCodecsOnly);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001211
1212 if (err != OK) {
1213 abortPrepare(err);
1214 return;
1215 }
1216 }
1217
1218 if (mAudioTrack != NULL && mAudioSource == NULL) {
James Dong00f742c2012-01-13 17:34:42 -08001219 status_t err = initAudioDecoder_l();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001220
1221 if (err != OK) {
1222 abortPrepare(err);
1223 return;
1224 }
1225 }
1226 finishAsyncPrepare_l();
1227
1228}
1229
1230void PreviewPlayer::finishAsyncPrepare_l() {
James Dong00f742c2012-01-13 17:34:42 -08001231 ALOGV("finishAsyncPrepare_l");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001232 if (mIsAsyncPrepare) {
1233 if (mVideoSource == NULL) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001234 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1235 } else {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001236 notifyVideoSize_l();
1237 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001238 notifyListener_l(MEDIA_PREPARED);
1239 }
1240
1241 mPrepareResult = OK;
1242 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1243 mFlags |= PREPARED;
1244 mAsyncPrepareEvent = NULL;
1245 mPreparedCondition.broadcast();
1246}
1247
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001248void PreviewPlayer::acquireLock() {
Steve Block2703f232011-10-20 11:56:09 +01001249 ALOGV("acquireLock");
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001250 mLockControl.lock();
1251}
1252
1253void PreviewPlayer::releaseLock() {
Steve Block2703f232011-10-20 11:56:09 +01001254 ALOGV("releaseLock");
Raghavender Pallafa31daf2011-03-18 22:32:51 -07001255 mLockControl.unlock();
1256}
1257
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001258status_t PreviewPlayer::loadEffectsSettings(
James Dong00f742c2012-01-13 17:34:42 -08001259 M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001260
James Dong00f742c2012-01-13 17:34:42 -08001261 ALOGV("loadEffectsSettings");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001262 mNumberEffects = nEffects;
1263 mEffectsSettings = pEffectSettings;
1264 return OK;
1265}
1266
1267status_t PreviewPlayer::loadAudioMixSettings(
James Dong00f742c2012-01-13 17:34:42 -08001268 M4xVSS_AudioMixingSettings* pAudioMixSettings) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001269
James Dong00f742c2012-01-13 17:34:42 -08001270 ALOGV("loadAudioMixSettings");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001271 mPreviewPlayerAudioMixSettings = pAudioMixSettings;
1272 return OK;
1273}
1274
1275status_t PreviewPlayer::setAudioMixPCMFileHandle(
James Dong00f742c2012-01-13 17:34:42 -08001276 M4OSA_Context pAudioMixPCMFileHandle) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001277
James Dong00f742c2012-01-13 17:34:42 -08001278 ALOGV("setAudioMixPCMFileHandle");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001279 mAudioMixPCMFileHandle = pAudioMixPCMFileHandle;
1280 return OK;
1281}
1282
1283status_t PreviewPlayer::setAudioMixStoryBoardParam(
James Dong00f742c2012-01-13 17:34:42 -08001284 M4OSA_UInt32 audioMixStoryBoardTS,
1285 M4OSA_UInt32 currentMediaBeginCutTime,
1286 M4OSA_UInt32 primaryTrackVolValue ) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001287
James Dong00f742c2012-01-13 17:34:42 -08001288 ALOGV("setAudioMixStoryBoardParam");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001289 mAudioMixStoryBoardTS = audioMixStoryBoardTS;
1290 mCurrentMediaBeginCutTime = currentMediaBeginCutTime;
1291 mCurrentMediaVolumeValue = primaryTrackVolValue;
1292 return OK;
1293}
1294
1295status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) {
1296
1297 mPlayBeginTimeMsec = msec;
1298 return OK;
1299}
1300
1301status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) {
1302
1303 mPlayEndTimeMsec = msec;
1304 return OK;
1305}
1306
1307status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) {
1308
1309 mStoryboardStartTimeMsec = msec;
James Dong00f742c2012-01-13 17:34:42 -08001310 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec * 1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001311 return OK;
1312}
1313
1314status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) {
1315
1316 mProgressCbInterval = cbInterval;
1317 return OK;
1318}
1319
1320
1321status_t PreviewPlayer::setMediaRenderingMode(
1322 M4xVSS_MediaRendering mode,
1323 M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
1324
1325 mRenderingMode = mode;
1326
Hong Teng8806b702011-07-06 18:29:28 -07001327 /* get the video width and height by resolution */
James Dong00f742c2012-01-13 17:34:42 -08001328 return getVideoSizeByResolution(
1329 outputVideoSize,
1330 &mOutputVideoWidth, &mOutputVideoHeight);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001331
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001332}
1333
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001334status_t PreviewPlayer::resetJniCallbackTimeStamp() {
1335
James Dong00f742c2012-01-13 17:34:42 -08001336 mDecVideoTsStoryBoard = mStoryboardStartTimeMsec * 1000LL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001337 return OK;
1338}
1339
1340void PreviewPlayer::postProgressCallbackEvent_l() {
1341 if (mProgressCbEventPending) {
1342 return;
1343 }
1344 mProgressCbEventPending = true;
1345
1346 mQueue.postEvent(mProgressCbEvent);
1347}
1348
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001349
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001350void PreviewPlayer::onProgressCbEvent() {
1351 Mutex::Autolock autoLock(mLock);
1352 if (!mProgressCbEventPending) {
1353 return;
1354 }
1355 mProgressCbEventPending = false;
1356 // If playback starts from previous I-frame,
1357 // then send frame storyboard duration
James Dong00f742c2012-01-13 17:34:42 -08001358 if ((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001359 notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000);
James Dong00f742c2012-01-13 17:34:42 -08001360 } else {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001361 notifyListener_l(MEDIA_INFO, 0,
1362 (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec));
1363 }
1364}
1365
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001366void PreviewPlayer::postOverlayUpdateEvent_l() {
1367 if (mOverlayUpdateEventPending) {
1368 return;
1369 }
1370 mOverlayUpdateEventPending = true;
1371 mQueue.postEvent(mOverlayUpdateEvent);
1372}
1373
1374void PreviewPlayer::onUpdateOverlayEvent() {
1375 Mutex::Autolock autoLock(mLock);
1376
1377 if (!mOverlayUpdateEventPending) {
1378 return;
1379 }
1380 mOverlayUpdateEventPending = false;
1381
James Dong00f742c2012-01-13 17:34:42 -08001382 int updateState = mOverlayUpdateEventPosted? 1: 0;
Dharmaray Kundargie6c07502011-01-21 16:58:31 -08001383 notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex);
1384}
1385
1386
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001387void PreviewPlayer::setVideoPostProcessingNode(
James Dong00f742c2012-01-13 17:34:42 -08001388 M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001389
1390 uint32_t effect = VIDEO_EFFECT_NONE;
1391
1392 //Map M4VSS3GPP_VideoEffectType to local enum
1393 switch(type) {
1394 case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
1395 effect = VIDEO_EFFECT_FADEFROMBLACK;
1396 break;
1397
1398 case M4VSS3GPP_kVideoEffectType_FadeToBlack:
1399 effect = VIDEO_EFFECT_FADETOBLACK;
1400 break;
1401
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001402 case M4xVSS_kVideoEffectType_BlackAndWhite:
1403 effect = VIDEO_EFFECT_BLACKANDWHITE;
1404 break;
1405
1406 case M4xVSS_kVideoEffectType_Pink:
1407 effect = VIDEO_EFFECT_PINK;
1408 break;
1409
1410 case M4xVSS_kVideoEffectType_Green:
1411 effect = VIDEO_EFFECT_GREEN;
1412 break;
1413
1414 case M4xVSS_kVideoEffectType_Sepia:
1415 effect = VIDEO_EFFECT_SEPIA;
1416 break;
1417
1418 case M4xVSS_kVideoEffectType_Negative:
1419 effect = VIDEO_EFFECT_NEGATIVE;
1420 break;
1421
1422 case M4xVSS_kVideoEffectType_Framing:
1423 effect = VIDEO_EFFECT_FRAMING;
1424 break;
1425
1426 case M4xVSS_kVideoEffectType_Fifties:
1427 effect = VIDEO_EFFECT_FIFTIES;
1428 break;
1429
1430 case M4xVSS_kVideoEffectType_ColorRGB16:
1431 effect = VIDEO_EFFECT_COLOR_RGB16;
1432 break;
1433
1434 case M4xVSS_kVideoEffectType_Gradient:
1435 effect = VIDEO_EFFECT_GRADIENT;
1436 break;
1437
1438 default:
1439 effect = VIDEO_EFFECT_NONE;
1440 break;
1441 }
1442
James Dong00f742c2012-01-13 17:34:42 -08001443 if (enable == M4OSA_TRUE) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001444 //If already set, then no need to set again
James Dong00f742c2012-01-13 17:34:42 -08001445 if (!(mCurrentVideoEffect & effect)) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001446 mCurrentVideoEffect |= effect;
James Dong00f742c2012-01-13 17:34:42 -08001447 if (effect == VIDEO_EFFECT_FIFTIES) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001448 mIsFiftiesEffectStarted = true;
1449 }
1450 }
James Dong00f742c2012-01-13 17:34:42 -08001451 } else {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001452 //Reset only if already set
James Dong00f742c2012-01-13 17:34:42 -08001453 if (mCurrentVideoEffect & effect) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001454 mCurrentVideoEffect &= ~effect;
1455 }
1456 }
1457}
1458
1459status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) {
1460 mVideoWidth = width;
1461 mVideoHeight = height;
1462 return OK;
1463}
1464
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001465status_t PreviewPlayer::readFirstVideoFrame() {
James Dong00f742c2012-01-13 17:34:42 -08001466 ALOGV("readFirstVideoFrame");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001467
1468 if (!mVideoBuffer) {
1469 MediaSource::ReadOptions options;
Andreas Hubera5872f72011-02-24 15:25:21 -08001470 if (mSeeking != NO_SEEK) {
James Dong00f742c2012-01-13 17:34:42 -08001471 ALOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001472 mSeekTimeUs / 1E6);
1473
1474 options.setSeekTo(
1475 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
1476 }
1477 for (;;) {
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001478 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001479 options.clearSeekTo();
1480
1481 if (err != OK) {
James Dong00f742c2012-01-13 17:34:42 -08001482 CHECK(!mVideoBuffer);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001483
1484 if (err == INFO_FORMAT_CHANGED) {
James Dong00f742c2012-01-13 17:34:42 -08001485 ALOGV("VideoSource signalled format change");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001486 notifyVideoSize_l();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001487
1488 if (mVideoRenderer != NULL) {
1489 mVideoRendererIsPreview = false;
Santosh Madhavabfece172011-02-03 16:59:47 -08001490 err = initRenderer_l();
Santosh Madhava4ca3e5d2011-02-11 20:28:45 -08001491 if (err != OK) {
1492 postStreamDoneEvent_l(err);
1493 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001494 }
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001495
1496 updateSizeToRender(mVideoSource->getFormat());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001497 continue;
1498 }
James Dong00f742c2012-01-13 17:34:42 -08001499 ALOGV("EOS reached.");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001500 mFlags |= VIDEO_AT_EOS;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -08001501 mFlags |= AUDIO_AT_EOS;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001502 postStreamDoneEvent_l(err);
1503 return OK;
1504 }
1505
1506 if (mVideoBuffer->range_length() == 0) {
1507 // Some decoders, notably the PV AVC software decoder
1508 // return spurious empty buffers that we just want to ignore.
1509
1510 mVideoBuffer->release();
1511 mVideoBuffer = NULL;
1512 continue;
1513 }
1514
1515 int64_t videoTimeUs;
1516 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
Andreas Hubera5872f72011-02-24 15:25:21 -08001517 if (mSeeking != NO_SEEK) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001518 if (videoTimeUs < mSeekTimeUs) {
1519 // buffers are before seek time
1520 // ignore them
1521 mVideoBuffer->release();
1522 mVideoBuffer = NULL;
1523 continue;
1524 }
1525 } else {
James Dong00f742c2012-01-13 17:34:42 -08001526 if ((videoTimeUs/1000) < mPlayBeginTimeMsec) {
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001527 // buffers are before begin cut time
1528 // ignore them
1529 mVideoBuffer->release();
1530 mVideoBuffer = NULL;
1531 continue;
1532 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001533 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001534 break;
1535 }
1536 }
1537
1538 int64_t timeUs;
1539 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
James Dong00f742c2012-01-13 17:34:42 -08001540 setPosition_l(timeUs);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001541
1542 mDecodedVideoTs = timeUs;
1543
1544 return OK;
1545
1546}
1547
Santosh Madhavab2d6e0f2011-02-16 22:24:42 -08001548status_t PreviewPlayer::getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs) {
1549 *lastRenderedTimeMs = (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec);
1550 return OK;
1551}
1552
Chih-Chung Chang43fcc392011-08-02 16:17:39 +08001553void PreviewPlayer::updateSizeToRender(sp<MetaData> meta) {
1554 if (mVideoRenderer) {
1555 mVideoRenderer->updateVideoSize(meta);
1556 }
1557}
1558
James Dong00f742c2012-01-13 17:34:42 -08001559void PreviewPlayer::setListener(const wp<MediaPlayerBase> &listener) {
1560 Mutex::Autolock autoLock(mLock);
1561 mListener = listener;
1562}
1563
1564status_t PreviewPlayer::setDataSource(const sp<IStreamSource> &source) {
1565 return INVALID_OPERATION;
1566}
1567
1568void PreviewPlayer::reset() {
1569 Mutex::Autolock autoLock(mLock);
1570 reset_l();
1571}
1572
1573void PreviewPlayer::clear_l() {
1574 mDisplayWidth = 0;
1575 mDisplayHeight = 0;
1576
1577 if (mFlags & PLAYING) {
1578 updateBatteryUsage_l();
1579 }
1580
1581 if (mFlags & PREPARING) {
1582 mFlags |= PREPARE_CANCELLED;
1583
1584 if (mFlags & PREPARING_CONNECTED) {
1585 // We are basically done preparing, we're just buffering
1586 // enough data to start playback, we can safely interrupt that.
1587 finishAsyncPrepare_l();
1588 }
1589 }
1590
1591 while (mFlags & PREPARING) {
1592 mPreparedCondition.wait(mLock);
1593 }
1594
1595 cancelPlayerEvents_l(true);
1596
1597 mAudioTrack.clear();
1598 mVideoTrack.clear();
1599
1600 // Shutdown audio first, so that the respone to the reset request
1601 // appears to happen instantaneously as far as the user is concerned
1602 // If we did this later, audio would continue playing while we
1603 // shutdown the video-related resources and the player appear to
1604 // not be as responsive to a reset request.
1605 if (mAudioPlayer == NULL && mAudioSource != NULL) {
1606 // If we had an audio player, it would have effectively
1607 // taken possession of the audio source and stopped it when
1608 // _it_ is stopped. Otherwise this is still our responsibility.
1609 mAudioSource->stop();
1610 }
1611 mAudioSource.clear();
1612
1613 mTimeSource = NULL;
1614
1615 delete mAudioPlayer;
1616 mAudioPlayer = NULL;
1617
1618 if (mVideoSource != NULL) {
1619 shutdownVideoDecoder_l();
1620 }
1621
1622 mDurationUs = -1;
1623 mFlags = 0;
1624 mExtractorFlags = 0;
1625 mTimeSourceDeltaUs = 0;
1626 mVideoTimeUs = 0;
1627
1628 mSeeking = NO_SEEK;
1629 mSeekNotificationSent = false;
1630 mSeekTimeUs = 0;
1631
1632 mUri.setTo("");
1633
1634 mBitrate = -1;
1635 mLastVideoTimeUs = -1;
1636}
1637
1638void PreviewPlayer::notifyListener_l(int msg, int ext1, int ext2) {
1639 if (mListener != NULL) {
1640 sp<MediaPlayerBase> listener = mListener.promote();
1641
1642 if (listener != NULL) {
1643 listener->sendEvent(msg, ext1, ext2);
1644 }
1645 }
1646}
1647
1648void PreviewPlayer::onVideoLagUpdate() {
1649 Mutex::Autolock autoLock(mLock);
1650 if (!mVideoLagEventPending) {
1651 return;
1652 }
1653 mVideoLagEventPending = false;
1654
1655 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
1656 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
1657
1658 if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) {
1659 ALOGV("video late by %lld ms.", videoLateByUs / 1000ll);
1660
1661 notifyListener_l(
1662 MEDIA_INFO,
1663 MEDIA_INFO_VIDEO_TRACK_LAGGING,
1664 videoLateByUs / 1000ll);
1665 }
1666
1667 postVideoLagEvent_l();
1668}
1669
1670void PreviewPlayer::notifyVideoSize_l() {
1671 sp<MetaData> meta = mVideoSource->getFormat();
1672
1673 int32_t vWidth, vHeight;
1674 int32_t cropLeft, cropTop, cropRight, cropBottom;
1675
1676 CHECK(meta->findInt32(kKeyWidth, &vWidth));
1677 CHECK(meta->findInt32(kKeyHeight, &vHeight));
1678
1679 mGivenWidth = vWidth;
1680 mGivenHeight = vHeight;
1681
1682 if (!meta->findRect(
1683 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
1684
1685 cropLeft = cropTop = 0;
1686 cropRight = vWidth - 1;
1687 cropBottom = vHeight - 1;
1688
1689 ALOGD("got dimensions only %d x %d", vWidth, vHeight);
1690 } else {
1691 ALOGD("got crop rect %d, %d, %d, %d",
1692 cropLeft, cropTop, cropRight, cropBottom);
1693 }
1694
1695 mCropRect.left = cropLeft;
1696 mCropRect.right = cropRight;
1697 mCropRect.top = cropTop;
1698 mCropRect.bottom = cropBottom;
1699
1700 int32_t displayWidth;
1701 if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
1702 ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
1703 mDisplayWidth = displayWidth;
1704 }
1705 int32_t displayHeight;
1706 if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
1707 ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
1708 mDisplayHeight = displayHeight;
1709 }
1710
1711 int32_t usableWidth = cropRight - cropLeft + 1;
1712 int32_t usableHeight = cropBottom - cropTop + 1;
1713 if (mDisplayWidth != 0) {
1714 usableWidth = mDisplayWidth;
1715 }
1716 if (mDisplayHeight != 0) {
1717 usableHeight = mDisplayHeight;
1718 }
1719
1720 int32_t rotationDegrees;
1721 if (!mVideoTrack->getFormat()->findInt32(
1722 kKeyRotation, &rotationDegrees)) {
1723 rotationDegrees = 0;
1724 }
1725
1726 if (rotationDegrees == 90 || rotationDegrees == 270) {
1727 notifyListener_l(
1728 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
1729 } else {
1730 notifyListener_l(
1731 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
1732 }
1733}
1734
1735status_t PreviewPlayer::pause() {
1736 Mutex::Autolock autoLock(mLock);
1737
1738 mFlags &= ~CACHE_UNDERRUN;
1739
1740 return pause_l();
1741}
1742
1743status_t PreviewPlayer::pause_l(bool at_eos) {
1744 if (!(mFlags & PLAYING)) {
1745 return OK;
1746 }
1747
1748 cancelPlayerEvents_l();
1749
1750 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1751 if (at_eos) {
1752 // If we played the audio stream to completion we
1753 // want to make sure that all samples remaining in the audio
1754 // track's queue are played out.
1755 mAudioPlayer->pause(true /* playPendingSamples */);
1756 } else {
1757 mAudioPlayer->pause();
1758 }
1759
1760 mFlags &= ~AUDIO_RUNNING;
1761 }
1762
1763 mFlags &= ~PLAYING;
1764 updateBatteryUsage_l();
1765
1766 return OK;
1767}
1768
1769bool PreviewPlayer::isPlaying() const {
1770 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
1771}
1772
1773void PreviewPlayer::setSurface(const sp<Surface> &surface) {
1774 Mutex::Autolock autoLock(mLock);
1775
1776 mSurface = surface;
1777 setNativeWindow_l(surface);
1778}
1779
Andy McFadden8ba01022012-12-18 09:46:54 -08001780void PreviewPlayer::setSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer) {
James Dong00f742c2012-01-13 17:34:42 -08001781 Mutex::Autolock autoLock(mLock);
1782
1783 mSurface.clear();
Andy McFadden8ba01022012-12-18 09:46:54 -08001784 if (bufferProducer != NULL) {
Mathias Agopian1a2952a2013-02-14 17:11:27 -08001785 setNativeWindow_l(new Surface(bufferProducer));
James Dong00f742c2012-01-13 17:34:42 -08001786 }
1787}
1788
1789void PreviewPlayer::shutdownVideoDecoder_l() {
1790 if (mVideoBuffer) {
1791 mVideoBuffer->release();
1792 mVideoBuffer = NULL;
1793 }
1794
1795 mVideoSource->stop();
1796
1797 // The following hack is necessary to ensure that the OMX
1798 // component is completely released by the time we may try
1799 // to instantiate it again.
1800 wp<MediaSource> tmp = mVideoSource;
1801 mVideoSource.clear();
1802 while (tmp.promote() != NULL) {
1803 usleep(1000);
1804 }
1805 IPCThreadState::self()->flushCommands();
1806}
1807
1808void PreviewPlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
1809 mNativeWindow = native;
1810
1811 if (mVideoSource == NULL) {
1812 return;
1813 }
1814
1815 ALOGI("attempting to reconfigure to use new surface");
1816
1817 bool wasPlaying = (mFlags & PLAYING) != 0;
1818
1819 pause_l();
1820
1821 shutdownVideoDecoder_l();
1822
1823 CHECK_EQ(initVideoDecoder_l(), (status_t)OK);
1824
1825 if (mLastVideoTimeUs >= 0) {
1826 mSeeking = SEEK;
1827 mSeekNotificationSent = true;
1828 mSeekTimeUs = mLastVideoTimeUs;
1829 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
1830 }
1831
1832 if (wasPlaying) {
1833 play_l();
1834 }
1835}
1836
1837void PreviewPlayer::setAudioSink(
1838 const sp<MediaPlayerBase::AudioSink> &audioSink) {
1839 Mutex::Autolock autoLock(mLock);
1840
1841 mAudioSink = audioSink;
1842}
1843
1844status_t PreviewPlayer::setLooping(bool shouldLoop) {
1845 Mutex::Autolock autoLock(mLock);
1846
1847 mFlags = mFlags & ~LOOPING;
1848
1849 if (shouldLoop) {
1850 mFlags |= LOOPING;
1851 }
1852
1853 return OK;
1854}
1855
1856void PreviewPlayer::setDuration_l(int64_t durationUs) {
1857 if (mDurationUs < 0 || durationUs > mDurationUs) {
1858 mDurationUs = durationUs;
1859 }
1860}
1861
1862status_t PreviewPlayer::getDuration(int64_t *durationUs) {
1863 Mutex::Autolock autoLock(mLock);
1864 if (mDurationUs < 0) {
1865 return UNKNOWN_ERROR;
1866 }
1867
1868 *durationUs = mDurationUs;
1869 return OK;
1870}
1871
1872status_t PreviewPlayer::getPosition(int64_t *positionUs) {
1873 Mutex::Autolock autoLock(mLock);
1874
1875 if (mSeeking != NO_SEEK) {
1876 *positionUs = mSeekTimeUs;
1877 } else if (mVideoSource != NULL
1878 && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
1879 *positionUs = mVideoTimeUs;
1880 } else if (mAudioPlayer != NULL) {
1881 *positionUs = mAudioPlayer->getMediaTimeUs();
1882 } else {
1883 *positionUs = 0;
1884 }
1885
1886 return OK;
1887}
1888
1889void PreviewPlayer::setPosition_l(int64_t timeUs) {
1890 mVideoTimeUs = timeUs;
1891}
1892
1893status_t PreviewPlayer::seekTo_l(int64_t timeUs) {
1894 ALOGV("seekTo_l");
1895 if (mFlags & CACHE_UNDERRUN) {
1896 mFlags &= ~CACHE_UNDERRUN;
1897 play_l();
1898 }
1899
1900 if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
1901 // Video playback completed before, there's no pending
1902 // video event right now. In order for this new seek
1903 // to be honored, we need to post one.
1904
1905 postVideoEvent_l();
1906 }
1907
1908 mSeeking = SEEK;
1909 mSeekNotificationSent = false;
1910 mSeekTimeUs = timeUs;
1911 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
1912
1913 seekAudioIfNecessary_l();
1914
1915 if (!(mFlags & PLAYING)) {
1916 ALOGV("seeking while paused, sending SEEK_COMPLETE notification"
1917 " immediately.");
1918
1919 notifyListener_l(MEDIA_SEEK_COMPLETE);
1920 mSeekNotificationSent = true;
1921
1922 if ((mFlags & PREPARED) && mVideoSource != NULL) {
1923 mFlags |= SEEK_PREVIEW;
1924 postVideoEvent_l();
1925 }
1926 }
1927
1928 return OK;
1929}
1930
1931void PreviewPlayer::seekAudioIfNecessary_l() {
1932 if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
1933 mAudioPlayer->seekTo(mSeekTimeUs);
1934
1935 mWatchForAudioSeekComplete = true;
1936 mWatchForAudioEOS = true;
1937 }
1938}
1939
1940void PreviewPlayer::setAudioSource(const sp<MediaSource>& source) {
1941 CHECK(source != NULL);
1942 mAudioTrack = source;
1943}
1944
1945void PreviewPlayer::setVideoSource(const sp<MediaSource>& source) {
1946 CHECK(source != NULL);
1947 mVideoTrack = source;
1948}
1949
1950void PreviewPlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
1951 if (mSeeking == SEEK_VIDEO_ONLY) {
1952 mSeeking = NO_SEEK;
1953 return;
1954 }
1955
1956 if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
1957 return;
1958 }
1959
1960 if (mAudioPlayer != NULL) {
1961 ALOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
1962
1963 // If we don't have a video time, seek audio to the originally
1964 // requested seek time instead.
1965
1966 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
1967 mWatchForAudioSeekComplete = true;
1968 mWatchForAudioEOS = true;
1969 } else if (!mSeekNotificationSent) {
1970 // If we're playing video only, report seek complete now,
1971 // otherwise audio player will notify us later.
1972 notifyListener_l(MEDIA_SEEK_COMPLETE);
1973 mSeekNotificationSent = true;
1974 }
1975
1976 mFlags |= FIRST_FRAME;
1977 mSeeking = NO_SEEK;
1978}
1979
1980void PreviewPlayer::onCheckAudioStatus() {
1981 Mutex::Autolock autoLock(mLock);
1982 if (!mAudioStatusEventPending) {
1983 // Event was dispatched and while we were blocking on the mutex,
1984 // has already been cancelled.
1985 return;
1986 }
1987
1988 mAudioStatusEventPending = false;
1989
1990 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1991 mWatchForAudioSeekComplete = false;
1992
1993 if (!mSeekNotificationSent) {
1994 notifyListener_l(MEDIA_SEEK_COMPLETE);
1995 mSeekNotificationSent = true;
1996 }
1997
1998 mSeeking = NO_SEEK;
1999 }
2000
2001 status_t finalStatus;
2002 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
2003 mWatchForAudioEOS = false;
2004 mFlags |= AUDIO_AT_EOS;
2005 mFlags |= FIRST_FRAME;
2006 postStreamDoneEvent_l(finalStatus);
2007 }
2008}
2009
2010void PreviewPlayer::postVideoEvent_l(int64_t delayUs) {
2011 if (mVideoEventPending) {
2012 return;
2013 }
2014
2015 mVideoEventPending = true;
2016 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
2017}
2018
2019void PreviewPlayer::postStreamDoneEvent_l(status_t status) {
2020 if (mStreamDoneEventPending) {
2021 return;
2022 }
2023 mStreamDoneEventPending = true;
2024
2025 mStreamDoneStatus = status;
2026 mQueue.postEvent(mStreamDoneEvent);
2027}
2028
2029void PreviewPlayer::postVideoLagEvent_l() {
2030 if (mVideoLagEventPending) {
2031 return;
2032 }
2033 mVideoLagEventPending = true;
2034 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
2035}
2036
2037void PreviewPlayer::postCheckAudioStatusEvent_l(int64_t delayUs) {
2038 if (mAudioStatusEventPending) {
2039 return;
2040 }
2041 mAudioStatusEventPending = true;
2042 mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
2043}
2044
2045void PreviewPlayer::abortPrepare(status_t err) {
2046 CHECK(err != OK);
2047
2048 if (mIsAsyncPrepare) {
2049 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2050 }
2051
2052 mPrepareResult = err;
2053 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
2054 mAsyncPrepareEvent = NULL;
2055 mPreparedCondition.broadcast();
2056}
2057
2058uint32_t PreviewPlayer::getSourceSeekFlags() const {
2059 Mutex::Autolock lock(mLock);
2060 return mExtractorFlags;
2061}
2062
2063void PreviewPlayer::postAudioEOS(int64_t delayUs) {
2064 Mutex::Autolock autoLock(mLock);
2065 postCheckAudioStatusEvent_l(delayUs);
2066}
2067
2068void PreviewPlayer::postAudioSeekComplete() {
2069 Mutex::Autolock autoLock(mLock);
2070 postCheckAudioStatusEvent_l(0 /* delayUs */);
2071}
2072
2073void PreviewPlayer::updateBatteryUsage_l() {
2074 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
2075 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
2076 params |= IMediaPlayerService::kBatteryDataTrackAudio;
2077 }
2078 if (mVideoSource != NULL) {
2079 params |= IMediaPlayerService::kBatteryDataTrackVideo;
2080 }
2081 addBatteryData(params);
2082}
2083
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002084} // namespace android