blob: 10b7be349103d08b24fede6eaf2769ea94454804 [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
426 if (mDurationUs >= 0) {
427 int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs();
Andreas Huberdc9927d2010-03-08 15:46:13 -0800428
429 LOGV("cache holds %.2f secs worth of data.", cachedDurationUs / 1E6);
430
Andreas Huberb9e63832010-01-26 16:20:10 -0800431 int64_t positionUs = 0;
Andreas Huber7085b6842010-02-03 16:02:02 -0800432 if (mVideoSource != NULL) {
Andreas Huberb9e63832010-01-26 16:20:10 -0800433 positionUs = mVideoTimeUs;
434 } else if (mAudioPlayer != NULL) {
435 positionUs = mAudioPlayer->getMediaTimeUs();
436 }
437
438 cachedDurationUs += positionUs;
439
440 double percentage = (double)cachedDurationUs / mDurationUs;
441 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
442
443 postBufferingEvent_l();
444 }
445}
446
Andreas Huber27366fc2009-11-20 09:32:46 -0800447void AwesomePlayer::onStreamDone() {
448 // Posted whenever any stream finishes playing.
449
450 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800451 if (!mStreamDoneEventPending) {
452 return;
453 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800454 mStreamDoneEventPending = false;
455
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800456 if (mStreamDoneStatus == ERROR_END_OF_STREAM && (mFlags & LOOPING)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800457 seekTo_l(0);
458
Andreas Huber7085b6842010-02-03 16:02:02 -0800459 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800460 postVideoEvent_l();
461 }
462 } else {
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800463 if (mStreamDoneStatus == ERROR_END_OF_STREAM) {
464 LOGV("MEDIA_PLAYBACK_COMPLETE");
465 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
466 } else {
467 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
468
469 notifyListener_l(
470 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
471 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800472
473 pause_l();
Andreas Huber406a18b2010-02-18 16:45:13 -0800474
475 mFlags |= AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800476 }
477}
478
479status_t AwesomePlayer::play() {
480 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800481 return play_l();
482}
Andreas Huber27366fc2009-11-20 09:32:46 -0800483
Andreas Huberba7ec912010-02-12 10:42:02 -0800484status_t AwesomePlayer::play_l() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800485 if (mFlags & PLAYING) {
486 return OK;
487 }
488
Andreas Huberffdf4782010-02-09 14:05:43 -0800489 if (!(mFlags & PREPARED)) {
490 status_t err = prepare_l();
491
492 if (err != OK) {
493 return err;
494 }
495 }
496
Andreas Huber27366fc2009-11-20 09:32:46 -0800497 mFlags |= PLAYING;
498 mFlags |= FIRST_FRAME;
499
Andreas Huberc1d5c922009-12-10 15:49:04 -0800500 bool deferredAudioSeek = false;
501
Andreas Huber27366fc2009-11-20 09:32:46 -0800502 if (mAudioSource != NULL) {
503 if (mAudioPlayer == NULL) {
504 if (mAudioSink != NULL) {
505 mAudioPlayer = new AudioPlayer(mAudioSink);
Andreas Huber27366fc2009-11-20 09:32:46 -0800506 mAudioPlayer->setSource(mAudioSource);
Andreas Huberdc9927d2010-03-08 15:46:13 -0800507
508 // We've already started the MediaSource in order to enable
509 // the prefetcher to read its data.
510 status_t err = mAudioPlayer->start(
511 true /* sourceAlreadyStarted */);
Andreas Huber62eac002010-01-29 13:24:58 -0800512
513 if (err != OK) {
514 delete mAudioPlayer;
515 mAudioPlayer = NULL;
516
517 mFlags &= ~(PLAYING | FIRST_FRAME);
518
519 return err;
520 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800521
522 delete mTimeSource;
523 mTimeSource = mAudioPlayer;
524
Andreas Huberc1d5c922009-12-10 15:49:04 -0800525 deferredAudioSeek = true;
Andreas Huber70d10c02010-02-03 11:37:29 -0800526
527 mWatchForAudioSeekComplete = false;
528 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800529 }
530 } else {
531 mAudioPlayer->resume();
532 }
Andreas Huber70d10c02010-02-03 11:37:29 -0800533
534 postCheckAudioStatusEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800535 }
536
537 if (mTimeSource == NULL && mAudioPlayer == NULL) {
538 mTimeSource = new SystemTimeSource;
539 }
540
541 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800542 // Kick off video playback
543 postVideoEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800544 }
545
Andreas Huberc1d5c922009-12-10 15:49:04 -0800546 if (deferredAudioSeek) {
547 // If there was a seek request while we were paused
548 // and we're just starting up again, honor the request now.
549 seekAudioIfNecessary_l();
550 }
551
Andreas Huberb9e63832010-01-26 16:20:10 -0800552 postBufferingEvent_l();
553
Andreas Huber406a18b2010-02-18 16:45:13 -0800554 if (mFlags & AT_EOS) {
555 // Legacy behaviour, if a stream finishes playing and then
556 // is started again, we play from the start...
557 seekTo_l(0);
558 }
559
Andreas Huber27366fc2009-11-20 09:32:46 -0800560 return OK;
561}
562
563void AwesomePlayer::initRenderer_l() {
564 if (mISurface != NULL) {
565 sp<MetaData> meta = mVideoSource->getFormat();
566
567 int32_t format;
568 const char *component;
569 int32_t decodedWidth, decodedHeight;
570 CHECK(meta->findInt32(kKeyColorFormat, &format));
571 CHECK(meta->findCString(kKeyDecoderComponent, &component));
572 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
573 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
574
Andreas Hubera67d5382009-12-10 15:32:12 -0800575 mVideoRenderer.clear();
576
577 // Must ensure that mVideoRenderer's destructor is actually executed
578 // before creating a new one.
579 IPCThreadState::self()->flushCommands();
580
Andreas Huber1314e732009-12-14 14:18:22 -0800581 if (!strncmp("OMX.", component, 4)) {
582 // Our OMX codecs allocate buffers on the media_server side
583 // therefore they require a remote IOMXRenderer that knows how
584 // to display them.
585 mVideoRenderer = new AwesomeRemoteRenderer(
586 mClient.interface()->createRenderer(
587 mISurface, component,
588 (OMX_COLOR_FORMATTYPE)format,
589 decodedWidth, decodedHeight,
590 mVideoWidth, mVideoHeight));
591 } else {
592 // Other decoders are instantiated locally and as a consequence
593 // allocate their buffers in local address space.
594 mVideoRenderer = new AwesomeLocalRenderer(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800595 false, // previewOnly
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800596 component,
Andreas Huber1314e732009-12-14 14:18:22 -0800597 (OMX_COLOR_FORMATTYPE)format,
598 mISurface,
599 mVideoWidth, mVideoHeight,
600 decodedWidth, decodedHeight);
601 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800602 }
603}
604
605status_t AwesomePlayer::pause() {
606 Mutex::Autolock autoLock(mLock);
607 return pause_l();
608}
609
610status_t AwesomePlayer::pause_l() {
611 if (!(mFlags & PLAYING)) {
612 return OK;
613 }
614
Andreas Huberb9e63832010-01-26 16:20:10 -0800615 cancelPlayerEvents(true /* keepBufferingGoing */);
Andreas Huber27366fc2009-11-20 09:32:46 -0800616
617 if (mAudioPlayer != NULL) {
618 mAudioPlayer->pause();
619 }
620
621 mFlags &= ~PLAYING;
622
623 return OK;
624}
625
626bool AwesomePlayer::isPlaying() const {
627 Mutex::Autolock autoLock(mLock);
628
629 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) {
658 Mutex::Autolock autoLock(mLock);
659
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) {
670 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800671 return getPosition_l(positionUs);
672}
Andreas Huber27366fc2009-11-20 09:32:46 -0800673
Andreas Huberba7ec912010-02-12 10:42:02 -0800674status_t AwesomePlayer::getPosition_l(int64_t *positionUs) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800675 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800676 *positionUs = mVideoTimeUs;
677 } else if (mAudioPlayer != NULL) {
678 *positionUs = mAudioPlayer->getMediaTimeUs();
679 } else {
680 *positionUs = 0;
681 }
682
683 return OK;
684}
685
686status_t AwesomePlayer::seekTo(int64_t timeUs) {
687 Mutex::Autolock autoLock(mLock);
688 return seekTo_l(timeUs);
689}
690
691status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
692 mSeeking = true;
693 mSeekTimeUs = timeUs;
Andreas Huber406a18b2010-02-18 16:45:13 -0800694 mFlags &= ~AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800695
696 seekAudioIfNecessary_l();
697
698 return OK;
699}
700
701void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Huber7085b6842010-02-03 16:02:02 -0800702 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800703 mAudioPlayer->seekTo(mSeekTimeUs);
704
Andreas Huber70d10c02010-02-03 11:37:29 -0800705 mWatchForAudioSeekComplete = true;
706 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800707 mSeeking = false;
708 }
709}
710
711status_t AwesomePlayer::getVideoDimensions(
712 int32_t *width, int32_t *height) const {
713 Mutex::Autolock autoLock(mLock);
714
715 if (mVideoWidth < 0 || mVideoHeight < 0) {
716 return UNKNOWN_ERROR;
717 }
718
719 *width = mVideoWidth;
720 *height = mVideoHeight;
721
722 return OK;
723}
724
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800725void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
726 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800727
Andreas Huberb9e63832010-01-26 16:20:10 -0800728 if (mPrefetcher != NULL) {
729 source = mPrefetcher->addSource(source);
730 }
731
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800732 mAudioTrack = source;
733}
734
735status_t AwesomePlayer::initAudioDecoder() {
736 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huberc79827a2010-01-05 10:54:55 -0800737
738 const char *mime;
739 CHECK(meta->findCString(kKeyMIMEType, &mime));
740
741 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800742 mAudioSource = mAudioTrack;
Andreas Huberc79827a2010-01-05 10:54:55 -0800743 } else {
744 mAudioSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800745 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huberc79827a2010-01-05 10:54:55 -0800746 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800747 mAudioTrack);
Andreas Huberc79827a2010-01-05 10:54:55 -0800748 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800749
750 if (mAudioSource != NULL) {
751 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800752 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800753 if (mDurationUs < 0 || durationUs > mDurationUs) {
754 mDurationUs = durationUs;
755 }
756 }
757 }
758
Andreas Huberdc9927d2010-03-08 15:46:13 -0800759 mAudioSource->start();
760
Andreas Huber27366fc2009-11-20 09:32:46 -0800761 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
762}
763
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800764void AwesomePlayer::setVideoSource(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 mVideoTrack = source;
772}
773
774status_t AwesomePlayer::initVideoDecoder() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800775 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800776 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -0800777 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800778 mVideoTrack);
Andreas Huber27366fc2009-11-20 09:32:46 -0800779
780 if (mVideoSource != NULL) {
781 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800782 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800783 if (mDurationUs < 0 || durationUs > mDurationUs) {
784 mDurationUs = durationUs;
785 }
786 }
787
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800788 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
789 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
Andreas Huber27366fc2009-11-20 09:32:46 -0800790
791 mVideoSource->start();
792 }
793
794 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
795}
796
Andreas Huber6be780e2010-02-08 14:40:30 -0800797void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800798 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800799 if (!mVideoEventPending) {
800 // The event has been cancelled in reset_l() but had already
801 // been scheduled for execution at that time.
802 return;
803 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800804 mVideoEventPending = false;
805
806 if (mSeeking) {
807 if (mLastVideoBuffer) {
808 mLastVideoBuffer->release();
809 mLastVideoBuffer = NULL;
810 }
811
812 if (mVideoBuffer) {
813 mVideoBuffer->release();
814 mVideoBuffer = NULL;
815 }
816 }
817
818 if (!mVideoBuffer) {
819 MediaSource::ReadOptions options;
820 if (mSeeking) {
821 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
822
823 options.setSeekTo(mSeekTimeUs);
824 }
825 for (;;) {
826 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -0800827 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -0800828
829 if (err != OK) {
830 CHECK_EQ(mVideoBuffer, NULL);
831
832 if (err == INFO_FORMAT_CHANGED) {
833 LOGV("VideoSource signalled format change.");
834
Andreas Huber7085b6842010-02-03 16:02:02 -0800835 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800836 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -0800837 initRenderer_l();
838 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800839 continue;
840 }
841
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800842 postStreamDoneEvent_l(err);
Andreas Huber27366fc2009-11-20 09:32:46 -0800843 return;
844 }
845
Andreas Hubera67d5382009-12-10 15:32:12 -0800846 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -0800847 // Some decoders, notably the PV AVC software decoder
848 // return spurious empty buffers that we just want to ignore.
849
Andreas Hubera67d5382009-12-10 15:32:12 -0800850 mVideoBuffer->release();
851 mVideoBuffer = NULL;
852 continue;
853 }
854
Andreas Huber27366fc2009-11-20 09:32:46 -0800855 break;
856 }
857 }
858
859 int64_t timeUs;
860 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
861
862 mVideoTimeUs = timeUs;
863
864 if (mSeeking) {
865 if (mAudioPlayer != NULL) {
866 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
867
868 mAudioPlayer->seekTo(timeUs);
Andreas Huber70d10c02010-02-03 11:37:29 -0800869 mWatchForAudioSeekComplete = true;
870 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800871 } else {
872 // If we're playing video only, report seek complete now,
873 // otherwise audio player will notify us later.
Andreas Hubera3f43842010-01-21 10:28:45 -0800874 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800875 }
876
877 mFlags |= FIRST_FRAME;
878 mSeeking = false;
879 }
880
881 if (mFlags & FIRST_FRAME) {
882 mFlags &= ~FIRST_FRAME;
883
884 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
885 }
886
887 int64_t realTimeUs, mediaTimeUs;
888 if (mAudioPlayer != NULL
889 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
890 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
891 }
892
893 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
894
895 int64_t latenessUs = nowUs - timeUs;
896
Andreas Huber24b0a952009-11-23 14:02:00 -0800897 if (latenessUs > 40000) {
898 // We're more than 40ms late.
Andreas Huber4a9375e2010-02-09 11:54:33 -0800899 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -0800900
901 mVideoBuffer->release();
902 mVideoBuffer = NULL;
903
904 postVideoEvent_l();
905 return;
906 }
907
908 if (latenessUs < -10000) {
909 // We're more than 10ms early.
910
911 postVideoEvent_l(10000);
912 return;
913 }
914
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800915 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
916 mVideoRendererIsPreview = false;
917
Andreas Huber7085b6842010-02-03 16:02:02 -0800918 initRenderer_l();
919 }
920
921 if (mVideoRenderer != NULL) {
922 mVideoRenderer->render(mVideoBuffer);
923 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800924
925 if (mLastVideoBuffer) {
926 mLastVideoBuffer->release();
927 mLastVideoBuffer = NULL;
928 }
929 mLastVideoBuffer = mVideoBuffer;
930 mVideoBuffer = NULL;
931
932 postVideoEvent_l();
933}
934
935void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
936 if (mVideoEventPending) {
937 return;
938 }
939
940 mVideoEventPending = true;
941 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
942}
943
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800944void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800945 if (mStreamDoneEventPending) {
946 return;
947 }
948 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800949
950 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -0800951 mQueue.postEvent(mStreamDoneEvent);
952}
953
Andreas Huberb9e63832010-01-26 16:20:10 -0800954void AwesomePlayer::postBufferingEvent_l() {
955 if (mPrefetcher == NULL) {
956 return;
957 }
958
959 if (mBufferingEventPending) {
960 return;
961 }
962 mBufferingEventPending = true;
963 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
964}
965
Andreas Huber70d10c02010-02-03 11:37:29 -0800966void AwesomePlayer::postCheckAudioStatusEvent_l() {
967 if (mAudioStatusEventPending) {
968 return;
969 }
970 mAudioStatusEventPending = true;
971 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
972}
973
974void AwesomePlayer::onCheckAudioStatus() {
975 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800976 if (!mAudioStatusEventPending) {
977 // Event was dispatched and while we were blocking on the mutex,
978 // has already been cancelled.
979 return;
980 }
981
Andreas Huber70d10c02010-02-03 11:37:29 -0800982 mAudioStatusEventPending = false;
983
984 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
985 mWatchForAudioSeekComplete = false;
986 notifyListener_l(MEDIA_SEEK_COMPLETE);
987 }
988
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800989 status_t finalStatus;
990 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -0800991 mWatchForAudioEOS = false;
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800992 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -0800993 }
994
995 postCheckAudioStatusEvent_l();
996}
997
Andreas Huber6be780e2010-02-08 14:40:30 -0800998status_t AwesomePlayer::prepare() {
999 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001000 return prepare_l();
1001}
Andreas Huber6be780e2010-02-08 14:40:30 -08001002
Andreas Huberffdf4782010-02-09 14:05:43 -08001003status_t AwesomePlayer::prepare_l() {
1004 if (mFlags & PREPARED) {
1005 return OK;
1006 }
1007
1008 if (mFlags & PREPARING) {
1009 return UNKNOWN_ERROR;
1010 }
1011
1012 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -08001013 status_t err = prepareAsync_l();
1014
1015 if (err != OK) {
1016 return err;
1017 }
1018
Andreas Huberffdf4782010-02-09 14:05:43 -08001019 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001020 mPreparedCondition.wait(mLock);
1021 }
1022
Andreas Huberffdf4782010-02-09 14:05:43 -08001023 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001024}
1025
1026status_t AwesomePlayer::prepareAsync() {
1027 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001028
1029 if (mFlags & PREPARING) {
1030 return UNKNOWN_ERROR; // async prepare already pending
1031 }
1032
1033 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001034 return prepareAsync_l();
1035}
1036
1037status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001038 if (mFlags & PREPARING) {
1039 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001040 }
1041
Andreas Huber406a18b2010-02-18 16:45:13 -08001042 if (!mQueueStarted) {
1043 mQueue.start();
1044 mQueueStarted = true;
1045 }
1046
Andreas Huberffdf4782010-02-09 14:05:43 -08001047 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -08001048 mAsyncPrepareEvent = new AwesomeEvent(
1049 this, &AwesomePlayer::onPrepareAsyncEvent);
1050
1051 mQueue.postEvent(mAsyncPrepareEvent);
1052
1053 return OK;
1054}
1055
Andreas Huberffdf4782010-02-09 14:05:43 -08001056status_t AwesomePlayer::finishSetDataSource_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001057 sp<DataSource> dataSource;
1058
1059 if (!strncasecmp("http://", mUri.string(), 7)) {
1060 mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders);
1061
1062 mLock.unlock();
1063 status_t err = mConnectingDataSource->connect();
1064 mLock.lock();
1065
1066 if (err != OK) {
1067 mConnectingDataSource.clear();
1068
1069 LOGI("mConnectingDataSource->connect() returned %d", err);
1070 return err;
1071 }
1072
1073 dataSource = new CachingDataSource(
1074 mConnectingDataSource, 32 * 1024, 20);
1075
1076 mConnectingDataSource.clear();
1077 } else {
1078 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1079 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001080
1081 if (dataSource == NULL) {
1082 return UNKNOWN_ERROR;
1083 }
1084
1085 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1086
1087 if (extractor == NULL) {
1088 return UNKNOWN_ERROR;
1089 }
1090
1091 if (dataSource->flags() & DataSource::kWantsPrefetching) {
1092 mPrefetcher = new Prefetcher;
1093 }
1094
1095 return setDataSource_l(extractor);
1096}
1097
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001098void AwesomePlayer::abortPrepare(status_t err) {
1099 CHECK(err != OK);
1100
1101 if (mIsAsyncPrepare) {
1102 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1103 }
1104
1105 mPrepareResult = err;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001106 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001107 mAsyncPrepareEvent = NULL;
1108 mPreparedCondition.broadcast();
1109}
1110
Andreas Huber6be780e2010-02-08 14:40:30 -08001111void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber55864df72010-03-08 12:28:22 -08001112 sp<Prefetcher> prefetcher;
1113
Andreas Huberffdf4782010-02-09 14:05:43 -08001114 {
1115 Mutex::Autolock autoLock(mLock);
1116
Andreas Huberedbb4d82010-03-12 08:59:22 -08001117 if (mFlags & PREPARE_CANCELLED) {
1118 LOGI("prepare was cancelled before doing anything");
1119 abortPrepare(UNKNOWN_ERROR);
1120 return;
1121 }
1122
Andreas Huberffdf4782010-02-09 14:05:43 -08001123 if (mUri.size() > 0) {
1124 status_t err = finishSetDataSource_l();
1125
1126 if (err != OK) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001127 abortPrepare(err);
Andreas Huberffdf4782010-02-09 14:05:43 -08001128 return;
1129 }
1130 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001131
Andreas Huber55864df72010-03-08 12:28:22 -08001132 if (mVideoTrack != NULL && mVideoSource == NULL) {
1133 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08001134
Andreas Huber55864df72010-03-08 12:28:22 -08001135 if (err != OK) {
1136 abortPrepare(err);
1137 return;
1138 }
1139 }
1140
1141 if (mAudioTrack != NULL && mAudioSource == NULL) {
1142 status_t err = initAudioDecoder();
1143
1144 if (err != OK) {
1145 abortPrepare(err);
1146 return;
1147 }
1148 }
1149
Andreas Huber6be780e2010-02-08 14:40:30 -08001150 prefetcher = mPrefetcher;
1151 }
1152
1153 if (prefetcher != NULL) {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001154 {
1155 Mutex::Autolock autoLock(mLock);
1156 if (mFlags & PREPARE_CANCELLED) {
1157 LOGI("prepare was cancelled before preparing the prefetcher");
1158 abortPrepare(UNKNOWN_ERROR);
1159 return;
1160 }
1161 }
1162
1163 LOGI("calling prefetcher->prepare()");
Andreas Huber6be780e2010-02-08 14:40:30 -08001164 prefetcher->prepare();
Andreas Huberedbb4d82010-03-12 08:59:22 -08001165 LOGV("prefetcher is done preparing");
1166
Andreas Huberba7ec912010-02-12 10:42:02 -08001167 prefetcher.clear();
Andreas Huber6be780e2010-02-08 14:40:30 -08001168 }
1169
1170 Mutex::Autolock autoLock(mLock);
1171
Andreas Huberffdf4782010-02-09 14:05:43 -08001172 if (mIsAsyncPrepare) {
1173 if (mVideoWidth < 0 || mVideoHeight < 0) {
1174 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1175 } else {
1176 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
1177 }
1178
1179 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08001180 }
1181
Andreas Huberffdf4782010-02-09 14:05:43 -08001182 mPrepareResult = OK;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001183 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huberffdf4782010-02-09 14:05:43 -08001184 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -08001185 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08001186 mPreparedCondition.broadcast();
Andreas Huber6be780e2010-02-08 14:40:30 -08001187}
1188
Andreas Huberba7ec912010-02-12 10:42:02 -08001189status_t AwesomePlayer::suspend() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001190 LOGV("suspend");
Andreas Huberba7ec912010-02-12 10:42:02 -08001191 Mutex::Autolock autoLock(mLock);
1192
1193 if (mSuspensionState != NULL) {
1194 return INVALID_OPERATION;
1195 }
1196
Andreas Huberedbb4d82010-03-12 08:59:22 -08001197 if (mFlags & PREPARING) {
1198 mFlags |= PREPARE_CANCELLED;
1199 if (mConnectingDataSource != NULL) {
1200 LOGI("interrupting the connection process");
1201 mConnectingDataSource->disconnect();
1202 }
1203 }
1204
Andreas Huberba7ec912010-02-12 10:42:02 -08001205 while (mFlags & PREPARING) {
1206 mPreparedCondition.wait(mLock);
1207 }
1208
1209 SuspensionState *state = new SuspensionState;
1210 state->mUri = mUri;
1211 state->mUriHeaders = mUriHeaders;
1212 state->mFileSource = mFileSource;
1213
Andreas Huber406a18b2010-02-18 16:45:13 -08001214 state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS);
Andreas Huberba7ec912010-02-12 10:42:02 -08001215 getPosition_l(&state->mPositionUs);
1216
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001217 if (mLastVideoBuffer) {
1218 size_t size = mLastVideoBuffer->range_length();
1219 if (size) {
1220 state->mLastVideoFrameSize = size;
1221 state->mLastVideoFrame = malloc(size);
1222 memcpy(state->mLastVideoFrame,
1223 (const uint8_t *)mLastVideoBuffer->data()
1224 + mLastVideoBuffer->range_offset(),
1225 size);
1226
1227 state->mVideoWidth = mVideoWidth;
1228 state->mVideoHeight = mVideoHeight;
1229
1230 sp<MetaData> meta = mVideoSource->getFormat();
1231 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1232 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1233 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1234 }
1235 }
1236
Andreas Huberba7ec912010-02-12 10:42:02 -08001237 reset_l();
1238
1239 mSuspensionState = state;
1240
1241 return OK;
1242}
1243
1244status_t AwesomePlayer::resume() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001245 LOGV("resume");
Andreas Huberba7ec912010-02-12 10:42:02 -08001246 Mutex::Autolock autoLock(mLock);
1247
1248 if (mSuspensionState == NULL) {
1249 return INVALID_OPERATION;
1250 }
1251
1252 SuspensionState *state = mSuspensionState;
1253 mSuspensionState = NULL;
1254
1255 status_t err;
1256 if (state->mFileSource != NULL) {
1257 err = setDataSource_l(state->mFileSource);
1258
1259 if (err == OK) {
1260 mFileSource = state->mFileSource;
1261 }
1262 } else {
1263 err = setDataSource_l(state->mUri, &state->mUriHeaders);
1264 }
1265
1266 if (err != OK) {
1267 delete state;
1268 state = NULL;
1269
1270 return err;
1271 }
1272
1273 seekTo_l(state->mPositionUs);
1274
Andreas Huber406a18b2010-02-18 16:45:13 -08001275 mFlags = state->mFlags & (LOOPING | AT_EOS);
Andreas Huberba7ec912010-02-12 10:42:02 -08001276
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001277 if (state->mLastVideoFrame && mISurface != NULL) {
1278 mVideoRenderer =
1279 new AwesomeLocalRenderer(
1280 true, // previewOnly
1281 "",
1282 (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1283 mISurface,
1284 state->mVideoWidth,
1285 state->mVideoHeight,
1286 state->mDecodedWidth,
1287 state->mDecodedHeight);
1288
1289 mVideoRendererIsPreview = true;
1290
1291 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render(
1292 state->mLastVideoFrame, state->mLastVideoFrameSize);
1293 }
1294
Andreas Huberba7ec912010-02-12 10:42:02 -08001295 if (state->mFlags & PLAYING) {
1296 play_l();
1297 }
1298
1299 delete state;
1300 state = NULL;
1301
1302 return OK;
1303}
1304
Andreas Huber27366fc2009-11-20 09:32:46 -08001305} // namespace android
1306