blob: 4c9856dbbd757386db6de1d41e5d0a04e010cbe4 [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 Huber7a747b82010-06-07 15:19:40 -070023#include "include/ARTSPController.h"
Andreas Huber27366fc2009-11-20 09:32:46 -080024#include "include/AwesomePlayer.h"
Andreas Huber7a747b82010-06-07 15:19:40 -070025#include "include/LiveSource.h"
Andreas Huberb9e63832010-01-26 16:20:10 -080026#include "include/Prefetcher.h"
Andreas Huber1314e732009-12-14 14:18:22 -080027#include "include/SoftwareRenderer.h"
Andreas Huber27366fc2009-11-20 09:32:46 -080028
Andreas Hubera67d5382009-12-10 15:32:12 -080029#include <binder/IPCThreadState.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080030#include <media/stagefright/AudioPlayer.h>
Andreas Huberedbb4d82010-03-12 08:59:22 -080031#include <media/stagefright/CachingDataSource.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080032#include <media/stagefright/DataSource.h>
33#include <media/stagefright/FileSource.h>
34#include <media/stagefright/MediaBuffer.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080035#include <media/stagefright/MediaDefs.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080036#include <media/stagefright/MediaExtractor.h>
37#include <media/stagefright/MediaDebug.h>
38#include <media/stagefright/MediaSource.h>
39#include <media/stagefright/MetaData.h>
40#include <media/stagefright/OMXCodec.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080041
Mathias Agopian000479f2010-02-09 17:46:37 -080042#include <surfaceflinger/ISurface.h>
43
Andreas Huber7a747b82010-06-07 15:19:40 -070044#include <media/stagefright/foundation/ALooper.h>
Andreas Huber202348e2010-06-07 14:35:29 -070045
Andreas Huber27366fc2009-11-20 09:32:46 -080046namespace android {
47
48struct AwesomeEvent : public TimedEventQueue::Event {
Andreas Huber6be780e2010-02-08 14:40:30 -080049 AwesomeEvent(
50 AwesomePlayer *player,
51 void (AwesomePlayer::*method)())
Andreas Huber27366fc2009-11-20 09:32:46 -080052 : mPlayer(player),
Andreas Huber6be780e2010-02-08 14:40:30 -080053 mMethod(method) {
Andreas Huber27366fc2009-11-20 09:32:46 -080054 }
55
56protected:
57 virtual ~AwesomeEvent() {}
58
59 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
Andreas Huber6be780e2010-02-08 14:40:30 -080060 (mPlayer->*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080061 }
62
63private:
64 AwesomePlayer *mPlayer;
Andreas Huber6be780e2010-02-08 14:40:30 -080065 void (AwesomePlayer::*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080066
67 AwesomeEvent(const AwesomeEvent &);
68 AwesomeEvent &operator=(const AwesomeEvent &);
69};
70
Andreas Huber1314e732009-12-14 14:18:22 -080071struct AwesomeRemoteRenderer : public AwesomeRenderer {
72 AwesomeRemoteRenderer(const sp<IOMXRenderer> &target)
73 : mTarget(target) {
74 }
75
76 virtual void render(MediaBuffer *buffer) {
77 void *id;
78 if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) {
79 mTarget->render((IOMX::buffer_id)id);
80 }
81 }
82
83private:
84 sp<IOMXRenderer> mTarget;
85
86 AwesomeRemoteRenderer(const AwesomeRemoteRenderer &);
87 AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &);
88};
89
90struct AwesomeLocalRenderer : public AwesomeRenderer {
91 AwesomeLocalRenderer(
Andreas Huber7b73cfc2010-02-12 14:40:08 -080092 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080093 const char *componentName,
Andreas Huber1314e732009-12-14 14:18:22 -080094 OMX_COLOR_FORMATTYPE colorFormat,
95 const sp<ISurface> &surface,
96 size_t displayWidth, size_t displayHeight,
97 size_t decodedWidth, size_t decodedHeight)
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080098 : mTarget(NULL),
99 mLibHandle(NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800100 init(previewOnly, componentName,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800101 colorFormat, surface, displayWidth,
102 displayHeight, decodedWidth, decodedHeight);
Andreas Huber1314e732009-12-14 14:18:22 -0800103 }
104
105 virtual void render(MediaBuffer *buffer) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800106 render((const uint8_t *)buffer->data() + buffer->range_offset(),
107 buffer->range_length());
108 }
109
110 void render(const void *data, size_t size) {
111 mTarget->render(data, size, NULL);
Andreas Huber1314e732009-12-14 14:18:22 -0800112 }
113
114protected:
115 virtual ~AwesomeLocalRenderer() {
116 delete mTarget;
117 mTarget = NULL;
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800118
119 if (mLibHandle) {
120 dlclose(mLibHandle);
121 mLibHandle = NULL;
122 }
Andreas Huber1314e732009-12-14 14:18:22 -0800123 }
124
125private:
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800126 VideoRenderer *mTarget;
127 void *mLibHandle;
128
129 void init(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800130 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800131 const char *componentName,
132 OMX_COLOR_FORMATTYPE colorFormat,
133 const sp<ISurface> &surface,
134 size_t displayWidth, size_t displayHeight,
135 size_t decodedWidth, size_t decodedHeight);
Andreas Huber1314e732009-12-14 14:18:22 -0800136
137 AwesomeLocalRenderer(const AwesomeLocalRenderer &);
138 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
139};
140
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800141void AwesomeLocalRenderer::init(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800142 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800143 const char *componentName,
144 OMX_COLOR_FORMATTYPE colorFormat,
145 const sp<ISurface> &surface,
146 size_t displayWidth, size_t displayHeight,
147 size_t decodedWidth, size_t decodedHeight) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800148 if (!previewOnly) {
149 // We will stick to the vanilla software-color-converting renderer
150 // for "previewOnly" mode, to avoid unneccessarily switching overlays
151 // more often than necessary.
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800152
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800153 mLibHandle = dlopen("libstagefrighthw.so", RTLD_NOW);
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800154
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800155 if (mLibHandle) {
156 typedef VideoRenderer *(*CreateRendererFunc)(
157 const sp<ISurface> &surface,
158 const char *componentName,
159 OMX_COLOR_FORMATTYPE colorFormat,
160 size_t displayWidth, size_t displayHeight,
161 size_t decodedWidth, size_t decodedHeight);
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800162
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800163 CreateRendererFunc func =
164 (CreateRendererFunc)dlsym(
165 mLibHandle,
166 "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20"
167 "OMX_COLOR_FORMATTYPEjjjj");
168
169 if (func) {
170 mTarget =
171 (*func)(surface, componentName, colorFormat,
172 displayWidth, displayHeight,
173 decodedWidth, decodedHeight);
174 }
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800175 }
176 }
177
178 if (mTarget == NULL) {
179 mTarget = new SoftwareRenderer(
180 colorFormat, surface, displayWidth, displayHeight,
181 decodedWidth, decodedHeight);
182 }
183}
184
Andreas Huber27366fc2009-11-20 09:32:46 -0800185AwesomePlayer::AwesomePlayer()
Andreas Huber406a18b2010-02-18 16:45:13 -0800186 : mQueueStarted(false),
187 mTimeSource(NULL),
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800188 mVideoRendererIsPreview(false),
Andreas Huber27366fc2009-11-20 09:32:46 -0800189 mAudioPlayer(NULL),
Andreas Huberffdf4782010-02-09 14:05:43 -0800190 mFlags(0),
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700191 mExtractorFlags(0),
Andreas Huber27366fc2009-11-20 09:32:46 -0800192 mLastVideoBuffer(NULL),
Andreas Huberba7ec912010-02-12 10:42:02 -0800193 mVideoBuffer(NULL),
194 mSuspensionState(NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800195 CHECK_EQ(mClient.connect(), OK);
196
197 DataSource::RegisterDefaultSniffers();
198
Andreas Huber6be780e2010-02-08 14:40:30 -0800199 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
Andreas Huber27366fc2009-11-20 09:32:46 -0800200 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800201 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
Andreas Huber27366fc2009-11-20 09:32:46 -0800202 mStreamDoneEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800203 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
Andreas Huberb9e63832010-01-26 16:20:10 -0800204 mBufferingEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800205
206 mCheckAudioStatusEvent = new AwesomeEvent(
207 this, &AwesomePlayer::onCheckAudioStatus);
208
Andreas Huber70d10c02010-02-03 11:37:29 -0800209 mAudioStatusEventPending = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800210
Andreas Huber27366fc2009-11-20 09:32:46 -0800211 reset();
212}
213
214AwesomePlayer::~AwesomePlayer() {
Andreas Huber406a18b2010-02-18 16:45:13 -0800215 if (mQueueStarted) {
216 mQueue.stop();
217 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800218
219 reset();
220
221 mClient.disconnect();
222}
223
Andreas Huberb9e63832010-01-26 16:20:10 -0800224void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800225 mQueue.cancelEvent(mVideoEvent->eventID());
226 mVideoEventPending = false;
227 mQueue.cancelEvent(mStreamDoneEvent->eventID());
228 mStreamDoneEventPending = false;
Andreas Huber70d10c02010-02-03 11:37:29 -0800229 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
230 mAudioStatusEventPending = false;
Andreas Huberb9e63832010-01-26 16:20:10 -0800231
232 if (!keepBufferingGoing) {
233 mQueue.cancelEvent(mBufferingEvent->eventID());
234 mBufferingEventPending = false;
235 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800236}
237
Andreas Hubera3f43842010-01-21 10:28:45 -0800238void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800239 Mutex::Autolock autoLock(mLock);
240 mListener = listener;
241}
242
Andreas Huber433c9ac2010-01-27 16:49:05 -0800243status_t AwesomePlayer::setDataSource(
244 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800245 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800246 return setDataSource_l(uri, headers);
247}
Andreas Huber27366fc2009-11-20 09:32:46 -0800248
Andreas Huberba7ec912010-02-12 10:42:02 -0800249status_t AwesomePlayer::setDataSource_l(
250 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800251 reset_l();
252
Andreas Huberffdf4782010-02-09 14:05:43 -0800253 mUri = uri;
Andreas Huberb9e63832010-01-26 16:20:10 -0800254
Andreas Huberffdf4782010-02-09 14:05:43 -0800255 if (headers) {
256 mUriHeaders = *headers;
Andreas Huberb9e63832010-01-26 16:20:10 -0800257 }
258
Andreas Huberffdf4782010-02-09 14:05:43 -0800259 // The actual work will be done during preparation in the call to
260 // ::finishSetDataSource_l to avoid blocking the calling thread in
261 // setDataSource for any significant time.
Andreas Huber27366fc2009-11-20 09:32:46 -0800262
Andreas Huberffdf4782010-02-09 14:05:43 -0800263 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800264}
265
266status_t AwesomePlayer::setDataSource(
267 int fd, int64_t offset, int64_t length) {
Andreas Huber202348e2010-06-07 14:35:29 -0700268#if 0
269 // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/nasatv/nasatv_96.m3u8");
270 // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/nasatv/nasatv_1500.m3u8");
271 return setDataSource("httplive://iphone.video.hsn.com/iPhone_high.m3u8");
272 // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/iphonewebcast/webcast090209_all/webcast090209_all.m3u8");
273 // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/usat/tt_062209_iphone/hi/prog_index.m3u8");
274 // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/usat/tt_googmaps/hi/prog_index.m3u8");
275 // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/mtv/ni_spo_25a_rt74137_clip_syn/hi/prog_index.m3u8");
276#endif
277
Andreas Huber27366fc2009-11-20 09:32:46 -0800278 Mutex::Autolock autoLock(mLock);
279
280 reset_l();
281
Andreas Huberba7ec912010-02-12 10:42:02 -0800282 sp<DataSource> dataSource = new FileSource(fd, offset, length);
Andreas Huber27366fc2009-11-20 09:32:46 -0800283
Andreas Huberba7ec912010-02-12 10:42:02 -0800284 status_t err = dataSource->initCheck();
Andreas Huber27366fc2009-11-20 09:32:46 -0800285
286 if (err != OK) {
287 return err;
288 }
289
Andreas Huberba7ec912010-02-12 10:42:02 -0800290 mFileSource = dataSource;
291
292 return setDataSource_l(dataSource);
293}
294
295status_t AwesomePlayer::setDataSource_l(
296 const sp<DataSource> &dataSource) {
297 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
Andreas Huber27366fc2009-11-20 09:32:46 -0800298
299 if (extractor == NULL) {
300 return UNKNOWN_ERROR;
301 }
302
303 return setDataSource_l(extractor);
304}
305
306status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800307 bool haveAudio = false;
308 bool haveVideo = false;
309 for (size_t i = 0; i < extractor->countTracks(); ++i) {
310 sp<MetaData> meta = extractor->getTrackMetaData(i);
311
312 const char *mime;
313 CHECK(meta->findCString(kKeyMIMEType, &mime));
314
315 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800316 setVideoSource(extractor->getTrack(i));
317 haveVideo = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800318 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800319 setAudioSource(extractor->getTrack(i));
320 haveAudio = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800321 }
322
323 if (haveAudio && haveVideo) {
324 break;
325 }
326 }
327
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700328 if (!haveAudio && !haveVideo) {
329 return UNKNOWN_ERROR;
330 }
331
332 mExtractorFlags = extractor->flags();
333
334 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800335}
336
337void AwesomePlayer::reset() {
338 Mutex::Autolock autoLock(mLock);
339 reset_l();
340}
341
342void AwesomePlayer::reset_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -0800343 if (mFlags & PREPARING) {
344 mFlags |= PREPARE_CANCELLED;
345 if (mConnectingDataSource != NULL) {
346 LOGI("interrupting the connection process");
347 mConnectingDataSource->disconnect();
348 }
349 }
350
Andreas Huberffdf4782010-02-09 14:05:43 -0800351 while (mFlags & PREPARING) {
352 mPreparedCondition.wait(mLock);
353 }
354
Andreas Huber27366fc2009-11-20 09:32:46 -0800355 cancelPlayerEvents();
356
Andreas Huberba7ec912010-02-12 10:42:02 -0800357 if (mPrefetcher != NULL) {
358 CHECK_EQ(mPrefetcher->getStrongCount(), 1);
359 }
360 mPrefetcher.clear();
361
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800362 mAudioTrack.clear();
363 mVideoTrack.clear();
364
Andreas Huberba7ec912010-02-12 10:42:02 -0800365 // Shutdown audio first, so that the respone to the reset request
366 // appears to happen instantaneously as far as the user is concerned
367 // If we did this later, audio would continue playing while we
368 // shutdown the video-related resources and the player appear to
369 // not be as responsive to a reset request.
Andreas Huberedbb4d82010-03-12 08:59:22 -0800370 if (mAudioPlayer == NULL && mAudioSource != NULL) {
371 // If we had an audio player, it would have effectively
372 // taken possession of the audio source and stopped it when
373 // _it_ is stopped. Otherwise this is still our responsibility.
374 mAudioSource->stop();
375 }
Andreas Huberba7ec912010-02-12 10:42:02 -0800376 mAudioSource.clear();
377
378 if (mTimeSource != mAudioPlayer) {
379 delete mTimeSource;
380 }
381 mTimeSource = NULL;
382
383 delete mAudioPlayer;
384 mAudioPlayer = NULL;
385
Andreas Huber3522b5a52010-01-22 14:36:53 -0800386 mVideoRenderer.clear();
387
Andreas Huber27366fc2009-11-20 09:32:46 -0800388 if (mLastVideoBuffer) {
389 mLastVideoBuffer->release();
390 mLastVideoBuffer = NULL;
391 }
392
393 if (mVideoBuffer) {
394 mVideoBuffer->release();
395 mVideoBuffer = NULL;
396 }
397
Andreas Huber7a747b82010-06-07 15:19:40 -0700398 mRTSPController.clear();
399
Andreas Huber27366fc2009-11-20 09:32:46 -0800400 if (mVideoSource != NULL) {
401 mVideoSource->stop();
Andreas Huber98b48de2010-01-29 10:10:22 -0800402
403 // The following hack is necessary to ensure that the OMX
404 // component is completely released by the time we may try
405 // to instantiate it again.
406 wp<MediaSource> tmp = mVideoSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800407 mVideoSource.clear();
Andreas Huber98b48de2010-01-29 10:10:22 -0800408 while (tmp.promote() != NULL) {
409 usleep(1000);
410 }
411 IPCThreadState::self()->flushCommands();
Andreas Huber27366fc2009-11-20 09:32:46 -0800412 }
413
Andreas Huber27366fc2009-11-20 09:32:46 -0800414 mDurationUs = -1;
415 mFlags = 0;
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700416 mExtractorFlags = 0;
Andreas Huber27366fc2009-11-20 09:32:46 -0800417 mVideoWidth = mVideoHeight = -1;
418 mTimeSourceDeltaUs = 0;
419 mVideoTimeUs = 0;
420
421 mSeeking = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700422 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800423 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800424
Andreas Huberffdf4782010-02-09 14:05:43 -0800425 mUri.setTo("");
426 mUriHeaders.clear();
Andreas Huberba7ec912010-02-12 10:42:02 -0800427
428 mFileSource.clear();
429
430 delete mSuspensionState;
431 mSuspensionState = NULL;
Andreas Huber27366fc2009-11-20 09:32:46 -0800432}
433
Andreas Huber6be780e2010-02-08 14:40:30 -0800434void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800435 if (mListener != NULL) {
436 sp<MediaPlayerBase> listener = mListener.promote();
437
438 if (listener != NULL) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800439 listener->sendEvent(msg, ext1, ext2);
Andreas Hubera3f43842010-01-21 10:28:45 -0800440 }
441 }
442}
443
Andreas Huberb9e63832010-01-26 16:20:10 -0800444void AwesomePlayer::onBufferingUpdate() {
445 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800446 if (!mBufferingEventPending) {
447 return;
448 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800449 mBufferingEventPending = false;
450
Andreas Huber252573c2010-03-26 10:17:17 -0700451 int64_t durationUs;
452 {
453 Mutex::Autolock autoLock(mMiscStateLock);
454 durationUs = mDurationUs;
455 }
456
Andreas Huber202348e2010-06-07 14:35:29 -0700457 int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs();
458
459 LOGI("cache holds %.2f secs worth of data.", cachedDurationUs / 1E6);
460
Andreas Huber252573c2010-03-26 10:17:17 -0700461 if (durationUs >= 0) {
Andreas Huber252573c2010-03-26 10:17:17 -0700462 int64_t positionUs;
463 getPosition(&positionUs);
Andreas Huberb9e63832010-01-26 16:20:10 -0800464
465 cachedDurationUs += positionUs;
466
Andreas Huber252573c2010-03-26 10:17:17 -0700467 double percentage = (double)cachedDurationUs / durationUs;
Andreas Huberb9e63832010-01-26 16:20:10 -0800468 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
469
470 postBufferingEvent_l();
Andreas Huber040301c2010-04-12 09:41:12 -0700471 } else {
Andreas Huber202348e2010-06-07 14:35:29 -0700472 // LOGE("Not sending buffering status because duration is unknown.");
473 postBufferingEvent_l();
Andreas Huberb9e63832010-01-26 16:20:10 -0800474 }
475}
476
Andreas Huber27366fc2009-11-20 09:32:46 -0800477void AwesomePlayer::onStreamDone() {
478 // Posted whenever any stream finishes playing.
479
480 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800481 if (!mStreamDoneEventPending) {
482 return;
483 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800484 mStreamDoneEventPending = false;
485
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800486 if (mStreamDoneStatus == ERROR_END_OF_STREAM && (mFlags & LOOPING)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800487 seekTo_l(0);
488
Andreas Huber7085b6842010-02-03 16:02:02 -0800489 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800490 postVideoEvent_l();
491 }
492 } else {
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800493 if (mStreamDoneStatus == ERROR_END_OF_STREAM) {
494 LOGV("MEDIA_PLAYBACK_COMPLETE");
495 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
496 } else {
497 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
498
499 notifyListener_l(
500 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
501 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800502
503 pause_l();
Andreas Huber406a18b2010-02-18 16:45:13 -0800504
505 mFlags |= AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800506 }
507}
508
509status_t AwesomePlayer::play() {
510 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800511 return play_l();
512}
Andreas Huber27366fc2009-11-20 09:32:46 -0800513
Andreas Huberba7ec912010-02-12 10:42:02 -0800514status_t AwesomePlayer::play_l() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800515 if (mFlags & PLAYING) {
516 return OK;
517 }
518
Andreas Huberffdf4782010-02-09 14:05:43 -0800519 if (!(mFlags & PREPARED)) {
520 status_t err = prepare_l();
521
522 if (err != OK) {
523 return err;
524 }
525 }
526
Andreas Huber27366fc2009-11-20 09:32:46 -0800527 mFlags |= PLAYING;
528 mFlags |= FIRST_FRAME;
529
Andreas Huberc1d5c922009-12-10 15:49:04 -0800530 bool deferredAudioSeek = false;
531
Andreas Huber27366fc2009-11-20 09:32:46 -0800532 if (mAudioSource != NULL) {
533 if (mAudioPlayer == NULL) {
534 if (mAudioSink != NULL) {
535 mAudioPlayer = new AudioPlayer(mAudioSink);
Andreas Huber27366fc2009-11-20 09:32:46 -0800536 mAudioPlayer->setSource(mAudioSource);
Andreas Huberdc9927d2010-03-08 15:46:13 -0800537
538 // We've already started the MediaSource in order to enable
539 // the prefetcher to read its data.
540 status_t err = mAudioPlayer->start(
541 true /* sourceAlreadyStarted */);
Andreas Huber62eac002010-01-29 13:24:58 -0800542
543 if (err != OK) {
544 delete mAudioPlayer;
545 mAudioPlayer = NULL;
546
547 mFlags &= ~(PLAYING | FIRST_FRAME);
548
549 return err;
550 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800551
552 delete mTimeSource;
553 mTimeSource = mAudioPlayer;
554
Andreas Huberc1d5c922009-12-10 15:49:04 -0800555 deferredAudioSeek = true;
Andreas Huber70d10c02010-02-03 11:37:29 -0800556
557 mWatchForAudioSeekComplete = false;
558 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800559 }
560 } else {
561 mAudioPlayer->resume();
562 }
Andreas Huber70d10c02010-02-03 11:37:29 -0800563
564 postCheckAudioStatusEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800565 }
566
567 if (mTimeSource == NULL && mAudioPlayer == NULL) {
568 mTimeSource = new SystemTimeSource;
569 }
570
571 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800572 // Kick off video playback
573 postVideoEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800574 }
575
Andreas Huberc1d5c922009-12-10 15:49:04 -0800576 if (deferredAudioSeek) {
577 // If there was a seek request while we were paused
578 // and we're just starting up again, honor the request now.
579 seekAudioIfNecessary_l();
580 }
581
Andreas Huber406a18b2010-02-18 16:45:13 -0800582 if (mFlags & AT_EOS) {
583 // Legacy behaviour, if a stream finishes playing and then
584 // is started again, we play from the start...
585 seekTo_l(0);
586 }
587
Andreas Huber27366fc2009-11-20 09:32:46 -0800588 return OK;
589}
590
591void AwesomePlayer::initRenderer_l() {
592 if (mISurface != NULL) {
593 sp<MetaData> meta = mVideoSource->getFormat();
594
595 int32_t format;
596 const char *component;
597 int32_t decodedWidth, decodedHeight;
598 CHECK(meta->findInt32(kKeyColorFormat, &format));
599 CHECK(meta->findCString(kKeyDecoderComponent, &component));
600 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
601 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
602
Andreas Hubera67d5382009-12-10 15:32:12 -0800603 mVideoRenderer.clear();
604
605 // Must ensure that mVideoRenderer's destructor is actually executed
606 // before creating a new one.
607 IPCThreadState::self()->flushCommands();
608
Andreas Huber1314e732009-12-14 14:18:22 -0800609 if (!strncmp("OMX.", component, 4)) {
610 // Our OMX codecs allocate buffers on the media_server side
611 // therefore they require a remote IOMXRenderer that knows how
612 // to display them.
613 mVideoRenderer = new AwesomeRemoteRenderer(
614 mClient.interface()->createRenderer(
615 mISurface, component,
616 (OMX_COLOR_FORMATTYPE)format,
617 decodedWidth, decodedHeight,
618 mVideoWidth, mVideoHeight));
619 } else {
620 // Other decoders are instantiated locally and as a consequence
621 // allocate their buffers in local address space.
622 mVideoRenderer = new AwesomeLocalRenderer(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800623 false, // previewOnly
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800624 component,
Andreas Huber1314e732009-12-14 14:18:22 -0800625 (OMX_COLOR_FORMATTYPE)format,
626 mISurface,
627 mVideoWidth, mVideoHeight,
628 decodedWidth, decodedHeight);
629 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800630 }
631}
632
633status_t AwesomePlayer::pause() {
634 Mutex::Autolock autoLock(mLock);
635 return pause_l();
636}
637
638status_t AwesomePlayer::pause_l() {
639 if (!(mFlags & PLAYING)) {
640 return OK;
641 }
642
Andreas Huberb9e63832010-01-26 16:20:10 -0800643 cancelPlayerEvents(true /* keepBufferingGoing */);
Andreas Huber27366fc2009-11-20 09:32:46 -0800644
645 if (mAudioPlayer != NULL) {
646 mAudioPlayer->pause();
647 }
648
649 mFlags &= ~PLAYING;
650
651 return OK;
652}
653
654bool AwesomePlayer::isPlaying() const {
Andreas Huber27366fc2009-11-20 09:32:46 -0800655 return mFlags & PLAYING;
656}
657
658void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
659 Mutex::Autolock autoLock(mLock);
660
661 mISurface = isurface;
662}
663
664void AwesomePlayer::setAudioSink(
665 const sp<MediaPlayerBase::AudioSink> &audioSink) {
666 Mutex::Autolock autoLock(mLock);
667
668 mAudioSink = audioSink;
669}
670
671status_t AwesomePlayer::setLooping(bool shouldLoop) {
672 Mutex::Autolock autoLock(mLock);
673
674 mFlags = mFlags & ~LOOPING;
675
676 if (shouldLoop) {
677 mFlags |= LOOPING;
678 }
679
680 return OK;
681}
682
683status_t AwesomePlayer::getDuration(int64_t *durationUs) {
Andreas Huber252573c2010-03-26 10:17:17 -0700684 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800685
686 if (mDurationUs < 0) {
687 return UNKNOWN_ERROR;
688 }
689
690 *durationUs = mDurationUs;
691
692 return OK;
693}
694
695status_t AwesomePlayer::getPosition(int64_t *positionUs) {
Andreas Huberddb709c2010-04-07 10:24:35 -0700696 if (mSeeking) {
697 *positionUs = mSeekTimeUs;
698 } else if (mVideoSource != NULL) {
Andreas Huber252573c2010-03-26 10:17:17 -0700699 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800700 *positionUs = mVideoTimeUs;
701 } else if (mAudioPlayer != NULL) {
702 *positionUs = mAudioPlayer->getMediaTimeUs();
703 } else {
704 *positionUs = 0;
705 }
706
707 return OK;
708}
709
710status_t AwesomePlayer::seekTo(int64_t timeUs) {
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700711 if (mExtractorFlags
712 & (MediaExtractor::CAN_SEEK_FORWARD
713 | MediaExtractor::CAN_SEEK_BACKWARD)) {
714 Mutex::Autolock autoLock(mLock);
715 return seekTo_l(timeUs);
716 }
717
718 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800719}
720
721status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
722 mSeeking = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700723 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800724 mSeekTimeUs = timeUs;
Andreas Huber406a18b2010-02-18 16:45:13 -0800725 mFlags &= ~AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800726
727 seekAudioIfNecessary_l();
728
Andreas Huber8e2b9412010-03-31 09:40:15 -0700729 if (!(mFlags & PLAYING)) {
730 LOGV("seeking while paused, sending SEEK_COMPLETE notification"
731 " immediately.");
732
733 notifyListener_l(MEDIA_SEEK_COMPLETE);
734 mSeekNotificationSent = true;
735 }
736
Andreas Huber27366fc2009-11-20 09:32:46 -0800737 return OK;
738}
739
740void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Huber7085b6842010-02-03 16:02:02 -0800741 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800742 mAudioPlayer->seekTo(mSeekTimeUs);
743
Andreas Huber70d10c02010-02-03 11:37:29 -0800744 mWatchForAudioSeekComplete = true;
745 mWatchForAudioEOS = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700746 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800747 }
748}
749
750status_t AwesomePlayer::getVideoDimensions(
751 int32_t *width, int32_t *height) const {
752 Mutex::Autolock autoLock(mLock);
753
754 if (mVideoWidth < 0 || mVideoHeight < 0) {
755 return UNKNOWN_ERROR;
756 }
757
758 *width = mVideoWidth;
759 *height = mVideoHeight;
760
761 return OK;
762}
763
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800764void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
765 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800766
Andreas Huberb9e63832010-01-26 16:20:10 -0800767 if (mPrefetcher != NULL) {
768 source = mPrefetcher->addSource(source);
769 }
770
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800771 mAudioTrack = source;
772}
773
774status_t AwesomePlayer::initAudioDecoder() {
775 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huberc79827a2010-01-05 10:54:55 -0800776
777 const char *mime;
778 CHECK(meta->findCString(kKeyMIMEType, &mime));
779
780 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800781 mAudioSource = mAudioTrack;
Andreas Huberc79827a2010-01-05 10:54:55 -0800782 } else {
783 mAudioSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800784 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huberc79827a2010-01-05 10:54:55 -0800785 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800786 mAudioTrack);
Andreas Huberc79827a2010-01-05 10:54:55 -0800787 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800788
789 if (mAudioSource != NULL) {
790 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800791 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -0700792 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800793 if (mDurationUs < 0 || durationUs > mDurationUs) {
794 mDurationUs = durationUs;
795 }
796 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800797
Andreas Huber3c78a1b2010-05-13 09:15:21 -0700798 status_t err = mAudioSource->start();
799
800 if (err != OK) {
801 mAudioSource.clear();
802 return err;
803 }
Andreas Huberd0332ad2010-04-12 16:05:57 -0700804 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
805 // For legacy reasons we're simply going to ignore the absence
806 // of an audio decoder for QCELP instead of aborting playback
807 // altogether.
808 return OK;
809 }
Andreas Huberdc9927d2010-03-08 15:46:13 -0800810
Andreas Huber27366fc2009-11-20 09:32:46 -0800811 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
812}
813
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800814void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
815 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800816
Andreas Huberb9e63832010-01-26 16:20:10 -0800817 if (mPrefetcher != NULL) {
818 source = mPrefetcher->addSource(source);
819 }
820
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800821 mVideoTrack = source;
822}
823
824status_t AwesomePlayer::initVideoDecoder() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800825 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800826 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -0800827 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800828 mVideoTrack);
Andreas Huber27366fc2009-11-20 09:32:46 -0800829
830 if (mVideoSource != NULL) {
831 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800832 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -0700833 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800834 if (mDurationUs < 0 || durationUs > mDurationUs) {
835 mDurationUs = durationUs;
836 }
837 }
838
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800839 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
840 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
Andreas Huber27366fc2009-11-20 09:32:46 -0800841
Andreas Huber1919e5a2010-05-20 10:37:06 -0700842 status_t err = mVideoSource->start();
843
844 if (err != OK) {
845 mVideoSource.clear();
846 return err;
847 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800848 }
849
850 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
851}
852
Andreas Huber6be780e2010-02-08 14:40:30 -0800853void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800854 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800855 if (!mVideoEventPending) {
856 // The event has been cancelled in reset_l() but had already
857 // been scheduled for execution at that time.
858 return;
859 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800860 mVideoEventPending = false;
861
862 if (mSeeking) {
863 if (mLastVideoBuffer) {
864 mLastVideoBuffer->release();
865 mLastVideoBuffer = NULL;
866 }
867
868 if (mVideoBuffer) {
869 mVideoBuffer->release();
870 mVideoBuffer = NULL;
871 }
872 }
873
874 if (!mVideoBuffer) {
875 MediaSource::ReadOptions options;
876 if (mSeeking) {
877 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
878
879 options.setSeekTo(mSeekTimeUs);
880 }
881 for (;;) {
882 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -0800883 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -0800884
885 if (err != OK) {
886 CHECK_EQ(mVideoBuffer, NULL);
887
888 if (err == INFO_FORMAT_CHANGED) {
889 LOGV("VideoSource signalled format change.");
890
Andreas Huber7085b6842010-02-03 16:02:02 -0800891 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800892 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -0800893 initRenderer_l();
894 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800895 continue;
896 }
897
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800898 postStreamDoneEvent_l(err);
Andreas Huber27366fc2009-11-20 09:32:46 -0800899 return;
900 }
901
Andreas Hubera67d5382009-12-10 15:32:12 -0800902 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -0800903 // Some decoders, notably the PV AVC software decoder
904 // return spurious empty buffers that we just want to ignore.
905
Andreas Hubera67d5382009-12-10 15:32:12 -0800906 mVideoBuffer->release();
907 mVideoBuffer = NULL;
908 continue;
909 }
910
Andreas Huber27366fc2009-11-20 09:32:46 -0800911 break;
912 }
913 }
914
915 int64_t timeUs;
916 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
917
Andreas Huber252573c2010-03-26 10:17:17 -0700918 {
919 Mutex::Autolock autoLock(mMiscStateLock);
920 mVideoTimeUs = timeUs;
921 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800922
923 if (mSeeking) {
924 if (mAudioPlayer != NULL) {
925 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
926
927 mAudioPlayer->seekTo(timeUs);
Andreas Huber70d10c02010-02-03 11:37:29 -0800928 mWatchForAudioSeekComplete = true;
929 mWatchForAudioEOS = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700930 } else if (!mSeekNotificationSent) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800931 // If we're playing video only, report seek complete now,
932 // otherwise audio player will notify us later.
Andreas Hubera3f43842010-01-21 10:28:45 -0800933 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800934 }
935
936 mFlags |= FIRST_FRAME;
937 mSeeking = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700938 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800939 }
940
941 if (mFlags & FIRST_FRAME) {
942 mFlags &= ~FIRST_FRAME;
943
944 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
945 }
946
947 int64_t realTimeUs, mediaTimeUs;
948 if (mAudioPlayer != NULL
949 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
950 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
951 }
952
953 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
954
955 int64_t latenessUs = nowUs - timeUs;
956
Andreas Huber24b0a952009-11-23 14:02:00 -0800957 if (latenessUs > 40000) {
958 // We're more than 40ms late.
Andreas Huber4a9375e2010-02-09 11:54:33 -0800959 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -0800960
961 mVideoBuffer->release();
962 mVideoBuffer = NULL;
963
964 postVideoEvent_l();
965 return;
966 }
967
968 if (latenessUs < -10000) {
969 // We're more than 10ms early.
970
971 postVideoEvent_l(10000);
972 return;
973 }
974
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800975 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
976 mVideoRendererIsPreview = false;
977
Andreas Huber7085b6842010-02-03 16:02:02 -0800978 initRenderer_l();
979 }
980
981 if (mVideoRenderer != NULL) {
982 mVideoRenderer->render(mVideoBuffer);
983 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800984
985 if (mLastVideoBuffer) {
986 mLastVideoBuffer->release();
987 mLastVideoBuffer = NULL;
988 }
989 mLastVideoBuffer = mVideoBuffer;
990 mVideoBuffer = NULL;
991
992 postVideoEvent_l();
993}
994
995void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
996 if (mVideoEventPending) {
997 return;
998 }
999
1000 mVideoEventPending = true;
1001 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1002}
1003
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001004void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001005 if (mStreamDoneEventPending) {
1006 return;
1007 }
1008 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001009
1010 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -08001011 mQueue.postEvent(mStreamDoneEvent);
1012}
1013
Andreas Huberb9e63832010-01-26 16:20:10 -08001014void AwesomePlayer::postBufferingEvent_l() {
1015 if (mPrefetcher == NULL) {
1016 return;
1017 }
1018
1019 if (mBufferingEventPending) {
1020 return;
1021 }
1022 mBufferingEventPending = true;
1023 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1024}
1025
Andreas Huber70d10c02010-02-03 11:37:29 -08001026void AwesomePlayer::postCheckAudioStatusEvent_l() {
1027 if (mAudioStatusEventPending) {
1028 return;
1029 }
1030 mAudioStatusEventPending = true;
1031 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
1032}
1033
1034void AwesomePlayer::onCheckAudioStatus() {
1035 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -08001036 if (!mAudioStatusEventPending) {
1037 // Event was dispatched and while we were blocking on the mutex,
1038 // has already been cancelled.
1039 return;
1040 }
1041
Andreas Huber70d10c02010-02-03 11:37:29 -08001042 mAudioStatusEventPending = false;
1043
1044 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1045 mWatchForAudioSeekComplete = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001046
1047 if (!mSeekNotificationSent) {
1048 notifyListener_l(MEDIA_SEEK_COMPLETE);
1049 mSeekNotificationSent = true;
1050 }
Andreas Huberddb709c2010-04-07 10:24:35 -07001051
1052 mSeeking = false;
Andreas Huber70d10c02010-02-03 11:37:29 -08001053 }
1054
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001055 status_t finalStatus;
1056 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -08001057 mWatchForAudioEOS = false;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001058 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -08001059 }
1060
1061 postCheckAudioStatusEvent_l();
1062}
1063
Andreas Huber6be780e2010-02-08 14:40:30 -08001064status_t AwesomePlayer::prepare() {
1065 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001066 return prepare_l();
1067}
Andreas Huber6be780e2010-02-08 14:40:30 -08001068
Andreas Huberffdf4782010-02-09 14:05:43 -08001069status_t AwesomePlayer::prepare_l() {
1070 if (mFlags & PREPARED) {
1071 return OK;
1072 }
1073
1074 if (mFlags & PREPARING) {
1075 return UNKNOWN_ERROR;
1076 }
1077
1078 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -08001079 status_t err = prepareAsync_l();
1080
1081 if (err != OK) {
1082 return err;
1083 }
1084
Andreas Huberffdf4782010-02-09 14:05:43 -08001085 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001086 mPreparedCondition.wait(mLock);
1087 }
1088
Andreas Huberffdf4782010-02-09 14:05:43 -08001089 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001090}
1091
1092status_t AwesomePlayer::prepareAsync() {
1093 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001094
1095 if (mFlags & PREPARING) {
1096 return UNKNOWN_ERROR; // async prepare already pending
1097 }
1098
1099 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001100 return prepareAsync_l();
1101}
1102
1103status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001104 if (mFlags & PREPARING) {
1105 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001106 }
1107
Andreas Huber406a18b2010-02-18 16:45:13 -08001108 if (!mQueueStarted) {
1109 mQueue.start();
1110 mQueueStarted = true;
1111 }
1112
Andreas Huberffdf4782010-02-09 14:05:43 -08001113 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -08001114 mAsyncPrepareEvent = new AwesomeEvent(
1115 this, &AwesomePlayer::onPrepareAsyncEvent);
1116
1117 mQueue.postEvent(mAsyncPrepareEvent);
1118
1119 return OK;
1120}
1121
Andreas Huberffdf4782010-02-09 14:05:43 -08001122status_t AwesomePlayer::finishSetDataSource_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001123 sp<DataSource> dataSource;
1124
1125 if (!strncasecmp("http://", mUri.string(), 7)) {
1126 mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders);
1127
1128 mLock.unlock();
1129 status_t err = mConnectingDataSource->connect();
1130 mLock.lock();
1131
1132 if (err != OK) {
1133 mConnectingDataSource.clear();
1134
1135 LOGI("mConnectingDataSource->connect() returned %d", err);
1136 return err;
1137 }
1138
1139 dataSource = new CachingDataSource(
Andreas Hubera51250b2010-04-08 07:51:20 -07001140 mConnectingDataSource, 64 * 1024, 10);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001141
1142 mConnectingDataSource.clear();
Andreas Huber202348e2010-06-07 14:35:29 -07001143 } else if (!strncasecmp(mUri.string(), "httplive://", 11)) {
1144 String8 uri("http://");
1145 uri.append(mUri.string() + 11);
1146
1147 dataSource = new LiveSource(uri.string());
1148
1149 if (dataSource->flags() & DataSource::kWantsPrefetching) {
1150 mPrefetcher = new Prefetcher;
1151 }
1152
1153 sp<MediaExtractor> extractor =
1154 MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
Andreas Huber7a747b82010-06-07 15:19:40 -07001155 } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
1156 if (mLooper == NULL) {
1157 mLooper = new ALooper;
1158 mLooper->start();
1159 }
1160 mRTSPController = new ARTSPController(mLooper);
1161 status_t err = mRTSPController->connect(mUri.string());
Andreas Huber202348e2010-06-07 14:35:29 -07001162
Andreas Huber7a747b82010-06-07 15:19:40 -07001163 LOGI("ARTSPController::connect returned %d", err);
1164
1165 if (err != OK) {
1166 mRTSPController.clear();
1167 return err;
1168 }
1169
1170 sp<MediaExtractor> extractor = mRTSPController.get();
Andreas Huber202348e2010-06-07 14:35:29 -07001171 return setDataSource_l(extractor);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001172 } else {
1173 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1174 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001175
1176 if (dataSource == NULL) {
1177 return UNKNOWN_ERROR;
1178 }
1179
1180 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1181
1182 if (extractor == NULL) {
1183 return UNKNOWN_ERROR;
1184 }
1185
1186 if (dataSource->flags() & DataSource::kWantsPrefetching) {
1187 mPrefetcher = new Prefetcher;
1188 }
1189
1190 return setDataSource_l(extractor);
1191}
1192
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001193void AwesomePlayer::abortPrepare(status_t err) {
1194 CHECK(err != OK);
1195
1196 if (mIsAsyncPrepare) {
1197 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1198 }
1199
1200 mPrepareResult = err;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001201 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001202 mAsyncPrepareEvent = NULL;
1203 mPreparedCondition.broadcast();
1204}
1205
Andreas Huberf71daba2010-03-24 09:24:40 -07001206// static
1207bool AwesomePlayer::ContinuePreparation(void *cookie) {
1208 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1209
1210 return (me->mFlags & PREPARE_CANCELLED) == 0;
1211}
1212
Andreas Huber6be780e2010-02-08 14:40:30 -08001213void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber55864df72010-03-08 12:28:22 -08001214 sp<Prefetcher> prefetcher;
1215
Andreas Huberffdf4782010-02-09 14:05:43 -08001216 {
1217 Mutex::Autolock autoLock(mLock);
1218
Andreas Huberedbb4d82010-03-12 08:59:22 -08001219 if (mFlags & PREPARE_CANCELLED) {
1220 LOGI("prepare was cancelled before doing anything");
1221 abortPrepare(UNKNOWN_ERROR);
1222 return;
1223 }
1224
Andreas Huberffdf4782010-02-09 14:05:43 -08001225 if (mUri.size() > 0) {
1226 status_t err = finishSetDataSource_l();
1227
1228 if (err != OK) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001229 abortPrepare(err);
Andreas Huberffdf4782010-02-09 14:05:43 -08001230 return;
1231 }
1232 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001233
Andreas Huber55864df72010-03-08 12:28:22 -08001234 if (mVideoTrack != NULL && mVideoSource == NULL) {
1235 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08001236
Andreas Huber55864df72010-03-08 12:28:22 -08001237 if (err != OK) {
1238 abortPrepare(err);
1239 return;
1240 }
1241 }
1242
1243 if (mAudioTrack != NULL && mAudioSource == NULL) {
1244 status_t err = initAudioDecoder();
1245
1246 if (err != OK) {
1247 abortPrepare(err);
1248 return;
1249 }
1250 }
1251
Andreas Huber6be780e2010-02-08 14:40:30 -08001252 prefetcher = mPrefetcher;
1253 }
1254
1255 if (prefetcher != NULL) {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001256 {
1257 Mutex::Autolock autoLock(mLock);
1258 if (mFlags & PREPARE_CANCELLED) {
1259 LOGI("prepare was cancelled before preparing the prefetcher");
Andreas Huber9b732de2010-03-23 15:30:57 -07001260
1261 prefetcher.clear();
Andreas Huberedbb4d82010-03-12 08:59:22 -08001262 abortPrepare(UNKNOWN_ERROR);
1263 return;
1264 }
1265 }
1266
1267 LOGI("calling prefetcher->prepare()");
Andreas Huberf71daba2010-03-24 09:24:40 -07001268 status_t result =
1269 prefetcher->prepare(&AwesomePlayer::ContinuePreparation, this);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001270
Andreas Huberba7ec912010-02-12 10:42:02 -08001271 prefetcher.clear();
Andreas Huberf71daba2010-03-24 09:24:40 -07001272
1273 if (result == OK) {
Andreas Huber252573c2010-03-26 10:17:17 -07001274 LOGI("prefetcher is done preparing");
Andreas Huberf71daba2010-03-24 09:24:40 -07001275 } else {
1276 Mutex::Autolock autoLock(mLock);
1277
1278 CHECK_EQ(result, -EINTR);
1279
1280 LOGI("prefetcher->prepare() was cancelled early.");
1281 abortPrepare(UNKNOWN_ERROR);
1282 return;
1283 }
Andreas Huber6be780e2010-02-08 14:40:30 -08001284 }
1285
1286 Mutex::Autolock autoLock(mLock);
1287
Andreas Huberffdf4782010-02-09 14:05:43 -08001288 if (mIsAsyncPrepare) {
1289 if (mVideoWidth < 0 || mVideoHeight < 0) {
1290 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1291 } else {
1292 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
1293 }
1294
1295 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08001296 }
1297
Andreas Huberffdf4782010-02-09 14:05:43 -08001298 mPrepareResult = OK;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001299 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huberffdf4782010-02-09 14:05:43 -08001300 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -08001301 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08001302 mPreparedCondition.broadcast();
Andreas Huber040301c2010-04-12 09:41:12 -07001303
1304 postBufferingEvent_l();
Andreas Huber6be780e2010-02-08 14:40:30 -08001305}
1306
Andreas Huberba7ec912010-02-12 10:42:02 -08001307status_t AwesomePlayer::suspend() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001308 LOGV("suspend");
Andreas Huberba7ec912010-02-12 10:42:02 -08001309 Mutex::Autolock autoLock(mLock);
1310
1311 if (mSuspensionState != NULL) {
Gloria Wangb19da8e2010-04-12 17:13:06 -07001312 if (mLastVideoBuffer == NULL) {
1313 //go into here if video is suspended again
1314 //after resuming without being played between
1315 //them
1316 SuspensionState *state = mSuspensionState;
1317 mSuspensionState = NULL;
1318 reset_l();
1319 mSuspensionState = state;
1320 return OK;
1321 }
1322
1323 delete mSuspensionState;
1324 mSuspensionState = NULL;
Andreas Huberba7ec912010-02-12 10:42:02 -08001325 }
1326
Andreas Huberedbb4d82010-03-12 08:59:22 -08001327 if (mFlags & PREPARING) {
1328 mFlags |= PREPARE_CANCELLED;
1329 if (mConnectingDataSource != NULL) {
1330 LOGI("interrupting the connection process");
1331 mConnectingDataSource->disconnect();
1332 }
1333 }
1334
Andreas Huberba7ec912010-02-12 10:42:02 -08001335 while (mFlags & PREPARING) {
1336 mPreparedCondition.wait(mLock);
1337 }
1338
1339 SuspensionState *state = new SuspensionState;
1340 state->mUri = mUri;
1341 state->mUriHeaders = mUriHeaders;
1342 state->mFileSource = mFileSource;
1343
Andreas Huber406a18b2010-02-18 16:45:13 -08001344 state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS);
Andreas Huber252573c2010-03-26 10:17:17 -07001345 getPosition(&state->mPositionUs);
Andreas Huberba7ec912010-02-12 10:42:02 -08001346
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001347 if (mLastVideoBuffer) {
1348 size_t size = mLastVideoBuffer->range_length();
1349 if (size) {
1350 state->mLastVideoFrameSize = size;
1351 state->mLastVideoFrame = malloc(size);
1352 memcpy(state->mLastVideoFrame,
1353 (const uint8_t *)mLastVideoBuffer->data()
1354 + mLastVideoBuffer->range_offset(),
1355 size);
1356
1357 state->mVideoWidth = mVideoWidth;
1358 state->mVideoHeight = mVideoHeight;
1359
1360 sp<MetaData> meta = mVideoSource->getFormat();
1361 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1362 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1363 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1364 }
1365 }
1366
Andreas Huberba7ec912010-02-12 10:42:02 -08001367 reset_l();
1368
1369 mSuspensionState = state;
1370
1371 return OK;
1372}
1373
1374status_t AwesomePlayer::resume() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001375 LOGV("resume");
Andreas Huberba7ec912010-02-12 10:42:02 -08001376 Mutex::Autolock autoLock(mLock);
1377
1378 if (mSuspensionState == NULL) {
1379 return INVALID_OPERATION;
1380 }
1381
1382 SuspensionState *state = mSuspensionState;
1383 mSuspensionState = NULL;
1384
1385 status_t err;
1386 if (state->mFileSource != NULL) {
1387 err = setDataSource_l(state->mFileSource);
1388
1389 if (err == OK) {
1390 mFileSource = state->mFileSource;
1391 }
1392 } else {
1393 err = setDataSource_l(state->mUri, &state->mUriHeaders);
1394 }
1395
1396 if (err != OK) {
1397 delete state;
1398 state = NULL;
1399
1400 return err;
1401 }
1402
1403 seekTo_l(state->mPositionUs);
1404
Andreas Huber406a18b2010-02-18 16:45:13 -08001405 mFlags = state->mFlags & (LOOPING | AT_EOS);
Andreas Huberba7ec912010-02-12 10:42:02 -08001406
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001407 if (state->mLastVideoFrame && mISurface != NULL) {
1408 mVideoRenderer =
1409 new AwesomeLocalRenderer(
1410 true, // previewOnly
1411 "",
1412 (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1413 mISurface,
1414 state->mVideoWidth,
1415 state->mVideoHeight,
1416 state->mDecodedWidth,
1417 state->mDecodedHeight);
1418
1419 mVideoRendererIsPreview = true;
1420
1421 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render(
1422 state->mLastVideoFrame, state->mLastVideoFrameSize);
1423 }
1424
Andreas Huberba7ec912010-02-12 10:42:02 -08001425 if (state->mFlags & PLAYING) {
1426 play_l();
1427 }
1428
Gloria Wangb19da8e2010-04-12 17:13:06 -07001429 mSuspensionState = state;
Andreas Huberba7ec912010-02-12 10:42:02 -08001430 state = NULL;
1431
1432 return OK;
1433}
1434
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001435uint32_t AwesomePlayer::flags() const {
1436 return mExtractorFlags;
1437}
1438
Andreas Huber27366fc2009-11-20 09:32:46 -08001439} // namespace android
1440