blob: 05e23d1689d1290fbab3e2aa3436dd5c0fa9b149 [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 {
Andreas Huber27366fc2009-11-20 09:32:46 -0800627 return mFlags & PLAYING;
628}
629
630void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
631 Mutex::Autolock autoLock(mLock);
632
633 mISurface = isurface;
634}
635
636void AwesomePlayer::setAudioSink(
637 const sp<MediaPlayerBase::AudioSink> &audioSink) {
638 Mutex::Autolock autoLock(mLock);
639
640 mAudioSink = audioSink;
641}
642
643status_t AwesomePlayer::setLooping(bool shouldLoop) {
644 Mutex::Autolock autoLock(mLock);
645
646 mFlags = mFlags & ~LOOPING;
647
648 if (shouldLoop) {
649 mFlags |= LOOPING;
650 }
651
652 return OK;
653}
654
655status_t AwesomePlayer::getDuration(int64_t *durationUs) {
656 Mutex::Autolock autoLock(mLock);
657
658 if (mDurationUs < 0) {
659 return UNKNOWN_ERROR;
660 }
661
662 *durationUs = mDurationUs;
663
664 return OK;
665}
666
667status_t AwesomePlayer::getPosition(int64_t *positionUs) {
668 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800669 return getPosition_l(positionUs);
670}
Andreas Huber27366fc2009-11-20 09:32:46 -0800671
Andreas Huberba7ec912010-02-12 10:42:02 -0800672status_t AwesomePlayer::getPosition_l(int64_t *positionUs) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800673 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800674 *positionUs = mVideoTimeUs;
675 } else if (mAudioPlayer != NULL) {
676 *positionUs = mAudioPlayer->getMediaTimeUs();
677 } else {
678 *positionUs = 0;
679 }
680
681 return OK;
682}
683
684status_t AwesomePlayer::seekTo(int64_t timeUs) {
685 Mutex::Autolock autoLock(mLock);
686 return seekTo_l(timeUs);
687}
688
689status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
690 mSeeking = true;
691 mSeekTimeUs = timeUs;
Andreas Huber406a18b2010-02-18 16:45:13 -0800692 mFlags &= ~AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800693
694 seekAudioIfNecessary_l();
695
696 return OK;
697}
698
699void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Huber7085b6842010-02-03 16:02:02 -0800700 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800701 mAudioPlayer->seekTo(mSeekTimeUs);
702
Andreas Huber70d10c02010-02-03 11:37:29 -0800703 mWatchForAudioSeekComplete = true;
704 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800705 mSeeking = false;
706 }
707}
708
709status_t AwesomePlayer::getVideoDimensions(
710 int32_t *width, int32_t *height) const {
711 Mutex::Autolock autoLock(mLock);
712
713 if (mVideoWidth < 0 || mVideoHeight < 0) {
714 return UNKNOWN_ERROR;
715 }
716
717 *width = mVideoWidth;
718 *height = mVideoHeight;
719
720 return OK;
721}
722
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800723void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
724 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800725
Andreas Huberb9e63832010-01-26 16:20:10 -0800726 if (mPrefetcher != NULL) {
727 source = mPrefetcher->addSource(source);
728 }
729
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800730 mAudioTrack = source;
731}
732
733status_t AwesomePlayer::initAudioDecoder() {
734 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huberc79827a2010-01-05 10:54:55 -0800735
736 const char *mime;
737 CHECK(meta->findCString(kKeyMIMEType, &mime));
738
739 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800740 mAudioSource = mAudioTrack;
Andreas Huberc79827a2010-01-05 10:54:55 -0800741 } else {
742 mAudioSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800743 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huberc79827a2010-01-05 10:54:55 -0800744 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800745 mAudioTrack);
Andreas Huberc79827a2010-01-05 10:54:55 -0800746 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800747
748 if (mAudioSource != NULL) {
749 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800750 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800751 if (mDurationUs < 0 || durationUs > mDurationUs) {
752 mDurationUs = durationUs;
753 }
754 }
755 }
756
Andreas Huberdc9927d2010-03-08 15:46:13 -0800757 mAudioSource->start();
758
Andreas Huber27366fc2009-11-20 09:32:46 -0800759 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
760}
761
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800762void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
763 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800764
Andreas Huberb9e63832010-01-26 16:20:10 -0800765 if (mPrefetcher != NULL) {
766 source = mPrefetcher->addSource(source);
767 }
768
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800769 mVideoTrack = source;
770}
771
772status_t AwesomePlayer::initVideoDecoder() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800773 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800774 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -0800775 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800776 mVideoTrack);
Andreas Huber27366fc2009-11-20 09:32:46 -0800777
778 if (mVideoSource != NULL) {
779 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800780 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
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
860 mVideoTimeUs = timeUs;
861
862 if (mSeeking) {
863 if (mAudioPlayer != NULL) {
864 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
865
866 mAudioPlayer->seekTo(timeUs);
Andreas Huber70d10c02010-02-03 11:37:29 -0800867 mWatchForAudioSeekComplete = true;
868 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800869 } else {
870 // If we're playing video only, report seek complete now,
871 // otherwise audio player will notify us later.
Andreas Hubera3f43842010-01-21 10:28:45 -0800872 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800873 }
874
875 mFlags |= FIRST_FRAME;
876 mSeeking = false;
877 }
878
879 if (mFlags & FIRST_FRAME) {
880 mFlags &= ~FIRST_FRAME;
881
882 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
883 }
884
885 int64_t realTimeUs, mediaTimeUs;
886 if (mAudioPlayer != NULL
887 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
888 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
889 }
890
891 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
892
893 int64_t latenessUs = nowUs - timeUs;
894
Andreas Huber24b0a952009-11-23 14:02:00 -0800895 if (latenessUs > 40000) {
896 // We're more than 40ms late.
Andreas Huber4a9375e2010-02-09 11:54:33 -0800897 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -0800898
899 mVideoBuffer->release();
900 mVideoBuffer = NULL;
901
902 postVideoEvent_l();
903 return;
904 }
905
906 if (latenessUs < -10000) {
907 // We're more than 10ms early.
908
909 postVideoEvent_l(10000);
910 return;
911 }
912
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800913 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
914 mVideoRendererIsPreview = false;
915
Andreas Huber7085b6842010-02-03 16:02:02 -0800916 initRenderer_l();
917 }
918
919 if (mVideoRenderer != NULL) {
920 mVideoRenderer->render(mVideoBuffer);
921 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800922
923 if (mLastVideoBuffer) {
924 mLastVideoBuffer->release();
925 mLastVideoBuffer = NULL;
926 }
927 mLastVideoBuffer = mVideoBuffer;
928 mVideoBuffer = NULL;
929
930 postVideoEvent_l();
931}
932
933void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
934 if (mVideoEventPending) {
935 return;
936 }
937
938 mVideoEventPending = true;
939 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
940}
941
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800942void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800943 if (mStreamDoneEventPending) {
944 return;
945 }
946 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800947
948 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -0800949 mQueue.postEvent(mStreamDoneEvent);
950}
951
Andreas Huberb9e63832010-01-26 16:20:10 -0800952void AwesomePlayer::postBufferingEvent_l() {
953 if (mPrefetcher == NULL) {
954 return;
955 }
956
957 if (mBufferingEventPending) {
958 return;
959 }
960 mBufferingEventPending = true;
961 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
962}
963
Andreas Huber70d10c02010-02-03 11:37:29 -0800964void AwesomePlayer::postCheckAudioStatusEvent_l() {
965 if (mAudioStatusEventPending) {
966 return;
967 }
968 mAudioStatusEventPending = true;
969 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
970}
971
972void AwesomePlayer::onCheckAudioStatus() {
973 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800974 if (!mAudioStatusEventPending) {
975 // Event was dispatched and while we were blocking on the mutex,
976 // has already been cancelled.
977 return;
978 }
979
Andreas Huber70d10c02010-02-03 11:37:29 -0800980 mAudioStatusEventPending = false;
981
982 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
983 mWatchForAudioSeekComplete = false;
984 notifyListener_l(MEDIA_SEEK_COMPLETE);
985 }
986
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800987 status_t finalStatus;
988 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -0800989 mWatchForAudioEOS = false;
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800990 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -0800991 }
992
993 postCheckAudioStatusEvent_l();
994}
995
Andreas Huber6be780e2010-02-08 14:40:30 -0800996status_t AwesomePlayer::prepare() {
997 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -0800998 return prepare_l();
999}
Andreas Huber6be780e2010-02-08 14:40:30 -08001000
Andreas Huberffdf4782010-02-09 14:05:43 -08001001status_t AwesomePlayer::prepare_l() {
1002 if (mFlags & PREPARED) {
1003 return OK;
1004 }
1005
1006 if (mFlags & PREPARING) {
1007 return UNKNOWN_ERROR;
1008 }
1009
1010 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -08001011 status_t err = prepareAsync_l();
1012
1013 if (err != OK) {
1014 return err;
1015 }
1016
Andreas Huberffdf4782010-02-09 14:05:43 -08001017 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001018 mPreparedCondition.wait(mLock);
1019 }
1020
Andreas Huberffdf4782010-02-09 14:05:43 -08001021 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001022}
1023
1024status_t AwesomePlayer::prepareAsync() {
1025 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001026
1027 if (mFlags & PREPARING) {
1028 return UNKNOWN_ERROR; // async prepare already pending
1029 }
1030
1031 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001032 return prepareAsync_l();
1033}
1034
1035status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001036 if (mFlags & PREPARING) {
1037 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001038 }
1039
Andreas Huber406a18b2010-02-18 16:45:13 -08001040 if (!mQueueStarted) {
1041 mQueue.start();
1042 mQueueStarted = true;
1043 }
1044
Andreas Huberffdf4782010-02-09 14:05:43 -08001045 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -08001046 mAsyncPrepareEvent = new AwesomeEvent(
1047 this, &AwesomePlayer::onPrepareAsyncEvent);
1048
1049 mQueue.postEvent(mAsyncPrepareEvent);
1050
1051 return OK;
1052}
1053
Andreas Huberffdf4782010-02-09 14:05:43 -08001054status_t AwesomePlayer::finishSetDataSource_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001055 sp<DataSource> dataSource;
1056
1057 if (!strncasecmp("http://", mUri.string(), 7)) {
1058 mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders);
1059
1060 mLock.unlock();
1061 status_t err = mConnectingDataSource->connect();
1062 mLock.lock();
1063
1064 if (err != OK) {
1065 mConnectingDataSource.clear();
1066
1067 LOGI("mConnectingDataSource->connect() returned %d", err);
1068 return err;
1069 }
1070
1071 dataSource = new CachingDataSource(
1072 mConnectingDataSource, 32 * 1024, 20);
1073
1074 mConnectingDataSource.clear();
1075 } else {
1076 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1077 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001078
1079 if (dataSource == NULL) {
1080 return UNKNOWN_ERROR;
1081 }
1082
1083 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1084
1085 if (extractor == NULL) {
1086 return UNKNOWN_ERROR;
1087 }
1088
1089 if (dataSource->flags() & DataSource::kWantsPrefetching) {
1090 mPrefetcher = new Prefetcher;
1091 }
1092
1093 return setDataSource_l(extractor);
1094}
1095
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001096void AwesomePlayer::abortPrepare(status_t err) {
1097 CHECK(err != OK);
1098
1099 if (mIsAsyncPrepare) {
1100 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1101 }
1102
1103 mPrepareResult = err;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001104 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001105 mAsyncPrepareEvent = NULL;
1106 mPreparedCondition.broadcast();
1107}
1108
Andreas Huberf71daba2010-03-24 09:24:40 -07001109// static
1110bool AwesomePlayer::ContinuePreparation(void *cookie) {
1111 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1112
1113 return (me->mFlags & PREPARE_CANCELLED) == 0;
1114}
1115
Andreas Huber6be780e2010-02-08 14:40:30 -08001116void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber55864df72010-03-08 12:28:22 -08001117 sp<Prefetcher> prefetcher;
1118
Andreas Huberffdf4782010-02-09 14:05:43 -08001119 {
1120 Mutex::Autolock autoLock(mLock);
1121
Andreas Huberedbb4d82010-03-12 08:59:22 -08001122 if (mFlags & PREPARE_CANCELLED) {
1123 LOGI("prepare was cancelled before doing anything");
1124 abortPrepare(UNKNOWN_ERROR);
1125 return;
1126 }
1127
Andreas Huberffdf4782010-02-09 14:05:43 -08001128 if (mUri.size() > 0) {
1129 status_t err = finishSetDataSource_l();
1130
1131 if (err != OK) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001132 abortPrepare(err);
Andreas Huberffdf4782010-02-09 14:05:43 -08001133 return;
1134 }
1135 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001136
Andreas Huber55864df72010-03-08 12:28:22 -08001137 if (mVideoTrack != NULL && mVideoSource == NULL) {
1138 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08001139
Andreas Huber55864df72010-03-08 12:28:22 -08001140 if (err != OK) {
1141 abortPrepare(err);
1142 return;
1143 }
1144 }
1145
1146 if (mAudioTrack != NULL && mAudioSource == NULL) {
1147 status_t err = initAudioDecoder();
1148
1149 if (err != OK) {
1150 abortPrepare(err);
1151 return;
1152 }
1153 }
1154
Andreas Huber6be780e2010-02-08 14:40:30 -08001155 prefetcher = mPrefetcher;
1156 }
1157
1158 if (prefetcher != NULL) {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001159 {
1160 Mutex::Autolock autoLock(mLock);
1161 if (mFlags & PREPARE_CANCELLED) {
1162 LOGI("prepare was cancelled before preparing the prefetcher");
Andreas Huber9b732de2010-03-23 15:30:57 -07001163
1164 prefetcher.clear();
Andreas Huberedbb4d82010-03-12 08:59:22 -08001165 abortPrepare(UNKNOWN_ERROR);
1166 return;
1167 }
1168 }
1169
1170 LOGI("calling prefetcher->prepare()");
Andreas Huberf71daba2010-03-24 09:24:40 -07001171 status_t result =
1172 prefetcher->prepare(&AwesomePlayer::ContinuePreparation, this);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001173
Andreas Huberba7ec912010-02-12 10:42:02 -08001174 prefetcher.clear();
Andreas Huberf71daba2010-03-24 09:24:40 -07001175
1176 if (result == OK) {
1177 LOGV("prefetcher is done preparing");
1178 } else {
1179 Mutex::Autolock autoLock(mLock);
1180
1181 CHECK_EQ(result, -EINTR);
1182
1183 LOGI("prefetcher->prepare() was cancelled early.");
1184 abortPrepare(UNKNOWN_ERROR);
1185 return;
1186 }
Andreas Huber6be780e2010-02-08 14:40:30 -08001187 }
1188
1189 Mutex::Autolock autoLock(mLock);
1190
Andreas Huberffdf4782010-02-09 14:05:43 -08001191 if (mIsAsyncPrepare) {
1192 if (mVideoWidth < 0 || mVideoHeight < 0) {
1193 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1194 } else {
1195 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
1196 }
1197
1198 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08001199 }
1200
Andreas Huberffdf4782010-02-09 14:05:43 -08001201 mPrepareResult = OK;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001202 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huberffdf4782010-02-09 14:05:43 -08001203 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -08001204 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08001205 mPreparedCondition.broadcast();
Andreas Huber6be780e2010-02-08 14:40:30 -08001206}
1207
Andreas Huberba7ec912010-02-12 10:42:02 -08001208status_t AwesomePlayer::suspend() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001209 LOGV("suspend");
Andreas Huberba7ec912010-02-12 10:42:02 -08001210 Mutex::Autolock autoLock(mLock);
1211
1212 if (mSuspensionState != NULL) {
1213 return INVALID_OPERATION;
1214 }
1215
Andreas Huberedbb4d82010-03-12 08:59:22 -08001216 if (mFlags & PREPARING) {
1217 mFlags |= PREPARE_CANCELLED;
1218 if (mConnectingDataSource != NULL) {
1219 LOGI("interrupting the connection process");
1220 mConnectingDataSource->disconnect();
1221 }
1222 }
1223
Andreas Huberba7ec912010-02-12 10:42:02 -08001224 while (mFlags & PREPARING) {
1225 mPreparedCondition.wait(mLock);
1226 }
1227
1228 SuspensionState *state = new SuspensionState;
1229 state->mUri = mUri;
1230 state->mUriHeaders = mUriHeaders;
1231 state->mFileSource = mFileSource;
1232
Andreas Huber406a18b2010-02-18 16:45:13 -08001233 state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS);
Andreas Huberba7ec912010-02-12 10:42:02 -08001234 getPosition_l(&state->mPositionUs);
1235
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001236 if (mLastVideoBuffer) {
1237 size_t size = mLastVideoBuffer->range_length();
1238 if (size) {
1239 state->mLastVideoFrameSize = size;
1240 state->mLastVideoFrame = malloc(size);
1241 memcpy(state->mLastVideoFrame,
1242 (const uint8_t *)mLastVideoBuffer->data()
1243 + mLastVideoBuffer->range_offset(),
1244 size);
1245
1246 state->mVideoWidth = mVideoWidth;
1247 state->mVideoHeight = mVideoHeight;
1248
1249 sp<MetaData> meta = mVideoSource->getFormat();
1250 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1251 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1252 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1253 }
1254 }
1255
Andreas Huberba7ec912010-02-12 10:42:02 -08001256 reset_l();
1257
1258 mSuspensionState = state;
1259
1260 return OK;
1261}
1262
1263status_t AwesomePlayer::resume() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001264 LOGV("resume");
Andreas Huberba7ec912010-02-12 10:42:02 -08001265 Mutex::Autolock autoLock(mLock);
1266
1267 if (mSuspensionState == NULL) {
1268 return INVALID_OPERATION;
1269 }
1270
1271 SuspensionState *state = mSuspensionState;
1272 mSuspensionState = NULL;
1273
1274 status_t err;
1275 if (state->mFileSource != NULL) {
1276 err = setDataSource_l(state->mFileSource);
1277
1278 if (err == OK) {
1279 mFileSource = state->mFileSource;
1280 }
1281 } else {
1282 err = setDataSource_l(state->mUri, &state->mUriHeaders);
1283 }
1284
1285 if (err != OK) {
1286 delete state;
1287 state = NULL;
1288
1289 return err;
1290 }
1291
1292 seekTo_l(state->mPositionUs);
1293
Andreas Huber406a18b2010-02-18 16:45:13 -08001294 mFlags = state->mFlags & (LOOPING | AT_EOS);
Andreas Huberba7ec912010-02-12 10:42:02 -08001295
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001296 if (state->mLastVideoFrame && mISurface != NULL) {
1297 mVideoRenderer =
1298 new AwesomeLocalRenderer(
1299 true, // previewOnly
1300 "",
1301 (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1302 mISurface,
1303 state->mVideoWidth,
1304 state->mVideoHeight,
1305 state->mDecodedWidth,
1306 state->mDecodedHeight);
1307
1308 mVideoRendererIsPreview = true;
1309
1310 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render(
1311 state->mLastVideoFrame, state->mLastVideoFrameSize);
1312 }
1313
Andreas Huberba7ec912010-02-12 10:42:02 -08001314 if (state->mFlags & PLAYING) {
1315 play_l();
1316 }
1317
1318 delete state;
1319 state = NULL;
1320
1321 return OK;
1322}
1323
Andreas Huber27366fc2009-11-20 09:32:46 -08001324} // namespace android
1325