blob: f668caacc2393c91be8b42be13289d1dc55d3326 [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 Huber3c78a1b2010-05-13 09:15:21 -0700781 status_t err = mAudioSource->start();
782
783 if (err != OK) {
784 mAudioSource.clear();
785 return err;
786 }
Andreas Huberd0332ad2010-04-12 16:05:57 -0700787 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
788 // For legacy reasons we're simply going to ignore the absence
789 // of an audio decoder for QCELP instead of aborting playback
790 // altogether.
791 return OK;
792 }
Andreas Huberdc9927d2010-03-08 15:46:13 -0800793
Andreas Huber27366fc2009-11-20 09:32:46 -0800794 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
795}
796
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800797void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
798 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800799
Andreas Huberb9e63832010-01-26 16:20:10 -0800800 if (mPrefetcher != NULL) {
801 source = mPrefetcher->addSource(source);
802 }
803
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800804 mVideoTrack = source;
805}
806
807status_t AwesomePlayer::initVideoDecoder() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800808 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800809 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -0800810 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800811 mVideoTrack);
Andreas Huber27366fc2009-11-20 09:32:46 -0800812
813 if (mVideoSource != NULL) {
814 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800815 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -0700816 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800817 if (mDurationUs < 0 || durationUs > mDurationUs) {
818 mDurationUs = durationUs;
819 }
820 }
821
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800822 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
823 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
Andreas Huber27366fc2009-11-20 09:32:46 -0800824
825 mVideoSource->start();
826 }
827
828 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
829}
830
Andreas Huber6be780e2010-02-08 14:40:30 -0800831void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800832 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800833 if (!mVideoEventPending) {
834 // The event has been cancelled in reset_l() but had already
835 // been scheduled for execution at that time.
836 return;
837 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800838 mVideoEventPending = false;
839
840 if (mSeeking) {
841 if (mLastVideoBuffer) {
842 mLastVideoBuffer->release();
843 mLastVideoBuffer = NULL;
844 }
845
846 if (mVideoBuffer) {
847 mVideoBuffer->release();
848 mVideoBuffer = NULL;
849 }
850 }
851
852 if (!mVideoBuffer) {
853 MediaSource::ReadOptions options;
854 if (mSeeking) {
855 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
856
857 options.setSeekTo(mSeekTimeUs);
858 }
859 for (;;) {
860 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -0800861 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -0800862
863 if (err != OK) {
864 CHECK_EQ(mVideoBuffer, NULL);
865
866 if (err == INFO_FORMAT_CHANGED) {
867 LOGV("VideoSource signalled format change.");
868
Andreas Huber7085b6842010-02-03 16:02:02 -0800869 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800870 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -0800871 initRenderer_l();
872 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800873 continue;
874 }
875
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800876 postStreamDoneEvent_l(err);
Andreas Huber27366fc2009-11-20 09:32:46 -0800877 return;
878 }
879
Andreas Hubera67d5382009-12-10 15:32:12 -0800880 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -0800881 // Some decoders, notably the PV AVC software decoder
882 // return spurious empty buffers that we just want to ignore.
883
Andreas Hubera67d5382009-12-10 15:32:12 -0800884 mVideoBuffer->release();
885 mVideoBuffer = NULL;
886 continue;
887 }
888
Andreas Huber27366fc2009-11-20 09:32:46 -0800889 break;
890 }
891 }
892
893 int64_t timeUs;
894 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
895
Andreas Huber252573c2010-03-26 10:17:17 -0700896 {
897 Mutex::Autolock autoLock(mMiscStateLock);
898 mVideoTimeUs = timeUs;
899 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800900
901 if (mSeeking) {
902 if (mAudioPlayer != NULL) {
903 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
904
905 mAudioPlayer->seekTo(timeUs);
Andreas Huber70d10c02010-02-03 11:37:29 -0800906 mWatchForAudioSeekComplete = true;
907 mWatchForAudioEOS = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700908 } else if (!mSeekNotificationSent) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800909 // If we're playing video only, report seek complete now,
910 // otherwise audio player will notify us later.
Andreas Hubera3f43842010-01-21 10:28:45 -0800911 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800912 }
913
914 mFlags |= FIRST_FRAME;
915 mSeeking = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700916 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800917 }
918
919 if (mFlags & FIRST_FRAME) {
920 mFlags &= ~FIRST_FRAME;
921
922 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
923 }
924
925 int64_t realTimeUs, mediaTimeUs;
926 if (mAudioPlayer != NULL
927 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
928 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
929 }
930
931 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
932
933 int64_t latenessUs = nowUs - timeUs;
934
Andreas Huber24b0a952009-11-23 14:02:00 -0800935 if (latenessUs > 40000) {
936 // We're more than 40ms late.
Andreas Huber4a9375e2010-02-09 11:54:33 -0800937 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -0800938
939 mVideoBuffer->release();
940 mVideoBuffer = NULL;
941
942 postVideoEvent_l();
943 return;
944 }
945
946 if (latenessUs < -10000) {
947 // We're more than 10ms early.
948
949 postVideoEvent_l(10000);
950 return;
951 }
952
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800953 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
954 mVideoRendererIsPreview = false;
955
Andreas Huber7085b6842010-02-03 16:02:02 -0800956 initRenderer_l();
957 }
958
959 if (mVideoRenderer != NULL) {
960 mVideoRenderer->render(mVideoBuffer);
961 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800962
963 if (mLastVideoBuffer) {
964 mLastVideoBuffer->release();
965 mLastVideoBuffer = NULL;
966 }
967 mLastVideoBuffer = mVideoBuffer;
968 mVideoBuffer = NULL;
969
970 postVideoEvent_l();
971}
972
973void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
974 if (mVideoEventPending) {
975 return;
976 }
977
978 mVideoEventPending = true;
979 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
980}
981
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800982void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800983 if (mStreamDoneEventPending) {
984 return;
985 }
986 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800987
988 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -0800989 mQueue.postEvent(mStreamDoneEvent);
990}
991
Andreas Huberb9e63832010-01-26 16:20:10 -0800992void AwesomePlayer::postBufferingEvent_l() {
993 if (mPrefetcher == NULL) {
994 return;
995 }
996
997 if (mBufferingEventPending) {
998 return;
999 }
1000 mBufferingEventPending = true;
1001 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1002}
1003
Andreas Huber70d10c02010-02-03 11:37:29 -08001004void AwesomePlayer::postCheckAudioStatusEvent_l() {
1005 if (mAudioStatusEventPending) {
1006 return;
1007 }
1008 mAudioStatusEventPending = true;
1009 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
1010}
1011
1012void AwesomePlayer::onCheckAudioStatus() {
1013 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -08001014 if (!mAudioStatusEventPending) {
1015 // Event was dispatched and while we were blocking on the mutex,
1016 // has already been cancelled.
1017 return;
1018 }
1019
Andreas Huber70d10c02010-02-03 11:37:29 -08001020 mAudioStatusEventPending = false;
1021
1022 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1023 mWatchForAudioSeekComplete = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001024
1025 if (!mSeekNotificationSent) {
1026 notifyListener_l(MEDIA_SEEK_COMPLETE);
1027 mSeekNotificationSent = true;
1028 }
Andreas Huberddb709c2010-04-07 10:24:35 -07001029
1030 mSeeking = false;
Andreas Huber70d10c02010-02-03 11:37:29 -08001031 }
1032
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001033 status_t finalStatus;
1034 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -08001035 mWatchForAudioEOS = false;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001036 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -08001037 }
1038
1039 postCheckAudioStatusEvent_l();
1040}
1041
Andreas Huber6be780e2010-02-08 14:40:30 -08001042status_t AwesomePlayer::prepare() {
1043 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001044 return prepare_l();
1045}
Andreas Huber6be780e2010-02-08 14:40:30 -08001046
Andreas Huberffdf4782010-02-09 14:05:43 -08001047status_t AwesomePlayer::prepare_l() {
1048 if (mFlags & PREPARED) {
1049 return OK;
1050 }
1051
1052 if (mFlags & PREPARING) {
1053 return UNKNOWN_ERROR;
1054 }
1055
1056 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -08001057 status_t err = prepareAsync_l();
1058
1059 if (err != OK) {
1060 return err;
1061 }
1062
Andreas Huberffdf4782010-02-09 14:05:43 -08001063 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001064 mPreparedCondition.wait(mLock);
1065 }
1066
Andreas Huberffdf4782010-02-09 14:05:43 -08001067 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001068}
1069
1070status_t AwesomePlayer::prepareAsync() {
1071 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001072
1073 if (mFlags & PREPARING) {
1074 return UNKNOWN_ERROR; // async prepare already pending
1075 }
1076
1077 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001078 return prepareAsync_l();
1079}
1080
1081status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001082 if (mFlags & PREPARING) {
1083 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001084 }
1085
Andreas Huber406a18b2010-02-18 16:45:13 -08001086 if (!mQueueStarted) {
1087 mQueue.start();
1088 mQueueStarted = true;
1089 }
1090
Andreas Huberffdf4782010-02-09 14:05:43 -08001091 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -08001092 mAsyncPrepareEvent = new AwesomeEvent(
1093 this, &AwesomePlayer::onPrepareAsyncEvent);
1094
1095 mQueue.postEvent(mAsyncPrepareEvent);
1096
1097 return OK;
1098}
1099
Andreas Huberffdf4782010-02-09 14:05:43 -08001100status_t AwesomePlayer::finishSetDataSource_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001101 sp<DataSource> dataSource;
1102
1103 if (!strncasecmp("http://", mUri.string(), 7)) {
1104 mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders);
1105
1106 mLock.unlock();
1107 status_t err = mConnectingDataSource->connect();
1108 mLock.lock();
1109
1110 if (err != OK) {
1111 mConnectingDataSource.clear();
1112
1113 LOGI("mConnectingDataSource->connect() returned %d", err);
1114 return err;
1115 }
1116
1117 dataSource = new CachingDataSource(
Andreas Hubera51250b2010-04-08 07:51:20 -07001118 mConnectingDataSource, 64 * 1024, 10);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001119
1120 mConnectingDataSource.clear();
1121 } else {
1122 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1123 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001124
1125 if (dataSource == NULL) {
1126 return UNKNOWN_ERROR;
1127 }
1128
1129 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1130
1131 if (extractor == NULL) {
1132 return UNKNOWN_ERROR;
1133 }
1134
1135 if (dataSource->flags() & DataSource::kWantsPrefetching) {
1136 mPrefetcher = new Prefetcher;
1137 }
1138
1139 return setDataSource_l(extractor);
1140}
1141
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001142void AwesomePlayer::abortPrepare(status_t err) {
1143 CHECK(err != OK);
1144
1145 if (mIsAsyncPrepare) {
1146 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1147 }
1148
1149 mPrepareResult = err;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001150 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001151 mAsyncPrepareEvent = NULL;
1152 mPreparedCondition.broadcast();
1153}
1154
Andreas Huberf71daba2010-03-24 09:24:40 -07001155// static
1156bool AwesomePlayer::ContinuePreparation(void *cookie) {
1157 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1158
1159 return (me->mFlags & PREPARE_CANCELLED) == 0;
1160}
1161
Andreas Huber6be780e2010-02-08 14:40:30 -08001162void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber55864df72010-03-08 12:28:22 -08001163 sp<Prefetcher> prefetcher;
1164
Andreas Huberffdf4782010-02-09 14:05:43 -08001165 {
1166 Mutex::Autolock autoLock(mLock);
1167
Andreas Huberedbb4d82010-03-12 08:59:22 -08001168 if (mFlags & PREPARE_CANCELLED) {
1169 LOGI("prepare was cancelled before doing anything");
1170 abortPrepare(UNKNOWN_ERROR);
1171 return;
1172 }
1173
Andreas Huberffdf4782010-02-09 14:05:43 -08001174 if (mUri.size() > 0) {
1175 status_t err = finishSetDataSource_l();
1176
1177 if (err != OK) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001178 abortPrepare(err);
Andreas Huberffdf4782010-02-09 14:05:43 -08001179 return;
1180 }
1181 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001182
Andreas Huber55864df72010-03-08 12:28:22 -08001183 if (mVideoTrack != NULL && mVideoSource == NULL) {
1184 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08001185
Andreas Huber55864df72010-03-08 12:28:22 -08001186 if (err != OK) {
1187 abortPrepare(err);
1188 return;
1189 }
1190 }
1191
1192 if (mAudioTrack != NULL && mAudioSource == NULL) {
1193 status_t err = initAudioDecoder();
1194
1195 if (err != OK) {
1196 abortPrepare(err);
1197 return;
1198 }
1199 }
1200
Andreas Huber6be780e2010-02-08 14:40:30 -08001201 prefetcher = mPrefetcher;
1202 }
1203
1204 if (prefetcher != NULL) {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001205 {
1206 Mutex::Autolock autoLock(mLock);
1207 if (mFlags & PREPARE_CANCELLED) {
1208 LOGI("prepare was cancelled before preparing the prefetcher");
Andreas Huber9b732de2010-03-23 15:30:57 -07001209
1210 prefetcher.clear();
Andreas Huberedbb4d82010-03-12 08:59:22 -08001211 abortPrepare(UNKNOWN_ERROR);
1212 return;
1213 }
1214 }
1215
1216 LOGI("calling prefetcher->prepare()");
Andreas Huberf71daba2010-03-24 09:24:40 -07001217 status_t result =
1218 prefetcher->prepare(&AwesomePlayer::ContinuePreparation, this);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001219
Andreas Huberba7ec912010-02-12 10:42:02 -08001220 prefetcher.clear();
Andreas Huberf71daba2010-03-24 09:24:40 -07001221
1222 if (result == OK) {
Andreas Huber252573c2010-03-26 10:17:17 -07001223 LOGI("prefetcher is done preparing");
Andreas Huberf71daba2010-03-24 09:24:40 -07001224 } else {
1225 Mutex::Autolock autoLock(mLock);
1226
1227 CHECK_EQ(result, -EINTR);
1228
1229 LOGI("prefetcher->prepare() was cancelled early.");
1230 abortPrepare(UNKNOWN_ERROR);
1231 return;
1232 }
Andreas Huber6be780e2010-02-08 14:40:30 -08001233 }
1234
1235 Mutex::Autolock autoLock(mLock);
1236
Andreas Huberffdf4782010-02-09 14:05:43 -08001237 if (mIsAsyncPrepare) {
1238 if (mVideoWidth < 0 || mVideoHeight < 0) {
1239 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1240 } else {
1241 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
1242 }
1243
1244 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08001245 }
1246
Andreas Huberffdf4782010-02-09 14:05:43 -08001247 mPrepareResult = OK;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001248 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huberffdf4782010-02-09 14:05:43 -08001249 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -08001250 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08001251 mPreparedCondition.broadcast();
Andreas Huber040301c2010-04-12 09:41:12 -07001252
1253 postBufferingEvent_l();
Andreas Huber6be780e2010-02-08 14:40:30 -08001254}
1255
Andreas Huberba7ec912010-02-12 10:42:02 -08001256status_t AwesomePlayer::suspend() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001257 LOGV("suspend");
Andreas Huberba7ec912010-02-12 10:42:02 -08001258 Mutex::Autolock autoLock(mLock);
1259
1260 if (mSuspensionState != NULL) {
Gloria Wangb19da8e2010-04-12 17:13:06 -07001261 if (mLastVideoBuffer == NULL) {
1262 //go into here if video is suspended again
1263 //after resuming without being played between
1264 //them
1265 SuspensionState *state = mSuspensionState;
1266 mSuspensionState = NULL;
1267 reset_l();
1268 mSuspensionState = state;
1269 return OK;
1270 }
1271
1272 delete mSuspensionState;
1273 mSuspensionState = NULL;
Andreas Huberba7ec912010-02-12 10:42:02 -08001274 }
1275
Andreas Huberedbb4d82010-03-12 08:59:22 -08001276 if (mFlags & PREPARING) {
1277 mFlags |= PREPARE_CANCELLED;
1278 if (mConnectingDataSource != NULL) {
1279 LOGI("interrupting the connection process");
1280 mConnectingDataSource->disconnect();
1281 }
1282 }
1283
Andreas Huberba7ec912010-02-12 10:42:02 -08001284 while (mFlags & PREPARING) {
1285 mPreparedCondition.wait(mLock);
1286 }
1287
1288 SuspensionState *state = new SuspensionState;
1289 state->mUri = mUri;
1290 state->mUriHeaders = mUriHeaders;
1291 state->mFileSource = mFileSource;
1292
Andreas Huber406a18b2010-02-18 16:45:13 -08001293 state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS);
Andreas Huber252573c2010-03-26 10:17:17 -07001294 getPosition(&state->mPositionUs);
Andreas Huberba7ec912010-02-12 10:42:02 -08001295
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001296 if (mLastVideoBuffer) {
1297 size_t size = mLastVideoBuffer->range_length();
1298 if (size) {
1299 state->mLastVideoFrameSize = size;
1300 state->mLastVideoFrame = malloc(size);
1301 memcpy(state->mLastVideoFrame,
1302 (const uint8_t *)mLastVideoBuffer->data()
1303 + mLastVideoBuffer->range_offset(),
1304 size);
1305
1306 state->mVideoWidth = mVideoWidth;
1307 state->mVideoHeight = mVideoHeight;
1308
1309 sp<MetaData> meta = mVideoSource->getFormat();
1310 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1311 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1312 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1313 }
1314 }
1315
Andreas Huberba7ec912010-02-12 10:42:02 -08001316 reset_l();
1317
1318 mSuspensionState = state;
1319
1320 return OK;
1321}
1322
1323status_t AwesomePlayer::resume() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001324 LOGV("resume");
Andreas Huberba7ec912010-02-12 10:42:02 -08001325 Mutex::Autolock autoLock(mLock);
1326
1327 if (mSuspensionState == NULL) {
1328 return INVALID_OPERATION;
1329 }
1330
1331 SuspensionState *state = mSuspensionState;
1332 mSuspensionState = NULL;
1333
1334 status_t err;
1335 if (state->mFileSource != NULL) {
1336 err = setDataSource_l(state->mFileSource);
1337
1338 if (err == OK) {
1339 mFileSource = state->mFileSource;
1340 }
1341 } else {
1342 err = setDataSource_l(state->mUri, &state->mUriHeaders);
1343 }
1344
1345 if (err != OK) {
1346 delete state;
1347 state = NULL;
1348
1349 return err;
1350 }
1351
1352 seekTo_l(state->mPositionUs);
1353
Andreas Huber406a18b2010-02-18 16:45:13 -08001354 mFlags = state->mFlags & (LOOPING | AT_EOS);
Andreas Huberba7ec912010-02-12 10:42:02 -08001355
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001356 if (state->mLastVideoFrame && mISurface != NULL) {
1357 mVideoRenderer =
1358 new AwesomeLocalRenderer(
1359 true, // previewOnly
1360 "",
1361 (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1362 mISurface,
1363 state->mVideoWidth,
1364 state->mVideoHeight,
1365 state->mDecodedWidth,
1366 state->mDecodedHeight);
1367
1368 mVideoRendererIsPreview = true;
1369
1370 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render(
1371 state->mLastVideoFrame, state->mLastVideoFrameSize);
1372 }
1373
Andreas Huberba7ec912010-02-12 10:42:02 -08001374 if (state->mFlags & PLAYING) {
1375 play_l();
1376 }
1377
Gloria Wangb19da8e2010-04-12 17:13:06 -07001378 mSuspensionState = state;
Andreas Huberba7ec912010-02-12 10:42:02 -08001379 state = NULL;
1380
1381 return OK;
1382}
1383
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001384uint32_t AwesomePlayer::flags() const {
1385 return mExtractorFlags;
1386}
1387
Andreas Huber27366fc2009-11-20 09:32:46 -08001388} // namespace android
1389