blob: 9789e36de068c983d66091ef89e6442e0a86a077 [file] [log] [blame]
Andreas Huber27366fc2009-11-20 09:32:46 -08001/*
2 * Copyright (C) 2009 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
17//#define LOG_NDEBUG 0
18#define LOG_TAG "AwesomePlayer"
19#include <utils/Log.h>
20
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080021#include <dlfcn.h>
22
Andreas Huber27366fc2009-11-20 09:32:46 -080023#include "include/AwesomePlayer.h"
Andreas Huberb9e63832010-01-26 16:20:10 -080024#include "include/Prefetcher.h"
Andreas Huber1314e732009-12-14 14:18:22 -080025#include "include/SoftwareRenderer.h"
Andreas Huber27366fc2009-11-20 09:32:46 -080026
Andreas Hubera67d5382009-12-10 15:32:12 -080027#include <binder/IPCThreadState.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080028#include <media/stagefright/AudioPlayer.h>
Andreas Huberedbb4d82010-03-12 08:59:22 -080029#include <media/stagefright/CachingDataSource.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080030#include <media/stagefright/DataSource.h>
31#include <media/stagefright/FileSource.h>
32#include <media/stagefright/MediaBuffer.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080033#include <media/stagefright/MediaDefs.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080034#include <media/stagefright/MediaExtractor.h>
35#include <media/stagefright/MediaDebug.h>
36#include <media/stagefright/MediaSource.h>
37#include <media/stagefright/MetaData.h>
38#include <media/stagefright/OMXCodec.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080039
Mathias Agopian000479f2010-02-09 17:46:37 -080040#include <surfaceflinger/ISurface.h>
41
Andreas Huber27366fc2009-11-20 09:32:46 -080042namespace android {
43
44struct AwesomeEvent : public TimedEventQueue::Event {
Andreas Huber6be780e2010-02-08 14:40:30 -080045 AwesomeEvent(
46 AwesomePlayer *player,
47 void (AwesomePlayer::*method)())
Andreas Huber27366fc2009-11-20 09:32:46 -080048 : mPlayer(player),
Andreas Huber6be780e2010-02-08 14:40:30 -080049 mMethod(method) {
Andreas Huber27366fc2009-11-20 09:32:46 -080050 }
51
52protected:
53 virtual ~AwesomeEvent() {}
54
55 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
Andreas Huber6be780e2010-02-08 14:40:30 -080056 (mPlayer->*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080057 }
58
59private:
60 AwesomePlayer *mPlayer;
Andreas Huber6be780e2010-02-08 14:40:30 -080061 void (AwesomePlayer::*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080062
63 AwesomeEvent(const AwesomeEvent &);
64 AwesomeEvent &operator=(const AwesomeEvent &);
65};
66
Andreas Huber1314e732009-12-14 14:18:22 -080067struct AwesomeRemoteRenderer : public AwesomeRenderer {
68 AwesomeRemoteRenderer(const sp<IOMXRenderer> &target)
69 : mTarget(target) {
70 }
71
72 virtual void render(MediaBuffer *buffer) {
73 void *id;
74 if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) {
75 mTarget->render((IOMX::buffer_id)id);
76 }
77 }
78
79private:
80 sp<IOMXRenderer> mTarget;
81
82 AwesomeRemoteRenderer(const AwesomeRemoteRenderer &);
83 AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &);
84};
85
86struct AwesomeLocalRenderer : public AwesomeRenderer {
87 AwesomeLocalRenderer(
Andreas Huber7b73cfc2010-02-12 14:40:08 -080088 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080089 const char *componentName,
Andreas Huber1314e732009-12-14 14:18:22 -080090 OMX_COLOR_FORMATTYPE colorFormat,
91 const sp<ISurface> &surface,
92 size_t displayWidth, size_t displayHeight,
93 size_t decodedWidth, size_t decodedHeight)
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080094 : mTarget(NULL),
95 mLibHandle(NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -080096 init(previewOnly, componentName,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080097 colorFormat, surface, displayWidth,
98 displayHeight, decodedWidth, decodedHeight);
Andreas Huber1314e732009-12-14 14:18:22 -080099 }
100
101 virtual void render(MediaBuffer *buffer) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800102 render((const uint8_t *)buffer->data() + buffer->range_offset(),
103 buffer->range_length());
104 }
105
106 void render(const void *data, size_t size) {
107 mTarget->render(data, size, NULL);
Andreas Huber1314e732009-12-14 14:18:22 -0800108 }
109
110protected:
111 virtual ~AwesomeLocalRenderer() {
112 delete mTarget;
113 mTarget = NULL;
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800114
115 if (mLibHandle) {
116 dlclose(mLibHandle);
117 mLibHandle = NULL;
118 }
Andreas Huber1314e732009-12-14 14:18:22 -0800119 }
120
121private:
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800122 VideoRenderer *mTarget;
123 void *mLibHandle;
124
125 void init(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800126 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800127 const char *componentName,
128 OMX_COLOR_FORMATTYPE colorFormat,
129 const sp<ISurface> &surface,
130 size_t displayWidth, size_t displayHeight,
131 size_t decodedWidth, size_t decodedHeight);
Andreas Huber1314e732009-12-14 14:18:22 -0800132
133 AwesomeLocalRenderer(const AwesomeLocalRenderer &);
134 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
135};
136
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800137void AwesomeLocalRenderer::init(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800138 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800139 const char *componentName,
140 OMX_COLOR_FORMATTYPE colorFormat,
141 const sp<ISurface> &surface,
142 size_t displayWidth, size_t displayHeight,
143 size_t decodedWidth, size_t decodedHeight) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800144 if (!previewOnly) {
145 // We will stick to the vanilla software-color-converting renderer
146 // for "previewOnly" mode, to avoid unneccessarily switching overlays
147 // more often than necessary.
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800148
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800149 mLibHandle = dlopen("libstagefrighthw.so", RTLD_NOW);
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800150
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800151 if (mLibHandle) {
152 typedef VideoRenderer *(*CreateRendererFunc)(
153 const sp<ISurface> &surface,
154 const char *componentName,
155 OMX_COLOR_FORMATTYPE colorFormat,
156 size_t displayWidth, size_t displayHeight,
157 size_t decodedWidth, size_t decodedHeight);
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800158
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800159 CreateRendererFunc func =
160 (CreateRendererFunc)dlsym(
161 mLibHandle,
162 "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20"
163 "OMX_COLOR_FORMATTYPEjjjj");
164
165 if (func) {
166 mTarget =
167 (*func)(surface, componentName, colorFormat,
168 displayWidth, displayHeight,
169 decodedWidth, decodedHeight);
170 }
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800171 }
172 }
173
174 if (mTarget == NULL) {
175 mTarget = new SoftwareRenderer(
176 colorFormat, surface, displayWidth, displayHeight,
177 decodedWidth, decodedHeight);
178 }
179}
180
Andreas Huber27366fc2009-11-20 09:32:46 -0800181AwesomePlayer::AwesomePlayer()
Andreas Huber406a18b2010-02-18 16:45:13 -0800182 : mQueueStarted(false),
183 mTimeSource(NULL),
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800184 mVideoRendererIsPreview(false),
Andreas Huber27366fc2009-11-20 09:32:46 -0800185 mAudioPlayer(NULL),
Andreas Huberffdf4782010-02-09 14:05:43 -0800186 mFlags(0),
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700187 mExtractorFlags(0),
Andreas Huber27366fc2009-11-20 09:32:46 -0800188 mLastVideoBuffer(NULL),
Andreas Huberba7ec912010-02-12 10:42:02 -0800189 mVideoBuffer(NULL),
Gloria Wangd5770912010-06-22 13:55:38 -0700190 mSuspensionState(NULL),
191 mDecryptHandle(NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800192 CHECK_EQ(mClient.connect(), OK);
193
194 DataSource::RegisterDefaultSniffers();
195
Andreas Huber6be780e2010-02-08 14:40:30 -0800196 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
Andreas Huber27366fc2009-11-20 09:32:46 -0800197 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800198 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
Andreas Huber27366fc2009-11-20 09:32:46 -0800199 mStreamDoneEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800200 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
Andreas Huberb9e63832010-01-26 16:20:10 -0800201 mBufferingEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800202
203 mCheckAudioStatusEvent = new AwesomeEvent(
204 this, &AwesomePlayer::onCheckAudioStatus);
205
Andreas Huber70d10c02010-02-03 11:37:29 -0800206 mAudioStatusEventPending = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800207
Andreas Huber27366fc2009-11-20 09:32:46 -0800208 reset();
209}
210
211AwesomePlayer::~AwesomePlayer() {
Andreas Huber406a18b2010-02-18 16:45:13 -0800212 if (mQueueStarted) {
213 mQueue.stop();
214 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800215
216 reset();
217
218 mClient.disconnect();
219}
220
Andreas Huberb9e63832010-01-26 16:20:10 -0800221void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800222 mQueue.cancelEvent(mVideoEvent->eventID());
223 mVideoEventPending = false;
224 mQueue.cancelEvent(mStreamDoneEvent->eventID());
225 mStreamDoneEventPending = false;
Andreas Huber70d10c02010-02-03 11:37:29 -0800226 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
227 mAudioStatusEventPending = false;
Andreas Huberb9e63832010-01-26 16:20:10 -0800228
229 if (!keepBufferingGoing) {
230 mQueue.cancelEvent(mBufferingEvent->eventID());
231 mBufferingEventPending = false;
232 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800233}
234
Andreas Hubera3f43842010-01-21 10:28:45 -0800235void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800236 Mutex::Autolock autoLock(mLock);
237 mListener = listener;
238}
239
Andreas Huber433c9ac2010-01-27 16:49:05 -0800240status_t AwesomePlayer::setDataSource(
241 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800242 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800243 return setDataSource_l(uri, headers);
244}
Andreas Huber27366fc2009-11-20 09:32:46 -0800245
Andreas Huberba7ec912010-02-12 10:42:02 -0800246status_t AwesomePlayer::setDataSource_l(
247 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800248 reset_l();
249
Andreas Huberffdf4782010-02-09 14:05:43 -0800250 mUri = uri;
Andreas Huberb9e63832010-01-26 16:20:10 -0800251
Andreas Huberffdf4782010-02-09 14:05:43 -0800252 if (headers) {
253 mUriHeaders = *headers;
Andreas Huberb9e63832010-01-26 16:20:10 -0800254 }
255
Andreas Huberffdf4782010-02-09 14:05:43 -0800256 // The actual work will be done during preparation in the call to
257 // ::finishSetDataSource_l to avoid blocking the calling thread in
258 // setDataSource for any significant time.
Andreas Huber27366fc2009-11-20 09:32:46 -0800259
Andreas Huberffdf4782010-02-09 14:05:43 -0800260 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800261}
262
263status_t AwesomePlayer::setDataSource(
264 int fd, int64_t offset, int64_t length) {
265 Mutex::Autolock autoLock(mLock);
266
267 reset_l();
268
Andreas Huberba7ec912010-02-12 10:42:02 -0800269 sp<DataSource> dataSource = new FileSource(fd, offset, length);
Andreas Huber27366fc2009-11-20 09:32:46 -0800270
Andreas Huberba7ec912010-02-12 10:42:02 -0800271 status_t err = dataSource->initCheck();
Andreas Huber27366fc2009-11-20 09:32:46 -0800272
273 if (err != OK) {
274 return err;
275 }
276
Andreas Huberba7ec912010-02-12 10:42:02 -0800277 mFileSource = dataSource;
278
279 return setDataSource_l(dataSource);
280}
281
282status_t AwesomePlayer::setDataSource_l(
283 const sp<DataSource> &dataSource) {
284 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
Andreas Huber27366fc2009-11-20 09:32:46 -0800285
286 if (extractor == NULL) {
287 return UNKNOWN_ERROR;
288 }
289
Gloria Wangd5770912010-06-22 13:55:38 -0700290 dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
Gloria Wangeab18ea2010-10-29 10:09:47 -0700291 if (mDecryptHandle != NULL
292 && RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
293 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
Gloria Wangd5770912010-06-22 13:55:38 -0700294 }
295
Andreas Huber27366fc2009-11-20 09:32:46 -0800296 return setDataSource_l(extractor);
297}
298
299status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800300 bool haveAudio = false;
301 bool haveVideo = false;
302 for (size_t i = 0; i < extractor->countTracks(); ++i) {
303 sp<MetaData> meta = extractor->getTrackMetaData(i);
304
305 const char *mime;
306 CHECK(meta->findCString(kKeyMIMEType, &mime));
307
308 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800309 setVideoSource(extractor->getTrack(i));
310 haveVideo = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800311 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800312 setAudioSource(extractor->getTrack(i));
313 haveAudio = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800314 }
315
316 if (haveAudio && haveVideo) {
317 break;
318 }
319 }
320
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700321 if (!haveAudio && !haveVideo) {
322 return UNKNOWN_ERROR;
323 }
324
325 mExtractorFlags = extractor->flags();
326
327 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800328}
329
330void AwesomePlayer::reset() {
331 Mutex::Autolock autoLock(mLock);
332 reset_l();
333}
334
335void AwesomePlayer::reset_l() {
Gloria Wangd5770912010-06-22 13:55:38 -0700336 if (mDecryptHandle != NULL) {
337 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
338 Playback::STOP, 0);
Gloria Wangd5770912010-06-22 13:55:38 -0700339 mDecryptHandle = NULL;
340 mDrmManagerClient = NULL;
341 }
342
Andreas Huberedbb4d82010-03-12 08:59:22 -0800343 if (mFlags & PREPARING) {
344 mFlags |= PREPARE_CANCELLED;
345 if (mConnectingDataSource != NULL) {
346 LOGI("interrupting the connection process");
347 mConnectingDataSource->disconnect();
348 }
349 }
350
Andreas Huberffdf4782010-02-09 14:05:43 -0800351 while (mFlags & PREPARING) {
352 mPreparedCondition.wait(mLock);
353 }
354
Andreas Huber27366fc2009-11-20 09:32:46 -0800355 cancelPlayerEvents();
356
Andreas Huberba7ec912010-02-12 10:42:02 -0800357 if (mPrefetcher != NULL) {
358 CHECK_EQ(mPrefetcher->getStrongCount(), 1);
359 }
360 mPrefetcher.clear();
361
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800362 mAudioTrack.clear();
363 mVideoTrack.clear();
364
Andreas Huberba7ec912010-02-12 10:42:02 -0800365 // Shutdown audio first, so that the respone to the reset request
366 // appears to happen instantaneously as far as the user is concerned
367 // If we did this later, audio would continue playing while we
368 // shutdown the video-related resources and the player appear to
369 // not be as responsive to a reset request.
Andreas Huberedbb4d82010-03-12 08:59:22 -0800370 if (mAudioPlayer == NULL && mAudioSource != NULL) {
371 // If we had an audio player, it would have effectively
372 // taken possession of the audio source and stopped it when
373 // _it_ is stopped. Otherwise this is still our responsibility.
374 mAudioSource->stop();
375 }
Andreas Huberba7ec912010-02-12 10:42:02 -0800376 mAudioSource.clear();
377
378 if (mTimeSource != mAudioPlayer) {
379 delete mTimeSource;
380 }
381 mTimeSource = NULL;
382
383 delete mAudioPlayer;
384 mAudioPlayer = NULL;
385
Andreas Huber3522b5a52010-01-22 14:36:53 -0800386 mVideoRenderer.clear();
387
Andreas Huber27366fc2009-11-20 09:32:46 -0800388 if (mLastVideoBuffer) {
389 mLastVideoBuffer->release();
390 mLastVideoBuffer = NULL;
391 }
392
393 if (mVideoBuffer) {
394 mVideoBuffer->release();
395 mVideoBuffer = NULL;
396 }
397
398 if (mVideoSource != NULL) {
399 mVideoSource->stop();
Andreas Huber98b48de2010-01-29 10:10:22 -0800400
401 // The following hack is necessary to ensure that the OMX
402 // component is completely released by the time we may try
403 // to instantiate it again.
404 wp<MediaSource> tmp = mVideoSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800405 mVideoSource.clear();
Andreas Huber98b48de2010-01-29 10:10:22 -0800406 while (tmp.promote() != NULL) {
407 usleep(1000);
408 }
409 IPCThreadState::self()->flushCommands();
Andreas Huber27366fc2009-11-20 09:32:46 -0800410 }
411
Andreas Huber27366fc2009-11-20 09:32:46 -0800412 mDurationUs = -1;
413 mFlags = 0;
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700414 mExtractorFlags = 0;
Andreas Huber27366fc2009-11-20 09:32:46 -0800415 mVideoWidth = mVideoHeight = -1;
416 mTimeSourceDeltaUs = 0;
417 mVideoTimeUs = 0;
418
419 mSeeking = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700420 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800421 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800422
Andreas Huberffdf4782010-02-09 14:05:43 -0800423 mUri.setTo("");
424 mUriHeaders.clear();
Andreas Huberba7ec912010-02-12 10:42:02 -0800425
426 mFileSource.clear();
427
428 delete mSuspensionState;
429 mSuspensionState = NULL;
Andreas Huber27366fc2009-11-20 09:32:46 -0800430}
431
Andreas Huber6be780e2010-02-08 14:40:30 -0800432void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800433 if (mListener != NULL) {
434 sp<MediaPlayerBase> listener = mListener.promote();
435
436 if (listener != NULL) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800437 listener->sendEvent(msg, ext1, ext2);
Andreas Hubera3f43842010-01-21 10:28:45 -0800438 }
439 }
440}
441
Andreas Huberb9e63832010-01-26 16:20:10 -0800442void AwesomePlayer::onBufferingUpdate() {
443 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800444 if (!mBufferingEventPending) {
445 return;
446 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800447 mBufferingEventPending = false;
448
Andreas Huber252573c2010-03-26 10:17:17 -0700449 int64_t durationUs;
450 {
451 Mutex::Autolock autoLock(mMiscStateLock);
452 durationUs = mDurationUs;
453 }
454
455 if (durationUs >= 0) {
Andreas Huberb9e63832010-01-26 16:20:10 -0800456 int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs();
Andreas Huberdc9927d2010-03-08 15:46:13 -0800457
458 LOGV("cache holds %.2f secs worth of data.", cachedDurationUs / 1E6);
459
Andreas Huber252573c2010-03-26 10:17:17 -0700460 int64_t positionUs;
461 getPosition(&positionUs);
Andreas Huberb9e63832010-01-26 16:20:10 -0800462
463 cachedDurationUs += positionUs;
464
Andreas Huber252573c2010-03-26 10:17:17 -0700465 double percentage = (double)cachedDurationUs / durationUs;
Andreas Huberb9e63832010-01-26 16:20:10 -0800466 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
467
468 postBufferingEvent_l();
Andreas Huber040301c2010-04-12 09:41:12 -0700469 } else {
470 LOGE("Not sending buffering status because duration is unknown.");
Andreas Huberb9e63832010-01-26 16:20:10 -0800471 }
472}
473
Andreas Huber27366fc2009-11-20 09:32:46 -0800474void AwesomePlayer::onStreamDone() {
475 // Posted whenever any stream finishes playing.
476
477 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800478 if (!mStreamDoneEventPending) {
479 return;
480 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800481 mStreamDoneEventPending = false;
482
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800483 if (mStreamDoneStatus == ERROR_END_OF_STREAM && (mFlags & LOOPING)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800484 seekTo_l(0);
485
Andreas Huber7085b6842010-02-03 16:02:02 -0800486 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800487 postVideoEvent_l();
488 }
489 } else {
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800490 if (mStreamDoneStatus == ERROR_END_OF_STREAM) {
491 LOGV("MEDIA_PLAYBACK_COMPLETE");
492 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
493 } else {
494 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
495
496 notifyListener_l(
497 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
498 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800499
500 pause_l();
Andreas Huber406a18b2010-02-18 16:45:13 -0800501
502 mFlags |= AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800503 }
504}
505
506status_t AwesomePlayer::play() {
507 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800508 return play_l();
509}
Andreas Huber27366fc2009-11-20 09:32:46 -0800510
Andreas Huberba7ec912010-02-12 10:42:02 -0800511status_t AwesomePlayer::play_l() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800512 if (mFlags & PLAYING) {
513 return OK;
514 }
515
Andreas Huberffdf4782010-02-09 14:05:43 -0800516 if (!(mFlags & PREPARED)) {
517 status_t err = prepare_l();
518
519 if (err != OK) {
520 return err;
521 }
522 }
523
Andreas Huber27366fc2009-11-20 09:32:46 -0800524 mFlags |= PLAYING;
525 mFlags |= FIRST_FRAME;
526
Andreas Huberc1d5c922009-12-10 15:49:04 -0800527 bool deferredAudioSeek = false;
528
Andreas Huber27366fc2009-11-20 09:32:46 -0800529 if (mAudioSource != NULL) {
530 if (mAudioPlayer == NULL) {
531 if (mAudioSink != NULL) {
532 mAudioPlayer = new AudioPlayer(mAudioSink);
Andreas Huber27366fc2009-11-20 09:32:46 -0800533 mAudioPlayer->setSource(mAudioSource);
Andreas Huberdc9927d2010-03-08 15:46:13 -0800534
535 // We've already started the MediaSource in order to enable
536 // the prefetcher to read its data.
537 status_t err = mAudioPlayer->start(
538 true /* sourceAlreadyStarted */);
Andreas Huber62eac002010-01-29 13:24:58 -0800539
540 if (err != OK) {
541 delete mAudioPlayer;
542 mAudioPlayer = NULL;
543
544 mFlags &= ~(PLAYING | FIRST_FRAME);
545
546 return err;
547 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800548
549 delete mTimeSource;
550 mTimeSource = mAudioPlayer;
551
Andreas Huberc1d5c922009-12-10 15:49:04 -0800552 deferredAudioSeek = true;
Andreas Huber70d10c02010-02-03 11:37:29 -0800553
554 mWatchForAudioSeekComplete = false;
555 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800556 }
557 } else {
558 mAudioPlayer->resume();
559 }
Andreas Huber70d10c02010-02-03 11:37:29 -0800560
561 postCheckAudioStatusEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800562 }
563
564 if (mTimeSource == NULL && mAudioPlayer == NULL) {
565 mTimeSource = new SystemTimeSource;
566 }
567
568 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800569 // Kick off video playback
570 postVideoEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800571 }
572
Andreas Huberc1d5c922009-12-10 15:49:04 -0800573 if (deferredAudioSeek) {
574 // If there was a seek request while we were paused
575 // and we're just starting up again, honor the request now.
576 seekAudioIfNecessary_l();
577 }
578
Andreas Huber406a18b2010-02-18 16:45:13 -0800579 if (mFlags & AT_EOS) {
580 // Legacy behaviour, if a stream finishes playing and then
581 // is started again, we play from the start...
582 seekTo_l(0);
583 }
584
Gloria Wangd5770912010-06-22 13:55:38 -0700585 if (mDecryptHandle != NULL) {
586 int64_t position;
587 getPosition(&position);
588 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
589 Playback::START, position / 1000);
590 }
591
Andreas Huber27366fc2009-11-20 09:32:46 -0800592 return OK;
593}
594
595void AwesomePlayer::initRenderer_l() {
596 if (mISurface != NULL) {
597 sp<MetaData> meta = mVideoSource->getFormat();
598
599 int32_t format;
600 const char *component;
601 int32_t decodedWidth, decodedHeight;
602 CHECK(meta->findInt32(kKeyColorFormat, &format));
603 CHECK(meta->findCString(kKeyDecoderComponent, &component));
604 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
605 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
606
Andreas Hubera67d5382009-12-10 15:32:12 -0800607 mVideoRenderer.clear();
608
609 // Must ensure that mVideoRenderer's destructor is actually executed
610 // before creating a new one.
611 IPCThreadState::self()->flushCommands();
612
Andreas Huber1314e732009-12-14 14:18:22 -0800613 if (!strncmp("OMX.", component, 4)) {
614 // Our OMX codecs allocate buffers on the media_server side
615 // therefore they require a remote IOMXRenderer that knows how
616 // to display them.
617 mVideoRenderer = new AwesomeRemoteRenderer(
618 mClient.interface()->createRenderer(
619 mISurface, component,
620 (OMX_COLOR_FORMATTYPE)format,
621 decodedWidth, decodedHeight,
622 mVideoWidth, mVideoHeight));
623 } else {
624 // Other decoders are instantiated locally and as a consequence
625 // allocate their buffers in local address space.
626 mVideoRenderer = new AwesomeLocalRenderer(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800627 false, // previewOnly
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800628 component,
Andreas Huber1314e732009-12-14 14:18:22 -0800629 (OMX_COLOR_FORMATTYPE)format,
630 mISurface,
631 mVideoWidth, mVideoHeight,
632 decodedWidth, decodedHeight);
633 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800634 }
635}
636
637status_t AwesomePlayer::pause() {
638 Mutex::Autolock autoLock(mLock);
639 return pause_l();
640}
641
642status_t AwesomePlayer::pause_l() {
643 if (!(mFlags & PLAYING)) {
644 return OK;
645 }
646
Andreas Huberb9e63832010-01-26 16:20:10 -0800647 cancelPlayerEvents(true /* keepBufferingGoing */);
Andreas Huber27366fc2009-11-20 09:32:46 -0800648
649 if (mAudioPlayer != NULL) {
650 mAudioPlayer->pause();
651 }
652
653 mFlags &= ~PLAYING;
654
Gloria Wangd5770912010-06-22 13:55:38 -0700655 if (mDecryptHandle != NULL) {
656 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
657 Playback::PAUSE, 0);
658 }
659
Andreas Huber27366fc2009-11-20 09:32:46 -0800660 return OK;
661}
662
663bool AwesomePlayer::isPlaying() const {
Andreas Huber27366fc2009-11-20 09:32:46 -0800664 return mFlags & PLAYING;
665}
666
667void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
668 Mutex::Autolock autoLock(mLock);
669
670 mISurface = isurface;
671}
672
673void AwesomePlayer::setAudioSink(
674 const sp<MediaPlayerBase::AudioSink> &audioSink) {
675 Mutex::Autolock autoLock(mLock);
676
677 mAudioSink = audioSink;
678}
679
680status_t AwesomePlayer::setLooping(bool shouldLoop) {
681 Mutex::Autolock autoLock(mLock);
682
683 mFlags = mFlags & ~LOOPING;
684
685 if (shouldLoop) {
686 mFlags |= LOOPING;
687 }
688
689 return OK;
690}
691
692status_t AwesomePlayer::getDuration(int64_t *durationUs) {
Andreas Huber252573c2010-03-26 10:17:17 -0700693 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800694
695 if (mDurationUs < 0) {
696 return UNKNOWN_ERROR;
697 }
698
699 *durationUs = mDurationUs;
700
701 return OK;
702}
703
704status_t AwesomePlayer::getPosition(int64_t *positionUs) {
Andreas Huberddb709c2010-04-07 10:24:35 -0700705 if (mSeeking) {
706 *positionUs = mSeekTimeUs;
707 } else if (mVideoSource != NULL) {
Andreas Huber252573c2010-03-26 10:17:17 -0700708 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800709 *positionUs = mVideoTimeUs;
710 } else if (mAudioPlayer != NULL) {
711 *positionUs = mAudioPlayer->getMediaTimeUs();
712 } else {
713 *positionUs = 0;
714 }
715
716 return OK;
717}
718
719status_t AwesomePlayer::seekTo(int64_t timeUs) {
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700720 if (mExtractorFlags
721 & (MediaExtractor::CAN_SEEK_FORWARD
722 | MediaExtractor::CAN_SEEK_BACKWARD)) {
723 Mutex::Autolock autoLock(mLock);
724 return seekTo_l(timeUs);
725 }
726
727 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800728}
729
730status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
731 mSeeking = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700732 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800733 mSeekTimeUs = timeUs;
Andreas Huber406a18b2010-02-18 16:45:13 -0800734 mFlags &= ~AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800735
736 seekAudioIfNecessary_l();
737
Andreas Huber8e2b9412010-03-31 09:40:15 -0700738 if (!(mFlags & PLAYING)) {
739 LOGV("seeking while paused, sending SEEK_COMPLETE notification"
740 " immediately.");
741
742 notifyListener_l(MEDIA_SEEK_COMPLETE);
743 mSeekNotificationSent = true;
744 }
745
Andreas Huber27366fc2009-11-20 09:32:46 -0800746 return OK;
747}
748
749void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Huber7085b6842010-02-03 16:02:02 -0800750 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800751 mAudioPlayer->seekTo(mSeekTimeUs);
752
Andreas Huber70d10c02010-02-03 11:37:29 -0800753 mWatchForAudioSeekComplete = true;
754 mWatchForAudioEOS = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700755 mSeekNotificationSent = false;
Gloria Wangd5770912010-06-22 13:55:38 -0700756
757 if (mDecryptHandle != NULL) {
758 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
759 Playback::PAUSE, 0);
760 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
761 Playback::START, mSeekTimeUs / 1000);
762 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800763 }
764}
765
766status_t AwesomePlayer::getVideoDimensions(
767 int32_t *width, int32_t *height) const {
768 Mutex::Autolock autoLock(mLock);
769
770 if (mVideoWidth < 0 || mVideoHeight < 0) {
771 return UNKNOWN_ERROR;
772 }
773
774 *width = mVideoWidth;
775 *height = mVideoHeight;
776
777 return OK;
778}
779
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800780void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
781 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800782
Andreas Huberb9e63832010-01-26 16:20:10 -0800783 if (mPrefetcher != NULL) {
784 source = mPrefetcher->addSource(source);
785 }
786
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800787 mAudioTrack = source;
788}
789
790status_t AwesomePlayer::initAudioDecoder() {
791 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huberc79827a2010-01-05 10:54:55 -0800792
793 const char *mime;
794 CHECK(meta->findCString(kKeyMIMEType, &mime));
795
796 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800797 mAudioSource = mAudioTrack;
Andreas Huberc79827a2010-01-05 10:54:55 -0800798 } else {
799 mAudioSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800800 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huberc79827a2010-01-05 10:54:55 -0800801 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800802 mAudioTrack);
Andreas Huberc79827a2010-01-05 10:54:55 -0800803 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800804
805 if (mAudioSource != NULL) {
806 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800807 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -0700808 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800809 if (mDurationUs < 0 || durationUs > mDurationUs) {
810 mDurationUs = durationUs;
811 }
812 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800813
Andreas Huber3c78a1b2010-05-13 09:15:21 -0700814 status_t err = mAudioSource->start();
815
816 if (err != OK) {
817 mAudioSource.clear();
818 return err;
819 }
Andreas Huberd0332ad2010-04-12 16:05:57 -0700820 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
821 // For legacy reasons we're simply going to ignore the absence
822 // of an audio decoder for QCELP instead of aborting playback
823 // altogether.
824 return OK;
825 }
Andreas Huberdc9927d2010-03-08 15:46:13 -0800826
Andreas Huber27366fc2009-11-20 09:32:46 -0800827 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
828}
829
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800830void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
831 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800832
Andreas Huberb9e63832010-01-26 16:20:10 -0800833 if (mPrefetcher != NULL) {
834 source = mPrefetcher->addSource(source);
835 }
836
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800837 mVideoTrack = source;
838}
839
840status_t AwesomePlayer::initVideoDecoder() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800841 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800842 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -0800843 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800844 mVideoTrack);
Andreas Huber27366fc2009-11-20 09:32:46 -0800845
846 if (mVideoSource != NULL) {
847 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800848 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -0700849 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800850 if (mDurationUs < 0 || durationUs > mDurationUs) {
851 mDurationUs = durationUs;
852 }
853 }
854
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800855 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
856 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
Andreas Huber27366fc2009-11-20 09:32:46 -0800857
Andreas Huber1919e5a2010-05-20 10:37:06 -0700858 status_t err = mVideoSource->start();
859
860 if (err != OK) {
861 mVideoSource.clear();
862 return err;
863 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800864 }
865
866 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
867}
868
Andreas Huber6be780e2010-02-08 14:40:30 -0800869void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800870 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800871 if (!mVideoEventPending) {
872 // The event has been cancelled in reset_l() but had already
873 // been scheduled for execution at that time.
874 return;
875 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800876 mVideoEventPending = false;
877
878 if (mSeeking) {
879 if (mLastVideoBuffer) {
880 mLastVideoBuffer->release();
881 mLastVideoBuffer = NULL;
882 }
883
884 if (mVideoBuffer) {
885 mVideoBuffer->release();
886 mVideoBuffer = NULL;
887 }
888 }
889
890 if (!mVideoBuffer) {
891 MediaSource::ReadOptions options;
892 if (mSeeking) {
893 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
894
895 options.setSeekTo(mSeekTimeUs);
896 }
897 for (;;) {
898 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -0800899 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -0800900
901 if (err != OK) {
902 CHECK_EQ(mVideoBuffer, NULL);
903
904 if (err == INFO_FORMAT_CHANGED) {
905 LOGV("VideoSource signalled format change.");
906
Andreas Huber7085b6842010-02-03 16:02:02 -0800907 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800908 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -0800909 initRenderer_l();
910 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800911 continue;
912 }
913
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800914 postStreamDoneEvent_l(err);
Andreas Huber27366fc2009-11-20 09:32:46 -0800915 return;
916 }
917
Andreas Hubera67d5382009-12-10 15:32:12 -0800918 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -0800919 // Some decoders, notably the PV AVC software decoder
920 // return spurious empty buffers that we just want to ignore.
921
Andreas Hubera67d5382009-12-10 15:32:12 -0800922 mVideoBuffer->release();
923 mVideoBuffer = NULL;
924 continue;
925 }
926
Andreas Huber27366fc2009-11-20 09:32:46 -0800927 break;
928 }
929 }
930
931 int64_t timeUs;
932 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
933
Andreas Huber252573c2010-03-26 10:17:17 -0700934 {
935 Mutex::Autolock autoLock(mMiscStateLock);
936 mVideoTimeUs = timeUs;
937 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800938
939 if (mSeeking) {
940 if (mAudioPlayer != NULL) {
941 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
942
943 mAudioPlayer->seekTo(timeUs);
Andreas Huber70d10c02010-02-03 11:37:29 -0800944 mWatchForAudioSeekComplete = true;
945 mWatchForAudioEOS = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700946 } else if (!mSeekNotificationSent) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800947 // If we're playing video only, report seek complete now,
948 // otherwise audio player will notify us later.
Andreas Hubera3f43842010-01-21 10:28:45 -0800949 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800950 }
951
952 mFlags |= FIRST_FRAME;
953 mSeeking = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700954 mSeekNotificationSent = false;
Gloria Wangd5770912010-06-22 13:55:38 -0700955
956 if (mDecryptHandle != NULL) {
957 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
958 Playback::PAUSE, 0);
959 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
960 Playback::START, timeUs / 1000);
961 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800962 }
963
964 if (mFlags & FIRST_FRAME) {
965 mFlags &= ~FIRST_FRAME;
966
967 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
968 }
969
970 int64_t realTimeUs, mediaTimeUs;
971 if (mAudioPlayer != NULL
972 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
973 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
974 }
975
976 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
977
978 int64_t latenessUs = nowUs - timeUs;
979
Andreas Huber24b0a952009-11-23 14:02:00 -0800980 if (latenessUs > 40000) {
981 // We're more than 40ms late.
Andreas Huber4a9375e2010-02-09 11:54:33 -0800982 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -0800983
984 mVideoBuffer->release();
985 mVideoBuffer = NULL;
986
987 postVideoEvent_l();
988 return;
989 }
990
991 if (latenessUs < -10000) {
992 // We're more than 10ms early.
993
994 postVideoEvent_l(10000);
995 return;
996 }
997
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800998 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
999 mVideoRendererIsPreview = false;
1000
Andreas Huber7085b6842010-02-03 16:02:02 -08001001 initRenderer_l();
1002 }
1003
1004 if (mVideoRenderer != NULL) {
1005 mVideoRenderer->render(mVideoBuffer);
1006 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001007
1008 if (mLastVideoBuffer) {
1009 mLastVideoBuffer->release();
1010 mLastVideoBuffer = NULL;
1011 }
1012 mLastVideoBuffer = mVideoBuffer;
1013 mVideoBuffer = NULL;
1014
1015 postVideoEvent_l();
1016}
1017
1018void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1019 if (mVideoEventPending) {
1020 return;
1021 }
1022
1023 mVideoEventPending = true;
1024 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1025}
1026
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001027void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001028 if (mStreamDoneEventPending) {
1029 return;
1030 }
1031 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001032
1033 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -08001034 mQueue.postEvent(mStreamDoneEvent);
1035}
1036
Andreas Huberb9e63832010-01-26 16:20:10 -08001037void AwesomePlayer::postBufferingEvent_l() {
1038 if (mPrefetcher == NULL) {
1039 return;
1040 }
1041
1042 if (mBufferingEventPending) {
1043 return;
1044 }
1045 mBufferingEventPending = true;
1046 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1047}
1048
Andreas Huber70d10c02010-02-03 11:37:29 -08001049void AwesomePlayer::postCheckAudioStatusEvent_l() {
1050 if (mAudioStatusEventPending) {
1051 return;
1052 }
1053 mAudioStatusEventPending = true;
1054 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
1055}
1056
1057void AwesomePlayer::onCheckAudioStatus() {
1058 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -08001059 if (!mAudioStatusEventPending) {
1060 // Event was dispatched and while we were blocking on the mutex,
1061 // has already been cancelled.
1062 return;
1063 }
1064
Andreas Huber70d10c02010-02-03 11:37:29 -08001065 mAudioStatusEventPending = false;
1066
1067 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1068 mWatchForAudioSeekComplete = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001069
1070 if (!mSeekNotificationSent) {
1071 notifyListener_l(MEDIA_SEEK_COMPLETE);
1072 mSeekNotificationSent = true;
1073 }
Andreas Huberddb709c2010-04-07 10:24:35 -07001074
1075 mSeeking = false;
Andreas Huber70d10c02010-02-03 11:37:29 -08001076 }
1077
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001078 status_t finalStatus;
1079 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -08001080 mWatchForAudioEOS = false;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001081 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -08001082 }
1083
1084 postCheckAudioStatusEvent_l();
1085}
1086
Andreas Huber6be780e2010-02-08 14:40:30 -08001087status_t AwesomePlayer::prepare() {
1088 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001089 return prepare_l();
1090}
Andreas Huber6be780e2010-02-08 14:40:30 -08001091
Andreas Huberffdf4782010-02-09 14:05:43 -08001092status_t AwesomePlayer::prepare_l() {
1093 if (mFlags & PREPARED) {
1094 return OK;
1095 }
1096
1097 if (mFlags & PREPARING) {
1098 return UNKNOWN_ERROR;
1099 }
1100
1101 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -08001102 status_t err = prepareAsync_l();
1103
1104 if (err != OK) {
1105 return err;
1106 }
1107
Andreas Huberffdf4782010-02-09 14:05:43 -08001108 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001109 mPreparedCondition.wait(mLock);
1110 }
1111
Andreas Huberffdf4782010-02-09 14:05:43 -08001112 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001113}
1114
1115status_t AwesomePlayer::prepareAsync() {
1116 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001117
1118 if (mFlags & PREPARING) {
1119 return UNKNOWN_ERROR; // async prepare already pending
1120 }
1121
1122 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001123 return prepareAsync_l();
1124}
1125
1126status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001127 if (mFlags & PREPARING) {
1128 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001129 }
1130
Andreas Huber406a18b2010-02-18 16:45:13 -08001131 if (!mQueueStarted) {
1132 mQueue.start();
1133 mQueueStarted = true;
1134 }
1135
Andreas Huberffdf4782010-02-09 14:05:43 -08001136 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -08001137 mAsyncPrepareEvent = new AwesomeEvent(
1138 this, &AwesomePlayer::onPrepareAsyncEvent);
1139
1140 mQueue.postEvent(mAsyncPrepareEvent);
1141
1142 return OK;
1143}
1144
Andreas Huberffdf4782010-02-09 14:05:43 -08001145status_t AwesomePlayer::finishSetDataSource_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001146 sp<DataSource> dataSource;
1147
1148 if (!strncasecmp("http://", mUri.string(), 7)) {
1149 mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders);
1150
1151 mLock.unlock();
1152 status_t err = mConnectingDataSource->connect();
1153 mLock.lock();
1154
1155 if (err != OK) {
1156 mConnectingDataSource.clear();
1157
1158 LOGI("mConnectingDataSource->connect() returned %d", err);
1159 return err;
1160 }
1161
1162 dataSource = new CachingDataSource(
Andreas Hubera51250b2010-04-08 07:51:20 -07001163 mConnectingDataSource, 64 * 1024, 10);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001164
1165 mConnectingDataSource.clear();
1166 } else {
1167 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1168 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001169
1170 if (dataSource == NULL) {
1171 return UNKNOWN_ERROR;
1172 }
1173
1174 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1175
1176 if (extractor == NULL) {
1177 return UNKNOWN_ERROR;
1178 }
1179
Gloria Wangd5770912010-06-22 13:55:38 -07001180 dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
Gloria Wangeab18ea2010-10-29 10:09:47 -07001181 if (mDecryptHandle != NULL
1182 && RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
1183 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
Gloria Wangd5770912010-06-22 13:55:38 -07001184 }
1185
Andreas Huberffdf4782010-02-09 14:05:43 -08001186 if (dataSource->flags() & DataSource::kWantsPrefetching) {
1187 mPrefetcher = new Prefetcher;
1188 }
1189
1190 return setDataSource_l(extractor);
1191}
1192
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001193void AwesomePlayer::abortPrepare(status_t err) {
1194 CHECK(err != OK);
1195
1196 if (mIsAsyncPrepare) {
1197 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1198 }
1199
1200 mPrepareResult = err;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001201 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001202 mAsyncPrepareEvent = NULL;
1203 mPreparedCondition.broadcast();
1204}
1205
Andreas Huberf71daba2010-03-24 09:24:40 -07001206// static
1207bool AwesomePlayer::ContinuePreparation(void *cookie) {
1208 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1209
1210 return (me->mFlags & PREPARE_CANCELLED) == 0;
1211}
1212
Andreas Huber6be780e2010-02-08 14:40:30 -08001213void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber55864df72010-03-08 12:28:22 -08001214 sp<Prefetcher> prefetcher;
1215
Andreas Huberffdf4782010-02-09 14:05:43 -08001216 {
1217 Mutex::Autolock autoLock(mLock);
1218
Andreas Huberedbb4d82010-03-12 08:59:22 -08001219 if (mFlags & PREPARE_CANCELLED) {
1220 LOGI("prepare was cancelled before doing anything");
1221 abortPrepare(UNKNOWN_ERROR);
1222 return;
1223 }
1224
Andreas Huberffdf4782010-02-09 14:05:43 -08001225 if (mUri.size() > 0) {
1226 status_t err = finishSetDataSource_l();
1227
1228 if (err != OK) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001229 abortPrepare(err);
Andreas Huberffdf4782010-02-09 14:05:43 -08001230 return;
1231 }
1232 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001233
Andreas Huber55864df72010-03-08 12:28:22 -08001234 if (mVideoTrack != NULL && mVideoSource == NULL) {
1235 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08001236
Andreas Huber55864df72010-03-08 12:28:22 -08001237 if (err != OK) {
1238 abortPrepare(err);
1239 return;
1240 }
1241 }
1242
1243 if (mAudioTrack != NULL && mAudioSource == NULL) {
1244 status_t err = initAudioDecoder();
1245
1246 if (err != OK) {
1247 abortPrepare(err);
1248 return;
1249 }
1250 }
1251
Andreas Huber6be780e2010-02-08 14:40:30 -08001252 prefetcher = mPrefetcher;
1253 }
1254
1255 if (prefetcher != NULL) {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001256 {
1257 Mutex::Autolock autoLock(mLock);
1258 if (mFlags & PREPARE_CANCELLED) {
1259 LOGI("prepare was cancelled before preparing the prefetcher");
Andreas Huber9b732de2010-03-23 15:30:57 -07001260
1261 prefetcher.clear();
Andreas Huberedbb4d82010-03-12 08:59:22 -08001262 abortPrepare(UNKNOWN_ERROR);
1263 return;
1264 }
1265 }
1266
1267 LOGI("calling prefetcher->prepare()");
Andreas Huberf71daba2010-03-24 09:24:40 -07001268 status_t result =
1269 prefetcher->prepare(&AwesomePlayer::ContinuePreparation, this);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001270
Andreas Huberba7ec912010-02-12 10:42:02 -08001271 prefetcher.clear();
Andreas Huberf71daba2010-03-24 09:24:40 -07001272
1273 if (result == OK) {
Andreas Huber252573c2010-03-26 10:17:17 -07001274 LOGI("prefetcher is done preparing");
Andreas Huberf71daba2010-03-24 09:24:40 -07001275 } else {
1276 Mutex::Autolock autoLock(mLock);
1277
1278 CHECK_EQ(result, -EINTR);
1279
1280 LOGI("prefetcher->prepare() was cancelled early.");
1281 abortPrepare(UNKNOWN_ERROR);
1282 return;
1283 }
Andreas Huber6be780e2010-02-08 14:40:30 -08001284 }
1285
1286 Mutex::Autolock autoLock(mLock);
1287
Andreas Huberffdf4782010-02-09 14:05:43 -08001288 if (mIsAsyncPrepare) {
1289 if (mVideoWidth < 0 || mVideoHeight < 0) {
1290 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1291 } else {
1292 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
1293 }
1294
1295 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08001296 }
1297
Andreas Huberffdf4782010-02-09 14:05:43 -08001298 mPrepareResult = OK;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001299 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huberffdf4782010-02-09 14:05:43 -08001300 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -08001301 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08001302 mPreparedCondition.broadcast();
Andreas Huber040301c2010-04-12 09:41:12 -07001303
1304 postBufferingEvent_l();
Andreas Huber6be780e2010-02-08 14:40:30 -08001305}
1306
Andreas Huberba7ec912010-02-12 10:42:02 -08001307status_t AwesomePlayer::suspend() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001308 LOGV("suspend");
Andreas Huberba7ec912010-02-12 10:42:02 -08001309 Mutex::Autolock autoLock(mLock);
1310
1311 if (mSuspensionState != NULL) {
Gloria Wangb19da8e2010-04-12 17:13:06 -07001312 if (mLastVideoBuffer == NULL) {
1313 //go into here if video is suspended again
1314 //after resuming without being played between
1315 //them
1316 SuspensionState *state = mSuspensionState;
1317 mSuspensionState = NULL;
1318 reset_l();
1319 mSuspensionState = state;
1320 return OK;
1321 }
1322
1323 delete mSuspensionState;
1324 mSuspensionState = NULL;
Andreas Huberba7ec912010-02-12 10:42:02 -08001325 }
1326
Andreas Huberedbb4d82010-03-12 08:59:22 -08001327 if (mFlags & PREPARING) {
1328 mFlags |= PREPARE_CANCELLED;
1329 if (mConnectingDataSource != NULL) {
1330 LOGI("interrupting the connection process");
1331 mConnectingDataSource->disconnect();
1332 }
1333 }
1334
Andreas Huberba7ec912010-02-12 10:42:02 -08001335 while (mFlags & PREPARING) {
1336 mPreparedCondition.wait(mLock);
1337 }
1338
1339 SuspensionState *state = new SuspensionState;
1340 state->mUri = mUri;
1341 state->mUriHeaders = mUriHeaders;
1342 state->mFileSource = mFileSource;
1343
Andreas Huber406a18b2010-02-18 16:45:13 -08001344 state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS);
Andreas Huber252573c2010-03-26 10:17:17 -07001345 getPosition(&state->mPositionUs);
Andreas Huberba7ec912010-02-12 10:42:02 -08001346
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001347 if (mLastVideoBuffer) {
1348 size_t size = mLastVideoBuffer->range_length();
1349 if (size) {
1350 state->mLastVideoFrameSize = size;
1351 state->mLastVideoFrame = malloc(size);
1352 memcpy(state->mLastVideoFrame,
1353 (const uint8_t *)mLastVideoBuffer->data()
1354 + mLastVideoBuffer->range_offset(),
1355 size);
1356
1357 state->mVideoWidth = mVideoWidth;
1358 state->mVideoHeight = mVideoHeight;
1359
1360 sp<MetaData> meta = mVideoSource->getFormat();
1361 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1362 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1363 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1364 }
1365 }
1366
Andreas Huberba7ec912010-02-12 10:42:02 -08001367 reset_l();
1368
1369 mSuspensionState = state;
1370
1371 return OK;
1372}
1373
1374status_t AwesomePlayer::resume() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001375 LOGV("resume");
Andreas Huberba7ec912010-02-12 10:42:02 -08001376 Mutex::Autolock autoLock(mLock);
1377
1378 if (mSuspensionState == NULL) {
1379 return INVALID_OPERATION;
1380 }
1381
1382 SuspensionState *state = mSuspensionState;
1383 mSuspensionState = NULL;
1384
1385 status_t err;
1386 if (state->mFileSource != NULL) {
1387 err = setDataSource_l(state->mFileSource);
1388
1389 if (err == OK) {
1390 mFileSource = state->mFileSource;
1391 }
1392 } else {
1393 err = setDataSource_l(state->mUri, &state->mUriHeaders);
1394 }
1395
1396 if (err != OK) {
1397 delete state;
1398 state = NULL;
1399
1400 return err;
1401 }
1402
1403 seekTo_l(state->mPositionUs);
1404
Andreas Huber406a18b2010-02-18 16:45:13 -08001405 mFlags = state->mFlags & (LOOPING | AT_EOS);
Andreas Huberba7ec912010-02-12 10:42:02 -08001406
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001407 if (state->mLastVideoFrame && mISurface != NULL) {
1408 mVideoRenderer =
1409 new AwesomeLocalRenderer(
1410 true, // previewOnly
1411 "",
1412 (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1413 mISurface,
1414 state->mVideoWidth,
1415 state->mVideoHeight,
1416 state->mDecodedWidth,
1417 state->mDecodedHeight);
1418
1419 mVideoRendererIsPreview = true;
1420
1421 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render(
1422 state->mLastVideoFrame, state->mLastVideoFrameSize);
1423 }
1424
Andreas Huberba7ec912010-02-12 10:42:02 -08001425 if (state->mFlags & PLAYING) {
1426 play_l();
1427 }
1428
Gloria Wangb19da8e2010-04-12 17:13:06 -07001429 mSuspensionState = state;
Andreas Huberba7ec912010-02-12 10:42:02 -08001430 state = NULL;
1431
1432 return OK;
1433}
1434
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001435uint32_t AwesomePlayer::flags() const {
1436 return mExtractorFlags;
1437}
1438
Andreas Huber27366fc2009-11-20 09:32:46 -08001439} // namespace android
1440