blob: 7bbc9ebc04e8cc6bb932738da11916e428bf9cc4 [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);
291 if (mDecryptHandle != NULL) {
292 if (RightsStatus::RIGHTS_VALID == mDecryptHandle->status) {
293 if (DecryptApiType::CONTAINER_BASED == mDecryptHandle->decryptApiType) {
294 mDrmManagerClient->consumeRights(mDecryptHandle, Action::PLAY, true);
295 }
296 } else {
297 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
298 }
299 }
300
Andreas Huber27366fc2009-11-20 09:32:46 -0800301 return setDataSource_l(extractor);
302}
303
304status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800305 bool haveAudio = false;
306 bool haveVideo = false;
307 for (size_t i = 0; i < extractor->countTracks(); ++i) {
308 sp<MetaData> meta = extractor->getTrackMetaData(i);
309
310 const char *mime;
311 CHECK(meta->findCString(kKeyMIMEType, &mime));
312
313 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800314 setVideoSource(extractor->getTrack(i));
315 haveVideo = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800316 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800317 setAudioSource(extractor->getTrack(i));
318 haveAudio = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800319 }
320
321 if (haveAudio && haveVideo) {
322 break;
323 }
324 }
325
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700326 if (!haveAudio && !haveVideo) {
327 return UNKNOWN_ERROR;
328 }
329
330 mExtractorFlags = extractor->flags();
Gloria Wangd5770912010-06-22 13:55:38 -0700331 if (mDecryptHandle != NULL) {
332 if (DecryptApiType::ELEMENTARY_STREAM_BASED == mDecryptHandle->decryptApiType) {
333 mDrmManagerClient->consumeRights(mDecryptHandle, Action::PLAY, true);
334 }
335 }
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700336
337 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800338}
339
340void AwesomePlayer::reset() {
341 Mutex::Autolock autoLock(mLock);
342 reset_l();
343}
344
345void AwesomePlayer::reset_l() {
Gloria Wangd5770912010-06-22 13:55:38 -0700346 if (mDecryptHandle != NULL) {
347 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
348 Playback::STOP, 0);
349 mDrmManagerClient->consumeRights(mDecryptHandle,
350 Action::PLAY, false);
351 mDecryptHandle = NULL;
352 mDrmManagerClient = NULL;
353 }
354
Andreas Huberedbb4d82010-03-12 08:59:22 -0800355 if (mFlags & PREPARING) {
356 mFlags |= PREPARE_CANCELLED;
357 if (mConnectingDataSource != NULL) {
358 LOGI("interrupting the connection process");
359 mConnectingDataSource->disconnect();
360 }
361 }
362
Andreas Huberffdf4782010-02-09 14:05:43 -0800363 while (mFlags & PREPARING) {
364 mPreparedCondition.wait(mLock);
365 }
366
Andreas Huber27366fc2009-11-20 09:32:46 -0800367 cancelPlayerEvents();
368
Andreas Huberba7ec912010-02-12 10:42:02 -0800369 if (mPrefetcher != NULL) {
370 CHECK_EQ(mPrefetcher->getStrongCount(), 1);
371 }
372 mPrefetcher.clear();
373
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800374 mAudioTrack.clear();
375 mVideoTrack.clear();
376
Andreas Huberba7ec912010-02-12 10:42:02 -0800377 // Shutdown audio first, so that the respone to the reset request
378 // appears to happen instantaneously as far as the user is concerned
379 // If we did this later, audio would continue playing while we
380 // shutdown the video-related resources and the player appear to
381 // not be as responsive to a reset request.
Andreas Huberedbb4d82010-03-12 08:59:22 -0800382 if (mAudioPlayer == NULL && mAudioSource != NULL) {
383 // If we had an audio player, it would have effectively
384 // taken possession of the audio source and stopped it when
385 // _it_ is stopped. Otherwise this is still our responsibility.
386 mAudioSource->stop();
387 }
Andreas Huberba7ec912010-02-12 10:42:02 -0800388 mAudioSource.clear();
389
390 if (mTimeSource != mAudioPlayer) {
391 delete mTimeSource;
392 }
393 mTimeSource = NULL;
394
395 delete mAudioPlayer;
396 mAudioPlayer = NULL;
397
Andreas Huber3522b5a52010-01-22 14:36:53 -0800398 mVideoRenderer.clear();
399
Andreas Huber27366fc2009-11-20 09:32:46 -0800400 if (mLastVideoBuffer) {
401 mLastVideoBuffer->release();
402 mLastVideoBuffer = NULL;
403 }
404
405 if (mVideoBuffer) {
406 mVideoBuffer->release();
407 mVideoBuffer = NULL;
408 }
409
410 if (mVideoSource != NULL) {
411 mVideoSource->stop();
Andreas Huber98b48de2010-01-29 10:10:22 -0800412
413 // The following hack is necessary to ensure that the OMX
414 // component is completely released by the time we may try
415 // to instantiate it again.
416 wp<MediaSource> tmp = mVideoSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800417 mVideoSource.clear();
Andreas Huber98b48de2010-01-29 10:10:22 -0800418 while (tmp.promote() != NULL) {
419 usleep(1000);
420 }
421 IPCThreadState::self()->flushCommands();
Andreas Huber27366fc2009-11-20 09:32:46 -0800422 }
423
Andreas Huber27366fc2009-11-20 09:32:46 -0800424 mDurationUs = -1;
425 mFlags = 0;
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700426 mExtractorFlags = 0;
Andreas Huber27366fc2009-11-20 09:32:46 -0800427 mVideoWidth = mVideoHeight = -1;
428 mTimeSourceDeltaUs = 0;
429 mVideoTimeUs = 0;
430
431 mSeeking = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700432 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800433 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800434
Andreas Huberffdf4782010-02-09 14:05:43 -0800435 mUri.setTo("");
436 mUriHeaders.clear();
Andreas Huberba7ec912010-02-12 10:42:02 -0800437
438 mFileSource.clear();
439
440 delete mSuspensionState;
441 mSuspensionState = NULL;
Andreas Huber27366fc2009-11-20 09:32:46 -0800442}
443
Andreas Huber6be780e2010-02-08 14:40:30 -0800444void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800445 if (mListener != NULL) {
446 sp<MediaPlayerBase> listener = mListener.promote();
447
448 if (listener != NULL) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800449 listener->sendEvent(msg, ext1, ext2);
Andreas Hubera3f43842010-01-21 10:28:45 -0800450 }
451 }
452}
453
Andreas Huberb9e63832010-01-26 16:20:10 -0800454void AwesomePlayer::onBufferingUpdate() {
455 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800456 if (!mBufferingEventPending) {
457 return;
458 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800459 mBufferingEventPending = false;
460
Andreas Huber252573c2010-03-26 10:17:17 -0700461 int64_t durationUs;
462 {
463 Mutex::Autolock autoLock(mMiscStateLock);
464 durationUs = mDurationUs;
465 }
466
467 if (durationUs >= 0) {
Andreas Huberb9e63832010-01-26 16:20:10 -0800468 int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs();
Andreas Huberdc9927d2010-03-08 15:46:13 -0800469
470 LOGV("cache holds %.2f secs worth of data.", cachedDurationUs / 1E6);
471
Andreas Huber252573c2010-03-26 10:17:17 -0700472 int64_t positionUs;
473 getPosition(&positionUs);
Andreas Huberb9e63832010-01-26 16:20:10 -0800474
475 cachedDurationUs += positionUs;
476
Andreas Huber252573c2010-03-26 10:17:17 -0700477 double percentage = (double)cachedDurationUs / durationUs;
Andreas Huberb9e63832010-01-26 16:20:10 -0800478 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
479
480 postBufferingEvent_l();
Andreas Huber040301c2010-04-12 09:41:12 -0700481 } else {
482 LOGE("Not sending buffering status because duration is unknown.");
Andreas Huberb9e63832010-01-26 16:20:10 -0800483 }
484}
485
Andreas Huber27366fc2009-11-20 09:32:46 -0800486void AwesomePlayer::onStreamDone() {
487 // Posted whenever any stream finishes playing.
488
489 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800490 if (!mStreamDoneEventPending) {
491 return;
492 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800493 mStreamDoneEventPending = false;
494
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800495 if (mStreamDoneStatus == ERROR_END_OF_STREAM && (mFlags & LOOPING)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800496 seekTo_l(0);
497
Andreas Huber7085b6842010-02-03 16:02:02 -0800498 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800499 postVideoEvent_l();
500 }
501 } else {
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800502 if (mStreamDoneStatus == ERROR_END_OF_STREAM) {
503 LOGV("MEDIA_PLAYBACK_COMPLETE");
504 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
505 } else {
506 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
507
508 notifyListener_l(
509 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
510 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800511
512 pause_l();
Andreas Huber406a18b2010-02-18 16:45:13 -0800513
514 mFlags |= AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800515 }
516}
517
518status_t AwesomePlayer::play() {
519 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800520 return play_l();
521}
Andreas Huber27366fc2009-11-20 09:32:46 -0800522
Andreas Huberba7ec912010-02-12 10:42:02 -0800523status_t AwesomePlayer::play_l() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800524 if (mFlags & PLAYING) {
525 return OK;
526 }
527
Andreas Huberffdf4782010-02-09 14:05:43 -0800528 if (!(mFlags & PREPARED)) {
529 status_t err = prepare_l();
530
531 if (err != OK) {
532 return err;
533 }
534 }
535
Andreas Huber27366fc2009-11-20 09:32:46 -0800536 mFlags |= PLAYING;
537 mFlags |= FIRST_FRAME;
538
Andreas Huberc1d5c922009-12-10 15:49:04 -0800539 bool deferredAudioSeek = false;
540
Andreas Huber27366fc2009-11-20 09:32:46 -0800541 if (mAudioSource != NULL) {
542 if (mAudioPlayer == NULL) {
543 if (mAudioSink != NULL) {
544 mAudioPlayer = new AudioPlayer(mAudioSink);
Andreas Huber27366fc2009-11-20 09:32:46 -0800545 mAudioPlayer->setSource(mAudioSource);
Andreas Huberdc9927d2010-03-08 15:46:13 -0800546
547 // We've already started the MediaSource in order to enable
548 // the prefetcher to read its data.
549 status_t err = mAudioPlayer->start(
550 true /* sourceAlreadyStarted */);
Andreas Huber62eac002010-01-29 13:24:58 -0800551
552 if (err != OK) {
553 delete mAudioPlayer;
554 mAudioPlayer = NULL;
555
556 mFlags &= ~(PLAYING | FIRST_FRAME);
557
558 return err;
559 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800560
561 delete mTimeSource;
562 mTimeSource = mAudioPlayer;
563
Andreas Huberc1d5c922009-12-10 15:49:04 -0800564 deferredAudioSeek = true;
Andreas Huber70d10c02010-02-03 11:37:29 -0800565
566 mWatchForAudioSeekComplete = false;
567 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800568 }
569 } else {
570 mAudioPlayer->resume();
571 }
Andreas Huber70d10c02010-02-03 11:37:29 -0800572
573 postCheckAudioStatusEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800574 }
575
576 if (mTimeSource == NULL && mAudioPlayer == NULL) {
577 mTimeSource = new SystemTimeSource;
578 }
579
580 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800581 // Kick off video playback
582 postVideoEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800583 }
584
Andreas Huberc1d5c922009-12-10 15:49:04 -0800585 if (deferredAudioSeek) {
586 // If there was a seek request while we were paused
587 // and we're just starting up again, honor the request now.
588 seekAudioIfNecessary_l();
589 }
590
Andreas Huber406a18b2010-02-18 16:45:13 -0800591 if (mFlags & AT_EOS) {
592 // Legacy behaviour, if a stream finishes playing and then
593 // is started again, we play from the start...
594 seekTo_l(0);
595 }
596
Gloria Wangd5770912010-06-22 13:55:38 -0700597 if (mDecryptHandle != NULL) {
598 int64_t position;
599 getPosition(&position);
600 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
601 Playback::START, position / 1000);
602 }
603
Andreas Huber27366fc2009-11-20 09:32:46 -0800604 return OK;
605}
606
607void AwesomePlayer::initRenderer_l() {
608 if (mISurface != NULL) {
609 sp<MetaData> meta = mVideoSource->getFormat();
610
611 int32_t format;
612 const char *component;
613 int32_t decodedWidth, decodedHeight;
614 CHECK(meta->findInt32(kKeyColorFormat, &format));
615 CHECK(meta->findCString(kKeyDecoderComponent, &component));
616 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
617 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
618
Andreas Hubera67d5382009-12-10 15:32:12 -0800619 mVideoRenderer.clear();
620
621 // Must ensure that mVideoRenderer's destructor is actually executed
622 // before creating a new one.
623 IPCThreadState::self()->flushCommands();
624
Andreas Huber1314e732009-12-14 14:18:22 -0800625 if (!strncmp("OMX.", component, 4)) {
626 // Our OMX codecs allocate buffers on the media_server side
627 // therefore they require a remote IOMXRenderer that knows how
628 // to display them.
629 mVideoRenderer = new AwesomeRemoteRenderer(
630 mClient.interface()->createRenderer(
631 mISurface, component,
632 (OMX_COLOR_FORMATTYPE)format,
633 decodedWidth, decodedHeight,
634 mVideoWidth, mVideoHeight));
635 } else {
636 // Other decoders are instantiated locally and as a consequence
637 // allocate their buffers in local address space.
638 mVideoRenderer = new AwesomeLocalRenderer(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800639 false, // previewOnly
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800640 component,
Andreas Huber1314e732009-12-14 14:18:22 -0800641 (OMX_COLOR_FORMATTYPE)format,
642 mISurface,
643 mVideoWidth, mVideoHeight,
644 decodedWidth, decodedHeight);
645 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800646 }
647}
648
649status_t AwesomePlayer::pause() {
650 Mutex::Autolock autoLock(mLock);
651 return pause_l();
652}
653
654status_t AwesomePlayer::pause_l() {
655 if (!(mFlags & PLAYING)) {
656 return OK;
657 }
658
Andreas Huberb9e63832010-01-26 16:20:10 -0800659 cancelPlayerEvents(true /* keepBufferingGoing */);
Andreas Huber27366fc2009-11-20 09:32:46 -0800660
661 if (mAudioPlayer != NULL) {
662 mAudioPlayer->pause();
663 }
664
665 mFlags &= ~PLAYING;
666
Gloria Wangd5770912010-06-22 13:55:38 -0700667 if (mDecryptHandle != NULL) {
668 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
669 Playback::PAUSE, 0);
670 }
671
Andreas Huber27366fc2009-11-20 09:32:46 -0800672 return OK;
673}
674
675bool AwesomePlayer::isPlaying() const {
Andreas Huber27366fc2009-11-20 09:32:46 -0800676 return mFlags & PLAYING;
677}
678
679void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
680 Mutex::Autolock autoLock(mLock);
681
682 mISurface = isurface;
683}
684
685void AwesomePlayer::setAudioSink(
686 const sp<MediaPlayerBase::AudioSink> &audioSink) {
687 Mutex::Autolock autoLock(mLock);
688
689 mAudioSink = audioSink;
690}
691
692status_t AwesomePlayer::setLooping(bool shouldLoop) {
693 Mutex::Autolock autoLock(mLock);
694
695 mFlags = mFlags & ~LOOPING;
696
697 if (shouldLoop) {
698 mFlags |= LOOPING;
699 }
700
701 return OK;
702}
703
704status_t AwesomePlayer::getDuration(int64_t *durationUs) {
Andreas Huber252573c2010-03-26 10:17:17 -0700705 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800706
707 if (mDurationUs < 0) {
708 return UNKNOWN_ERROR;
709 }
710
711 *durationUs = mDurationUs;
712
713 return OK;
714}
715
716status_t AwesomePlayer::getPosition(int64_t *positionUs) {
Andreas Huberddb709c2010-04-07 10:24:35 -0700717 if (mSeeking) {
718 *positionUs = mSeekTimeUs;
719 } else if (mVideoSource != NULL) {
Andreas Huber252573c2010-03-26 10:17:17 -0700720 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800721 *positionUs = mVideoTimeUs;
722 } else if (mAudioPlayer != NULL) {
723 *positionUs = mAudioPlayer->getMediaTimeUs();
724 } else {
725 *positionUs = 0;
726 }
727
728 return OK;
729}
730
731status_t AwesomePlayer::seekTo(int64_t timeUs) {
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700732 if (mExtractorFlags
733 & (MediaExtractor::CAN_SEEK_FORWARD
734 | MediaExtractor::CAN_SEEK_BACKWARD)) {
735 Mutex::Autolock autoLock(mLock);
736 return seekTo_l(timeUs);
737 }
738
739 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800740}
741
742status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
743 mSeeking = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700744 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800745 mSeekTimeUs = timeUs;
Andreas Huber406a18b2010-02-18 16:45:13 -0800746 mFlags &= ~AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800747
748 seekAudioIfNecessary_l();
749
Andreas Huber8e2b9412010-03-31 09:40:15 -0700750 if (!(mFlags & PLAYING)) {
751 LOGV("seeking while paused, sending SEEK_COMPLETE notification"
752 " immediately.");
753
754 notifyListener_l(MEDIA_SEEK_COMPLETE);
755 mSeekNotificationSent = true;
756 }
757
Andreas Huber27366fc2009-11-20 09:32:46 -0800758 return OK;
759}
760
761void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Huber7085b6842010-02-03 16:02:02 -0800762 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800763 mAudioPlayer->seekTo(mSeekTimeUs);
764
Andreas Huber70d10c02010-02-03 11:37:29 -0800765 mWatchForAudioSeekComplete = true;
766 mWatchForAudioEOS = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700767 mSeekNotificationSent = false;
Gloria Wangd5770912010-06-22 13:55:38 -0700768
769 if (mDecryptHandle != NULL) {
770 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
771 Playback::PAUSE, 0);
772 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
773 Playback::START, mSeekTimeUs / 1000);
774 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800775 }
776}
777
778status_t AwesomePlayer::getVideoDimensions(
779 int32_t *width, int32_t *height) const {
780 Mutex::Autolock autoLock(mLock);
781
782 if (mVideoWidth < 0 || mVideoHeight < 0) {
783 return UNKNOWN_ERROR;
784 }
785
786 *width = mVideoWidth;
787 *height = mVideoHeight;
788
789 return OK;
790}
791
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800792void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
793 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800794
Andreas Huberb9e63832010-01-26 16:20:10 -0800795 if (mPrefetcher != NULL) {
796 source = mPrefetcher->addSource(source);
797 }
798
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800799 mAudioTrack = source;
800}
801
802status_t AwesomePlayer::initAudioDecoder() {
803 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huberc79827a2010-01-05 10:54:55 -0800804
805 const char *mime;
806 CHECK(meta->findCString(kKeyMIMEType, &mime));
807
808 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800809 mAudioSource = mAudioTrack;
Andreas Huberc79827a2010-01-05 10:54:55 -0800810 } else {
811 mAudioSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800812 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huberc79827a2010-01-05 10:54:55 -0800813 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800814 mAudioTrack);
Andreas Huberc79827a2010-01-05 10:54:55 -0800815 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800816
817 if (mAudioSource != NULL) {
818 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800819 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -0700820 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800821 if (mDurationUs < 0 || durationUs > mDurationUs) {
822 mDurationUs = durationUs;
823 }
824 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800825
Andreas Huber3c78a1b2010-05-13 09:15:21 -0700826 status_t err = mAudioSource->start();
827
828 if (err != OK) {
829 mAudioSource.clear();
830 return err;
831 }
Andreas Huberd0332ad2010-04-12 16:05:57 -0700832 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
833 // For legacy reasons we're simply going to ignore the absence
834 // of an audio decoder for QCELP instead of aborting playback
835 // altogether.
836 return OK;
837 }
Andreas Huberdc9927d2010-03-08 15:46:13 -0800838
Andreas Huber27366fc2009-11-20 09:32:46 -0800839 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
840}
841
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800842void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
843 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800844
Andreas Huberb9e63832010-01-26 16:20:10 -0800845 if (mPrefetcher != NULL) {
846 source = mPrefetcher->addSource(source);
847 }
848
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800849 mVideoTrack = source;
850}
851
852status_t AwesomePlayer::initVideoDecoder() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800853 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800854 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -0800855 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800856 mVideoTrack);
Andreas Huber27366fc2009-11-20 09:32:46 -0800857
858 if (mVideoSource != NULL) {
859 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800860 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -0700861 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800862 if (mDurationUs < 0 || durationUs > mDurationUs) {
863 mDurationUs = durationUs;
864 }
865 }
866
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800867 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
868 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
Andreas Huber27366fc2009-11-20 09:32:46 -0800869
Andreas Huber1919e5a2010-05-20 10:37:06 -0700870 status_t err = mVideoSource->start();
871
872 if (err != OK) {
873 mVideoSource.clear();
874 return err;
875 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800876 }
877
878 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
879}
880
Andreas Huber6be780e2010-02-08 14:40:30 -0800881void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800882 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800883 if (!mVideoEventPending) {
884 // The event has been cancelled in reset_l() but had already
885 // been scheduled for execution at that time.
886 return;
887 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800888 mVideoEventPending = false;
889
890 if (mSeeking) {
891 if (mLastVideoBuffer) {
892 mLastVideoBuffer->release();
893 mLastVideoBuffer = NULL;
894 }
895
896 if (mVideoBuffer) {
897 mVideoBuffer->release();
898 mVideoBuffer = NULL;
899 }
900 }
901
902 if (!mVideoBuffer) {
903 MediaSource::ReadOptions options;
904 if (mSeeking) {
905 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
906
907 options.setSeekTo(mSeekTimeUs);
908 }
909 for (;;) {
910 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -0800911 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -0800912
913 if (err != OK) {
914 CHECK_EQ(mVideoBuffer, NULL);
915
916 if (err == INFO_FORMAT_CHANGED) {
917 LOGV("VideoSource signalled format change.");
918
Andreas Huber7085b6842010-02-03 16:02:02 -0800919 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800920 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -0800921 initRenderer_l();
922 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800923 continue;
924 }
925
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800926 postStreamDoneEvent_l(err);
Andreas Huber27366fc2009-11-20 09:32:46 -0800927 return;
928 }
929
Andreas Hubera67d5382009-12-10 15:32:12 -0800930 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -0800931 // Some decoders, notably the PV AVC software decoder
932 // return spurious empty buffers that we just want to ignore.
933
Andreas Hubera67d5382009-12-10 15:32:12 -0800934 mVideoBuffer->release();
935 mVideoBuffer = NULL;
936 continue;
937 }
938
Andreas Huber27366fc2009-11-20 09:32:46 -0800939 break;
940 }
941 }
942
943 int64_t timeUs;
944 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
945
Andreas Huber252573c2010-03-26 10:17:17 -0700946 {
947 Mutex::Autolock autoLock(mMiscStateLock);
948 mVideoTimeUs = timeUs;
949 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800950
951 if (mSeeking) {
952 if (mAudioPlayer != NULL) {
953 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
954
955 mAudioPlayer->seekTo(timeUs);
Andreas Huber70d10c02010-02-03 11:37:29 -0800956 mWatchForAudioSeekComplete = true;
957 mWatchForAudioEOS = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700958 } else if (!mSeekNotificationSent) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800959 // If we're playing video only, report seek complete now,
960 // otherwise audio player will notify us later.
Andreas Hubera3f43842010-01-21 10:28:45 -0800961 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800962 }
963
964 mFlags |= FIRST_FRAME;
965 mSeeking = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700966 mSeekNotificationSent = false;
Gloria Wangd5770912010-06-22 13:55:38 -0700967
968 if (mDecryptHandle != NULL) {
969 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
970 Playback::PAUSE, 0);
971 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
972 Playback::START, timeUs / 1000);
973 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800974 }
975
976 if (mFlags & FIRST_FRAME) {
977 mFlags &= ~FIRST_FRAME;
978
979 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
980 }
981
982 int64_t realTimeUs, mediaTimeUs;
983 if (mAudioPlayer != NULL
984 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
985 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
986 }
987
988 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
989
990 int64_t latenessUs = nowUs - timeUs;
991
Andreas Huber24b0a952009-11-23 14:02:00 -0800992 if (latenessUs > 40000) {
993 // We're more than 40ms late.
Andreas Huber4a9375e2010-02-09 11:54:33 -0800994 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -0800995
996 mVideoBuffer->release();
997 mVideoBuffer = NULL;
998
999 postVideoEvent_l();
1000 return;
1001 }
1002
1003 if (latenessUs < -10000) {
1004 // We're more than 10ms early.
1005
1006 postVideoEvent_l(10000);
1007 return;
1008 }
1009
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001010 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
1011 mVideoRendererIsPreview = false;
1012
Andreas Huber7085b6842010-02-03 16:02:02 -08001013 initRenderer_l();
1014 }
1015
1016 if (mVideoRenderer != NULL) {
1017 mVideoRenderer->render(mVideoBuffer);
1018 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001019
1020 if (mLastVideoBuffer) {
1021 mLastVideoBuffer->release();
1022 mLastVideoBuffer = NULL;
1023 }
1024 mLastVideoBuffer = mVideoBuffer;
1025 mVideoBuffer = NULL;
1026
1027 postVideoEvent_l();
1028}
1029
1030void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1031 if (mVideoEventPending) {
1032 return;
1033 }
1034
1035 mVideoEventPending = true;
1036 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1037}
1038
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001039void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001040 if (mStreamDoneEventPending) {
1041 return;
1042 }
1043 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001044
1045 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -08001046 mQueue.postEvent(mStreamDoneEvent);
1047}
1048
Andreas Huberb9e63832010-01-26 16:20:10 -08001049void AwesomePlayer::postBufferingEvent_l() {
1050 if (mPrefetcher == NULL) {
1051 return;
1052 }
1053
1054 if (mBufferingEventPending) {
1055 return;
1056 }
1057 mBufferingEventPending = true;
1058 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1059}
1060
Andreas Huber70d10c02010-02-03 11:37:29 -08001061void AwesomePlayer::postCheckAudioStatusEvent_l() {
1062 if (mAudioStatusEventPending) {
1063 return;
1064 }
1065 mAudioStatusEventPending = true;
1066 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
1067}
1068
1069void AwesomePlayer::onCheckAudioStatus() {
1070 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -08001071 if (!mAudioStatusEventPending) {
1072 // Event was dispatched and while we were blocking on the mutex,
1073 // has already been cancelled.
1074 return;
1075 }
1076
Andreas Huber70d10c02010-02-03 11:37:29 -08001077 mAudioStatusEventPending = false;
1078
1079 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1080 mWatchForAudioSeekComplete = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001081
1082 if (!mSeekNotificationSent) {
1083 notifyListener_l(MEDIA_SEEK_COMPLETE);
1084 mSeekNotificationSent = true;
1085 }
Andreas Huberddb709c2010-04-07 10:24:35 -07001086
1087 mSeeking = false;
Andreas Huber70d10c02010-02-03 11:37:29 -08001088 }
1089
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001090 status_t finalStatus;
1091 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -08001092 mWatchForAudioEOS = false;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001093 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -08001094 }
1095
1096 postCheckAudioStatusEvent_l();
1097}
1098
Andreas Huber6be780e2010-02-08 14:40:30 -08001099status_t AwesomePlayer::prepare() {
1100 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001101 return prepare_l();
1102}
Andreas Huber6be780e2010-02-08 14:40:30 -08001103
Andreas Huberffdf4782010-02-09 14:05:43 -08001104status_t AwesomePlayer::prepare_l() {
1105 if (mFlags & PREPARED) {
1106 return OK;
1107 }
1108
1109 if (mFlags & PREPARING) {
1110 return UNKNOWN_ERROR;
1111 }
1112
1113 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -08001114 status_t err = prepareAsync_l();
1115
1116 if (err != OK) {
1117 return err;
1118 }
1119
Andreas Huberffdf4782010-02-09 14:05:43 -08001120 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001121 mPreparedCondition.wait(mLock);
1122 }
1123
Andreas Huberffdf4782010-02-09 14:05:43 -08001124 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001125}
1126
1127status_t AwesomePlayer::prepareAsync() {
1128 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001129
1130 if (mFlags & PREPARING) {
1131 return UNKNOWN_ERROR; // async prepare already pending
1132 }
1133
1134 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001135 return prepareAsync_l();
1136}
1137
1138status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001139 if (mFlags & PREPARING) {
1140 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001141 }
1142
Andreas Huber406a18b2010-02-18 16:45:13 -08001143 if (!mQueueStarted) {
1144 mQueue.start();
1145 mQueueStarted = true;
1146 }
1147
Andreas Huberffdf4782010-02-09 14:05:43 -08001148 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -08001149 mAsyncPrepareEvent = new AwesomeEvent(
1150 this, &AwesomePlayer::onPrepareAsyncEvent);
1151
1152 mQueue.postEvent(mAsyncPrepareEvent);
1153
1154 return OK;
1155}
1156
Andreas Huberffdf4782010-02-09 14:05:43 -08001157status_t AwesomePlayer::finishSetDataSource_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001158 sp<DataSource> dataSource;
1159
1160 if (!strncasecmp("http://", mUri.string(), 7)) {
1161 mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders);
1162
1163 mLock.unlock();
1164 status_t err = mConnectingDataSource->connect();
1165 mLock.lock();
1166
1167 if (err != OK) {
1168 mConnectingDataSource.clear();
1169
1170 LOGI("mConnectingDataSource->connect() returned %d", err);
1171 return err;
1172 }
1173
1174 dataSource = new CachingDataSource(
Andreas Hubera51250b2010-04-08 07:51:20 -07001175 mConnectingDataSource, 64 * 1024, 10);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001176
1177 mConnectingDataSource.clear();
1178 } else {
1179 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1180 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001181
1182 if (dataSource == NULL) {
1183 return UNKNOWN_ERROR;
1184 }
1185
1186 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1187
1188 if (extractor == NULL) {
1189 return UNKNOWN_ERROR;
1190 }
1191
Gloria Wangd5770912010-06-22 13:55:38 -07001192 dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
1193 if (mDecryptHandle != NULL) {
1194 if (RightsStatus::RIGHTS_VALID == mDecryptHandle->status) {
1195 if (DecryptApiType::CONTAINER_BASED == mDecryptHandle->decryptApiType) {
1196 mDrmManagerClient->consumeRights(mDecryptHandle, Action::PLAY, true);
1197 }
1198 } else {
1199 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
1200 }
1201 }
1202
Andreas Huberffdf4782010-02-09 14:05:43 -08001203 if (dataSource->flags() & DataSource::kWantsPrefetching) {
1204 mPrefetcher = new Prefetcher;
1205 }
1206
1207 return setDataSource_l(extractor);
1208}
1209
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001210void AwesomePlayer::abortPrepare(status_t err) {
1211 CHECK(err != OK);
1212
1213 if (mIsAsyncPrepare) {
1214 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1215 }
1216
1217 mPrepareResult = err;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001218 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001219 mAsyncPrepareEvent = NULL;
1220 mPreparedCondition.broadcast();
1221}
1222
Andreas Huberf71daba2010-03-24 09:24:40 -07001223// static
1224bool AwesomePlayer::ContinuePreparation(void *cookie) {
1225 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1226
1227 return (me->mFlags & PREPARE_CANCELLED) == 0;
1228}
1229
Andreas Huber6be780e2010-02-08 14:40:30 -08001230void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber55864df72010-03-08 12:28:22 -08001231 sp<Prefetcher> prefetcher;
1232
Andreas Huberffdf4782010-02-09 14:05:43 -08001233 {
1234 Mutex::Autolock autoLock(mLock);
1235
Andreas Huberedbb4d82010-03-12 08:59:22 -08001236 if (mFlags & PREPARE_CANCELLED) {
1237 LOGI("prepare was cancelled before doing anything");
1238 abortPrepare(UNKNOWN_ERROR);
1239 return;
1240 }
1241
Andreas Huberffdf4782010-02-09 14:05:43 -08001242 if (mUri.size() > 0) {
1243 status_t err = finishSetDataSource_l();
1244
1245 if (err != OK) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001246 abortPrepare(err);
Andreas Huberffdf4782010-02-09 14:05:43 -08001247 return;
1248 }
1249 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001250
Andreas Huber55864df72010-03-08 12:28:22 -08001251 if (mVideoTrack != NULL && mVideoSource == NULL) {
1252 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08001253
Andreas Huber55864df72010-03-08 12:28:22 -08001254 if (err != OK) {
1255 abortPrepare(err);
1256 return;
1257 }
1258 }
1259
1260 if (mAudioTrack != NULL && mAudioSource == NULL) {
1261 status_t err = initAudioDecoder();
1262
1263 if (err != OK) {
1264 abortPrepare(err);
1265 return;
1266 }
1267 }
1268
Andreas Huber6be780e2010-02-08 14:40:30 -08001269 prefetcher = mPrefetcher;
1270 }
1271
1272 if (prefetcher != NULL) {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001273 {
1274 Mutex::Autolock autoLock(mLock);
1275 if (mFlags & PREPARE_CANCELLED) {
1276 LOGI("prepare was cancelled before preparing the prefetcher");
Andreas Huber9b732de2010-03-23 15:30:57 -07001277
1278 prefetcher.clear();
Andreas Huberedbb4d82010-03-12 08:59:22 -08001279 abortPrepare(UNKNOWN_ERROR);
1280 return;
1281 }
1282 }
1283
1284 LOGI("calling prefetcher->prepare()");
Andreas Huberf71daba2010-03-24 09:24:40 -07001285 status_t result =
1286 prefetcher->prepare(&AwesomePlayer::ContinuePreparation, this);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001287
Andreas Huberba7ec912010-02-12 10:42:02 -08001288 prefetcher.clear();
Andreas Huberf71daba2010-03-24 09:24:40 -07001289
1290 if (result == OK) {
Andreas Huber252573c2010-03-26 10:17:17 -07001291 LOGI("prefetcher is done preparing");
Andreas Huberf71daba2010-03-24 09:24:40 -07001292 } else {
1293 Mutex::Autolock autoLock(mLock);
1294
1295 CHECK_EQ(result, -EINTR);
1296
1297 LOGI("prefetcher->prepare() was cancelled early.");
1298 abortPrepare(UNKNOWN_ERROR);
1299 return;
1300 }
Andreas Huber6be780e2010-02-08 14:40:30 -08001301 }
1302
1303 Mutex::Autolock autoLock(mLock);
1304
Andreas Huberffdf4782010-02-09 14:05:43 -08001305 if (mIsAsyncPrepare) {
1306 if (mVideoWidth < 0 || mVideoHeight < 0) {
1307 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1308 } else {
1309 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
1310 }
1311
1312 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08001313 }
1314
Andreas Huberffdf4782010-02-09 14:05:43 -08001315 mPrepareResult = OK;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001316 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huberffdf4782010-02-09 14:05:43 -08001317 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -08001318 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08001319 mPreparedCondition.broadcast();
Andreas Huber040301c2010-04-12 09:41:12 -07001320
1321 postBufferingEvent_l();
Andreas Huber6be780e2010-02-08 14:40:30 -08001322}
1323
Andreas Huberba7ec912010-02-12 10:42:02 -08001324status_t AwesomePlayer::suspend() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001325 LOGV("suspend");
Andreas Huberba7ec912010-02-12 10:42:02 -08001326 Mutex::Autolock autoLock(mLock);
1327
1328 if (mSuspensionState != NULL) {
Gloria Wangb19da8e2010-04-12 17:13:06 -07001329 if (mLastVideoBuffer == NULL) {
1330 //go into here if video is suspended again
1331 //after resuming without being played between
1332 //them
1333 SuspensionState *state = mSuspensionState;
1334 mSuspensionState = NULL;
1335 reset_l();
1336 mSuspensionState = state;
1337 return OK;
1338 }
1339
1340 delete mSuspensionState;
1341 mSuspensionState = NULL;
Andreas Huberba7ec912010-02-12 10:42:02 -08001342 }
1343
Andreas Huberedbb4d82010-03-12 08:59:22 -08001344 if (mFlags & PREPARING) {
1345 mFlags |= PREPARE_CANCELLED;
1346 if (mConnectingDataSource != NULL) {
1347 LOGI("interrupting the connection process");
1348 mConnectingDataSource->disconnect();
1349 }
1350 }
1351
Andreas Huberba7ec912010-02-12 10:42:02 -08001352 while (mFlags & PREPARING) {
1353 mPreparedCondition.wait(mLock);
1354 }
1355
1356 SuspensionState *state = new SuspensionState;
1357 state->mUri = mUri;
1358 state->mUriHeaders = mUriHeaders;
1359 state->mFileSource = mFileSource;
1360
Andreas Huber406a18b2010-02-18 16:45:13 -08001361 state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS);
Andreas Huber252573c2010-03-26 10:17:17 -07001362 getPosition(&state->mPositionUs);
Andreas Huberba7ec912010-02-12 10:42:02 -08001363
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001364 if (mLastVideoBuffer) {
1365 size_t size = mLastVideoBuffer->range_length();
1366 if (size) {
1367 state->mLastVideoFrameSize = size;
1368 state->mLastVideoFrame = malloc(size);
1369 memcpy(state->mLastVideoFrame,
1370 (const uint8_t *)mLastVideoBuffer->data()
1371 + mLastVideoBuffer->range_offset(),
1372 size);
1373
1374 state->mVideoWidth = mVideoWidth;
1375 state->mVideoHeight = mVideoHeight;
1376
1377 sp<MetaData> meta = mVideoSource->getFormat();
1378 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1379 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1380 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1381 }
1382 }
1383
Andreas Huberba7ec912010-02-12 10:42:02 -08001384 reset_l();
1385
1386 mSuspensionState = state;
1387
1388 return OK;
1389}
1390
1391status_t AwesomePlayer::resume() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001392 LOGV("resume");
Andreas Huberba7ec912010-02-12 10:42:02 -08001393 Mutex::Autolock autoLock(mLock);
1394
1395 if (mSuspensionState == NULL) {
1396 return INVALID_OPERATION;
1397 }
1398
1399 SuspensionState *state = mSuspensionState;
1400 mSuspensionState = NULL;
1401
1402 status_t err;
1403 if (state->mFileSource != NULL) {
1404 err = setDataSource_l(state->mFileSource);
1405
1406 if (err == OK) {
1407 mFileSource = state->mFileSource;
1408 }
1409 } else {
1410 err = setDataSource_l(state->mUri, &state->mUriHeaders);
1411 }
1412
1413 if (err != OK) {
1414 delete state;
1415 state = NULL;
1416
1417 return err;
1418 }
1419
1420 seekTo_l(state->mPositionUs);
1421
Andreas Huber406a18b2010-02-18 16:45:13 -08001422 mFlags = state->mFlags & (LOOPING | AT_EOS);
Andreas Huberba7ec912010-02-12 10:42:02 -08001423
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001424 if (state->mLastVideoFrame && mISurface != NULL) {
1425 mVideoRenderer =
1426 new AwesomeLocalRenderer(
1427 true, // previewOnly
1428 "",
1429 (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1430 mISurface,
1431 state->mVideoWidth,
1432 state->mVideoHeight,
1433 state->mDecodedWidth,
1434 state->mDecodedHeight);
1435
1436 mVideoRendererIsPreview = true;
1437
1438 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render(
1439 state->mLastVideoFrame, state->mLastVideoFrameSize);
1440 }
1441
Andreas Huberba7ec912010-02-12 10:42:02 -08001442 if (state->mFlags & PLAYING) {
1443 play_l();
1444 }
1445
Gloria Wangb19da8e2010-04-12 17:13:06 -07001446 mSuspensionState = state;
Andreas Huberba7ec912010-02-12 10:42:02 -08001447 state = NULL;
1448
1449 return OK;
1450}
1451
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001452uint32_t AwesomePlayer::flags() const {
1453 return mExtractorFlags;
1454}
1455
Andreas Huber27366fc2009-11-20 09:32:46 -08001456} // namespace android
1457