blob: 842176ed3cdc463bbd9a8d0acb01ab1d78ce4754 [file] [log] [blame]
Andreas Huber27366fc2009-11-20 09:32:46 -08001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "AwesomePlayer"
19#include <utils/Log.h>
20
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080021#include <dlfcn.h>
22
Andreas Huber27366fc2009-11-20 09:32:46 -080023#include "include/AwesomePlayer.h"
Andreas Huberb9e63832010-01-26 16:20:10 -080024#include "include/Prefetcher.h"
Andreas Huber1314e732009-12-14 14:18:22 -080025#include "include/SoftwareRenderer.h"
Andreas Huber27366fc2009-11-20 09:32:46 -080026
Andreas Hubera67d5382009-12-10 15:32:12 -080027#include <binder/IPCThreadState.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080028#include <media/stagefright/AudioPlayer.h>
Andreas Huberedbb4d82010-03-12 08:59:22 -080029#include <media/stagefright/CachingDataSource.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080030#include <media/stagefright/DataSource.h>
31#include <media/stagefright/FileSource.h>
32#include <media/stagefright/MediaBuffer.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080033#include <media/stagefright/MediaDefs.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080034#include <media/stagefright/MediaExtractor.h>
35#include <media/stagefright/MediaDebug.h>
36#include <media/stagefright/MediaSource.h>
37#include <media/stagefright/MetaData.h>
38#include <media/stagefright/OMXCodec.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080039
Mathias Agopian000479f2010-02-09 17:46:37 -080040#include <surfaceflinger/ISurface.h>
41
Andreas Huber27366fc2009-11-20 09:32:46 -080042namespace android {
43
44struct AwesomeEvent : public TimedEventQueue::Event {
Andreas Huber6be780e2010-02-08 14:40:30 -080045 AwesomeEvent(
46 AwesomePlayer *player,
47 void (AwesomePlayer::*method)())
Andreas Huber27366fc2009-11-20 09:32:46 -080048 : mPlayer(player),
Andreas Huber6be780e2010-02-08 14:40:30 -080049 mMethod(method) {
Andreas Huber27366fc2009-11-20 09:32:46 -080050 }
51
52protected:
53 virtual ~AwesomeEvent() {}
54
55 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
Andreas Huber6be780e2010-02-08 14:40:30 -080056 (mPlayer->*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080057 }
58
59private:
60 AwesomePlayer *mPlayer;
Andreas Huber6be780e2010-02-08 14:40:30 -080061 void (AwesomePlayer::*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080062
63 AwesomeEvent(const AwesomeEvent &);
64 AwesomeEvent &operator=(const AwesomeEvent &);
65};
66
Andreas Huber1314e732009-12-14 14:18:22 -080067struct AwesomeRemoteRenderer : public AwesomeRenderer {
68 AwesomeRemoteRenderer(const sp<IOMXRenderer> &target)
69 : mTarget(target) {
70 }
71
72 virtual void render(MediaBuffer *buffer) {
73 void *id;
74 if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) {
75 mTarget->render((IOMX::buffer_id)id);
76 }
77 }
78
79private:
80 sp<IOMXRenderer> mTarget;
81
82 AwesomeRemoteRenderer(const AwesomeRemoteRenderer &);
83 AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &);
84};
85
86struct AwesomeLocalRenderer : public AwesomeRenderer {
87 AwesomeLocalRenderer(
Andreas Huber7b73cfc2010-02-12 14:40:08 -080088 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080089 const char *componentName,
Andreas Huber1314e732009-12-14 14:18:22 -080090 OMX_COLOR_FORMATTYPE colorFormat,
91 const sp<ISurface> &surface,
92 size_t displayWidth, size_t displayHeight,
93 size_t decodedWidth, size_t decodedHeight)
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080094 : mTarget(NULL),
95 mLibHandle(NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -080096 init(previewOnly, componentName,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080097 colorFormat, surface, displayWidth,
98 displayHeight, decodedWidth, decodedHeight);
Andreas Huber1314e732009-12-14 14:18:22 -080099 }
100
101 virtual void render(MediaBuffer *buffer) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800102 render((const uint8_t *)buffer->data() + buffer->range_offset(),
103 buffer->range_length());
104 }
105
106 void render(const void *data, size_t size) {
107 mTarget->render(data, size, NULL);
Andreas Huber1314e732009-12-14 14:18:22 -0800108 }
109
110protected:
111 virtual ~AwesomeLocalRenderer() {
112 delete mTarget;
113 mTarget = NULL;
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800114
115 if (mLibHandle) {
116 dlclose(mLibHandle);
117 mLibHandle = NULL;
118 }
Andreas Huber1314e732009-12-14 14:18:22 -0800119 }
120
121private:
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800122 VideoRenderer *mTarget;
123 void *mLibHandle;
124
125 void init(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800126 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800127 const char *componentName,
128 OMX_COLOR_FORMATTYPE colorFormat,
129 const sp<ISurface> &surface,
130 size_t displayWidth, size_t displayHeight,
131 size_t decodedWidth, size_t decodedHeight);
Andreas Huber1314e732009-12-14 14:18:22 -0800132
133 AwesomeLocalRenderer(const AwesomeLocalRenderer &);
134 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
135};
136
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800137void AwesomeLocalRenderer::init(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800138 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800139 const char *componentName,
140 OMX_COLOR_FORMATTYPE colorFormat,
141 const sp<ISurface> &surface,
142 size_t displayWidth, size_t displayHeight,
143 size_t decodedWidth, size_t decodedHeight) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800144 if (!previewOnly) {
145 // We will stick to the vanilla software-color-converting renderer
146 // for "previewOnly" mode, to avoid unneccessarily switching overlays
147 // more often than necessary.
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800148
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800149 mLibHandle = dlopen("libstagefrighthw.so", RTLD_NOW);
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800150
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800151 if (mLibHandle) {
152 typedef VideoRenderer *(*CreateRendererFunc)(
153 const sp<ISurface> &surface,
154 const char *componentName,
155 OMX_COLOR_FORMATTYPE colorFormat,
156 size_t displayWidth, size_t displayHeight,
157 size_t decodedWidth, size_t decodedHeight);
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800158
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800159 CreateRendererFunc func =
160 (CreateRendererFunc)dlsym(
161 mLibHandle,
162 "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20"
163 "OMX_COLOR_FORMATTYPEjjjj");
164
165 if (func) {
166 mTarget =
167 (*func)(surface, componentName, colorFormat,
168 displayWidth, displayHeight,
169 decodedWidth, decodedHeight);
170 }
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800171 }
172 }
173
174 if (mTarget == NULL) {
175 mTarget = new SoftwareRenderer(
176 colorFormat, surface, displayWidth, displayHeight,
177 decodedWidth, decodedHeight);
178 }
179}
180
Andreas Huber27366fc2009-11-20 09:32:46 -0800181AwesomePlayer::AwesomePlayer()
Andreas Huber406a18b2010-02-18 16:45:13 -0800182 : mQueueStarted(false),
183 mTimeSource(NULL),
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800184 mVideoRendererIsPreview(false),
Andreas Huber27366fc2009-11-20 09:32:46 -0800185 mAudioPlayer(NULL),
Andreas Huberffdf4782010-02-09 14:05:43 -0800186 mFlags(0),
Andreas Huber27366fc2009-11-20 09:32:46 -0800187 mLastVideoBuffer(NULL),
Andreas Huberba7ec912010-02-12 10:42:02 -0800188 mVideoBuffer(NULL),
189 mSuspensionState(NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800190 CHECK_EQ(mClient.connect(), OK);
191
192 DataSource::RegisterDefaultSniffers();
193
Andreas Huber6be780e2010-02-08 14:40:30 -0800194 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
Andreas Huber27366fc2009-11-20 09:32:46 -0800195 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800196 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
Andreas Huber27366fc2009-11-20 09:32:46 -0800197 mStreamDoneEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800198 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
Andreas Huberb9e63832010-01-26 16:20:10 -0800199 mBufferingEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800200
201 mCheckAudioStatusEvent = new AwesomeEvent(
202 this, &AwesomePlayer::onCheckAudioStatus);
203
Andreas Huber70d10c02010-02-03 11:37:29 -0800204 mAudioStatusEventPending = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800205
Andreas Huber27366fc2009-11-20 09:32:46 -0800206 reset();
207}
208
209AwesomePlayer::~AwesomePlayer() {
Andreas Huber406a18b2010-02-18 16:45:13 -0800210 if (mQueueStarted) {
211 mQueue.stop();
212 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800213
214 reset();
215
216 mClient.disconnect();
217}
218
Andreas Huberb9e63832010-01-26 16:20:10 -0800219void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800220 mQueue.cancelEvent(mVideoEvent->eventID());
221 mVideoEventPending = false;
222 mQueue.cancelEvent(mStreamDoneEvent->eventID());
223 mStreamDoneEventPending = false;
Andreas Huber70d10c02010-02-03 11:37:29 -0800224 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
225 mAudioStatusEventPending = false;
Andreas Huberb9e63832010-01-26 16:20:10 -0800226
227 if (!keepBufferingGoing) {
228 mQueue.cancelEvent(mBufferingEvent->eventID());
229 mBufferingEventPending = false;
230 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800231}
232
Andreas Hubera3f43842010-01-21 10:28:45 -0800233void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800234 Mutex::Autolock autoLock(mLock);
235 mListener = listener;
236}
237
Andreas Huber433c9ac2010-01-27 16:49:05 -0800238status_t AwesomePlayer::setDataSource(
239 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800240 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800241 return setDataSource_l(uri, headers);
242}
Andreas Huber27366fc2009-11-20 09:32:46 -0800243
Andreas Huberba7ec912010-02-12 10:42:02 -0800244status_t AwesomePlayer::setDataSource_l(
245 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800246 reset_l();
247
Andreas Huberffdf4782010-02-09 14:05:43 -0800248 mUri = uri;
Andreas Huberb9e63832010-01-26 16:20:10 -0800249
Andreas Huberffdf4782010-02-09 14:05:43 -0800250 if (headers) {
251 mUriHeaders = *headers;
Andreas Huberb9e63832010-01-26 16:20:10 -0800252 }
253
Andreas Huberffdf4782010-02-09 14:05:43 -0800254 // The actual work will be done during preparation in the call to
255 // ::finishSetDataSource_l to avoid blocking the calling thread in
256 // setDataSource for any significant time.
Andreas Huber27366fc2009-11-20 09:32:46 -0800257
Andreas Huberffdf4782010-02-09 14:05:43 -0800258 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800259}
260
261status_t AwesomePlayer::setDataSource(
262 int fd, int64_t offset, int64_t length) {
263 Mutex::Autolock autoLock(mLock);
264
265 reset_l();
266
Andreas Huberba7ec912010-02-12 10:42:02 -0800267 sp<DataSource> dataSource = new FileSource(fd, offset, length);
Andreas Huber27366fc2009-11-20 09:32:46 -0800268
Andreas Huberba7ec912010-02-12 10:42:02 -0800269 status_t err = dataSource->initCheck();
Andreas Huber27366fc2009-11-20 09:32:46 -0800270
271 if (err != OK) {
272 return err;
273 }
274
Andreas Huberba7ec912010-02-12 10:42:02 -0800275 mFileSource = dataSource;
276
277 return setDataSource_l(dataSource);
278}
279
280status_t AwesomePlayer::setDataSource_l(
281 const sp<DataSource> &dataSource) {
282 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
Andreas Huber27366fc2009-11-20 09:32:46 -0800283
284 if (extractor == NULL) {
285 return UNKNOWN_ERROR;
286 }
287
288 return setDataSource_l(extractor);
289}
290
291status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800292 bool haveAudio = false;
293 bool haveVideo = false;
294 for (size_t i = 0; i < extractor->countTracks(); ++i) {
295 sp<MetaData> meta = extractor->getTrackMetaData(i);
296
297 const char *mime;
298 CHECK(meta->findCString(kKeyMIMEType, &mime));
299
300 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800301 setVideoSource(extractor->getTrack(i));
302 haveVideo = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800303 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800304 setAudioSource(extractor->getTrack(i));
305 haveAudio = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800306 }
307
308 if (haveAudio && haveVideo) {
309 break;
310 }
311 }
312
313 return !haveAudio && !haveVideo ? UNKNOWN_ERROR : OK;
314}
315
316void AwesomePlayer::reset() {
317 Mutex::Autolock autoLock(mLock);
318 reset_l();
319}
320
321void AwesomePlayer::reset_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -0800322 if (mFlags & PREPARING) {
323 mFlags |= PREPARE_CANCELLED;
324 if (mConnectingDataSource != NULL) {
325 LOGI("interrupting the connection process");
326 mConnectingDataSource->disconnect();
327 }
328 }
329
Andreas Huberffdf4782010-02-09 14:05:43 -0800330 while (mFlags & PREPARING) {
331 mPreparedCondition.wait(mLock);
332 }
333
Andreas Huber27366fc2009-11-20 09:32:46 -0800334 cancelPlayerEvents();
335
Andreas Huberba7ec912010-02-12 10:42:02 -0800336 if (mPrefetcher != NULL) {
337 CHECK_EQ(mPrefetcher->getStrongCount(), 1);
338 }
339 mPrefetcher.clear();
340
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800341 mAudioTrack.clear();
342 mVideoTrack.clear();
343
Andreas Huberba7ec912010-02-12 10:42:02 -0800344 // Shutdown audio first, so that the respone to the reset request
345 // appears to happen instantaneously as far as the user is concerned
346 // If we did this later, audio would continue playing while we
347 // shutdown the video-related resources and the player appear to
348 // not be as responsive to a reset request.
Andreas Huberedbb4d82010-03-12 08:59:22 -0800349 if (mAudioPlayer == NULL && mAudioSource != NULL) {
350 // If we had an audio player, it would have effectively
351 // taken possession of the audio source and stopped it when
352 // _it_ is stopped. Otherwise this is still our responsibility.
353 mAudioSource->stop();
354 }
Andreas Huberba7ec912010-02-12 10:42:02 -0800355 mAudioSource.clear();
356
357 if (mTimeSource != mAudioPlayer) {
358 delete mTimeSource;
359 }
360 mTimeSource = NULL;
361
362 delete mAudioPlayer;
363 mAudioPlayer = NULL;
364
Andreas Huber3522b5a52010-01-22 14:36:53 -0800365 mVideoRenderer.clear();
366
Andreas Huber27366fc2009-11-20 09:32:46 -0800367 if (mLastVideoBuffer) {
368 mLastVideoBuffer->release();
369 mLastVideoBuffer = NULL;
370 }
371
372 if (mVideoBuffer) {
373 mVideoBuffer->release();
374 mVideoBuffer = NULL;
375 }
376
377 if (mVideoSource != NULL) {
378 mVideoSource->stop();
Andreas Huber98b48de2010-01-29 10:10:22 -0800379
380 // The following hack is necessary to ensure that the OMX
381 // component is completely released by the time we may try
382 // to instantiate it again.
383 wp<MediaSource> tmp = mVideoSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800384 mVideoSource.clear();
Andreas Huber98b48de2010-01-29 10:10:22 -0800385 while (tmp.promote() != NULL) {
386 usleep(1000);
387 }
388 IPCThreadState::self()->flushCommands();
Andreas Huber27366fc2009-11-20 09:32:46 -0800389 }
390
Andreas Huber27366fc2009-11-20 09:32:46 -0800391 mDurationUs = -1;
392 mFlags = 0;
393 mVideoWidth = mVideoHeight = -1;
394 mTimeSourceDeltaUs = 0;
395 mVideoTimeUs = 0;
396
397 mSeeking = false;
398 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800399
Andreas Huberffdf4782010-02-09 14:05:43 -0800400 mUri.setTo("");
401 mUriHeaders.clear();
Andreas Huberba7ec912010-02-12 10:42:02 -0800402
403 mFileSource.clear();
404
405 delete mSuspensionState;
406 mSuspensionState = NULL;
Andreas Huber27366fc2009-11-20 09:32:46 -0800407}
408
Andreas Huber6be780e2010-02-08 14:40:30 -0800409void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800410 if (mListener != NULL) {
411 sp<MediaPlayerBase> listener = mListener.promote();
412
413 if (listener != NULL) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800414 listener->sendEvent(msg, ext1, ext2);
Andreas Hubera3f43842010-01-21 10:28:45 -0800415 }
416 }
417}
418
Andreas Huberb9e63832010-01-26 16:20:10 -0800419void AwesomePlayer::onBufferingUpdate() {
420 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800421 if (!mBufferingEventPending) {
422 return;
423 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800424 mBufferingEventPending = false;
425
Andreas Huber252573c2010-03-26 10:17:17 -0700426 int64_t durationUs;
427 {
428 Mutex::Autolock autoLock(mMiscStateLock);
429 durationUs = mDurationUs;
430 }
431
432 if (durationUs >= 0) {
Andreas Huberb9e63832010-01-26 16:20:10 -0800433 int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs();
Andreas Huberdc9927d2010-03-08 15:46:13 -0800434
435 LOGV("cache holds %.2f secs worth of data.", cachedDurationUs / 1E6);
436
Andreas Huber252573c2010-03-26 10:17:17 -0700437 int64_t positionUs;
438 getPosition(&positionUs);
Andreas Huberb9e63832010-01-26 16:20:10 -0800439
440 cachedDurationUs += positionUs;
441
Andreas Huber252573c2010-03-26 10:17:17 -0700442 double percentage = (double)cachedDurationUs / durationUs;
Andreas Huberb9e63832010-01-26 16:20:10 -0800443 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
444
445 postBufferingEvent_l();
446 }
447}
448
Andreas Huber27366fc2009-11-20 09:32:46 -0800449void AwesomePlayer::onStreamDone() {
450 // Posted whenever any stream finishes playing.
451
452 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800453 if (!mStreamDoneEventPending) {
454 return;
455 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800456 mStreamDoneEventPending = false;
457
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800458 if (mStreamDoneStatus == ERROR_END_OF_STREAM && (mFlags & LOOPING)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800459 seekTo_l(0);
460
Andreas Huber7085b6842010-02-03 16:02:02 -0800461 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800462 postVideoEvent_l();
463 }
464 } else {
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800465 if (mStreamDoneStatus == ERROR_END_OF_STREAM) {
466 LOGV("MEDIA_PLAYBACK_COMPLETE");
467 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
468 } else {
469 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
470
471 notifyListener_l(
472 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
473 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800474
475 pause_l();
Andreas Huber406a18b2010-02-18 16:45:13 -0800476
477 mFlags |= AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800478 }
479}
480
481status_t AwesomePlayer::play() {
482 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800483 return play_l();
484}
Andreas Huber27366fc2009-11-20 09:32:46 -0800485
Andreas Huberba7ec912010-02-12 10:42:02 -0800486status_t AwesomePlayer::play_l() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800487 if (mFlags & PLAYING) {
488 return OK;
489 }
490
Andreas Huberffdf4782010-02-09 14:05:43 -0800491 if (!(mFlags & PREPARED)) {
492 status_t err = prepare_l();
493
494 if (err != OK) {
495 return err;
496 }
497 }
498
Andreas Huber27366fc2009-11-20 09:32:46 -0800499 mFlags |= PLAYING;
500 mFlags |= FIRST_FRAME;
501
Andreas Huberc1d5c922009-12-10 15:49:04 -0800502 bool deferredAudioSeek = false;
503
Andreas Huber27366fc2009-11-20 09:32:46 -0800504 if (mAudioSource != NULL) {
505 if (mAudioPlayer == NULL) {
506 if (mAudioSink != NULL) {
507 mAudioPlayer = new AudioPlayer(mAudioSink);
Andreas Huber27366fc2009-11-20 09:32:46 -0800508 mAudioPlayer->setSource(mAudioSource);
Andreas Huberdc9927d2010-03-08 15:46:13 -0800509
510 // We've already started the MediaSource in order to enable
511 // the prefetcher to read its data.
512 status_t err = mAudioPlayer->start(
513 true /* sourceAlreadyStarted */);
Andreas Huber62eac002010-01-29 13:24:58 -0800514
515 if (err != OK) {
516 delete mAudioPlayer;
517 mAudioPlayer = NULL;
518
519 mFlags &= ~(PLAYING | FIRST_FRAME);
520
521 return err;
522 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800523
524 delete mTimeSource;
525 mTimeSource = mAudioPlayer;
526
Andreas Huberc1d5c922009-12-10 15:49:04 -0800527 deferredAudioSeek = true;
Andreas Huber70d10c02010-02-03 11:37:29 -0800528
529 mWatchForAudioSeekComplete = false;
530 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800531 }
532 } else {
533 mAudioPlayer->resume();
534 }
Andreas Huber70d10c02010-02-03 11:37:29 -0800535
536 postCheckAudioStatusEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800537 }
538
539 if (mTimeSource == NULL && mAudioPlayer == NULL) {
540 mTimeSource = new SystemTimeSource;
541 }
542
543 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800544 // Kick off video playback
545 postVideoEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800546 }
547
Andreas Huberc1d5c922009-12-10 15:49:04 -0800548 if (deferredAudioSeek) {
549 // If there was a seek request while we were paused
550 // and we're just starting up again, honor the request now.
551 seekAudioIfNecessary_l();
552 }
553
Andreas Huberb9e63832010-01-26 16:20:10 -0800554 postBufferingEvent_l();
555
Andreas Huber406a18b2010-02-18 16:45:13 -0800556 if (mFlags & AT_EOS) {
557 // Legacy behaviour, if a stream finishes playing and then
558 // is started again, we play from the start...
559 seekTo_l(0);
560 }
561
Andreas Huber27366fc2009-11-20 09:32:46 -0800562 return OK;
563}
564
565void AwesomePlayer::initRenderer_l() {
566 if (mISurface != NULL) {
567 sp<MetaData> meta = mVideoSource->getFormat();
568
569 int32_t format;
570 const char *component;
571 int32_t decodedWidth, decodedHeight;
572 CHECK(meta->findInt32(kKeyColorFormat, &format));
573 CHECK(meta->findCString(kKeyDecoderComponent, &component));
574 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
575 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
576
Andreas Hubera67d5382009-12-10 15:32:12 -0800577 mVideoRenderer.clear();
578
579 // Must ensure that mVideoRenderer's destructor is actually executed
580 // before creating a new one.
581 IPCThreadState::self()->flushCommands();
582
Andreas Huber1314e732009-12-14 14:18:22 -0800583 if (!strncmp("OMX.", component, 4)) {
584 // Our OMX codecs allocate buffers on the media_server side
585 // therefore they require a remote IOMXRenderer that knows how
586 // to display them.
587 mVideoRenderer = new AwesomeRemoteRenderer(
588 mClient.interface()->createRenderer(
589 mISurface, component,
590 (OMX_COLOR_FORMATTYPE)format,
591 decodedWidth, decodedHeight,
592 mVideoWidth, mVideoHeight));
593 } else {
594 // Other decoders are instantiated locally and as a consequence
595 // allocate their buffers in local address space.
596 mVideoRenderer = new AwesomeLocalRenderer(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800597 false, // previewOnly
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800598 component,
Andreas Huber1314e732009-12-14 14:18:22 -0800599 (OMX_COLOR_FORMATTYPE)format,
600 mISurface,
601 mVideoWidth, mVideoHeight,
602 decodedWidth, decodedHeight);
603 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800604 }
605}
606
607status_t AwesomePlayer::pause() {
608 Mutex::Autolock autoLock(mLock);
609 return pause_l();
610}
611
612status_t AwesomePlayer::pause_l() {
613 if (!(mFlags & PLAYING)) {
614 return OK;
615 }
616
Andreas Huberb9e63832010-01-26 16:20:10 -0800617 cancelPlayerEvents(true /* keepBufferingGoing */);
Andreas Huber27366fc2009-11-20 09:32:46 -0800618
619 if (mAudioPlayer != NULL) {
620 mAudioPlayer->pause();
621 }
622
623 mFlags &= ~PLAYING;
624
625 return OK;
626}
627
628bool AwesomePlayer::isPlaying() const {
Andreas Huber27366fc2009-11-20 09:32:46 -0800629 return mFlags & PLAYING;
630}
631
632void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
633 Mutex::Autolock autoLock(mLock);
634
635 mISurface = isurface;
636}
637
638void AwesomePlayer::setAudioSink(
639 const sp<MediaPlayerBase::AudioSink> &audioSink) {
640 Mutex::Autolock autoLock(mLock);
641
642 mAudioSink = audioSink;
643}
644
645status_t AwesomePlayer::setLooping(bool shouldLoop) {
646 Mutex::Autolock autoLock(mLock);
647
648 mFlags = mFlags & ~LOOPING;
649
650 if (shouldLoop) {
651 mFlags |= LOOPING;
652 }
653
654 return OK;
655}
656
657status_t AwesomePlayer::getDuration(int64_t *durationUs) {
Andreas Huber252573c2010-03-26 10:17:17 -0700658 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800659
660 if (mDurationUs < 0) {
661 return UNKNOWN_ERROR;
662 }
663
664 *durationUs = mDurationUs;
665
666 return OK;
667}
668
669status_t AwesomePlayer::getPosition(int64_t *positionUs) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800670 if (mVideoSource != NULL) {
Andreas Huber252573c2010-03-26 10:17:17 -0700671 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800672 *positionUs = mVideoTimeUs;
673 } else if (mAudioPlayer != NULL) {
674 *positionUs = mAudioPlayer->getMediaTimeUs();
675 } else {
676 *positionUs = 0;
677 }
678
679 return OK;
680}
681
682status_t AwesomePlayer::seekTo(int64_t timeUs) {
683 Mutex::Autolock autoLock(mLock);
684 return seekTo_l(timeUs);
685}
686
687status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
688 mSeeking = true;
689 mSeekTimeUs = timeUs;
Andreas Huber406a18b2010-02-18 16:45:13 -0800690 mFlags &= ~AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800691
692 seekAudioIfNecessary_l();
693
694 return OK;
695}
696
697void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Huber7085b6842010-02-03 16:02:02 -0800698 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800699 mAudioPlayer->seekTo(mSeekTimeUs);
700
Andreas Huber70d10c02010-02-03 11:37:29 -0800701 mWatchForAudioSeekComplete = true;
702 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800703 mSeeking = false;
704 }
705}
706
707status_t AwesomePlayer::getVideoDimensions(
708 int32_t *width, int32_t *height) const {
709 Mutex::Autolock autoLock(mLock);
710
711 if (mVideoWidth < 0 || mVideoHeight < 0) {
712 return UNKNOWN_ERROR;
713 }
714
715 *width = mVideoWidth;
716 *height = mVideoHeight;
717
718 return OK;
719}
720
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800721void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
722 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800723
Andreas Huberb9e63832010-01-26 16:20:10 -0800724 if (mPrefetcher != NULL) {
725 source = mPrefetcher->addSource(source);
726 }
727
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800728 mAudioTrack = source;
729}
730
731status_t AwesomePlayer::initAudioDecoder() {
732 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huberc79827a2010-01-05 10:54:55 -0800733
734 const char *mime;
735 CHECK(meta->findCString(kKeyMIMEType, &mime));
736
737 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800738 mAudioSource = mAudioTrack;
Andreas Huberc79827a2010-01-05 10:54:55 -0800739 } else {
740 mAudioSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800741 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huberc79827a2010-01-05 10:54:55 -0800742 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800743 mAudioTrack);
Andreas Huberc79827a2010-01-05 10:54:55 -0800744 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800745
746 if (mAudioSource != NULL) {
747 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800748 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -0700749 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800750 if (mDurationUs < 0 || durationUs > mDurationUs) {
751 mDurationUs = durationUs;
752 }
753 }
754 }
755
Andreas Huberdc9927d2010-03-08 15:46:13 -0800756 mAudioSource->start();
757
Andreas Huber27366fc2009-11-20 09:32:46 -0800758 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
759}
760
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800761void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
762 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800763
Andreas Huberb9e63832010-01-26 16:20:10 -0800764 if (mPrefetcher != NULL) {
765 source = mPrefetcher->addSource(source);
766 }
767
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800768 mVideoTrack = source;
769}
770
771status_t AwesomePlayer::initVideoDecoder() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800772 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800773 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -0800774 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800775 mVideoTrack);
Andreas Huber27366fc2009-11-20 09:32:46 -0800776
777 if (mVideoSource != NULL) {
778 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800779 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -0700780 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800781 if (mDurationUs < 0 || durationUs > mDurationUs) {
782 mDurationUs = durationUs;
783 }
784 }
785
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800786 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
787 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
Andreas Huber27366fc2009-11-20 09:32:46 -0800788
789 mVideoSource->start();
790 }
791
792 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
793}
794
Andreas Huber6be780e2010-02-08 14:40:30 -0800795void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800796 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800797 if (!mVideoEventPending) {
798 // The event has been cancelled in reset_l() but had already
799 // been scheduled for execution at that time.
800 return;
801 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800802 mVideoEventPending = false;
803
804 if (mSeeking) {
805 if (mLastVideoBuffer) {
806 mLastVideoBuffer->release();
807 mLastVideoBuffer = NULL;
808 }
809
810 if (mVideoBuffer) {
811 mVideoBuffer->release();
812 mVideoBuffer = NULL;
813 }
814 }
815
816 if (!mVideoBuffer) {
817 MediaSource::ReadOptions options;
818 if (mSeeking) {
819 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
820
821 options.setSeekTo(mSeekTimeUs);
822 }
823 for (;;) {
824 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -0800825 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -0800826
827 if (err != OK) {
828 CHECK_EQ(mVideoBuffer, NULL);
829
830 if (err == INFO_FORMAT_CHANGED) {
831 LOGV("VideoSource signalled format change.");
832
Andreas Huber7085b6842010-02-03 16:02:02 -0800833 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800834 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -0800835 initRenderer_l();
836 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800837 continue;
838 }
839
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800840 postStreamDoneEvent_l(err);
Andreas Huber27366fc2009-11-20 09:32:46 -0800841 return;
842 }
843
Andreas Hubera67d5382009-12-10 15:32:12 -0800844 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -0800845 // Some decoders, notably the PV AVC software decoder
846 // return spurious empty buffers that we just want to ignore.
847
Andreas Hubera67d5382009-12-10 15:32:12 -0800848 mVideoBuffer->release();
849 mVideoBuffer = NULL;
850 continue;
851 }
852
Andreas Huber27366fc2009-11-20 09:32:46 -0800853 break;
854 }
855 }
856
857 int64_t timeUs;
858 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
859
Andreas Huber252573c2010-03-26 10:17:17 -0700860 {
861 Mutex::Autolock autoLock(mMiscStateLock);
862 mVideoTimeUs = timeUs;
863 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800864
865 if (mSeeking) {
866 if (mAudioPlayer != NULL) {
867 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
868
869 mAudioPlayer->seekTo(timeUs);
Andreas Huber70d10c02010-02-03 11:37:29 -0800870 mWatchForAudioSeekComplete = true;
871 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800872 } else {
873 // If we're playing video only, report seek complete now,
874 // otherwise audio player will notify us later.
Andreas Hubera3f43842010-01-21 10:28:45 -0800875 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800876 }
877
878 mFlags |= FIRST_FRAME;
879 mSeeking = false;
880 }
881
882 if (mFlags & FIRST_FRAME) {
883 mFlags &= ~FIRST_FRAME;
884
885 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
886 }
887
888 int64_t realTimeUs, mediaTimeUs;
889 if (mAudioPlayer != NULL
890 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
891 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
892 }
893
894 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
895
896 int64_t latenessUs = nowUs - timeUs;
897
Andreas Huber24b0a952009-11-23 14:02:00 -0800898 if (latenessUs > 40000) {
899 // We're more than 40ms late.
Andreas Huber4a9375e2010-02-09 11:54:33 -0800900 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -0800901
902 mVideoBuffer->release();
903 mVideoBuffer = NULL;
904
905 postVideoEvent_l();
906 return;
907 }
908
909 if (latenessUs < -10000) {
910 // We're more than 10ms early.
911
912 postVideoEvent_l(10000);
913 return;
914 }
915
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800916 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
917 mVideoRendererIsPreview = false;
918
Andreas Huber7085b6842010-02-03 16:02:02 -0800919 initRenderer_l();
920 }
921
922 if (mVideoRenderer != NULL) {
923 mVideoRenderer->render(mVideoBuffer);
924 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800925
926 if (mLastVideoBuffer) {
927 mLastVideoBuffer->release();
928 mLastVideoBuffer = NULL;
929 }
930 mLastVideoBuffer = mVideoBuffer;
931 mVideoBuffer = NULL;
932
933 postVideoEvent_l();
934}
935
936void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
937 if (mVideoEventPending) {
938 return;
939 }
940
941 mVideoEventPending = true;
942 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
943}
944
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800945void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800946 if (mStreamDoneEventPending) {
947 return;
948 }
949 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800950
951 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -0800952 mQueue.postEvent(mStreamDoneEvent);
953}
954
Andreas Huberb9e63832010-01-26 16:20:10 -0800955void AwesomePlayer::postBufferingEvent_l() {
956 if (mPrefetcher == NULL) {
957 return;
958 }
959
960 if (mBufferingEventPending) {
961 return;
962 }
963 mBufferingEventPending = true;
964 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
965}
966
Andreas Huber70d10c02010-02-03 11:37:29 -0800967void AwesomePlayer::postCheckAudioStatusEvent_l() {
968 if (mAudioStatusEventPending) {
969 return;
970 }
971 mAudioStatusEventPending = true;
972 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
973}
974
975void AwesomePlayer::onCheckAudioStatus() {
976 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800977 if (!mAudioStatusEventPending) {
978 // Event was dispatched and while we were blocking on the mutex,
979 // has already been cancelled.
980 return;
981 }
982
Andreas Huber70d10c02010-02-03 11:37:29 -0800983 mAudioStatusEventPending = false;
984
985 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
986 mWatchForAudioSeekComplete = false;
987 notifyListener_l(MEDIA_SEEK_COMPLETE);
988 }
989
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800990 status_t finalStatus;
991 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -0800992 mWatchForAudioEOS = false;
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800993 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -0800994 }
995
996 postCheckAudioStatusEvent_l();
997}
998
Andreas Huber6be780e2010-02-08 14:40:30 -0800999status_t AwesomePlayer::prepare() {
1000 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001001 return prepare_l();
1002}
Andreas Huber6be780e2010-02-08 14:40:30 -08001003
Andreas Huberffdf4782010-02-09 14:05:43 -08001004status_t AwesomePlayer::prepare_l() {
1005 if (mFlags & PREPARED) {
1006 return OK;
1007 }
1008
1009 if (mFlags & PREPARING) {
1010 return UNKNOWN_ERROR;
1011 }
1012
1013 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -08001014 status_t err = prepareAsync_l();
1015
1016 if (err != OK) {
1017 return err;
1018 }
1019
Andreas Huberffdf4782010-02-09 14:05:43 -08001020 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001021 mPreparedCondition.wait(mLock);
1022 }
1023
Andreas Huberffdf4782010-02-09 14:05:43 -08001024 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001025}
1026
1027status_t AwesomePlayer::prepareAsync() {
1028 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001029
1030 if (mFlags & PREPARING) {
1031 return UNKNOWN_ERROR; // async prepare already pending
1032 }
1033
1034 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001035 return prepareAsync_l();
1036}
1037
1038status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001039 if (mFlags & PREPARING) {
1040 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001041 }
1042
Andreas Huber406a18b2010-02-18 16:45:13 -08001043 if (!mQueueStarted) {
1044 mQueue.start();
1045 mQueueStarted = true;
1046 }
1047
Andreas Huberffdf4782010-02-09 14:05:43 -08001048 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -08001049 mAsyncPrepareEvent = new AwesomeEvent(
1050 this, &AwesomePlayer::onPrepareAsyncEvent);
1051
1052 mQueue.postEvent(mAsyncPrepareEvent);
1053
1054 return OK;
1055}
1056
Andreas Huberffdf4782010-02-09 14:05:43 -08001057status_t AwesomePlayer::finishSetDataSource_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001058 sp<DataSource> dataSource;
1059
1060 if (!strncasecmp("http://", mUri.string(), 7)) {
1061 mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders);
1062
1063 mLock.unlock();
1064 status_t err = mConnectingDataSource->connect();
1065 mLock.lock();
1066
1067 if (err != OK) {
1068 mConnectingDataSource.clear();
1069
1070 LOGI("mConnectingDataSource->connect() returned %d", err);
1071 return err;
1072 }
1073
1074 dataSource = new CachingDataSource(
1075 mConnectingDataSource, 32 * 1024, 20);
1076
1077 mConnectingDataSource.clear();
1078 } else {
1079 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1080 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001081
1082 if (dataSource == NULL) {
1083 return UNKNOWN_ERROR;
1084 }
1085
1086 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1087
1088 if (extractor == NULL) {
1089 return UNKNOWN_ERROR;
1090 }
1091
1092 if (dataSource->flags() & DataSource::kWantsPrefetching) {
1093 mPrefetcher = new Prefetcher;
1094 }
1095
1096 return setDataSource_l(extractor);
1097}
1098
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001099void AwesomePlayer::abortPrepare(status_t err) {
1100 CHECK(err != OK);
1101
1102 if (mIsAsyncPrepare) {
1103 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1104 }
1105
1106 mPrepareResult = err;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001107 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001108 mAsyncPrepareEvent = NULL;
1109 mPreparedCondition.broadcast();
1110}
1111
Andreas Huberf71daba2010-03-24 09:24:40 -07001112// static
1113bool AwesomePlayer::ContinuePreparation(void *cookie) {
1114 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1115
1116 return (me->mFlags & PREPARE_CANCELLED) == 0;
1117}
1118
Andreas Huber6be780e2010-02-08 14:40:30 -08001119void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber55864df72010-03-08 12:28:22 -08001120 sp<Prefetcher> prefetcher;
1121
Andreas Huberffdf4782010-02-09 14:05:43 -08001122 {
1123 Mutex::Autolock autoLock(mLock);
1124
Andreas Huberedbb4d82010-03-12 08:59:22 -08001125 if (mFlags & PREPARE_CANCELLED) {
1126 LOGI("prepare was cancelled before doing anything");
1127 abortPrepare(UNKNOWN_ERROR);
1128 return;
1129 }
1130
Andreas Huberffdf4782010-02-09 14:05:43 -08001131 if (mUri.size() > 0) {
1132 status_t err = finishSetDataSource_l();
1133
1134 if (err != OK) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001135 abortPrepare(err);
Andreas Huberffdf4782010-02-09 14:05:43 -08001136 return;
1137 }
1138 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001139
Andreas Huber55864df72010-03-08 12:28:22 -08001140 if (mVideoTrack != NULL && mVideoSource == NULL) {
1141 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08001142
Andreas Huber55864df72010-03-08 12:28:22 -08001143 if (err != OK) {
1144 abortPrepare(err);
1145 return;
1146 }
1147 }
1148
1149 if (mAudioTrack != NULL && mAudioSource == NULL) {
1150 status_t err = initAudioDecoder();
1151
1152 if (err != OK) {
1153 abortPrepare(err);
1154 return;
1155 }
1156 }
1157
Andreas Huber6be780e2010-02-08 14:40:30 -08001158 prefetcher = mPrefetcher;
1159 }
1160
1161 if (prefetcher != NULL) {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001162 {
1163 Mutex::Autolock autoLock(mLock);
1164 if (mFlags & PREPARE_CANCELLED) {
1165 LOGI("prepare was cancelled before preparing the prefetcher");
Andreas Huber9b732de2010-03-23 15:30:57 -07001166
1167 prefetcher.clear();
Andreas Huberedbb4d82010-03-12 08:59:22 -08001168 abortPrepare(UNKNOWN_ERROR);
1169 return;
1170 }
1171 }
1172
1173 LOGI("calling prefetcher->prepare()");
Andreas Huberf71daba2010-03-24 09:24:40 -07001174 status_t result =
1175 prefetcher->prepare(&AwesomePlayer::ContinuePreparation, this);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001176
Andreas Huberba7ec912010-02-12 10:42:02 -08001177 prefetcher.clear();
Andreas Huberf71daba2010-03-24 09:24:40 -07001178
1179 if (result == OK) {
Andreas Huber252573c2010-03-26 10:17:17 -07001180 LOGI("prefetcher is done preparing");
Andreas Huberf71daba2010-03-24 09:24:40 -07001181 } else {
1182 Mutex::Autolock autoLock(mLock);
1183
1184 CHECK_EQ(result, -EINTR);
1185
1186 LOGI("prefetcher->prepare() was cancelled early.");
1187 abortPrepare(UNKNOWN_ERROR);
1188 return;
1189 }
Andreas Huber6be780e2010-02-08 14:40:30 -08001190 }
1191
1192 Mutex::Autolock autoLock(mLock);
1193
Andreas Huberffdf4782010-02-09 14:05:43 -08001194 if (mIsAsyncPrepare) {
1195 if (mVideoWidth < 0 || mVideoHeight < 0) {
1196 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1197 } else {
1198 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
1199 }
1200
1201 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08001202 }
1203
Andreas Huberffdf4782010-02-09 14:05:43 -08001204 mPrepareResult = OK;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001205 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huberffdf4782010-02-09 14:05:43 -08001206 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -08001207 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08001208 mPreparedCondition.broadcast();
Andreas Huber6be780e2010-02-08 14:40:30 -08001209}
1210
Andreas Huberba7ec912010-02-12 10:42:02 -08001211status_t AwesomePlayer::suspend() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001212 LOGV("suspend");
Andreas Huberba7ec912010-02-12 10:42:02 -08001213 Mutex::Autolock autoLock(mLock);
1214
1215 if (mSuspensionState != NULL) {
1216 return INVALID_OPERATION;
1217 }
1218
Andreas Huberedbb4d82010-03-12 08:59:22 -08001219 if (mFlags & PREPARING) {
1220 mFlags |= PREPARE_CANCELLED;
1221 if (mConnectingDataSource != NULL) {
1222 LOGI("interrupting the connection process");
1223 mConnectingDataSource->disconnect();
1224 }
1225 }
1226
Andreas Huberba7ec912010-02-12 10:42:02 -08001227 while (mFlags & PREPARING) {
1228 mPreparedCondition.wait(mLock);
1229 }
1230
1231 SuspensionState *state = new SuspensionState;
1232 state->mUri = mUri;
1233 state->mUriHeaders = mUriHeaders;
1234 state->mFileSource = mFileSource;
1235
Andreas Huber406a18b2010-02-18 16:45:13 -08001236 state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS);
Andreas Huber252573c2010-03-26 10:17:17 -07001237 getPosition(&state->mPositionUs);
Andreas Huberba7ec912010-02-12 10:42:02 -08001238
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001239 if (mLastVideoBuffer) {
1240 size_t size = mLastVideoBuffer->range_length();
1241 if (size) {
1242 state->mLastVideoFrameSize = size;
1243 state->mLastVideoFrame = malloc(size);
1244 memcpy(state->mLastVideoFrame,
1245 (const uint8_t *)mLastVideoBuffer->data()
1246 + mLastVideoBuffer->range_offset(),
1247 size);
1248
1249 state->mVideoWidth = mVideoWidth;
1250 state->mVideoHeight = mVideoHeight;
1251
1252 sp<MetaData> meta = mVideoSource->getFormat();
1253 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1254 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1255 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1256 }
1257 }
1258
Andreas Huberba7ec912010-02-12 10:42:02 -08001259 reset_l();
1260
1261 mSuspensionState = state;
1262
1263 return OK;
1264}
1265
1266status_t AwesomePlayer::resume() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001267 LOGV("resume");
Andreas Huberba7ec912010-02-12 10:42:02 -08001268 Mutex::Autolock autoLock(mLock);
1269
1270 if (mSuspensionState == NULL) {
1271 return INVALID_OPERATION;
1272 }
1273
1274 SuspensionState *state = mSuspensionState;
1275 mSuspensionState = NULL;
1276
1277 status_t err;
1278 if (state->mFileSource != NULL) {
1279 err = setDataSource_l(state->mFileSource);
1280
1281 if (err == OK) {
1282 mFileSource = state->mFileSource;
1283 }
1284 } else {
1285 err = setDataSource_l(state->mUri, &state->mUriHeaders);
1286 }
1287
1288 if (err != OK) {
1289 delete state;
1290 state = NULL;
1291
1292 return err;
1293 }
1294
1295 seekTo_l(state->mPositionUs);
1296
Andreas Huber406a18b2010-02-18 16:45:13 -08001297 mFlags = state->mFlags & (LOOPING | AT_EOS);
Andreas Huberba7ec912010-02-12 10:42:02 -08001298
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001299 if (state->mLastVideoFrame && mISurface != NULL) {
1300 mVideoRenderer =
1301 new AwesomeLocalRenderer(
1302 true, // previewOnly
1303 "",
1304 (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1305 mISurface,
1306 state->mVideoWidth,
1307 state->mVideoHeight,
1308 state->mDecodedWidth,
1309 state->mDecodedHeight);
1310
1311 mVideoRendererIsPreview = true;
1312
1313 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render(
1314 state->mLastVideoFrame, state->mLastVideoFrameSize);
1315 }
1316
Andreas Huberba7ec912010-02-12 10:42:02 -08001317 if (state->mFlags & PLAYING) {
1318 play_l();
1319 }
1320
1321 delete state;
1322 state = NULL;
1323
1324 return OK;
1325}
1326
Andreas Huber27366fc2009-11-20 09:32:46 -08001327} // namespace android
1328