blob: 88c8ee4e3d51c28628f31f53987ef48d4c1105ff [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 Huber202348e2010-06-07 14:35:29 -070042#include "include/LiveSource.h"
43
Andreas Huber27366fc2009-11-20 09:32:46 -080044namespace android {
45
46struct AwesomeEvent : public TimedEventQueue::Event {
Andreas Huber6be780e2010-02-08 14:40:30 -080047 AwesomeEvent(
48 AwesomePlayer *player,
49 void (AwesomePlayer::*method)())
Andreas Huber27366fc2009-11-20 09:32:46 -080050 : mPlayer(player),
Andreas Huber6be780e2010-02-08 14:40:30 -080051 mMethod(method) {
Andreas Huber27366fc2009-11-20 09:32:46 -080052 }
53
54protected:
55 virtual ~AwesomeEvent() {}
56
57 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
Andreas Huber6be780e2010-02-08 14:40:30 -080058 (mPlayer->*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080059 }
60
61private:
62 AwesomePlayer *mPlayer;
Andreas Huber6be780e2010-02-08 14:40:30 -080063 void (AwesomePlayer::*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080064
65 AwesomeEvent(const AwesomeEvent &);
66 AwesomeEvent &operator=(const AwesomeEvent &);
67};
68
Andreas Huber1314e732009-12-14 14:18:22 -080069struct AwesomeRemoteRenderer : public AwesomeRenderer {
70 AwesomeRemoteRenderer(const sp<IOMXRenderer> &target)
71 : mTarget(target) {
72 }
73
74 virtual void render(MediaBuffer *buffer) {
75 void *id;
76 if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) {
77 mTarget->render((IOMX::buffer_id)id);
78 }
79 }
80
81private:
82 sp<IOMXRenderer> mTarget;
83
84 AwesomeRemoteRenderer(const AwesomeRemoteRenderer &);
85 AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &);
86};
87
88struct AwesomeLocalRenderer : public AwesomeRenderer {
89 AwesomeLocalRenderer(
Andreas Huber7b73cfc2010-02-12 14:40:08 -080090 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080091 const char *componentName,
Andreas Huber1314e732009-12-14 14:18:22 -080092 OMX_COLOR_FORMATTYPE colorFormat,
93 const sp<ISurface> &surface,
94 size_t displayWidth, size_t displayHeight,
95 size_t decodedWidth, size_t decodedHeight)
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080096 : mTarget(NULL),
97 mLibHandle(NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -080098 init(previewOnly, componentName,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080099 colorFormat, surface, displayWidth,
100 displayHeight, decodedWidth, decodedHeight);
Andreas Huber1314e732009-12-14 14:18:22 -0800101 }
102
103 virtual void render(MediaBuffer *buffer) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800104 render((const uint8_t *)buffer->data() + buffer->range_offset(),
105 buffer->range_length());
106 }
107
108 void render(const void *data, size_t size) {
109 mTarget->render(data, size, NULL);
Andreas Huber1314e732009-12-14 14:18:22 -0800110 }
111
112protected:
113 virtual ~AwesomeLocalRenderer() {
114 delete mTarget;
115 mTarget = NULL;
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800116
117 if (mLibHandle) {
118 dlclose(mLibHandle);
119 mLibHandle = NULL;
120 }
Andreas Huber1314e732009-12-14 14:18:22 -0800121 }
122
123private:
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800124 VideoRenderer *mTarget;
125 void *mLibHandle;
126
127 void init(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800128 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800129 const char *componentName,
130 OMX_COLOR_FORMATTYPE colorFormat,
131 const sp<ISurface> &surface,
132 size_t displayWidth, size_t displayHeight,
133 size_t decodedWidth, size_t decodedHeight);
Andreas Huber1314e732009-12-14 14:18:22 -0800134
135 AwesomeLocalRenderer(const AwesomeLocalRenderer &);
136 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
137};
138
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800139void AwesomeLocalRenderer::init(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800140 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800141 const char *componentName,
142 OMX_COLOR_FORMATTYPE colorFormat,
143 const sp<ISurface> &surface,
144 size_t displayWidth, size_t displayHeight,
145 size_t decodedWidth, size_t decodedHeight) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800146 if (!previewOnly) {
147 // We will stick to the vanilla software-color-converting renderer
148 // for "previewOnly" mode, to avoid unneccessarily switching overlays
149 // more often than necessary.
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800150
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800151 mLibHandle = dlopen("libstagefrighthw.so", RTLD_NOW);
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800152
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800153 if (mLibHandle) {
154 typedef VideoRenderer *(*CreateRendererFunc)(
155 const sp<ISurface> &surface,
156 const char *componentName,
157 OMX_COLOR_FORMATTYPE colorFormat,
158 size_t displayWidth, size_t displayHeight,
159 size_t decodedWidth, size_t decodedHeight);
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800160
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800161 CreateRendererFunc func =
162 (CreateRendererFunc)dlsym(
163 mLibHandle,
164 "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20"
165 "OMX_COLOR_FORMATTYPEjjjj");
166
167 if (func) {
168 mTarget =
169 (*func)(surface, componentName, colorFormat,
170 displayWidth, displayHeight,
171 decodedWidth, decodedHeight);
172 }
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800173 }
174 }
175
176 if (mTarget == NULL) {
177 mTarget = new SoftwareRenderer(
178 colorFormat, surface, displayWidth, displayHeight,
179 decodedWidth, decodedHeight);
180 }
181}
182
Andreas Huber27366fc2009-11-20 09:32:46 -0800183AwesomePlayer::AwesomePlayer()
Andreas Huber406a18b2010-02-18 16:45:13 -0800184 : mQueueStarted(false),
185 mTimeSource(NULL),
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800186 mVideoRendererIsPreview(false),
Andreas Huber27366fc2009-11-20 09:32:46 -0800187 mAudioPlayer(NULL),
Andreas Huberffdf4782010-02-09 14:05:43 -0800188 mFlags(0),
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700189 mExtractorFlags(0),
Andreas Huber27366fc2009-11-20 09:32:46 -0800190 mLastVideoBuffer(NULL),
Andreas Huberba7ec912010-02-12 10:42:02 -0800191 mVideoBuffer(NULL),
192 mSuspensionState(NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800193 CHECK_EQ(mClient.connect(), OK);
194
195 DataSource::RegisterDefaultSniffers();
196
Andreas Huber6be780e2010-02-08 14:40:30 -0800197 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
Andreas Huber27366fc2009-11-20 09:32:46 -0800198 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800199 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
Andreas Huber27366fc2009-11-20 09:32:46 -0800200 mStreamDoneEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800201 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
Andreas Huberb9e63832010-01-26 16:20:10 -0800202 mBufferingEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800203
204 mCheckAudioStatusEvent = new AwesomeEvent(
205 this, &AwesomePlayer::onCheckAudioStatus);
206
Andreas Huber70d10c02010-02-03 11:37:29 -0800207 mAudioStatusEventPending = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800208
Andreas Huber27366fc2009-11-20 09:32:46 -0800209 reset();
210}
211
212AwesomePlayer::~AwesomePlayer() {
Andreas Huber406a18b2010-02-18 16:45:13 -0800213 if (mQueueStarted) {
214 mQueue.stop();
215 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800216
217 reset();
218
219 mClient.disconnect();
220}
221
Andreas Huberb9e63832010-01-26 16:20:10 -0800222void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800223 mQueue.cancelEvent(mVideoEvent->eventID());
224 mVideoEventPending = false;
225 mQueue.cancelEvent(mStreamDoneEvent->eventID());
226 mStreamDoneEventPending = false;
Andreas Huber70d10c02010-02-03 11:37:29 -0800227 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
228 mAudioStatusEventPending = false;
Andreas Huberb9e63832010-01-26 16:20:10 -0800229
230 if (!keepBufferingGoing) {
231 mQueue.cancelEvent(mBufferingEvent->eventID());
232 mBufferingEventPending = false;
233 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800234}
235
Andreas Hubera3f43842010-01-21 10:28:45 -0800236void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800237 Mutex::Autolock autoLock(mLock);
238 mListener = listener;
239}
240
Andreas Huber433c9ac2010-01-27 16:49:05 -0800241status_t AwesomePlayer::setDataSource(
242 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800243 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800244 return setDataSource_l(uri, headers);
245}
Andreas Huber27366fc2009-11-20 09:32:46 -0800246
Andreas Huberba7ec912010-02-12 10:42:02 -0800247status_t AwesomePlayer::setDataSource_l(
248 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800249 reset_l();
250
Andreas Huberffdf4782010-02-09 14:05:43 -0800251 mUri = uri;
Andreas Huberb9e63832010-01-26 16:20:10 -0800252
Andreas Huberffdf4782010-02-09 14:05:43 -0800253 if (headers) {
254 mUriHeaders = *headers;
Andreas Huberb9e63832010-01-26 16:20:10 -0800255 }
256
Andreas Huberffdf4782010-02-09 14:05:43 -0800257 // The actual work will be done during preparation in the call to
258 // ::finishSetDataSource_l to avoid blocking the calling thread in
259 // setDataSource for any significant time.
Andreas Huber27366fc2009-11-20 09:32:46 -0800260
Andreas Huberffdf4782010-02-09 14:05:43 -0800261 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800262}
263
264status_t AwesomePlayer::setDataSource(
265 int fd, int64_t offset, int64_t length) {
Andreas Huber202348e2010-06-07 14:35:29 -0700266#if 0
267 // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/nasatv/nasatv_96.m3u8");
268 // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/nasatv/nasatv_1500.m3u8");
269 return setDataSource("httplive://iphone.video.hsn.com/iPhone_high.m3u8");
270 // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/iphonewebcast/webcast090209_all/webcast090209_all.m3u8");
271 // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/usat/tt_062209_iphone/hi/prog_index.m3u8");
272 // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/usat/tt_googmaps/hi/prog_index.m3u8");
273 // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/mtv/ni_spo_25a_rt74137_clip_syn/hi/prog_index.m3u8");
274#endif
275
Andreas Huber27366fc2009-11-20 09:32:46 -0800276 Mutex::Autolock autoLock(mLock);
277
278 reset_l();
279
Andreas Huberba7ec912010-02-12 10:42:02 -0800280 sp<DataSource> dataSource = new FileSource(fd, offset, length);
Andreas Huber27366fc2009-11-20 09:32:46 -0800281
Andreas Huberba7ec912010-02-12 10:42:02 -0800282 status_t err = dataSource->initCheck();
Andreas Huber27366fc2009-11-20 09:32:46 -0800283
284 if (err != OK) {
285 return err;
286 }
287
Andreas Huberba7ec912010-02-12 10:42:02 -0800288 mFileSource = dataSource;
289
290 return setDataSource_l(dataSource);
291}
292
293status_t AwesomePlayer::setDataSource_l(
294 const sp<DataSource> &dataSource) {
295 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
Andreas Huber27366fc2009-11-20 09:32:46 -0800296
297 if (extractor == NULL) {
298 return UNKNOWN_ERROR;
299 }
300
301 return setDataSource_l(extractor);
302}
303
304status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800305 bool haveAudio = false;
306 bool haveVideo = false;
307 for (size_t i = 0; i < extractor->countTracks(); ++i) {
308 sp<MetaData> meta = extractor->getTrackMetaData(i);
309
310 const char *mime;
311 CHECK(meta->findCString(kKeyMIMEType, &mime));
312
313 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800314 setVideoSource(extractor->getTrack(i));
315 haveVideo = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800316 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800317 setAudioSource(extractor->getTrack(i));
318 haveAudio = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800319 }
320
321 if (haveAudio && haveVideo) {
322 break;
323 }
324 }
325
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700326 if (!haveAudio && !haveVideo) {
327 return UNKNOWN_ERROR;
328 }
329
330 mExtractorFlags = extractor->flags();
331
332 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800333}
334
335void AwesomePlayer::reset() {
336 Mutex::Autolock autoLock(mLock);
337 reset_l();
338}
339
340void AwesomePlayer::reset_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -0800341 if (mFlags & PREPARING) {
342 mFlags |= PREPARE_CANCELLED;
343 if (mConnectingDataSource != NULL) {
344 LOGI("interrupting the connection process");
345 mConnectingDataSource->disconnect();
346 }
347 }
348
Andreas Huberffdf4782010-02-09 14:05:43 -0800349 while (mFlags & PREPARING) {
350 mPreparedCondition.wait(mLock);
351 }
352
Andreas Huber27366fc2009-11-20 09:32:46 -0800353 cancelPlayerEvents();
354
Andreas Huberba7ec912010-02-12 10:42:02 -0800355 if (mPrefetcher != NULL) {
356 CHECK_EQ(mPrefetcher->getStrongCount(), 1);
357 }
358 mPrefetcher.clear();
359
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800360 mAudioTrack.clear();
361 mVideoTrack.clear();
362
Andreas Huberba7ec912010-02-12 10:42:02 -0800363 // Shutdown audio first, so that the respone to the reset request
364 // appears to happen instantaneously as far as the user is concerned
365 // If we did this later, audio would continue playing while we
366 // shutdown the video-related resources and the player appear to
367 // not be as responsive to a reset request.
Andreas Huberedbb4d82010-03-12 08:59:22 -0800368 if (mAudioPlayer == NULL && mAudioSource != NULL) {
369 // If we had an audio player, it would have effectively
370 // taken possession of the audio source and stopped it when
371 // _it_ is stopped. Otherwise this is still our responsibility.
372 mAudioSource->stop();
373 }
Andreas Huberba7ec912010-02-12 10:42:02 -0800374 mAudioSource.clear();
375
376 if (mTimeSource != mAudioPlayer) {
377 delete mTimeSource;
378 }
379 mTimeSource = NULL;
380
381 delete mAudioPlayer;
382 mAudioPlayer = NULL;
383
Andreas Huber3522b5a52010-01-22 14:36:53 -0800384 mVideoRenderer.clear();
385
Andreas Huber27366fc2009-11-20 09:32:46 -0800386 if (mLastVideoBuffer) {
387 mLastVideoBuffer->release();
388 mLastVideoBuffer = NULL;
389 }
390
391 if (mVideoBuffer) {
392 mVideoBuffer->release();
393 mVideoBuffer = NULL;
394 }
395
396 if (mVideoSource != NULL) {
397 mVideoSource->stop();
Andreas Huber98b48de2010-01-29 10:10:22 -0800398
399 // The following hack is necessary to ensure that the OMX
400 // component is completely released by the time we may try
401 // to instantiate it again.
402 wp<MediaSource> tmp = mVideoSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800403 mVideoSource.clear();
Andreas Huber98b48de2010-01-29 10:10:22 -0800404 while (tmp.promote() != NULL) {
405 usleep(1000);
406 }
407 IPCThreadState::self()->flushCommands();
Andreas Huber27366fc2009-11-20 09:32:46 -0800408 }
409
Andreas Huber27366fc2009-11-20 09:32:46 -0800410 mDurationUs = -1;
411 mFlags = 0;
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700412 mExtractorFlags = 0;
Andreas Huber27366fc2009-11-20 09:32:46 -0800413 mVideoWidth = mVideoHeight = -1;
414 mTimeSourceDeltaUs = 0;
415 mVideoTimeUs = 0;
416
417 mSeeking = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700418 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800419 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800420
Andreas Huberffdf4782010-02-09 14:05:43 -0800421 mUri.setTo("");
422 mUriHeaders.clear();
Andreas Huberba7ec912010-02-12 10:42:02 -0800423
424 mFileSource.clear();
425
426 delete mSuspensionState;
427 mSuspensionState = NULL;
Andreas Huber27366fc2009-11-20 09:32:46 -0800428}
429
Andreas Huber6be780e2010-02-08 14:40:30 -0800430void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800431 if (mListener != NULL) {
432 sp<MediaPlayerBase> listener = mListener.promote();
433
434 if (listener != NULL) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800435 listener->sendEvent(msg, ext1, ext2);
Andreas Hubera3f43842010-01-21 10:28:45 -0800436 }
437 }
438}
439
Andreas Huberb9e63832010-01-26 16:20:10 -0800440void AwesomePlayer::onBufferingUpdate() {
441 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800442 if (!mBufferingEventPending) {
443 return;
444 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800445 mBufferingEventPending = false;
446
Andreas Huber252573c2010-03-26 10:17:17 -0700447 int64_t durationUs;
448 {
449 Mutex::Autolock autoLock(mMiscStateLock);
450 durationUs = mDurationUs;
451 }
452
Andreas Huber202348e2010-06-07 14:35:29 -0700453 int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs();
454
455 LOGI("cache holds %.2f secs worth of data.", cachedDurationUs / 1E6);
456
Andreas Huber252573c2010-03-26 10:17:17 -0700457 if (durationUs >= 0) {
Andreas Huber252573c2010-03-26 10:17:17 -0700458 int64_t positionUs;
459 getPosition(&positionUs);
Andreas Huberb9e63832010-01-26 16:20:10 -0800460
461 cachedDurationUs += positionUs;
462
Andreas Huber252573c2010-03-26 10:17:17 -0700463 double percentage = (double)cachedDurationUs / durationUs;
Andreas Huberb9e63832010-01-26 16:20:10 -0800464 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
465
466 postBufferingEvent_l();
Andreas Huber040301c2010-04-12 09:41:12 -0700467 } else {
Andreas Huber202348e2010-06-07 14:35:29 -0700468 // LOGE("Not sending buffering status because duration is unknown.");
469 postBufferingEvent_l();
Andreas Huberb9e63832010-01-26 16:20:10 -0800470 }
471}
472
Andreas Huber27366fc2009-11-20 09:32:46 -0800473void AwesomePlayer::onStreamDone() {
474 // Posted whenever any stream finishes playing.
475
476 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800477 if (!mStreamDoneEventPending) {
478 return;
479 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800480 mStreamDoneEventPending = false;
481
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800482 if (mStreamDoneStatus == ERROR_END_OF_STREAM && (mFlags & LOOPING)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800483 seekTo_l(0);
484
Andreas Huber7085b6842010-02-03 16:02:02 -0800485 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800486 postVideoEvent_l();
487 }
488 } else {
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800489 if (mStreamDoneStatus == ERROR_END_OF_STREAM) {
490 LOGV("MEDIA_PLAYBACK_COMPLETE");
491 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
492 } else {
493 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
494
495 notifyListener_l(
496 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
497 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800498
499 pause_l();
Andreas Huber406a18b2010-02-18 16:45:13 -0800500
501 mFlags |= AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800502 }
503}
504
505status_t AwesomePlayer::play() {
506 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800507 return play_l();
508}
Andreas Huber27366fc2009-11-20 09:32:46 -0800509
Andreas Huberba7ec912010-02-12 10:42:02 -0800510status_t AwesomePlayer::play_l() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800511 if (mFlags & PLAYING) {
512 return OK;
513 }
514
Andreas Huberffdf4782010-02-09 14:05:43 -0800515 if (!(mFlags & PREPARED)) {
516 status_t err = prepare_l();
517
518 if (err != OK) {
519 return err;
520 }
521 }
522
Andreas Huber27366fc2009-11-20 09:32:46 -0800523 mFlags |= PLAYING;
524 mFlags |= FIRST_FRAME;
525
Andreas Huberc1d5c922009-12-10 15:49:04 -0800526 bool deferredAudioSeek = false;
527
Andreas Huber27366fc2009-11-20 09:32:46 -0800528 if (mAudioSource != NULL) {
529 if (mAudioPlayer == NULL) {
530 if (mAudioSink != NULL) {
531 mAudioPlayer = new AudioPlayer(mAudioSink);
Andreas Huber27366fc2009-11-20 09:32:46 -0800532 mAudioPlayer->setSource(mAudioSource);
Andreas Huberdc9927d2010-03-08 15:46:13 -0800533
534 // We've already started the MediaSource in order to enable
535 // the prefetcher to read its data.
536 status_t err = mAudioPlayer->start(
537 true /* sourceAlreadyStarted */);
Andreas Huber62eac002010-01-29 13:24:58 -0800538
539 if (err != OK) {
540 delete mAudioPlayer;
541 mAudioPlayer = NULL;
542
543 mFlags &= ~(PLAYING | FIRST_FRAME);
544
545 return err;
546 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800547
548 delete mTimeSource;
549 mTimeSource = mAudioPlayer;
550
Andreas Huberc1d5c922009-12-10 15:49:04 -0800551 deferredAudioSeek = true;
Andreas Huber70d10c02010-02-03 11:37:29 -0800552
553 mWatchForAudioSeekComplete = false;
554 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800555 }
556 } else {
557 mAudioPlayer->resume();
558 }
Andreas Huber70d10c02010-02-03 11:37:29 -0800559
560 postCheckAudioStatusEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800561 }
562
563 if (mTimeSource == NULL && mAudioPlayer == NULL) {
564 mTimeSource = new SystemTimeSource;
565 }
566
567 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800568 // Kick off video playback
569 postVideoEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800570 }
571
Andreas Huberc1d5c922009-12-10 15:49:04 -0800572 if (deferredAudioSeek) {
573 // If there was a seek request while we were paused
574 // and we're just starting up again, honor the request now.
575 seekAudioIfNecessary_l();
576 }
577
Andreas Huber406a18b2010-02-18 16:45:13 -0800578 if (mFlags & AT_EOS) {
579 // Legacy behaviour, if a stream finishes playing and then
580 // is started again, we play from the start...
581 seekTo_l(0);
582 }
583
Andreas Huber27366fc2009-11-20 09:32:46 -0800584 return OK;
585}
586
587void AwesomePlayer::initRenderer_l() {
588 if (mISurface != NULL) {
589 sp<MetaData> meta = mVideoSource->getFormat();
590
591 int32_t format;
592 const char *component;
593 int32_t decodedWidth, decodedHeight;
594 CHECK(meta->findInt32(kKeyColorFormat, &format));
595 CHECK(meta->findCString(kKeyDecoderComponent, &component));
596 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
597 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
598
Andreas Hubera67d5382009-12-10 15:32:12 -0800599 mVideoRenderer.clear();
600
601 // Must ensure that mVideoRenderer's destructor is actually executed
602 // before creating a new one.
603 IPCThreadState::self()->flushCommands();
604
Andreas Huber1314e732009-12-14 14:18:22 -0800605 if (!strncmp("OMX.", component, 4)) {
606 // Our OMX codecs allocate buffers on the media_server side
607 // therefore they require a remote IOMXRenderer that knows how
608 // to display them.
609 mVideoRenderer = new AwesomeRemoteRenderer(
610 mClient.interface()->createRenderer(
611 mISurface, component,
612 (OMX_COLOR_FORMATTYPE)format,
613 decodedWidth, decodedHeight,
614 mVideoWidth, mVideoHeight));
615 } else {
616 // Other decoders are instantiated locally and as a consequence
617 // allocate their buffers in local address space.
618 mVideoRenderer = new AwesomeLocalRenderer(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800619 false, // previewOnly
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800620 component,
Andreas Huber1314e732009-12-14 14:18:22 -0800621 (OMX_COLOR_FORMATTYPE)format,
622 mISurface,
623 mVideoWidth, mVideoHeight,
624 decodedWidth, decodedHeight);
625 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800626 }
627}
628
629status_t AwesomePlayer::pause() {
630 Mutex::Autolock autoLock(mLock);
631 return pause_l();
632}
633
634status_t AwesomePlayer::pause_l() {
635 if (!(mFlags & PLAYING)) {
636 return OK;
637 }
638
Andreas Huberb9e63832010-01-26 16:20:10 -0800639 cancelPlayerEvents(true /* keepBufferingGoing */);
Andreas Huber27366fc2009-11-20 09:32:46 -0800640
641 if (mAudioPlayer != NULL) {
642 mAudioPlayer->pause();
643 }
644
645 mFlags &= ~PLAYING;
646
647 return OK;
648}
649
650bool AwesomePlayer::isPlaying() const {
Andreas Huber27366fc2009-11-20 09:32:46 -0800651 return mFlags & PLAYING;
652}
653
654void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
655 Mutex::Autolock autoLock(mLock);
656
657 mISurface = isurface;
658}
659
660void AwesomePlayer::setAudioSink(
661 const sp<MediaPlayerBase::AudioSink> &audioSink) {
662 Mutex::Autolock autoLock(mLock);
663
664 mAudioSink = audioSink;
665}
666
667status_t AwesomePlayer::setLooping(bool shouldLoop) {
668 Mutex::Autolock autoLock(mLock);
669
670 mFlags = mFlags & ~LOOPING;
671
672 if (shouldLoop) {
673 mFlags |= LOOPING;
674 }
675
676 return OK;
677}
678
679status_t AwesomePlayer::getDuration(int64_t *durationUs) {
Andreas Huber252573c2010-03-26 10:17:17 -0700680 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800681
682 if (mDurationUs < 0) {
683 return UNKNOWN_ERROR;
684 }
685
686 *durationUs = mDurationUs;
687
688 return OK;
689}
690
691status_t AwesomePlayer::getPosition(int64_t *positionUs) {
Andreas Huberddb709c2010-04-07 10:24:35 -0700692 if (mSeeking) {
693 *positionUs = mSeekTimeUs;
694 } else if (mVideoSource != NULL) {
Andreas Huber252573c2010-03-26 10:17:17 -0700695 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800696 *positionUs = mVideoTimeUs;
697 } else if (mAudioPlayer != NULL) {
698 *positionUs = mAudioPlayer->getMediaTimeUs();
699 } else {
700 *positionUs = 0;
701 }
702
703 return OK;
704}
705
706status_t AwesomePlayer::seekTo(int64_t timeUs) {
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700707 if (mExtractorFlags
708 & (MediaExtractor::CAN_SEEK_FORWARD
709 | MediaExtractor::CAN_SEEK_BACKWARD)) {
710 Mutex::Autolock autoLock(mLock);
711 return seekTo_l(timeUs);
712 }
713
714 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800715}
716
717status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
718 mSeeking = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700719 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800720 mSeekTimeUs = timeUs;
Andreas Huber406a18b2010-02-18 16:45:13 -0800721 mFlags &= ~AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800722
723 seekAudioIfNecessary_l();
724
Andreas Huber8e2b9412010-03-31 09:40:15 -0700725 if (!(mFlags & PLAYING)) {
726 LOGV("seeking while paused, sending SEEK_COMPLETE notification"
727 " immediately.");
728
729 notifyListener_l(MEDIA_SEEK_COMPLETE);
730 mSeekNotificationSent = true;
731 }
732
Andreas Huber27366fc2009-11-20 09:32:46 -0800733 return OK;
734}
735
736void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Huber7085b6842010-02-03 16:02:02 -0800737 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800738 mAudioPlayer->seekTo(mSeekTimeUs);
739
Andreas Huber70d10c02010-02-03 11:37:29 -0800740 mWatchForAudioSeekComplete = true;
741 mWatchForAudioEOS = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700742 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800743 }
744}
745
746status_t AwesomePlayer::getVideoDimensions(
747 int32_t *width, int32_t *height) const {
748 Mutex::Autolock autoLock(mLock);
749
750 if (mVideoWidth < 0 || mVideoHeight < 0) {
751 return UNKNOWN_ERROR;
752 }
753
754 *width = mVideoWidth;
755 *height = mVideoHeight;
756
757 return OK;
758}
759
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800760void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
761 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800762
Andreas Huberb9e63832010-01-26 16:20:10 -0800763 if (mPrefetcher != NULL) {
764 source = mPrefetcher->addSource(source);
765 }
766
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800767 mAudioTrack = source;
768}
769
770status_t AwesomePlayer::initAudioDecoder() {
771 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huberc79827a2010-01-05 10:54:55 -0800772
773 const char *mime;
774 CHECK(meta->findCString(kKeyMIMEType, &mime));
775
776 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800777 mAudioSource = mAudioTrack;
Andreas Huberc79827a2010-01-05 10:54:55 -0800778 } else {
779 mAudioSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800780 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huberc79827a2010-01-05 10:54:55 -0800781 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800782 mAudioTrack);
Andreas Huberc79827a2010-01-05 10:54:55 -0800783 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800784
785 if (mAudioSource != NULL) {
786 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800787 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -0700788 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800789 if (mDurationUs < 0 || durationUs > mDurationUs) {
790 mDurationUs = durationUs;
791 }
792 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800793
Andreas Huber3c78a1b2010-05-13 09:15:21 -0700794 status_t err = mAudioSource->start();
795
796 if (err != OK) {
797 mAudioSource.clear();
798 return err;
799 }
Andreas Huberd0332ad2010-04-12 16:05:57 -0700800 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
801 // For legacy reasons we're simply going to ignore the absence
802 // of an audio decoder for QCELP instead of aborting playback
803 // altogether.
804 return OK;
805 }
Andreas Huberdc9927d2010-03-08 15:46:13 -0800806
Andreas Huber27366fc2009-11-20 09:32:46 -0800807 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
808}
809
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800810void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
811 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800812
Andreas Huberb9e63832010-01-26 16:20:10 -0800813 if (mPrefetcher != NULL) {
814 source = mPrefetcher->addSource(source);
815 }
816
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800817 mVideoTrack = source;
818}
819
820status_t AwesomePlayer::initVideoDecoder() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800821 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800822 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -0800823 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800824 mVideoTrack);
Andreas Huber27366fc2009-11-20 09:32:46 -0800825
826 if (mVideoSource != NULL) {
827 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800828 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -0700829 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800830 if (mDurationUs < 0 || durationUs > mDurationUs) {
831 mDurationUs = durationUs;
832 }
833 }
834
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800835 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
836 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
Andreas Huber27366fc2009-11-20 09:32:46 -0800837
Andreas Huber1919e5a2010-05-20 10:37:06 -0700838 status_t err = mVideoSource->start();
839
840 if (err != OK) {
841 mVideoSource.clear();
842 return err;
843 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800844 }
845
846 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
847}
848
Andreas Huber6be780e2010-02-08 14:40:30 -0800849void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800850 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800851 if (!mVideoEventPending) {
852 // The event has been cancelled in reset_l() but had already
853 // been scheduled for execution at that time.
854 return;
855 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800856 mVideoEventPending = false;
857
858 if (mSeeking) {
859 if (mLastVideoBuffer) {
860 mLastVideoBuffer->release();
861 mLastVideoBuffer = NULL;
862 }
863
864 if (mVideoBuffer) {
865 mVideoBuffer->release();
866 mVideoBuffer = NULL;
867 }
868 }
869
870 if (!mVideoBuffer) {
871 MediaSource::ReadOptions options;
872 if (mSeeking) {
873 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
874
875 options.setSeekTo(mSeekTimeUs);
876 }
877 for (;;) {
878 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -0800879 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -0800880
881 if (err != OK) {
882 CHECK_EQ(mVideoBuffer, NULL);
883
884 if (err == INFO_FORMAT_CHANGED) {
885 LOGV("VideoSource signalled format change.");
886
Andreas Huber7085b6842010-02-03 16:02:02 -0800887 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800888 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -0800889 initRenderer_l();
890 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800891 continue;
892 }
893
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800894 postStreamDoneEvent_l(err);
Andreas Huber27366fc2009-11-20 09:32:46 -0800895 return;
896 }
897
Andreas Hubera67d5382009-12-10 15:32:12 -0800898 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -0800899 // Some decoders, notably the PV AVC software decoder
900 // return spurious empty buffers that we just want to ignore.
901
Andreas Hubera67d5382009-12-10 15:32:12 -0800902 mVideoBuffer->release();
903 mVideoBuffer = NULL;
904 continue;
905 }
906
Andreas Huber27366fc2009-11-20 09:32:46 -0800907 break;
908 }
909 }
910
911 int64_t timeUs;
912 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
913
Andreas Huber252573c2010-03-26 10:17:17 -0700914 {
915 Mutex::Autolock autoLock(mMiscStateLock);
916 mVideoTimeUs = timeUs;
917 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800918
919 if (mSeeking) {
920 if (mAudioPlayer != NULL) {
921 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
922
923 mAudioPlayer->seekTo(timeUs);
Andreas Huber70d10c02010-02-03 11:37:29 -0800924 mWatchForAudioSeekComplete = true;
925 mWatchForAudioEOS = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700926 } else if (!mSeekNotificationSent) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800927 // If we're playing video only, report seek complete now,
928 // otherwise audio player will notify us later.
Andreas Hubera3f43842010-01-21 10:28:45 -0800929 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800930 }
931
932 mFlags |= FIRST_FRAME;
933 mSeeking = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700934 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800935 }
936
937 if (mFlags & FIRST_FRAME) {
938 mFlags &= ~FIRST_FRAME;
939
940 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
941 }
942
943 int64_t realTimeUs, mediaTimeUs;
944 if (mAudioPlayer != NULL
945 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
946 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
947 }
948
949 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
950
951 int64_t latenessUs = nowUs - timeUs;
952
Andreas Huber24b0a952009-11-23 14:02:00 -0800953 if (latenessUs > 40000) {
954 // We're more than 40ms late.
Andreas Huber4a9375e2010-02-09 11:54:33 -0800955 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -0800956
957 mVideoBuffer->release();
958 mVideoBuffer = NULL;
959
960 postVideoEvent_l();
961 return;
962 }
963
964 if (latenessUs < -10000) {
965 // We're more than 10ms early.
966
967 postVideoEvent_l(10000);
968 return;
969 }
970
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800971 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
972 mVideoRendererIsPreview = false;
973
Andreas Huber7085b6842010-02-03 16:02:02 -0800974 initRenderer_l();
975 }
976
977 if (mVideoRenderer != NULL) {
978 mVideoRenderer->render(mVideoBuffer);
979 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800980
981 if (mLastVideoBuffer) {
982 mLastVideoBuffer->release();
983 mLastVideoBuffer = NULL;
984 }
985 mLastVideoBuffer = mVideoBuffer;
986 mVideoBuffer = NULL;
987
988 postVideoEvent_l();
989}
990
991void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
992 if (mVideoEventPending) {
993 return;
994 }
995
996 mVideoEventPending = true;
997 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
998}
999
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001000void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001001 if (mStreamDoneEventPending) {
1002 return;
1003 }
1004 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001005
1006 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -08001007 mQueue.postEvent(mStreamDoneEvent);
1008}
1009
Andreas Huberb9e63832010-01-26 16:20:10 -08001010void AwesomePlayer::postBufferingEvent_l() {
1011 if (mPrefetcher == NULL) {
1012 return;
1013 }
1014
1015 if (mBufferingEventPending) {
1016 return;
1017 }
1018 mBufferingEventPending = true;
1019 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1020}
1021
Andreas Huber70d10c02010-02-03 11:37:29 -08001022void AwesomePlayer::postCheckAudioStatusEvent_l() {
1023 if (mAudioStatusEventPending) {
1024 return;
1025 }
1026 mAudioStatusEventPending = true;
1027 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
1028}
1029
1030void AwesomePlayer::onCheckAudioStatus() {
1031 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -08001032 if (!mAudioStatusEventPending) {
1033 // Event was dispatched and while we were blocking on the mutex,
1034 // has already been cancelled.
1035 return;
1036 }
1037
Andreas Huber70d10c02010-02-03 11:37:29 -08001038 mAudioStatusEventPending = false;
1039
1040 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1041 mWatchForAudioSeekComplete = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001042
1043 if (!mSeekNotificationSent) {
1044 notifyListener_l(MEDIA_SEEK_COMPLETE);
1045 mSeekNotificationSent = true;
1046 }
Andreas Huberddb709c2010-04-07 10:24:35 -07001047
1048 mSeeking = false;
Andreas Huber70d10c02010-02-03 11:37:29 -08001049 }
1050
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001051 status_t finalStatus;
1052 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -08001053 mWatchForAudioEOS = false;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001054 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -08001055 }
1056
1057 postCheckAudioStatusEvent_l();
1058}
1059
Andreas Huber6be780e2010-02-08 14:40:30 -08001060status_t AwesomePlayer::prepare() {
1061 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001062 return prepare_l();
1063}
Andreas Huber6be780e2010-02-08 14:40:30 -08001064
Andreas Huberffdf4782010-02-09 14:05:43 -08001065status_t AwesomePlayer::prepare_l() {
1066 if (mFlags & PREPARED) {
1067 return OK;
1068 }
1069
1070 if (mFlags & PREPARING) {
1071 return UNKNOWN_ERROR;
1072 }
1073
1074 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -08001075 status_t err = prepareAsync_l();
1076
1077 if (err != OK) {
1078 return err;
1079 }
1080
Andreas Huberffdf4782010-02-09 14:05:43 -08001081 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001082 mPreparedCondition.wait(mLock);
1083 }
1084
Andreas Huberffdf4782010-02-09 14:05:43 -08001085 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001086}
1087
1088status_t AwesomePlayer::prepareAsync() {
1089 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001090
1091 if (mFlags & PREPARING) {
1092 return UNKNOWN_ERROR; // async prepare already pending
1093 }
1094
1095 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001096 return prepareAsync_l();
1097}
1098
1099status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001100 if (mFlags & PREPARING) {
1101 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001102 }
1103
Andreas Huber406a18b2010-02-18 16:45:13 -08001104 if (!mQueueStarted) {
1105 mQueue.start();
1106 mQueueStarted = true;
1107 }
1108
Andreas Huberffdf4782010-02-09 14:05:43 -08001109 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -08001110 mAsyncPrepareEvent = new AwesomeEvent(
1111 this, &AwesomePlayer::onPrepareAsyncEvent);
1112
1113 mQueue.postEvent(mAsyncPrepareEvent);
1114
1115 return OK;
1116}
1117
Andreas Huberffdf4782010-02-09 14:05:43 -08001118status_t AwesomePlayer::finishSetDataSource_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001119 sp<DataSource> dataSource;
1120
1121 if (!strncasecmp("http://", mUri.string(), 7)) {
1122 mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders);
1123
1124 mLock.unlock();
1125 status_t err = mConnectingDataSource->connect();
1126 mLock.lock();
1127
1128 if (err != OK) {
1129 mConnectingDataSource.clear();
1130
1131 LOGI("mConnectingDataSource->connect() returned %d", err);
1132 return err;
1133 }
1134
1135 dataSource = new CachingDataSource(
Andreas Hubera51250b2010-04-08 07:51:20 -07001136 mConnectingDataSource, 64 * 1024, 10);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001137
1138 mConnectingDataSource.clear();
Andreas Huber202348e2010-06-07 14:35:29 -07001139 } else if (!strncasecmp(mUri.string(), "httplive://", 11)) {
1140 String8 uri("http://");
1141 uri.append(mUri.string() + 11);
1142
1143 dataSource = new LiveSource(uri.string());
1144
1145 if (dataSource->flags() & DataSource::kWantsPrefetching) {
1146 mPrefetcher = new Prefetcher;
1147 }
1148
1149 sp<MediaExtractor> extractor =
1150 MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
1151
1152 return setDataSource_l(extractor);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001153 } else {
1154 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1155 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001156
1157 if (dataSource == NULL) {
1158 return UNKNOWN_ERROR;
1159 }
1160
1161 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1162
1163 if (extractor == NULL) {
1164 return UNKNOWN_ERROR;
1165 }
1166
1167 if (dataSource->flags() & DataSource::kWantsPrefetching) {
1168 mPrefetcher = new Prefetcher;
1169 }
1170
1171 return setDataSource_l(extractor);
1172}
1173
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001174void AwesomePlayer::abortPrepare(status_t err) {
1175 CHECK(err != OK);
1176
1177 if (mIsAsyncPrepare) {
1178 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1179 }
1180
1181 mPrepareResult = err;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001182 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001183 mAsyncPrepareEvent = NULL;
1184 mPreparedCondition.broadcast();
1185}
1186
Andreas Huberf71daba2010-03-24 09:24:40 -07001187// static
1188bool AwesomePlayer::ContinuePreparation(void *cookie) {
1189 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1190
1191 return (me->mFlags & PREPARE_CANCELLED) == 0;
1192}
1193
Andreas Huber6be780e2010-02-08 14:40:30 -08001194void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber55864df72010-03-08 12:28:22 -08001195 sp<Prefetcher> prefetcher;
1196
Andreas Huberffdf4782010-02-09 14:05:43 -08001197 {
1198 Mutex::Autolock autoLock(mLock);
1199
Andreas Huberedbb4d82010-03-12 08:59:22 -08001200 if (mFlags & PREPARE_CANCELLED) {
1201 LOGI("prepare was cancelled before doing anything");
1202 abortPrepare(UNKNOWN_ERROR);
1203 return;
1204 }
1205
Andreas Huberffdf4782010-02-09 14:05:43 -08001206 if (mUri.size() > 0) {
1207 status_t err = finishSetDataSource_l();
1208
1209 if (err != OK) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001210 abortPrepare(err);
Andreas Huberffdf4782010-02-09 14:05:43 -08001211 return;
1212 }
1213 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001214
Andreas Huber55864df72010-03-08 12:28:22 -08001215 if (mVideoTrack != NULL && mVideoSource == NULL) {
1216 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08001217
Andreas Huber55864df72010-03-08 12:28:22 -08001218 if (err != OK) {
1219 abortPrepare(err);
1220 return;
1221 }
1222 }
1223
1224 if (mAudioTrack != NULL && mAudioSource == NULL) {
1225 status_t err = initAudioDecoder();
1226
1227 if (err != OK) {
1228 abortPrepare(err);
1229 return;
1230 }
1231 }
1232
Andreas Huber6be780e2010-02-08 14:40:30 -08001233 prefetcher = mPrefetcher;
1234 }
1235
1236 if (prefetcher != NULL) {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001237 {
1238 Mutex::Autolock autoLock(mLock);
1239 if (mFlags & PREPARE_CANCELLED) {
1240 LOGI("prepare was cancelled before preparing the prefetcher");
Andreas Huber9b732de2010-03-23 15:30:57 -07001241
1242 prefetcher.clear();
Andreas Huberedbb4d82010-03-12 08:59:22 -08001243 abortPrepare(UNKNOWN_ERROR);
1244 return;
1245 }
1246 }
1247
1248 LOGI("calling prefetcher->prepare()");
Andreas Huberf71daba2010-03-24 09:24:40 -07001249 status_t result =
1250 prefetcher->prepare(&AwesomePlayer::ContinuePreparation, this);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001251
Andreas Huberba7ec912010-02-12 10:42:02 -08001252 prefetcher.clear();
Andreas Huberf71daba2010-03-24 09:24:40 -07001253
1254 if (result == OK) {
Andreas Huber252573c2010-03-26 10:17:17 -07001255 LOGI("prefetcher is done preparing");
Andreas Huberf71daba2010-03-24 09:24:40 -07001256 } else {
1257 Mutex::Autolock autoLock(mLock);
1258
1259 CHECK_EQ(result, -EINTR);
1260
1261 LOGI("prefetcher->prepare() was cancelled early.");
1262 abortPrepare(UNKNOWN_ERROR);
1263 return;
1264 }
Andreas Huber6be780e2010-02-08 14:40:30 -08001265 }
1266
1267 Mutex::Autolock autoLock(mLock);
1268
Andreas Huberffdf4782010-02-09 14:05:43 -08001269 if (mIsAsyncPrepare) {
1270 if (mVideoWidth < 0 || mVideoHeight < 0) {
1271 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1272 } else {
1273 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
1274 }
1275
1276 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08001277 }
1278
Andreas Huberffdf4782010-02-09 14:05:43 -08001279 mPrepareResult = OK;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001280 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huberffdf4782010-02-09 14:05:43 -08001281 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -08001282 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08001283 mPreparedCondition.broadcast();
Andreas Huber040301c2010-04-12 09:41:12 -07001284
1285 postBufferingEvent_l();
Andreas Huber6be780e2010-02-08 14:40:30 -08001286}
1287
Andreas Huberba7ec912010-02-12 10:42:02 -08001288status_t AwesomePlayer::suspend() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001289 LOGV("suspend");
Andreas Huberba7ec912010-02-12 10:42:02 -08001290 Mutex::Autolock autoLock(mLock);
1291
1292 if (mSuspensionState != NULL) {
Gloria Wangb19da8e2010-04-12 17:13:06 -07001293 if (mLastVideoBuffer == NULL) {
1294 //go into here if video is suspended again
1295 //after resuming without being played between
1296 //them
1297 SuspensionState *state = mSuspensionState;
1298 mSuspensionState = NULL;
1299 reset_l();
1300 mSuspensionState = state;
1301 return OK;
1302 }
1303
1304 delete mSuspensionState;
1305 mSuspensionState = NULL;
Andreas Huberba7ec912010-02-12 10:42:02 -08001306 }
1307
Andreas Huberedbb4d82010-03-12 08:59:22 -08001308 if (mFlags & PREPARING) {
1309 mFlags |= PREPARE_CANCELLED;
1310 if (mConnectingDataSource != NULL) {
1311 LOGI("interrupting the connection process");
1312 mConnectingDataSource->disconnect();
1313 }
1314 }
1315
Andreas Huberba7ec912010-02-12 10:42:02 -08001316 while (mFlags & PREPARING) {
1317 mPreparedCondition.wait(mLock);
1318 }
1319
1320 SuspensionState *state = new SuspensionState;
1321 state->mUri = mUri;
1322 state->mUriHeaders = mUriHeaders;
1323 state->mFileSource = mFileSource;
1324
Andreas Huber406a18b2010-02-18 16:45:13 -08001325 state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS);
Andreas Huber252573c2010-03-26 10:17:17 -07001326 getPosition(&state->mPositionUs);
Andreas Huberba7ec912010-02-12 10:42:02 -08001327
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001328 if (mLastVideoBuffer) {
1329 size_t size = mLastVideoBuffer->range_length();
1330 if (size) {
1331 state->mLastVideoFrameSize = size;
1332 state->mLastVideoFrame = malloc(size);
1333 memcpy(state->mLastVideoFrame,
1334 (const uint8_t *)mLastVideoBuffer->data()
1335 + mLastVideoBuffer->range_offset(),
1336 size);
1337
1338 state->mVideoWidth = mVideoWidth;
1339 state->mVideoHeight = mVideoHeight;
1340
1341 sp<MetaData> meta = mVideoSource->getFormat();
1342 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1343 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1344 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1345 }
1346 }
1347
Andreas Huberba7ec912010-02-12 10:42:02 -08001348 reset_l();
1349
1350 mSuspensionState = state;
1351
1352 return OK;
1353}
1354
1355status_t AwesomePlayer::resume() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001356 LOGV("resume");
Andreas Huberba7ec912010-02-12 10:42:02 -08001357 Mutex::Autolock autoLock(mLock);
1358
1359 if (mSuspensionState == NULL) {
1360 return INVALID_OPERATION;
1361 }
1362
1363 SuspensionState *state = mSuspensionState;
1364 mSuspensionState = NULL;
1365
1366 status_t err;
1367 if (state->mFileSource != NULL) {
1368 err = setDataSource_l(state->mFileSource);
1369
1370 if (err == OK) {
1371 mFileSource = state->mFileSource;
1372 }
1373 } else {
1374 err = setDataSource_l(state->mUri, &state->mUriHeaders);
1375 }
1376
1377 if (err != OK) {
1378 delete state;
1379 state = NULL;
1380
1381 return err;
1382 }
1383
1384 seekTo_l(state->mPositionUs);
1385
Andreas Huber406a18b2010-02-18 16:45:13 -08001386 mFlags = state->mFlags & (LOOPING | AT_EOS);
Andreas Huberba7ec912010-02-12 10:42:02 -08001387
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001388 if (state->mLastVideoFrame && mISurface != NULL) {
1389 mVideoRenderer =
1390 new AwesomeLocalRenderer(
1391 true, // previewOnly
1392 "",
1393 (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1394 mISurface,
1395 state->mVideoWidth,
1396 state->mVideoHeight,
1397 state->mDecodedWidth,
1398 state->mDecodedHeight);
1399
1400 mVideoRendererIsPreview = true;
1401
1402 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render(
1403 state->mLastVideoFrame, state->mLastVideoFrameSize);
1404 }
1405
Andreas Huberba7ec912010-02-12 10:42:02 -08001406 if (state->mFlags & PLAYING) {
1407 play_l();
1408 }
1409
Gloria Wangb19da8e2010-04-12 17:13:06 -07001410 mSuspensionState = state;
Andreas Huberba7ec912010-02-12 10:42:02 -08001411 state = NULL;
1412
1413 return OK;
1414}
1415
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001416uint32_t AwesomePlayer::flags() const {
1417 return mExtractorFlags;
1418}
1419
Andreas Huber27366fc2009-11-20 09:32:46 -08001420} // namespace android
1421