blob: 475160eeb45c7091d410508f6a8d679d3775a818 [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),
190 mSuspensionState(NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800191 CHECK_EQ(mClient.connect(), OK);
192
193 DataSource::RegisterDefaultSniffers();
194
Andreas Huber6be780e2010-02-08 14:40:30 -0800195 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
Andreas Huber27366fc2009-11-20 09:32:46 -0800196 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800197 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
Andreas Huber27366fc2009-11-20 09:32:46 -0800198 mStreamDoneEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800199 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
Andreas Huberb9e63832010-01-26 16:20:10 -0800200 mBufferingEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800201
202 mCheckAudioStatusEvent = new AwesomeEvent(
203 this, &AwesomePlayer::onCheckAudioStatus);
204
Andreas Huber70d10c02010-02-03 11:37:29 -0800205 mAudioStatusEventPending = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800206
Andreas Huber27366fc2009-11-20 09:32:46 -0800207 reset();
208}
209
210AwesomePlayer::~AwesomePlayer() {
Andreas Huber406a18b2010-02-18 16:45:13 -0800211 if (mQueueStarted) {
212 mQueue.stop();
213 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800214
215 reset();
216
217 mClient.disconnect();
218}
219
Andreas Huberb9e63832010-01-26 16:20:10 -0800220void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800221 mQueue.cancelEvent(mVideoEvent->eventID());
222 mVideoEventPending = false;
223 mQueue.cancelEvent(mStreamDoneEvent->eventID());
224 mStreamDoneEventPending = false;
Andreas Huber70d10c02010-02-03 11:37:29 -0800225 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
226 mAudioStatusEventPending = false;
Andreas Huberb9e63832010-01-26 16:20:10 -0800227
228 if (!keepBufferingGoing) {
229 mQueue.cancelEvent(mBufferingEvent->eventID());
230 mBufferingEventPending = false;
231 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800232}
233
Andreas Hubera3f43842010-01-21 10:28:45 -0800234void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800235 Mutex::Autolock autoLock(mLock);
236 mListener = listener;
237}
238
Andreas Huber433c9ac2010-01-27 16:49:05 -0800239status_t AwesomePlayer::setDataSource(
240 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800241 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800242 return setDataSource_l(uri, headers);
243}
Andreas Huber27366fc2009-11-20 09:32:46 -0800244
Andreas Huberba7ec912010-02-12 10:42:02 -0800245status_t AwesomePlayer::setDataSource_l(
246 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800247 reset_l();
248
Andreas Huberffdf4782010-02-09 14:05:43 -0800249 mUri = uri;
Andreas Huberb9e63832010-01-26 16:20:10 -0800250
Andreas Huberffdf4782010-02-09 14:05:43 -0800251 if (headers) {
252 mUriHeaders = *headers;
Andreas Huberb9e63832010-01-26 16:20:10 -0800253 }
254
Andreas Huberffdf4782010-02-09 14:05:43 -0800255 // The actual work will be done during preparation in the call to
256 // ::finishSetDataSource_l to avoid blocking the calling thread in
257 // setDataSource for any significant time.
Andreas Huber27366fc2009-11-20 09:32:46 -0800258
Andreas Huberffdf4782010-02-09 14:05:43 -0800259 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800260}
261
262status_t AwesomePlayer::setDataSource(
263 int fd, int64_t offset, int64_t length) {
264 Mutex::Autolock autoLock(mLock);
265
266 reset_l();
267
Andreas Huberba7ec912010-02-12 10:42:02 -0800268 sp<DataSource> dataSource = new FileSource(fd, offset, length);
Andreas Huber27366fc2009-11-20 09:32:46 -0800269
Andreas Huberba7ec912010-02-12 10:42:02 -0800270 status_t err = dataSource->initCheck();
Andreas Huber27366fc2009-11-20 09:32:46 -0800271
272 if (err != OK) {
273 return err;
274 }
275
Andreas Huberba7ec912010-02-12 10:42:02 -0800276 mFileSource = dataSource;
277
278 return setDataSource_l(dataSource);
279}
280
281status_t AwesomePlayer::setDataSource_l(
282 const sp<DataSource> &dataSource) {
283 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
Andreas Huber27366fc2009-11-20 09:32:46 -0800284
285 if (extractor == NULL) {
286 return UNKNOWN_ERROR;
287 }
288
289 return setDataSource_l(extractor);
290}
291
292status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800293 bool haveAudio = false;
294 bool haveVideo = false;
295 for (size_t i = 0; i < extractor->countTracks(); ++i) {
296 sp<MetaData> meta = extractor->getTrackMetaData(i);
297
298 const char *mime;
299 CHECK(meta->findCString(kKeyMIMEType, &mime));
300
301 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800302 setVideoSource(extractor->getTrack(i));
303 haveVideo = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800304 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800305 setAudioSource(extractor->getTrack(i));
306 haveAudio = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800307 }
308
309 if (haveAudio && haveVideo) {
310 break;
311 }
312 }
313
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700314 if (!haveAudio && !haveVideo) {
315 return UNKNOWN_ERROR;
316 }
317
318 mExtractorFlags = extractor->flags();
319
320 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800321}
322
323void AwesomePlayer::reset() {
324 Mutex::Autolock autoLock(mLock);
325 reset_l();
326}
327
328void AwesomePlayer::reset_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -0800329 if (mFlags & PREPARING) {
330 mFlags |= PREPARE_CANCELLED;
331 if (mConnectingDataSource != NULL) {
332 LOGI("interrupting the connection process");
333 mConnectingDataSource->disconnect();
334 }
335 }
336
Andreas Huberffdf4782010-02-09 14:05:43 -0800337 while (mFlags & PREPARING) {
338 mPreparedCondition.wait(mLock);
339 }
340
Andreas Huber27366fc2009-11-20 09:32:46 -0800341 cancelPlayerEvents();
342
Andreas Huberba7ec912010-02-12 10:42:02 -0800343 if (mPrefetcher != NULL) {
344 CHECK_EQ(mPrefetcher->getStrongCount(), 1);
345 }
346 mPrefetcher.clear();
347
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800348 mAudioTrack.clear();
349 mVideoTrack.clear();
350
Andreas Huberba7ec912010-02-12 10:42:02 -0800351 // Shutdown audio first, so that the respone to the reset request
352 // appears to happen instantaneously as far as the user is concerned
353 // If we did this later, audio would continue playing while we
354 // shutdown the video-related resources and the player appear to
355 // not be as responsive to a reset request.
Andreas Huberedbb4d82010-03-12 08:59:22 -0800356 if (mAudioPlayer == NULL && mAudioSource != NULL) {
357 // If we had an audio player, it would have effectively
358 // taken possession of the audio source and stopped it when
359 // _it_ is stopped. Otherwise this is still our responsibility.
360 mAudioSource->stop();
361 }
Andreas Huberba7ec912010-02-12 10:42:02 -0800362 mAudioSource.clear();
363
364 if (mTimeSource != mAudioPlayer) {
365 delete mTimeSource;
366 }
367 mTimeSource = NULL;
368
369 delete mAudioPlayer;
370 mAudioPlayer = NULL;
371
Andreas Huber3522b5a52010-01-22 14:36:53 -0800372 mVideoRenderer.clear();
373
Andreas Huber27366fc2009-11-20 09:32:46 -0800374 if (mLastVideoBuffer) {
375 mLastVideoBuffer->release();
376 mLastVideoBuffer = NULL;
377 }
378
379 if (mVideoBuffer) {
380 mVideoBuffer->release();
381 mVideoBuffer = NULL;
382 }
383
384 if (mVideoSource != NULL) {
385 mVideoSource->stop();
Andreas Huber98b48de2010-01-29 10:10:22 -0800386
387 // The following hack is necessary to ensure that the OMX
388 // component is completely released by the time we may try
389 // to instantiate it again.
390 wp<MediaSource> tmp = mVideoSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800391 mVideoSource.clear();
Andreas Huber98b48de2010-01-29 10:10:22 -0800392 while (tmp.promote() != NULL) {
393 usleep(1000);
394 }
395 IPCThreadState::self()->flushCommands();
Andreas Huber27366fc2009-11-20 09:32:46 -0800396 }
397
Andreas Huber27366fc2009-11-20 09:32:46 -0800398 mDurationUs = -1;
399 mFlags = 0;
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700400 mExtractorFlags = 0;
Andreas Huber27366fc2009-11-20 09:32:46 -0800401 mVideoWidth = mVideoHeight = -1;
402 mTimeSourceDeltaUs = 0;
403 mVideoTimeUs = 0;
404
405 mSeeking = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700406 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800407 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800408
Andreas Huberffdf4782010-02-09 14:05:43 -0800409 mUri.setTo("");
410 mUriHeaders.clear();
Andreas Huberba7ec912010-02-12 10:42:02 -0800411
412 mFileSource.clear();
413
414 delete mSuspensionState;
415 mSuspensionState = NULL;
Andreas Huber27366fc2009-11-20 09:32:46 -0800416}
417
Andreas Huber6be780e2010-02-08 14:40:30 -0800418void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800419 if (mListener != NULL) {
420 sp<MediaPlayerBase> listener = mListener.promote();
421
422 if (listener != NULL) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800423 listener->sendEvent(msg, ext1, ext2);
Andreas Hubera3f43842010-01-21 10:28:45 -0800424 }
425 }
426}
427
Andreas Huberb9e63832010-01-26 16:20:10 -0800428void AwesomePlayer::onBufferingUpdate() {
429 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800430 if (!mBufferingEventPending) {
431 return;
432 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800433 mBufferingEventPending = false;
434
Andreas Huber252573c2010-03-26 10:17:17 -0700435 int64_t durationUs;
436 {
437 Mutex::Autolock autoLock(mMiscStateLock);
438 durationUs = mDurationUs;
439 }
440
441 if (durationUs >= 0) {
Andreas Huberb9e63832010-01-26 16:20:10 -0800442 int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs();
Andreas Huberdc9927d2010-03-08 15:46:13 -0800443
444 LOGV("cache holds %.2f secs worth of data.", cachedDurationUs / 1E6);
445
Andreas Huber252573c2010-03-26 10:17:17 -0700446 int64_t positionUs;
447 getPosition(&positionUs);
Andreas Huberb9e63832010-01-26 16:20:10 -0800448
449 cachedDurationUs += positionUs;
450
Andreas Huber252573c2010-03-26 10:17:17 -0700451 double percentage = (double)cachedDurationUs / durationUs;
Andreas Huberb9e63832010-01-26 16:20:10 -0800452 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
453
454 postBufferingEvent_l();
Andreas Huber040301c2010-04-12 09:41:12 -0700455 } else {
456 LOGE("Not sending buffering status because duration is unknown.");
Andreas Huberb9e63832010-01-26 16:20:10 -0800457 }
458}
459
Andreas Huber27366fc2009-11-20 09:32:46 -0800460void AwesomePlayer::onStreamDone() {
461 // Posted whenever any stream finishes playing.
462
463 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800464 if (!mStreamDoneEventPending) {
465 return;
466 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800467 mStreamDoneEventPending = false;
468
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800469 if (mStreamDoneStatus == ERROR_END_OF_STREAM && (mFlags & LOOPING)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800470 seekTo_l(0);
471
Andreas Huber7085b6842010-02-03 16:02:02 -0800472 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800473 postVideoEvent_l();
474 }
475 } else {
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800476 if (mStreamDoneStatus == ERROR_END_OF_STREAM) {
477 LOGV("MEDIA_PLAYBACK_COMPLETE");
478 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
479 } else {
480 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
481
482 notifyListener_l(
483 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
484 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800485
486 pause_l();
Andreas Huber406a18b2010-02-18 16:45:13 -0800487
488 mFlags |= AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800489 }
490}
491
492status_t AwesomePlayer::play() {
493 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800494 return play_l();
495}
Andreas Huber27366fc2009-11-20 09:32:46 -0800496
Andreas Huberba7ec912010-02-12 10:42:02 -0800497status_t AwesomePlayer::play_l() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800498 if (mFlags & PLAYING) {
499 return OK;
500 }
501
Andreas Huberffdf4782010-02-09 14:05:43 -0800502 if (!(mFlags & PREPARED)) {
503 status_t err = prepare_l();
504
505 if (err != OK) {
506 return err;
507 }
508 }
509
Andreas Huber27366fc2009-11-20 09:32:46 -0800510 mFlags |= PLAYING;
511 mFlags |= FIRST_FRAME;
512
Andreas Huberc1d5c922009-12-10 15:49:04 -0800513 bool deferredAudioSeek = false;
514
Andreas Huber27366fc2009-11-20 09:32:46 -0800515 if (mAudioSource != NULL) {
516 if (mAudioPlayer == NULL) {
517 if (mAudioSink != NULL) {
518 mAudioPlayer = new AudioPlayer(mAudioSink);
Andreas Huber27366fc2009-11-20 09:32:46 -0800519 mAudioPlayer->setSource(mAudioSource);
Andreas Huberdc9927d2010-03-08 15:46:13 -0800520
521 // We've already started the MediaSource in order to enable
522 // the prefetcher to read its data.
523 status_t err = mAudioPlayer->start(
524 true /* sourceAlreadyStarted */);
Andreas Huber62eac002010-01-29 13:24:58 -0800525
526 if (err != OK) {
527 delete mAudioPlayer;
528 mAudioPlayer = NULL;
529
530 mFlags &= ~(PLAYING | FIRST_FRAME);
531
532 return err;
533 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800534
535 delete mTimeSource;
536 mTimeSource = mAudioPlayer;
537
Andreas Huberc1d5c922009-12-10 15:49:04 -0800538 deferredAudioSeek = true;
Andreas Huber70d10c02010-02-03 11:37:29 -0800539
540 mWatchForAudioSeekComplete = false;
541 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800542 }
543 } else {
544 mAudioPlayer->resume();
545 }
Andreas Huber70d10c02010-02-03 11:37:29 -0800546
547 postCheckAudioStatusEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800548 }
549
550 if (mTimeSource == NULL && mAudioPlayer == NULL) {
551 mTimeSource = new SystemTimeSource;
552 }
553
554 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800555 // Kick off video playback
556 postVideoEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800557 }
558
Andreas Huberc1d5c922009-12-10 15:49:04 -0800559 if (deferredAudioSeek) {
560 // If there was a seek request while we were paused
561 // and we're just starting up again, honor the request now.
562 seekAudioIfNecessary_l();
563 }
564
Andreas Huber406a18b2010-02-18 16:45:13 -0800565 if (mFlags & AT_EOS) {
566 // Legacy behaviour, if a stream finishes playing and then
567 // is started again, we play from the start...
568 seekTo_l(0);
569 }
570
Andreas Huber27366fc2009-11-20 09:32:46 -0800571 return OK;
572}
573
574void AwesomePlayer::initRenderer_l() {
575 if (mISurface != NULL) {
576 sp<MetaData> meta = mVideoSource->getFormat();
577
578 int32_t format;
579 const char *component;
580 int32_t decodedWidth, decodedHeight;
581 CHECK(meta->findInt32(kKeyColorFormat, &format));
582 CHECK(meta->findCString(kKeyDecoderComponent, &component));
583 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
584 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
585
Andreas Hubera67d5382009-12-10 15:32:12 -0800586 mVideoRenderer.clear();
587
588 // Must ensure that mVideoRenderer's destructor is actually executed
589 // before creating a new one.
590 IPCThreadState::self()->flushCommands();
591
Andreas Huber1314e732009-12-14 14:18:22 -0800592 if (!strncmp("OMX.", component, 4)) {
593 // Our OMX codecs allocate buffers on the media_server side
594 // therefore they require a remote IOMXRenderer that knows how
595 // to display them.
596 mVideoRenderer = new AwesomeRemoteRenderer(
597 mClient.interface()->createRenderer(
598 mISurface, component,
599 (OMX_COLOR_FORMATTYPE)format,
600 decodedWidth, decodedHeight,
601 mVideoWidth, mVideoHeight));
602 } else {
603 // Other decoders are instantiated locally and as a consequence
604 // allocate their buffers in local address space.
605 mVideoRenderer = new AwesomeLocalRenderer(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800606 false, // previewOnly
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800607 component,
Andreas Huber1314e732009-12-14 14:18:22 -0800608 (OMX_COLOR_FORMATTYPE)format,
609 mISurface,
610 mVideoWidth, mVideoHeight,
611 decodedWidth, decodedHeight);
612 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800613 }
614}
615
616status_t AwesomePlayer::pause() {
617 Mutex::Autolock autoLock(mLock);
618 return pause_l();
619}
620
621status_t AwesomePlayer::pause_l() {
622 if (!(mFlags & PLAYING)) {
623 return OK;
624 }
625
Andreas Huberb9e63832010-01-26 16:20:10 -0800626 cancelPlayerEvents(true /* keepBufferingGoing */);
Andreas Huber27366fc2009-11-20 09:32:46 -0800627
628 if (mAudioPlayer != NULL) {
629 mAudioPlayer->pause();
630 }
631
632 mFlags &= ~PLAYING;
633
634 return OK;
635}
636
637bool AwesomePlayer::isPlaying() const {
Andreas Huber27366fc2009-11-20 09:32:46 -0800638 return mFlags & PLAYING;
639}
640
641void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
642 Mutex::Autolock autoLock(mLock);
643
644 mISurface = isurface;
645}
646
647void AwesomePlayer::setAudioSink(
648 const sp<MediaPlayerBase::AudioSink> &audioSink) {
649 Mutex::Autolock autoLock(mLock);
650
651 mAudioSink = audioSink;
652}
653
654status_t AwesomePlayer::setLooping(bool shouldLoop) {
655 Mutex::Autolock autoLock(mLock);
656
657 mFlags = mFlags & ~LOOPING;
658
659 if (shouldLoop) {
660 mFlags |= LOOPING;
661 }
662
663 return OK;
664}
665
666status_t AwesomePlayer::getDuration(int64_t *durationUs) {
Andreas Huber252573c2010-03-26 10:17:17 -0700667 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800668
669 if (mDurationUs < 0) {
670 return UNKNOWN_ERROR;
671 }
672
673 *durationUs = mDurationUs;
674
675 return OK;
676}
677
678status_t AwesomePlayer::getPosition(int64_t *positionUs) {
Andreas Huberddb709c2010-04-07 10:24:35 -0700679 if (mSeeking) {
680 *positionUs = mSeekTimeUs;
681 } else if (mVideoSource != NULL) {
Andreas Huber252573c2010-03-26 10:17:17 -0700682 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800683 *positionUs = mVideoTimeUs;
684 } else if (mAudioPlayer != NULL) {
685 *positionUs = mAudioPlayer->getMediaTimeUs();
686 } else {
687 *positionUs = 0;
688 }
689
690 return OK;
691}
692
693status_t AwesomePlayer::seekTo(int64_t timeUs) {
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700694 if (mExtractorFlags
695 & (MediaExtractor::CAN_SEEK_FORWARD
696 | MediaExtractor::CAN_SEEK_BACKWARD)) {
697 Mutex::Autolock autoLock(mLock);
698 return seekTo_l(timeUs);
699 }
700
701 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800702}
703
704status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
705 mSeeking = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700706 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800707 mSeekTimeUs = timeUs;
Andreas Huber406a18b2010-02-18 16:45:13 -0800708 mFlags &= ~AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800709
710 seekAudioIfNecessary_l();
711
Andreas Huber8e2b9412010-03-31 09:40:15 -0700712 if (!(mFlags & PLAYING)) {
713 LOGV("seeking while paused, sending SEEK_COMPLETE notification"
714 " immediately.");
715
716 notifyListener_l(MEDIA_SEEK_COMPLETE);
717 mSeekNotificationSent = true;
718 }
719
Andreas Huber27366fc2009-11-20 09:32:46 -0800720 return OK;
721}
722
723void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Huber7085b6842010-02-03 16:02:02 -0800724 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800725 mAudioPlayer->seekTo(mSeekTimeUs);
726
Andreas Huber70d10c02010-02-03 11:37:29 -0800727 mWatchForAudioSeekComplete = true;
728 mWatchForAudioEOS = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700729 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800730 }
731}
732
733status_t AwesomePlayer::getVideoDimensions(
734 int32_t *width, int32_t *height) const {
735 Mutex::Autolock autoLock(mLock);
736
737 if (mVideoWidth < 0 || mVideoHeight < 0) {
738 return UNKNOWN_ERROR;
739 }
740
741 *width = mVideoWidth;
742 *height = mVideoHeight;
743
744 return OK;
745}
746
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800747void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
748 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800749
Andreas Huberb9e63832010-01-26 16:20:10 -0800750 if (mPrefetcher != NULL) {
751 source = mPrefetcher->addSource(source);
752 }
753
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800754 mAudioTrack = source;
755}
756
757status_t AwesomePlayer::initAudioDecoder() {
758 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huberc79827a2010-01-05 10:54:55 -0800759
760 const char *mime;
761 CHECK(meta->findCString(kKeyMIMEType, &mime));
762
763 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800764 mAudioSource = mAudioTrack;
Andreas Huberc79827a2010-01-05 10:54:55 -0800765 } else {
766 mAudioSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800767 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huberc79827a2010-01-05 10:54:55 -0800768 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800769 mAudioTrack);
Andreas Huberc79827a2010-01-05 10:54:55 -0800770 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800771
772 if (mAudioSource != NULL) {
773 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800774 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -0700775 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800776 if (mDurationUs < 0 || durationUs > mDurationUs) {
777 mDurationUs = durationUs;
778 }
779 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800780
Andreas Huberd0332ad2010-04-12 16:05:57 -0700781 mAudioSource->start();
782 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
783 // For legacy reasons we're simply going to ignore the absence
784 // of an audio decoder for QCELP instead of aborting playback
785 // altogether.
786 return OK;
787 }
Andreas Huberdc9927d2010-03-08 15:46:13 -0800788
Andreas Huber27366fc2009-11-20 09:32:46 -0800789 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
790}
791
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800792void AwesomePlayer::setVideoSource(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 mVideoTrack = source;
800}
801
802status_t AwesomePlayer::initVideoDecoder() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800803 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800804 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -0800805 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800806 mVideoTrack);
Andreas Huber27366fc2009-11-20 09:32:46 -0800807
808 if (mVideoSource != NULL) {
809 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800810 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -0700811 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800812 if (mDurationUs < 0 || durationUs > mDurationUs) {
813 mDurationUs = durationUs;
814 }
815 }
816
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800817 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
818 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
Andreas Huber27366fc2009-11-20 09:32:46 -0800819
820 mVideoSource->start();
821 }
822
823 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
824}
825
Andreas Huber6be780e2010-02-08 14:40:30 -0800826void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800827 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800828 if (!mVideoEventPending) {
829 // The event has been cancelled in reset_l() but had already
830 // been scheduled for execution at that time.
831 return;
832 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800833 mVideoEventPending = false;
834
835 if (mSeeking) {
836 if (mLastVideoBuffer) {
837 mLastVideoBuffer->release();
838 mLastVideoBuffer = NULL;
839 }
840
841 if (mVideoBuffer) {
842 mVideoBuffer->release();
843 mVideoBuffer = NULL;
844 }
845 }
846
847 if (!mVideoBuffer) {
848 MediaSource::ReadOptions options;
849 if (mSeeking) {
850 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
851
852 options.setSeekTo(mSeekTimeUs);
853 }
854 for (;;) {
855 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -0800856 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -0800857
858 if (err != OK) {
859 CHECK_EQ(mVideoBuffer, NULL);
860
861 if (err == INFO_FORMAT_CHANGED) {
862 LOGV("VideoSource signalled format change.");
863
Andreas Huber7085b6842010-02-03 16:02:02 -0800864 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800865 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -0800866 initRenderer_l();
867 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800868 continue;
869 }
870
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800871 postStreamDoneEvent_l(err);
Andreas Huber27366fc2009-11-20 09:32:46 -0800872 return;
873 }
874
Andreas Hubera67d5382009-12-10 15:32:12 -0800875 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -0800876 // Some decoders, notably the PV AVC software decoder
877 // return spurious empty buffers that we just want to ignore.
878
Andreas Hubera67d5382009-12-10 15:32:12 -0800879 mVideoBuffer->release();
880 mVideoBuffer = NULL;
881 continue;
882 }
883
Andreas Huber27366fc2009-11-20 09:32:46 -0800884 break;
885 }
886 }
887
888 int64_t timeUs;
889 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
890
Andreas Huber252573c2010-03-26 10:17:17 -0700891 {
892 Mutex::Autolock autoLock(mMiscStateLock);
893 mVideoTimeUs = timeUs;
894 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800895
896 if (mSeeking) {
897 if (mAudioPlayer != NULL) {
898 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
899
900 mAudioPlayer->seekTo(timeUs);
Andreas Huber70d10c02010-02-03 11:37:29 -0800901 mWatchForAudioSeekComplete = true;
902 mWatchForAudioEOS = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700903 } else if (!mSeekNotificationSent) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800904 // If we're playing video only, report seek complete now,
905 // otherwise audio player will notify us later.
Andreas Hubera3f43842010-01-21 10:28:45 -0800906 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800907 }
908
909 mFlags |= FIRST_FRAME;
910 mSeeking = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700911 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800912 }
913
914 if (mFlags & FIRST_FRAME) {
915 mFlags &= ~FIRST_FRAME;
916
917 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
918 }
919
920 int64_t realTimeUs, mediaTimeUs;
921 if (mAudioPlayer != NULL
922 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
923 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
924 }
925
926 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
927
928 int64_t latenessUs = nowUs - timeUs;
929
Andreas Huber24b0a952009-11-23 14:02:00 -0800930 if (latenessUs > 40000) {
931 // We're more than 40ms late.
Andreas Huber4a9375e2010-02-09 11:54:33 -0800932 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -0800933
934 mVideoBuffer->release();
935 mVideoBuffer = NULL;
936
937 postVideoEvent_l();
938 return;
939 }
940
941 if (latenessUs < -10000) {
942 // We're more than 10ms early.
943
944 postVideoEvent_l(10000);
945 return;
946 }
947
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800948 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
949 mVideoRendererIsPreview = false;
950
Andreas Huber7085b6842010-02-03 16:02:02 -0800951 initRenderer_l();
952 }
953
954 if (mVideoRenderer != NULL) {
955 mVideoRenderer->render(mVideoBuffer);
956 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800957
958 if (mLastVideoBuffer) {
959 mLastVideoBuffer->release();
960 mLastVideoBuffer = NULL;
961 }
962 mLastVideoBuffer = mVideoBuffer;
963 mVideoBuffer = NULL;
964
965 postVideoEvent_l();
966}
967
968void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
969 if (mVideoEventPending) {
970 return;
971 }
972
973 mVideoEventPending = true;
974 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
975}
976
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800977void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800978 if (mStreamDoneEventPending) {
979 return;
980 }
981 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800982
983 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -0800984 mQueue.postEvent(mStreamDoneEvent);
985}
986
Andreas Huberb9e63832010-01-26 16:20:10 -0800987void AwesomePlayer::postBufferingEvent_l() {
988 if (mPrefetcher == NULL) {
989 return;
990 }
991
992 if (mBufferingEventPending) {
993 return;
994 }
995 mBufferingEventPending = true;
996 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
997}
998
Andreas Huber70d10c02010-02-03 11:37:29 -0800999void AwesomePlayer::postCheckAudioStatusEvent_l() {
1000 if (mAudioStatusEventPending) {
1001 return;
1002 }
1003 mAudioStatusEventPending = true;
1004 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
1005}
1006
1007void AwesomePlayer::onCheckAudioStatus() {
1008 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -08001009 if (!mAudioStatusEventPending) {
1010 // Event was dispatched and while we were blocking on the mutex,
1011 // has already been cancelled.
1012 return;
1013 }
1014
Andreas Huber70d10c02010-02-03 11:37:29 -08001015 mAudioStatusEventPending = false;
1016
1017 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1018 mWatchForAudioSeekComplete = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001019
1020 if (!mSeekNotificationSent) {
1021 notifyListener_l(MEDIA_SEEK_COMPLETE);
1022 mSeekNotificationSent = true;
1023 }
Andreas Huberddb709c2010-04-07 10:24:35 -07001024
1025 mSeeking = false;
Andreas Huber70d10c02010-02-03 11:37:29 -08001026 }
1027
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001028 status_t finalStatus;
1029 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -08001030 mWatchForAudioEOS = false;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001031 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -08001032 }
1033
1034 postCheckAudioStatusEvent_l();
1035}
1036
Andreas Huber6be780e2010-02-08 14:40:30 -08001037status_t AwesomePlayer::prepare() {
1038 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001039 return prepare_l();
1040}
Andreas Huber6be780e2010-02-08 14:40:30 -08001041
Andreas Huberffdf4782010-02-09 14:05:43 -08001042status_t AwesomePlayer::prepare_l() {
1043 if (mFlags & PREPARED) {
1044 return OK;
1045 }
1046
1047 if (mFlags & PREPARING) {
1048 return UNKNOWN_ERROR;
1049 }
1050
1051 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -08001052 status_t err = prepareAsync_l();
1053
1054 if (err != OK) {
1055 return err;
1056 }
1057
Andreas Huberffdf4782010-02-09 14:05:43 -08001058 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001059 mPreparedCondition.wait(mLock);
1060 }
1061
Andreas Huberffdf4782010-02-09 14:05:43 -08001062 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001063}
1064
1065status_t AwesomePlayer::prepareAsync() {
1066 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001067
1068 if (mFlags & PREPARING) {
1069 return UNKNOWN_ERROR; // async prepare already pending
1070 }
1071
1072 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001073 return prepareAsync_l();
1074}
1075
1076status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001077 if (mFlags & PREPARING) {
1078 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001079 }
1080
Andreas Huber406a18b2010-02-18 16:45:13 -08001081 if (!mQueueStarted) {
1082 mQueue.start();
1083 mQueueStarted = true;
1084 }
1085
Andreas Huberffdf4782010-02-09 14:05:43 -08001086 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -08001087 mAsyncPrepareEvent = new AwesomeEvent(
1088 this, &AwesomePlayer::onPrepareAsyncEvent);
1089
1090 mQueue.postEvent(mAsyncPrepareEvent);
1091
1092 return OK;
1093}
1094
Andreas Huberffdf4782010-02-09 14:05:43 -08001095status_t AwesomePlayer::finishSetDataSource_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001096 sp<DataSource> dataSource;
1097
1098 if (!strncasecmp("http://", mUri.string(), 7)) {
1099 mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders);
1100
1101 mLock.unlock();
1102 status_t err = mConnectingDataSource->connect();
1103 mLock.lock();
1104
1105 if (err != OK) {
1106 mConnectingDataSource.clear();
1107
1108 LOGI("mConnectingDataSource->connect() returned %d", err);
1109 return err;
1110 }
1111
1112 dataSource = new CachingDataSource(
Andreas Hubera51250b2010-04-08 07:51:20 -07001113 mConnectingDataSource, 64 * 1024, 10);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001114
1115 mConnectingDataSource.clear();
1116 } else {
1117 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1118 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001119
1120 if (dataSource == NULL) {
1121 return UNKNOWN_ERROR;
1122 }
1123
1124 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1125
1126 if (extractor == NULL) {
1127 return UNKNOWN_ERROR;
1128 }
1129
1130 if (dataSource->flags() & DataSource::kWantsPrefetching) {
1131 mPrefetcher = new Prefetcher;
1132 }
1133
1134 return setDataSource_l(extractor);
1135}
1136
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001137void AwesomePlayer::abortPrepare(status_t err) {
1138 CHECK(err != OK);
1139
1140 if (mIsAsyncPrepare) {
1141 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1142 }
1143
1144 mPrepareResult = err;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001145 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001146 mAsyncPrepareEvent = NULL;
1147 mPreparedCondition.broadcast();
1148}
1149
Andreas Huberf71daba2010-03-24 09:24:40 -07001150// static
1151bool AwesomePlayer::ContinuePreparation(void *cookie) {
1152 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1153
1154 return (me->mFlags & PREPARE_CANCELLED) == 0;
1155}
1156
Andreas Huber6be780e2010-02-08 14:40:30 -08001157void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber55864df72010-03-08 12:28:22 -08001158 sp<Prefetcher> prefetcher;
1159
Andreas Huberffdf4782010-02-09 14:05:43 -08001160 {
1161 Mutex::Autolock autoLock(mLock);
1162
Andreas Huberedbb4d82010-03-12 08:59:22 -08001163 if (mFlags & PREPARE_CANCELLED) {
1164 LOGI("prepare was cancelled before doing anything");
1165 abortPrepare(UNKNOWN_ERROR);
1166 return;
1167 }
1168
Andreas Huberffdf4782010-02-09 14:05:43 -08001169 if (mUri.size() > 0) {
1170 status_t err = finishSetDataSource_l();
1171
1172 if (err != OK) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001173 abortPrepare(err);
Andreas Huberffdf4782010-02-09 14:05:43 -08001174 return;
1175 }
1176 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001177
Andreas Huber55864df72010-03-08 12:28:22 -08001178 if (mVideoTrack != NULL && mVideoSource == NULL) {
1179 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08001180
Andreas Huber55864df72010-03-08 12:28:22 -08001181 if (err != OK) {
1182 abortPrepare(err);
1183 return;
1184 }
1185 }
1186
1187 if (mAudioTrack != NULL && mAudioSource == NULL) {
1188 status_t err = initAudioDecoder();
1189
1190 if (err != OK) {
1191 abortPrepare(err);
1192 return;
1193 }
1194 }
1195
Andreas Huber6be780e2010-02-08 14:40:30 -08001196 prefetcher = mPrefetcher;
1197 }
1198
1199 if (prefetcher != NULL) {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001200 {
1201 Mutex::Autolock autoLock(mLock);
1202 if (mFlags & PREPARE_CANCELLED) {
1203 LOGI("prepare was cancelled before preparing the prefetcher");
Andreas Huber9b732de2010-03-23 15:30:57 -07001204
1205 prefetcher.clear();
Andreas Huberedbb4d82010-03-12 08:59:22 -08001206 abortPrepare(UNKNOWN_ERROR);
1207 return;
1208 }
1209 }
1210
1211 LOGI("calling prefetcher->prepare()");
Andreas Huberf71daba2010-03-24 09:24:40 -07001212 status_t result =
1213 prefetcher->prepare(&AwesomePlayer::ContinuePreparation, this);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001214
Andreas Huberba7ec912010-02-12 10:42:02 -08001215 prefetcher.clear();
Andreas Huberf71daba2010-03-24 09:24:40 -07001216
1217 if (result == OK) {
Andreas Huber252573c2010-03-26 10:17:17 -07001218 LOGI("prefetcher is done preparing");
Andreas Huberf71daba2010-03-24 09:24:40 -07001219 } else {
1220 Mutex::Autolock autoLock(mLock);
1221
1222 CHECK_EQ(result, -EINTR);
1223
1224 LOGI("prefetcher->prepare() was cancelled early.");
1225 abortPrepare(UNKNOWN_ERROR);
1226 return;
1227 }
Andreas Huber6be780e2010-02-08 14:40:30 -08001228 }
1229
1230 Mutex::Autolock autoLock(mLock);
1231
Andreas Huberffdf4782010-02-09 14:05:43 -08001232 if (mIsAsyncPrepare) {
1233 if (mVideoWidth < 0 || mVideoHeight < 0) {
1234 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1235 } else {
1236 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
1237 }
1238
1239 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08001240 }
1241
Andreas Huberffdf4782010-02-09 14:05:43 -08001242 mPrepareResult = OK;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001243 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huberffdf4782010-02-09 14:05:43 -08001244 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -08001245 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08001246 mPreparedCondition.broadcast();
Andreas Huber040301c2010-04-12 09:41:12 -07001247
1248 postBufferingEvent_l();
Andreas Huber6be780e2010-02-08 14:40:30 -08001249}
1250
Andreas Huberba7ec912010-02-12 10:42:02 -08001251status_t AwesomePlayer::suspend() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001252 LOGV("suspend");
Andreas Huberba7ec912010-02-12 10:42:02 -08001253 Mutex::Autolock autoLock(mLock);
1254
1255 if (mSuspensionState != NULL) {
Gloria Wangb19da8e2010-04-12 17:13:06 -07001256 if (mLastVideoBuffer == NULL) {
1257 //go into here if video is suspended again
1258 //after resuming without being played between
1259 //them
1260 SuspensionState *state = mSuspensionState;
1261 mSuspensionState = NULL;
1262 reset_l();
1263 mSuspensionState = state;
1264 return OK;
1265 }
1266
1267 delete mSuspensionState;
1268 mSuspensionState = NULL;
Andreas Huberba7ec912010-02-12 10:42:02 -08001269 }
1270
Andreas Huberedbb4d82010-03-12 08:59:22 -08001271 if (mFlags & PREPARING) {
1272 mFlags |= PREPARE_CANCELLED;
1273 if (mConnectingDataSource != NULL) {
1274 LOGI("interrupting the connection process");
1275 mConnectingDataSource->disconnect();
1276 }
1277 }
1278
Andreas Huberba7ec912010-02-12 10:42:02 -08001279 while (mFlags & PREPARING) {
1280 mPreparedCondition.wait(mLock);
1281 }
1282
1283 SuspensionState *state = new SuspensionState;
1284 state->mUri = mUri;
1285 state->mUriHeaders = mUriHeaders;
1286 state->mFileSource = mFileSource;
1287
Andreas Huber406a18b2010-02-18 16:45:13 -08001288 state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS);
Andreas Huber252573c2010-03-26 10:17:17 -07001289 getPosition(&state->mPositionUs);
Andreas Huberba7ec912010-02-12 10:42:02 -08001290
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001291 if (mLastVideoBuffer) {
1292 size_t size = mLastVideoBuffer->range_length();
1293 if (size) {
1294 state->mLastVideoFrameSize = size;
1295 state->mLastVideoFrame = malloc(size);
1296 memcpy(state->mLastVideoFrame,
1297 (const uint8_t *)mLastVideoBuffer->data()
1298 + mLastVideoBuffer->range_offset(),
1299 size);
1300
1301 state->mVideoWidth = mVideoWidth;
1302 state->mVideoHeight = mVideoHeight;
1303
1304 sp<MetaData> meta = mVideoSource->getFormat();
1305 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1306 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1307 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1308 }
1309 }
1310
Andreas Huberba7ec912010-02-12 10:42:02 -08001311 reset_l();
1312
1313 mSuspensionState = state;
1314
1315 return OK;
1316}
1317
1318status_t AwesomePlayer::resume() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001319 LOGV("resume");
Andreas Huberba7ec912010-02-12 10:42:02 -08001320 Mutex::Autolock autoLock(mLock);
1321
1322 if (mSuspensionState == NULL) {
1323 return INVALID_OPERATION;
1324 }
1325
1326 SuspensionState *state = mSuspensionState;
1327 mSuspensionState = NULL;
1328
1329 status_t err;
1330 if (state->mFileSource != NULL) {
1331 err = setDataSource_l(state->mFileSource);
1332
1333 if (err == OK) {
1334 mFileSource = state->mFileSource;
1335 }
1336 } else {
1337 err = setDataSource_l(state->mUri, &state->mUriHeaders);
1338 }
1339
1340 if (err != OK) {
1341 delete state;
1342 state = NULL;
1343
1344 return err;
1345 }
1346
1347 seekTo_l(state->mPositionUs);
1348
Andreas Huber406a18b2010-02-18 16:45:13 -08001349 mFlags = state->mFlags & (LOOPING | AT_EOS);
Andreas Huberba7ec912010-02-12 10:42:02 -08001350
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001351 if (state->mLastVideoFrame && mISurface != NULL) {
1352 mVideoRenderer =
1353 new AwesomeLocalRenderer(
1354 true, // previewOnly
1355 "",
1356 (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1357 mISurface,
1358 state->mVideoWidth,
1359 state->mVideoHeight,
1360 state->mDecodedWidth,
1361 state->mDecodedHeight);
1362
1363 mVideoRendererIsPreview = true;
1364
1365 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render(
1366 state->mLastVideoFrame, state->mLastVideoFrameSize);
1367 }
1368
Andreas Huberba7ec912010-02-12 10:42:02 -08001369 if (state->mFlags & PLAYING) {
1370 play_l();
1371 }
1372
Gloria Wangb19da8e2010-04-12 17:13:06 -07001373 mSuspensionState = state;
Andreas Huberba7ec912010-02-12 10:42:02 -08001374 state = NULL;
1375
1376 return OK;
1377}
1378
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001379uint32_t AwesomePlayer::flags() const {
1380 return mExtractorFlags;
1381}
1382
Andreas Huber27366fc2009-11-20 09:32:46 -08001383} // namespace android
1384