blob: e00ba47098d962433c3e231c91980d5835de5cf9 [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>
29#include <media/stagefright/DataSource.h>
30#include <media/stagefright/FileSource.h>
31#include <media/stagefright/MediaBuffer.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080032#include <media/stagefright/MediaDefs.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080033#include <media/stagefright/MediaExtractor.h>
34#include <media/stagefright/MediaDebug.h>
35#include <media/stagefright/MediaSource.h>
36#include <media/stagefright/MetaData.h>
37#include <media/stagefright/OMXCodec.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080038
Mathias Agopian000479f2010-02-09 17:46:37 -080039#include <surfaceflinger/ISurface.h>
40
Andreas Huber27366fc2009-11-20 09:32:46 -080041namespace android {
42
43struct AwesomeEvent : public TimedEventQueue::Event {
Andreas Huber6be780e2010-02-08 14:40:30 -080044 AwesomeEvent(
45 AwesomePlayer *player,
46 void (AwesomePlayer::*method)())
Andreas Huber27366fc2009-11-20 09:32:46 -080047 : mPlayer(player),
Andreas Huber6be780e2010-02-08 14:40:30 -080048 mMethod(method) {
Andreas Huber27366fc2009-11-20 09:32:46 -080049 }
50
51protected:
52 virtual ~AwesomeEvent() {}
53
54 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
Andreas Huber6be780e2010-02-08 14:40:30 -080055 (mPlayer->*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080056 }
57
58private:
59 AwesomePlayer *mPlayer;
Andreas Huber6be780e2010-02-08 14:40:30 -080060 void (AwesomePlayer::*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080061
62 AwesomeEvent(const AwesomeEvent &);
63 AwesomeEvent &operator=(const AwesomeEvent &);
64};
65
Andreas Huber1314e732009-12-14 14:18:22 -080066struct AwesomeRemoteRenderer : public AwesomeRenderer {
67 AwesomeRemoteRenderer(const sp<IOMXRenderer> &target)
68 : mTarget(target) {
69 }
70
71 virtual void render(MediaBuffer *buffer) {
72 void *id;
73 if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) {
74 mTarget->render((IOMX::buffer_id)id);
75 }
76 }
77
78private:
79 sp<IOMXRenderer> mTarget;
80
81 AwesomeRemoteRenderer(const AwesomeRemoteRenderer &);
82 AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &);
83};
84
85struct AwesomeLocalRenderer : public AwesomeRenderer {
86 AwesomeLocalRenderer(
Andreas Huber7b73cfc2010-02-12 14:40:08 -080087 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080088 const char *componentName,
Andreas Huber1314e732009-12-14 14:18:22 -080089 OMX_COLOR_FORMATTYPE colorFormat,
90 const sp<ISurface> &surface,
91 size_t displayWidth, size_t displayHeight,
92 size_t decodedWidth, size_t decodedHeight)
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080093 : mTarget(NULL),
94 mLibHandle(NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -080095 init(previewOnly, componentName,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080096 colorFormat, surface, displayWidth,
97 displayHeight, decodedWidth, decodedHeight);
Andreas Huber1314e732009-12-14 14:18:22 -080098 }
99
100 virtual void render(MediaBuffer *buffer) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800101 render((const uint8_t *)buffer->data() + buffer->range_offset(),
102 buffer->range_length());
103 }
104
105 void render(const void *data, size_t size) {
106 mTarget->render(data, size, NULL);
Andreas Huber1314e732009-12-14 14:18:22 -0800107 }
108
109protected:
110 virtual ~AwesomeLocalRenderer() {
111 delete mTarget;
112 mTarget = NULL;
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800113
114 if (mLibHandle) {
115 dlclose(mLibHandle);
116 mLibHandle = NULL;
117 }
Andreas Huber1314e732009-12-14 14:18:22 -0800118 }
119
120private:
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800121 VideoRenderer *mTarget;
122 void *mLibHandle;
123
124 void init(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800125 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800126 const char *componentName,
127 OMX_COLOR_FORMATTYPE colorFormat,
128 const sp<ISurface> &surface,
129 size_t displayWidth, size_t displayHeight,
130 size_t decodedWidth, size_t decodedHeight);
Andreas Huber1314e732009-12-14 14:18:22 -0800131
132 AwesomeLocalRenderer(const AwesomeLocalRenderer &);
133 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
134};
135
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800136void AwesomeLocalRenderer::init(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800137 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800138 const char *componentName,
139 OMX_COLOR_FORMATTYPE colorFormat,
140 const sp<ISurface> &surface,
141 size_t displayWidth, size_t displayHeight,
142 size_t decodedWidth, size_t decodedHeight) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800143 if (!previewOnly) {
144 // We will stick to the vanilla software-color-converting renderer
145 // for "previewOnly" mode, to avoid unneccessarily switching overlays
146 // more often than necessary.
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800147
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800148 mLibHandle = dlopen("libstagefrighthw.so", RTLD_NOW);
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800149
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800150 if (mLibHandle) {
151 typedef VideoRenderer *(*CreateRendererFunc)(
152 const sp<ISurface> &surface,
153 const char *componentName,
154 OMX_COLOR_FORMATTYPE colorFormat,
155 size_t displayWidth, size_t displayHeight,
156 size_t decodedWidth, size_t decodedHeight);
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800157
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800158 CreateRendererFunc func =
159 (CreateRendererFunc)dlsym(
160 mLibHandle,
161 "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20"
162 "OMX_COLOR_FORMATTYPEjjjj");
163
164 if (func) {
165 mTarget =
166 (*func)(surface, componentName, colorFormat,
167 displayWidth, displayHeight,
168 decodedWidth, decodedHeight);
169 }
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800170 }
171 }
172
173 if (mTarget == NULL) {
174 mTarget = new SoftwareRenderer(
175 colorFormat, surface, displayWidth, displayHeight,
176 decodedWidth, decodedHeight);
177 }
178}
179
Andreas Huber27366fc2009-11-20 09:32:46 -0800180AwesomePlayer::AwesomePlayer()
Andreas Huber406a18b2010-02-18 16:45:13 -0800181 : mQueueStarted(false),
182 mTimeSource(NULL),
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800183 mVideoRendererIsPreview(false),
Andreas Huber27366fc2009-11-20 09:32:46 -0800184 mAudioPlayer(NULL),
Andreas Huberffdf4782010-02-09 14:05:43 -0800185 mFlags(0),
Andreas Huber27366fc2009-11-20 09:32:46 -0800186 mLastVideoBuffer(NULL),
Andreas Huberba7ec912010-02-12 10:42:02 -0800187 mVideoBuffer(NULL),
188 mSuspensionState(NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800189 CHECK_EQ(mClient.connect(), OK);
190
191 DataSource::RegisterDefaultSniffers();
192
Andreas Huber6be780e2010-02-08 14:40:30 -0800193 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
Andreas Huber27366fc2009-11-20 09:32:46 -0800194 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800195 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
Andreas Huber27366fc2009-11-20 09:32:46 -0800196 mStreamDoneEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800197 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
Andreas Huberb9e63832010-01-26 16:20:10 -0800198 mBufferingEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800199
200 mCheckAudioStatusEvent = new AwesomeEvent(
201 this, &AwesomePlayer::onCheckAudioStatus);
202
Andreas Huber70d10c02010-02-03 11:37:29 -0800203 mAudioStatusEventPending = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800204
Andreas Huber27366fc2009-11-20 09:32:46 -0800205 reset();
206}
207
208AwesomePlayer::~AwesomePlayer() {
Andreas Huber406a18b2010-02-18 16:45:13 -0800209 if (mQueueStarted) {
210 mQueue.stop();
211 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800212
213 reset();
214
215 mClient.disconnect();
216}
217
Andreas Huberb9e63832010-01-26 16:20:10 -0800218void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800219 mQueue.cancelEvent(mVideoEvent->eventID());
220 mVideoEventPending = false;
221 mQueue.cancelEvent(mStreamDoneEvent->eventID());
222 mStreamDoneEventPending = false;
Andreas Huber70d10c02010-02-03 11:37:29 -0800223 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
224 mAudioStatusEventPending = false;
Andreas Huberb9e63832010-01-26 16:20:10 -0800225
226 if (!keepBufferingGoing) {
227 mQueue.cancelEvent(mBufferingEvent->eventID());
228 mBufferingEventPending = false;
229 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800230}
231
Andreas Hubera3f43842010-01-21 10:28:45 -0800232void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800233 Mutex::Autolock autoLock(mLock);
234 mListener = listener;
235}
236
Andreas Huber433c9ac2010-01-27 16:49:05 -0800237status_t AwesomePlayer::setDataSource(
238 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800239 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800240 return setDataSource_l(uri, headers);
241}
Andreas Huber27366fc2009-11-20 09:32:46 -0800242
Andreas Huberba7ec912010-02-12 10:42:02 -0800243status_t AwesomePlayer::setDataSource_l(
244 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800245 reset_l();
246
Andreas Huberffdf4782010-02-09 14:05:43 -0800247 mUri = uri;
Andreas Huberb9e63832010-01-26 16:20:10 -0800248
Andreas Huberffdf4782010-02-09 14:05:43 -0800249 if (headers) {
250 mUriHeaders = *headers;
Andreas Huberb9e63832010-01-26 16:20:10 -0800251 }
252
Andreas Huberffdf4782010-02-09 14:05:43 -0800253 // The actual work will be done during preparation in the call to
254 // ::finishSetDataSource_l to avoid blocking the calling thread in
255 // setDataSource for any significant time.
Andreas Huber27366fc2009-11-20 09:32:46 -0800256
Andreas Huberffdf4782010-02-09 14:05:43 -0800257 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800258}
259
260status_t AwesomePlayer::setDataSource(
261 int fd, int64_t offset, int64_t length) {
262 Mutex::Autolock autoLock(mLock);
263
264 reset_l();
265
Andreas Huberba7ec912010-02-12 10:42:02 -0800266 sp<DataSource> dataSource = new FileSource(fd, offset, length);
Andreas Huber27366fc2009-11-20 09:32:46 -0800267
Andreas Huberba7ec912010-02-12 10:42:02 -0800268 status_t err = dataSource->initCheck();
Andreas Huber27366fc2009-11-20 09:32:46 -0800269
270 if (err != OK) {
271 return err;
272 }
273
Andreas Huberba7ec912010-02-12 10:42:02 -0800274 mFileSource = dataSource;
275
276 return setDataSource_l(dataSource);
277}
278
279status_t AwesomePlayer::setDataSource_l(
280 const sp<DataSource> &dataSource) {
281 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
Andreas Huber27366fc2009-11-20 09:32:46 -0800282
283 if (extractor == NULL) {
284 return UNKNOWN_ERROR;
285 }
286
287 return setDataSource_l(extractor);
288}
289
290status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800291 bool haveAudio = false;
292 bool haveVideo = false;
293 for (size_t i = 0; i < extractor->countTracks(); ++i) {
294 sp<MetaData> meta = extractor->getTrackMetaData(i);
295
296 const char *mime;
297 CHECK(meta->findCString(kKeyMIMEType, &mime));
298
299 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800300 setVideoSource(extractor->getTrack(i));
301 haveVideo = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800302 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800303 setAudioSource(extractor->getTrack(i));
304 haveAudio = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800305 }
306
307 if (haveAudio && haveVideo) {
308 break;
309 }
310 }
311
312 return !haveAudio && !haveVideo ? UNKNOWN_ERROR : OK;
313}
314
315void AwesomePlayer::reset() {
316 Mutex::Autolock autoLock(mLock);
317 reset_l();
318}
319
320void AwesomePlayer::reset_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -0800321 while (mFlags & PREPARING) {
322 mPreparedCondition.wait(mLock);
323 }
324
Andreas Huber27366fc2009-11-20 09:32:46 -0800325 cancelPlayerEvents();
326
Andreas Huberba7ec912010-02-12 10:42:02 -0800327 if (mPrefetcher != NULL) {
328 CHECK_EQ(mPrefetcher->getStrongCount(), 1);
329 }
330 mPrefetcher.clear();
331
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800332 mAudioTrack.clear();
333 mVideoTrack.clear();
334
Andreas Huberba7ec912010-02-12 10:42:02 -0800335 // Shutdown audio first, so that the respone to the reset request
336 // appears to happen instantaneously as far as the user is concerned
337 // If we did this later, audio would continue playing while we
338 // shutdown the video-related resources and the player appear to
339 // not be as responsive to a reset request.
340 mAudioSource.clear();
341
342 if (mTimeSource != mAudioPlayer) {
343 delete mTimeSource;
344 }
345 mTimeSource = NULL;
346
347 delete mAudioPlayer;
348 mAudioPlayer = NULL;
349
Andreas Huber3522b5a52010-01-22 14:36:53 -0800350 mVideoRenderer.clear();
351
Andreas Huber27366fc2009-11-20 09:32:46 -0800352 if (mLastVideoBuffer) {
353 mLastVideoBuffer->release();
354 mLastVideoBuffer = NULL;
355 }
356
357 if (mVideoBuffer) {
358 mVideoBuffer->release();
359 mVideoBuffer = NULL;
360 }
361
362 if (mVideoSource != NULL) {
363 mVideoSource->stop();
Andreas Huber98b48de2010-01-29 10:10:22 -0800364
365 // The following hack is necessary to ensure that the OMX
366 // component is completely released by the time we may try
367 // to instantiate it again.
368 wp<MediaSource> tmp = mVideoSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800369 mVideoSource.clear();
Andreas Huber98b48de2010-01-29 10:10:22 -0800370 while (tmp.promote() != NULL) {
371 usleep(1000);
372 }
373 IPCThreadState::self()->flushCommands();
Andreas Huber27366fc2009-11-20 09:32:46 -0800374 }
375
Andreas Huber27366fc2009-11-20 09:32:46 -0800376 mDurationUs = -1;
377 mFlags = 0;
378 mVideoWidth = mVideoHeight = -1;
379 mTimeSourceDeltaUs = 0;
380 mVideoTimeUs = 0;
381
382 mSeeking = false;
383 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800384
Andreas Huberffdf4782010-02-09 14:05:43 -0800385 mUri.setTo("");
386 mUriHeaders.clear();
Andreas Huberba7ec912010-02-12 10:42:02 -0800387
388 mFileSource.clear();
389
390 delete mSuspensionState;
391 mSuspensionState = NULL;
Andreas Huber27366fc2009-11-20 09:32:46 -0800392}
393
Andreas Huber6be780e2010-02-08 14:40:30 -0800394void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800395 if (mListener != NULL) {
396 sp<MediaPlayerBase> listener = mListener.promote();
397
398 if (listener != NULL) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800399 listener->sendEvent(msg, ext1, ext2);
Andreas Hubera3f43842010-01-21 10:28:45 -0800400 }
401 }
402}
403
Andreas Huberb9e63832010-01-26 16:20:10 -0800404void AwesomePlayer::onBufferingUpdate() {
405 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800406 if (!mBufferingEventPending) {
407 return;
408 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800409 mBufferingEventPending = false;
410
411 if (mDurationUs >= 0) {
412 int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs();
Andreas Huberdc9927d2010-03-08 15:46:13 -0800413
414 LOGV("cache holds %.2f secs worth of data.", cachedDurationUs / 1E6);
415
Andreas Huberb9e63832010-01-26 16:20:10 -0800416 int64_t positionUs = 0;
Andreas Huber7085b6842010-02-03 16:02:02 -0800417 if (mVideoSource != NULL) {
Andreas Huberb9e63832010-01-26 16:20:10 -0800418 positionUs = mVideoTimeUs;
419 } else if (mAudioPlayer != NULL) {
420 positionUs = mAudioPlayer->getMediaTimeUs();
421 }
422
423 cachedDurationUs += positionUs;
424
425 double percentage = (double)cachedDurationUs / mDurationUs;
426 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
427
428 postBufferingEvent_l();
429 }
430}
431
Andreas Huber27366fc2009-11-20 09:32:46 -0800432void AwesomePlayer::onStreamDone() {
433 // Posted whenever any stream finishes playing.
434
435 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800436 if (!mStreamDoneEventPending) {
437 return;
438 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800439 mStreamDoneEventPending = false;
440
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800441 if (mStreamDoneStatus == ERROR_END_OF_STREAM && (mFlags & LOOPING)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800442 seekTo_l(0);
443
Andreas Huber7085b6842010-02-03 16:02:02 -0800444 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800445 postVideoEvent_l();
446 }
447 } else {
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800448 if (mStreamDoneStatus == ERROR_END_OF_STREAM) {
449 LOGV("MEDIA_PLAYBACK_COMPLETE");
450 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
451 } else {
452 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
453
454 notifyListener_l(
455 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
456 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800457
458 pause_l();
Andreas Huber406a18b2010-02-18 16:45:13 -0800459
460 mFlags |= AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800461 }
462}
463
464status_t AwesomePlayer::play() {
465 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800466 return play_l();
467}
Andreas Huber27366fc2009-11-20 09:32:46 -0800468
Andreas Huberba7ec912010-02-12 10:42:02 -0800469status_t AwesomePlayer::play_l() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800470 if (mFlags & PLAYING) {
471 return OK;
472 }
473
Andreas Huberffdf4782010-02-09 14:05:43 -0800474 if (!(mFlags & PREPARED)) {
475 status_t err = prepare_l();
476
477 if (err != OK) {
478 return err;
479 }
480 }
481
Andreas Huber27366fc2009-11-20 09:32:46 -0800482 mFlags |= PLAYING;
483 mFlags |= FIRST_FRAME;
484
Andreas Huberc1d5c922009-12-10 15:49:04 -0800485 bool deferredAudioSeek = false;
486
Andreas Huber27366fc2009-11-20 09:32:46 -0800487 if (mAudioSource != NULL) {
488 if (mAudioPlayer == NULL) {
489 if (mAudioSink != NULL) {
490 mAudioPlayer = new AudioPlayer(mAudioSink);
Andreas Huber27366fc2009-11-20 09:32:46 -0800491 mAudioPlayer->setSource(mAudioSource);
Andreas Huberdc9927d2010-03-08 15:46:13 -0800492
493 // We've already started the MediaSource in order to enable
494 // the prefetcher to read its data.
495 status_t err = mAudioPlayer->start(
496 true /* sourceAlreadyStarted */);
Andreas Huber62eac002010-01-29 13:24:58 -0800497
498 if (err != OK) {
499 delete mAudioPlayer;
500 mAudioPlayer = NULL;
501
502 mFlags &= ~(PLAYING | FIRST_FRAME);
503
504 return err;
505 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800506
507 delete mTimeSource;
508 mTimeSource = mAudioPlayer;
509
Andreas Huberc1d5c922009-12-10 15:49:04 -0800510 deferredAudioSeek = true;
Andreas Huber70d10c02010-02-03 11:37:29 -0800511
512 mWatchForAudioSeekComplete = false;
513 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800514 }
515 } else {
516 mAudioPlayer->resume();
517 }
Andreas Huber70d10c02010-02-03 11:37:29 -0800518
519 postCheckAudioStatusEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800520 }
521
522 if (mTimeSource == NULL && mAudioPlayer == NULL) {
523 mTimeSource = new SystemTimeSource;
524 }
525
526 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800527 // Kick off video playback
528 postVideoEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800529 }
530
Andreas Huberc1d5c922009-12-10 15:49:04 -0800531 if (deferredAudioSeek) {
532 // If there was a seek request while we were paused
533 // and we're just starting up again, honor the request now.
534 seekAudioIfNecessary_l();
535 }
536
Andreas Huberb9e63832010-01-26 16:20:10 -0800537 postBufferingEvent_l();
538
Andreas Huber406a18b2010-02-18 16:45:13 -0800539 if (mFlags & AT_EOS) {
540 // Legacy behaviour, if a stream finishes playing and then
541 // is started again, we play from the start...
542 seekTo_l(0);
543 }
544
Andreas Huber27366fc2009-11-20 09:32:46 -0800545 return OK;
546}
547
548void AwesomePlayer::initRenderer_l() {
549 if (mISurface != NULL) {
550 sp<MetaData> meta = mVideoSource->getFormat();
551
552 int32_t format;
553 const char *component;
554 int32_t decodedWidth, decodedHeight;
555 CHECK(meta->findInt32(kKeyColorFormat, &format));
556 CHECK(meta->findCString(kKeyDecoderComponent, &component));
557 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
558 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
559
Andreas Hubera67d5382009-12-10 15:32:12 -0800560 mVideoRenderer.clear();
561
562 // Must ensure that mVideoRenderer's destructor is actually executed
563 // before creating a new one.
564 IPCThreadState::self()->flushCommands();
565
Andreas Huber1314e732009-12-14 14:18:22 -0800566 if (!strncmp("OMX.", component, 4)) {
567 // Our OMX codecs allocate buffers on the media_server side
568 // therefore they require a remote IOMXRenderer that knows how
569 // to display them.
570 mVideoRenderer = new AwesomeRemoteRenderer(
571 mClient.interface()->createRenderer(
572 mISurface, component,
573 (OMX_COLOR_FORMATTYPE)format,
574 decodedWidth, decodedHeight,
575 mVideoWidth, mVideoHeight));
576 } else {
577 // Other decoders are instantiated locally and as a consequence
578 // allocate their buffers in local address space.
579 mVideoRenderer = new AwesomeLocalRenderer(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800580 false, // previewOnly
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800581 component,
Andreas Huber1314e732009-12-14 14:18:22 -0800582 (OMX_COLOR_FORMATTYPE)format,
583 mISurface,
584 mVideoWidth, mVideoHeight,
585 decodedWidth, decodedHeight);
586 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800587 }
588}
589
590status_t AwesomePlayer::pause() {
591 Mutex::Autolock autoLock(mLock);
592 return pause_l();
593}
594
595status_t AwesomePlayer::pause_l() {
596 if (!(mFlags & PLAYING)) {
597 return OK;
598 }
599
Andreas Huberb9e63832010-01-26 16:20:10 -0800600 cancelPlayerEvents(true /* keepBufferingGoing */);
Andreas Huber27366fc2009-11-20 09:32:46 -0800601
602 if (mAudioPlayer != NULL) {
603 mAudioPlayer->pause();
604 }
605
606 mFlags &= ~PLAYING;
607
608 return OK;
609}
610
611bool AwesomePlayer::isPlaying() const {
612 Mutex::Autolock autoLock(mLock);
613
614 return mFlags & PLAYING;
615}
616
617void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
618 Mutex::Autolock autoLock(mLock);
619
620 mISurface = isurface;
621}
622
623void AwesomePlayer::setAudioSink(
624 const sp<MediaPlayerBase::AudioSink> &audioSink) {
625 Mutex::Autolock autoLock(mLock);
626
627 mAudioSink = audioSink;
628}
629
630status_t AwesomePlayer::setLooping(bool shouldLoop) {
631 Mutex::Autolock autoLock(mLock);
632
633 mFlags = mFlags & ~LOOPING;
634
635 if (shouldLoop) {
636 mFlags |= LOOPING;
637 }
638
639 return OK;
640}
641
642status_t AwesomePlayer::getDuration(int64_t *durationUs) {
643 Mutex::Autolock autoLock(mLock);
644
645 if (mDurationUs < 0) {
646 return UNKNOWN_ERROR;
647 }
648
649 *durationUs = mDurationUs;
650
651 return OK;
652}
653
654status_t AwesomePlayer::getPosition(int64_t *positionUs) {
655 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800656 return getPosition_l(positionUs);
657}
Andreas Huber27366fc2009-11-20 09:32:46 -0800658
Andreas Huberba7ec912010-02-12 10:42:02 -0800659status_t AwesomePlayer::getPosition_l(int64_t *positionUs) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800660 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800661 *positionUs = mVideoTimeUs;
662 } else if (mAudioPlayer != NULL) {
663 *positionUs = mAudioPlayer->getMediaTimeUs();
664 } else {
665 *positionUs = 0;
666 }
667
668 return OK;
669}
670
671status_t AwesomePlayer::seekTo(int64_t timeUs) {
672 Mutex::Autolock autoLock(mLock);
673 return seekTo_l(timeUs);
674}
675
676status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
677 mSeeking = true;
678 mSeekTimeUs = timeUs;
Andreas Huber406a18b2010-02-18 16:45:13 -0800679 mFlags &= ~AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800680
681 seekAudioIfNecessary_l();
682
683 return OK;
684}
685
686void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Huber7085b6842010-02-03 16:02:02 -0800687 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800688 mAudioPlayer->seekTo(mSeekTimeUs);
689
Andreas Huber70d10c02010-02-03 11:37:29 -0800690 mWatchForAudioSeekComplete = true;
691 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800692 mSeeking = false;
693 }
694}
695
696status_t AwesomePlayer::getVideoDimensions(
697 int32_t *width, int32_t *height) const {
698 Mutex::Autolock autoLock(mLock);
699
700 if (mVideoWidth < 0 || mVideoHeight < 0) {
701 return UNKNOWN_ERROR;
702 }
703
704 *width = mVideoWidth;
705 *height = mVideoHeight;
706
707 return OK;
708}
709
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800710void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
711 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800712
Andreas Huberb9e63832010-01-26 16:20:10 -0800713 if (mPrefetcher != NULL) {
714 source = mPrefetcher->addSource(source);
715 }
716
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800717 mAudioTrack = source;
718}
719
720status_t AwesomePlayer::initAudioDecoder() {
721 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huberc79827a2010-01-05 10:54:55 -0800722
723 const char *mime;
724 CHECK(meta->findCString(kKeyMIMEType, &mime));
725
726 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800727 mAudioSource = mAudioTrack;
Andreas Huberc79827a2010-01-05 10:54:55 -0800728 } else {
729 mAudioSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800730 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huberc79827a2010-01-05 10:54:55 -0800731 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800732 mAudioTrack);
Andreas Huberc79827a2010-01-05 10:54:55 -0800733 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800734
735 if (mAudioSource != NULL) {
736 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800737 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800738 if (mDurationUs < 0 || durationUs > mDurationUs) {
739 mDurationUs = durationUs;
740 }
741 }
742 }
743
Andreas Huberdc9927d2010-03-08 15:46:13 -0800744 mAudioSource->start();
745
Andreas Huber27366fc2009-11-20 09:32:46 -0800746 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
747}
748
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800749void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
750 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800751
Andreas Huberb9e63832010-01-26 16:20:10 -0800752 if (mPrefetcher != NULL) {
753 source = mPrefetcher->addSource(source);
754 }
755
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800756 mVideoTrack = source;
757}
758
759status_t AwesomePlayer::initVideoDecoder() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800760 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800761 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -0800762 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800763 mVideoTrack);
Andreas Huber27366fc2009-11-20 09:32:46 -0800764
765 if (mVideoSource != NULL) {
766 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800767 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800768 if (mDurationUs < 0 || durationUs > mDurationUs) {
769 mDurationUs = durationUs;
770 }
771 }
772
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800773 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
774 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
Andreas Huber27366fc2009-11-20 09:32:46 -0800775
776 mVideoSource->start();
777 }
778
779 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
780}
781
Andreas Huber6be780e2010-02-08 14:40:30 -0800782void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800783 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800784 if (!mVideoEventPending) {
785 // The event has been cancelled in reset_l() but had already
786 // been scheduled for execution at that time.
787 return;
788 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800789 mVideoEventPending = false;
790
791 if (mSeeking) {
792 if (mLastVideoBuffer) {
793 mLastVideoBuffer->release();
794 mLastVideoBuffer = NULL;
795 }
796
797 if (mVideoBuffer) {
798 mVideoBuffer->release();
799 mVideoBuffer = NULL;
800 }
801 }
802
803 if (!mVideoBuffer) {
804 MediaSource::ReadOptions options;
805 if (mSeeking) {
806 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
807
808 options.setSeekTo(mSeekTimeUs);
809 }
810 for (;;) {
811 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -0800812 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -0800813
814 if (err != OK) {
815 CHECK_EQ(mVideoBuffer, NULL);
816
817 if (err == INFO_FORMAT_CHANGED) {
818 LOGV("VideoSource signalled format change.");
819
Andreas Huber7085b6842010-02-03 16:02:02 -0800820 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800821 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -0800822 initRenderer_l();
823 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800824 continue;
825 }
826
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800827 postStreamDoneEvent_l(err);
Andreas Huber27366fc2009-11-20 09:32:46 -0800828 return;
829 }
830
Andreas Hubera67d5382009-12-10 15:32:12 -0800831 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -0800832 // Some decoders, notably the PV AVC software decoder
833 // return spurious empty buffers that we just want to ignore.
834
Andreas Hubera67d5382009-12-10 15:32:12 -0800835 mVideoBuffer->release();
836 mVideoBuffer = NULL;
837 continue;
838 }
839
Andreas Huber27366fc2009-11-20 09:32:46 -0800840 break;
841 }
842 }
843
844 int64_t timeUs;
845 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
846
847 mVideoTimeUs = timeUs;
848
849 if (mSeeking) {
850 if (mAudioPlayer != NULL) {
851 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
852
853 mAudioPlayer->seekTo(timeUs);
Andreas Huber70d10c02010-02-03 11:37:29 -0800854 mWatchForAudioSeekComplete = true;
855 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800856 } else {
857 // If we're playing video only, report seek complete now,
858 // otherwise audio player will notify us later.
Andreas Hubera3f43842010-01-21 10:28:45 -0800859 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800860 }
861
862 mFlags |= FIRST_FRAME;
863 mSeeking = false;
864 }
865
866 if (mFlags & FIRST_FRAME) {
867 mFlags &= ~FIRST_FRAME;
868
869 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
870 }
871
872 int64_t realTimeUs, mediaTimeUs;
873 if (mAudioPlayer != NULL
874 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
875 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
876 }
877
878 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
879
880 int64_t latenessUs = nowUs - timeUs;
881
Andreas Huber24b0a952009-11-23 14:02:00 -0800882 if (latenessUs > 40000) {
883 // We're more than 40ms late.
Andreas Huber4a9375e2010-02-09 11:54:33 -0800884 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -0800885
886 mVideoBuffer->release();
887 mVideoBuffer = NULL;
888
889 postVideoEvent_l();
890 return;
891 }
892
893 if (latenessUs < -10000) {
894 // We're more than 10ms early.
895
896 postVideoEvent_l(10000);
897 return;
898 }
899
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800900 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
901 mVideoRendererIsPreview = false;
902
Andreas Huber7085b6842010-02-03 16:02:02 -0800903 initRenderer_l();
904 }
905
906 if (mVideoRenderer != NULL) {
907 mVideoRenderer->render(mVideoBuffer);
908 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800909
910 if (mLastVideoBuffer) {
911 mLastVideoBuffer->release();
912 mLastVideoBuffer = NULL;
913 }
914 mLastVideoBuffer = mVideoBuffer;
915 mVideoBuffer = NULL;
916
917 postVideoEvent_l();
918}
919
920void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
921 if (mVideoEventPending) {
922 return;
923 }
924
925 mVideoEventPending = true;
926 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
927}
928
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800929void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800930 if (mStreamDoneEventPending) {
931 return;
932 }
933 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800934
935 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -0800936 mQueue.postEvent(mStreamDoneEvent);
937}
938
Andreas Huberb9e63832010-01-26 16:20:10 -0800939void AwesomePlayer::postBufferingEvent_l() {
940 if (mPrefetcher == NULL) {
941 return;
942 }
943
944 if (mBufferingEventPending) {
945 return;
946 }
947 mBufferingEventPending = true;
948 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
949}
950
Andreas Huber70d10c02010-02-03 11:37:29 -0800951void AwesomePlayer::postCheckAudioStatusEvent_l() {
952 if (mAudioStatusEventPending) {
953 return;
954 }
955 mAudioStatusEventPending = true;
956 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
957}
958
959void AwesomePlayer::onCheckAudioStatus() {
960 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800961 if (!mAudioStatusEventPending) {
962 // Event was dispatched and while we were blocking on the mutex,
963 // has already been cancelled.
964 return;
965 }
966
Andreas Huber70d10c02010-02-03 11:37:29 -0800967 mAudioStatusEventPending = false;
968
969 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
970 mWatchForAudioSeekComplete = false;
971 notifyListener_l(MEDIA_SEEK_COMPLETE);
972 }
973
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800974 status_t finalStatus;
975 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -0800976 mWatchForAudioEOS = false;
Andreas Huberd7d22eb2010-02-23 13:45:33 -0800977 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -0800978 }
979
980 postCheckAudioStatusEvent_l();
981}
982
Andreas Huber6be780e2010-02-08 14:40:30 -0800983status_t AwesomePlayer::prepare() {
984 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -0800985 return prepare_l();
986}
Andreas Huber6be780e2010-02-08 14:40:30 -0800987
Andreas Huberffdf4782010-02-09 14:05:43 -0800988status_t AwesomePlayer::prepare_l() {
989 if (mFlags & PREPARED) {
990 return OK;
991 }
992
993 if (mFlags & PREPARING) {
994 return UNKNOWN_ERROR;
995 }
996
997 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800998 status_t err = prepareAsync_l();
999
1000 if (err != OK) {
1001 return err;
1002 }
1003
Andreas Huberffdf4782010-02-09 14:05:43 -08001004 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001005 mPreparedCondition.wait(mLock);
1006 }
1007
Andreas Huberffdf4782010-02-09 14:05:43 -08001008 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001009}
1010
1011status_t AwesomePlayer::prepareAsync() {
1012 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001013
1014 if (mFlags & PREPARING) {
1015 return UNKNOWN_ERROR; // async prepare already pending
1016 }
1017
1018 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001019 return prepareAsync_l();
1020}
1021
1022status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001023 if (mFlags & PREPARING) {
1024 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001025 }
1026
Andreas Huber406a18b2010-02-18 16:45:13 -08001027 if (!mQueueStarted) {
1028 mQueue.start();
1029 mQueueStarted = true;
1030 }
1031
Andreas Huberffdf4782010-02-09 14:05:43 -08001032 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -08001033 mAsyncPrepareEvent = new AwesomeEvent(
1034 this, &AwesomePlayer::onPrepareAsyncEvent);
1035
1036 mQueue.postEvent(mAsyncPrepareEvent);
1037
1038 return OK;
1039}
1040
Andreas Huberffdf4782010-02-09 14:05:43 -08001041status_t AwesomePlayer::finishSetDataSource_l() {
1042 sp<DataSource> dataSource =
1043 DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1044
1045 if (dataSource == NULL) {
1046 return UNKNOWN_ERROR;
1047 }
1048
1049 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1050
1051 if (extractor == NULL) {
1052 return UNKNOWN_ERROR;
1053 }
1054
1055 if (dataSource->flags() & DataSource::kWantsPrefetching) {
1056 mPrefetcher = new Prefetcher;
1057 }
1058
1059 return setDataSource_l(extractor);
1060}
1061
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001062void AwesomePlayer::abortPrepare(status_t err) {
1063 CHECK(err != OK);
1064
1065 if (mIsAsyncPrepare) {
1066 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1067 }
1068
1069 mPrepareResult = err;
1070 mFlags &= ~PREPARING;
1071 mAsyncPrepareEvent = NULL;
1072 mPreparedCondition.broadcast();
1073}
1074
Andreas Huber6be780e2010-02-08 14:40:30 -08001075void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber55864df72010-03-08 12:28:22 -08001076 sp<Prefetcher> prefetcher;
1077
Andreas Huberffdf4782010-02-09 14:05:43 -08001078 {
1079 Mutex::Autolock autoLock(mLock);
1080
1081 if (mUri.size() > 0) {
1082 status_t err = finishSetDataSource_l();
1083
1084 if (err != OK) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001085 abortPrepare(err);
Andreas Huberffdf4782010-02-09 14:05:43 -08001086 return;
1087 }
1088 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001089
Andreas Huber55864df72010-03-08 12:28:22 -08001090 if (mVideoTrack != NULL && mVideoSource == NULL) {
1091 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08001092
Andreas Huber55864df72010-03-08 12:28:22 -08001093 if (err != OK) {
1094 abortPrepare(err);
1095 return;
1096 }
1097 }
1098
1099 if (mAudioTrack != NULL && mAudioSource == NULL) {
1100 status_t err = initAudioDecoder();
1101
1102 if (err != OK) {
1103 abortPrepare(err);
1104 return;
1105 }
1106 }
1107
Andreas Huber6be780e2010-02-08 14:40:30 -08001108 prefetcher = mPrefetcher;
1109 }
1110
1111 if (prefetcher != NULL) {
1112 prefetcher->prepare();
Andreas Huberba7ec912010-02-12 10:42:02 -08001113 prefetcher.clear();
Andreas Huber6be780e2010-02-08 14:40:30 -08001114 }
1115
1116 Mutex::Autolock autoLock(mLock);
1117
Andreas Huberffdf4782010-02-09 14:05:43 -08001118 if (mIsAsyncPrepare) {
1119 if (mVideoWidth < 0 || mVideoHeight < 0) {
1120 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1121 } else {
1122 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
1123 }
1124
1125 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08001126 }
1127
Andreas Huberffdf4782010-02-09 14:05:43 -08001128 mPrepareResult = OK;
1129 mFlags &= ~PREPARING;
1130 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -08001131 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08001132 mPreparedCondition.broadcast();
Andreas Huber6be780e2010-02-08 14:40:30 -08001133}
1134
Andreas Huberba7ec912010-02-12 10:42:02 -08001135status_t AwesomePlayer::suspend() {
1136 LOGI("suspend");
1137 Mutex::Autolock autoLock(mLock);
1138
1139 if (mSuspensionState != NULL) {
1140 return INVALID_OPERATION;
1141 }
1142
1143 while (mFlags & PREPARING) {
1144 mPreparedCondition.wait(mLock);
1145 }
1146
1147 SuspensionState *state = new SuspensionState;
1148 state->mUri = mUri;
1149 state->mUriHeaders = mUriHeaders;
1150 state->mFileSource = mFileSource;
1151
Andreas Huber406a18b2010-02-18 16:45:13 -08001152 state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS);
Andreas Huberba7ec912010-02-12 10:42:02 -08001153 getPosition_l(&state->mPositionUs);
1154
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001155 if (mLastVideoBuffer) {
1156 size_t size = mLastVideoBuffer->range_length();
1157 if (size) {
1158 state->mLastVideoFrameSize = size;
1159 state->mLastVideoFrame = malloc(size);
1160 memcpy(state->mLastVideoFrame,
1161 (const uint8_t *)mLastVideoBuffer->data()
1162 + mLastVideoBuffer->range_offset(),
1163 size);
1164
1165 state->mVideoWidth = mVideoWidth;
1166 state->mVideoHeight = mVideoHeight;
1167
1168 sp<MetaData> meta = mVideoSource->getFormat();
1169 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1170 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1171 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1172 }
1173 }
1174
Andreas Huberba7ec912010-02-12 10:42:02 -08001175 reset_l();
1176
1177 mSuspensionState = state;
1178
1179 return OK;
1180}
1181
1182status_t AwesomePlayer::resume() {
1183 LOGI("resume");
1184 Mutex::Autolock autoLock(mLock);
1185
1186 if (mSuspensionState == NULL) {
1187 return INVALID_OPERATION;
1188 }
1189
1190 SuspensionState *state = mSuspensionState;
1191 mSuspensionState = NULL;
1192
1193 status_t err;
1194 if (state->mFileSource != NULL) {
1195 err = setDataSource_l(state->mFileSource);
1196
1197 if (err == OK) {
1198 mFileSource = state->mFileSource;
1199 }
1200 } else {
1201 err = setDataSource_l(state->mUri, &state->mUriHeaders);
1202 }
1203
1204 if (err != OK) {
1205 delete state;
1206 state = NULL;
1207
1208 return err;
1209 }
1210
1211 seekTo_l(state->mPositionUs);
1212
Andreas Huber406a18b2010-02-18 16:45:13 -08001213 mFlags = state->mFlags & (LOOPING | AT_EOS);
Andreas Huberba7ec912010-02-12 10:42:02 -08001214
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001215 if (state->mLastVideoFrame && mISurface != NULL) {
1216 mVideoRenderer =
1217 new AwesomeLocalRenderer(
1218 true, // previewOnly
1219 "",
1220 (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1221 mISurface,
1222 state->mVideoWidth,
1223 state->mVideoHeight,
1224 state->mDecodedWidth,
1225 state->mDecodedHeight);
1226
1227 mVideoRendererIsPreview = true;
1228
1229 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render(
1230 state->mLastVideoFrame, state->mLastVideoFrameSize);
1231 }
1232
Andreas Huberba7ec912010-02-12 10:42:02 -08001233 if (state->mFlags & PLAYING) {
1234 play_l();
1235 }
1236
1237 delete state;
1238 state = NULL;
1239
1240 return OK;
1241}
1242
Andreas Huber27366fc2009-11-20 09:32:46 -08001243} // namespace android
1244