blob: b3a73b0aa4fda3dae6ec3275c6236f79ab3d58cd [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)) {
300 if (setVideoSource(extractor->getTrack(i)) == OK) {
301 haveVideo = true;
302 }
303 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
304 if (setAudioSource(extractor->getTrack(i)) == OK) {
305 haveAudio = true;
306 }
307 }
308
309 if (haveAudio && haveVideo) {
310 break;
311 }
312 }
313
314 return !haveAudio && !haveVideo ? UNKNOWN_ERROR : OK;
315}
316
317void AwesomePlayer::reset() {
318 Mutex::Autolock autoLock(mLock);
319 reset_l();
320}
321
322void AwesomePlayer::reset_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -0800323 while (mFlags & PREPARING) {
324 mPreparedCondition.wait(mLock);
325 }
326
Andreas Huber27366fc2009-11-20 09:32:46 -0800327 cancelPlayerEvents();
328
Andreas Huberba7ec912010-02-12 10:42:02 -0800329 if (mPrefetcher != NULL) {
330 CHECK_EQ(mPrefetcher->getStrongCount(), 1);
331 }
332 mPrefetcher.clear();
333
334 // Shutdown audio first, so that the respone to the reset request
335 // appears to happen instantaneously as far as the user is concerned
336 // If we did this later, audio would continue playing while we
337 // shutdown the video-related resources and the player appear to
338 // not be as responsive to a reset request.
339 mAudioSource.clear();
340
341 if (mTimeSource != mAudioPlayer) {
342 delete mTimeSource;
343 }
344 mTimeSource = NULL;
345
346 delete mAudioPlayer;
347 mAudioPlayer = NULL;
348
Andreas Huber3522b5a52010-01-22 14:36:53 -0800349 mVideoRenderer.clear();
350
Andreas Huber27366fc2009-11-20 09:32:46 -0800351 if (mLastVideoBuffer) {
352 mLastVideoBuffer->release();
353 mLastVideoBuffer = NULL;
354 }
355
356 if (mVideoBuffer) {
357 mVideoBuffer->release();
358 mVideoBuffer = NULL;
359 }
360
361 if (mVideoSource != NULL) {
362 mVideoSource->stop();
Andreas Huber98b48de2010-01-29 10:10:22 -0800363
364 // The following hack is necessary to ensure that the OMX
365 // component is completely released by the time we may try
366 // to instantiate it again.
367 wp<MediaSource> tmp = mVideoSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800368 mVideoSource.clear();
Andreas Huber98b48de2010-01-29 10:10:22 -0800369 while (tmp.promote() != NULL) {
370 usleep(1000);
371 }
372 IPCThreadState::self()->flushCommands();
Andreas Huber27366fc2009-11-20 09:32:46 -0800373 }
374
Andreas Huber27366fc2009-11-20 09:32:46 -0800375 mDurationUs = -1;
376 mFlags = 0;
377 mVideoWidth = mVideoHeight = -1;
378 mTimeSourceDeltaUs = 0;
379 mVideoTimeUs = 0;
380
381 mSeeking = false;
382 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800383
Andreas Huberffdf4782010-02-09 14:05:43 -0800384 mUri.setTo("");
385 mUriHeaders.clear();
Andreas Huberba7ec912010-02-12 10:42:02 -0800386
387 mFileSource.clear();
388
389 delete mSuspensionState;
390 mSuspensionState = NULL;
Andreas Huber27366fc2009-11-20 09:32:46 -0800391}
392
Andreas Huber6be780e2010-02-08 14:40:30 -0800393void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800394 if (mListener != NULL) {
395 sp<MediaPlayerBase> listener = mListener.promote();
396
397 if (listener != NULL) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800398 listener->sendEvent(msg, ext1, ext2);
Andreas Hubera3f43842010-01-21 10:28:45 -0800399 }
400 }
401}
402
Andreas Huberb9e63832010-01-26 16:20:10 -0800403void AwesomePlayer::onBufferingUpdate() {
404 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800405 if (!mBufferingEventPending) {
406 return;
407 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800408 mBufferingEventPending = false;
409
410 if (mDurationUs >= 0) {
411 int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs();
412 int64_t positionUs = 0;
Andreas Huber7085b6842010-02-03 16:02:02 -0800413 if (mVideoSource != NULL) {
Andreas Huberb9e63832010-01-26 16:20:10 -0800414 positionUs = mVideoTimeUs;
415 } else if (mAudioPlayer != NULL) {
416 positionUs = mAudioPlayer->getMediaTimeUs();
417 }
418
419 cachedDurationUs += positionUs;
420
421 double percentage = (double)cachedDurationUs / mDurationUs;
422 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
423
424 postBufferingEvent_l();
425 }
426}
427
Andreas Huber27366fc2009-11-20 09:32:46 -0800428void AwesomePlayer::onStreamDone() {
429 // Posted whenever any stream finishes playing.
430
431 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800432 if (!mStreamDoneEventPending) {
433 return;
434 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800435 mStreamDoneEventPending = false;
436
437 if (mFlags & LOOPING) {
438 seekTo_l(0);
439
Andreas Huber7085b6842010-02-03 16:02:02 -0800440 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800441 postVideoEvent_l();
442 }
443 } else {
Andreas Hubera3f43842010-01-21 10:28:45 -0800444 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800445
446 pause_l();
Andreas Huber406a18b2010-02-18 16:45:13 -0800447
448 mFlags |= AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800449 }
450}
451
452status_t AwesomePlayer::play() {
453 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800454 return play_l();
455}
Andreas Huber27366fc2009-11-20 09:32:46 -0800456
Andreas Huberba7ec912010-02-12 10:42:02 -0800457status_t AwesomePlayer::play_l() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800458 if (mFlags & PLAYING) {
459 return OK;
460 }
461
Andreas Huberffdf4782010-02-09 14:05:43 -0800462 if (!(mFlags & PREPARED)) {
463 status_t err = prepare_l();
464
465 if (err != OK) {
466 return err;
467 }
468 }
469
Andreas Huber27366fc2009-11-20 09:32:46 -0800470 mFlags |= PLAYING;
471 mFlags |= FIRST_FRAME;
472
Andreas Huberc1d5c922009-12-10 15:49:04 -0800473 bool deferredAudioSeek = false;
474
Andreas Huber27366fc2009-11-20 09:32:46 -0800475 if (mAudioSource != NULL) {
476 if (mAudioPlayer == NULL) {
477 if (mAudioSink != NULL) {
478 mAudioPlayer = new AudioPlayer(mAudioSink);
Andreas Huber27366fc2009-11-20 09:32:46 -0800479 mAudioPlayer->setSource(mAudioSource);
Andreas Huber62eac002010-01-29 13:24:58 -0800480 status_t err = mAudioPlayer->start();
481
482 if (err != OK) {
483 delete mAudioPlayer;
484 mAudioPlayer = NULL;
485
486 mFlags &= ~(PLAYING | FIRST_FRAME);
487
488 return err;
489 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800490
491 delete mTimeSource;
492 mTimeSource = mAudioPlayer;
493
Andreas Huberc1d5c922009-12-10 15:49:04 -0800494 deferredAudioSeek = true;
Andreas Huber70d10c02010-02-03 11:37:29 -0800495
496 mWatchForAudioSeekComplete = false;
497 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800498 }
499 } else {
500 mAudioPlayer->resume();
501 }
Andreas Huber70d10c02010-02-03 11:37:29 -0800502
503 postCheckAudioStatusEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800504 }
505
506 if (mTimeSource == NULL && mAudioPlayer == NULL) {
507 mTimeSource = new SystemTimeSource;
508 }
509
510 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800511 // Kick off video playback
512 postVideoEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800513 }
514
Andreas Huberc1d5c922009-12-10 15:49:04 -0800515 if (deferredAudioSeek) {
516 // If there was a seek request while we were paused
517 // and we're just starting up again, honor the request now.
518 seekAudioIfNecessary_l();
519 }
520
Andreas Huberb9e63832010-01-26 16:20:10 -0800521 postBufferingEvent_l();
522
Andreas Huber406a18b2010-02-18 16:45:13 -0800523 if (mFlags & AT_EOS) {
524 // Legacy behaviour, if a stream finishes playing and then
525 // is started again, we play from the start...
526 seekTo_l(0);
527 }
528
Andreas Huber27366fc2009-11-20 09:32:46 -0800529 return OK;
530}
531
532void AwesomePlayer::initRenderer_l() {
533 if (mISurface != NULL) {
534 sp<MetaData> meta = mVideoSource->getFormat();
535
536 int32_t format;
537 const char *component;
538 int32_t decodedWidth, decodedHeight;
539 CHECK(meta->findInt32(kKeyColorFormat, &format));
540 CHECK(meta->findCString(kKeyDecoderComponent, &component));
541 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
542 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
543
Andreas Hubera67d5382009-12-10 15:32:12 -0800544 mVideoRenderer.clear();
545
546 // Must ensure that mVideoRenderer's destructor is actually executed
547 // before creating a new one.
548 IPCThreadState::self()->flushCommands();
549
Andreas Huber1314e732009-12-14 14:18:22 -0800550 if (!strncmp("OMX.", component, 4)) {
551 // Our OMX codecs allocate buffers on the media_server side
552 // therefore they require a remote IOMXRenderer that knows how
553 // to display them.
554 mVideoRenderer = new AwesomeRemoteRenderer(
555 mClient.interface()->createRenderer(
556 mISurface, component,
557 (OMX_COLOR_FORMATTYPE)format,
558 decodedWidth, decodedHeight,
559 mVideoWidth, mVideoHeight));
560 } else {
561 // Other decoders are instantiated locally and as a consequence
562 // allocate their buffers in local address space.
563 mVideoRenderer = new AwesomeLocalRenderer(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800564 false, // previewOnly
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800565 component,
Andreas Huber1314e732009-12-14 14:18:22 -0800566 (OMX_COLOR_FORMATTYPE)format,
567 mISurface,
568 mVideoWidth, mVideoHeight,
569 decodedWidth, decodedHeight);
570 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800571 }
572}
573
574status_t AwesomePlayer::pause() {
575 Mutex::Autolock autoLock(mLock);
576 return pause_l();
577}
578
579status_t AwesomePlayer::pause_l() {
580 if (!(mFlags & PLAYING)) {
581 return OK;
582 }
583
Andreas Huberb9e63832010-01-26 16:20:10 -0800584 cancelPlayerEvents(true /* keepBufferingGoing */);
Andreas Huber27366fc2009-11-20 09:32:46 -0800585
586 if (mAudioPlayer != NULL) {
587 mAudioPlayer->pause();
588 }
589
590 mFlags &= ~PLAYING;
591
592 return OK;
593}
594
595bool AwesomePlayer::isPlaying() const {
596 Mutex::Autolock autoLock(mLock);
597
598 return mFlags & PLAYING;
599}
600
601void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
602 Mutex::Autolock autoLock(mLock);
603
604 mISurface = isurface;
605}
606
607void AwesomePlayer::setAudioSink(
608 const sp<MediaPlayerBase::AudioSink> &audioSink) {
609 Mutex::Autolock autoLock(mLock);
610
611 mAudioSink = audioSink;
612}
613
614status_t AwesomePlayer::setLooping(bool shouldLoop) {
615 Mutex::Autolock autoLock(mLock);
616
617 mFlags = mFlags & ~LOOPING;
618
619 if (shouldLoop) {
620 mFlags |= LOOPING;
621 }
622
623 return OK;
624}
625
626status_t AwesomePlayer::getDuration(int64_t *durationUs) {
627 Mutex::Autolock autoLock(mLock);
628
629 if (mDurationUs < 0) {
630 return UNKNOWN_ERROR;
631 }
632
633 *durationUs = mDurationUs;
634
635 return OK;
636}
637
638status_t AwesomePlayer::getPosition(int64_t *positionUs) {
639 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800640 return getPosition_l(positionUs);
641}
Andreas Huber27366fc2009-11-20 09:32:46 -0800642
Andreas Huberba7ec912010-02-12 10:42:02 -0800643status_t AwesomePlayer::getPosition_l(int64_t *positionUs) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800644 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800645 *positionUs = mVideoTimeUs;
646 } else if (mAudioPlayer != NULL) {
647 *positionUs = mAudioPlayer->getMediaTimeUs();
648 } else {
649 *positionUs = 0;
650 }
651
652 return OK;
653}
654
655status_t AwesomePlayer::seekTo(int64_t timeUs) {
656 Mutex::Autolock autoLock(mLock);
657 return seekTo_l(timeUs);
658}
659
660status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
661 mSeeking = true;
662 mSeekTimeUs = timeUs;
Andreas Huber406a18b2010-02-18 16:45:13 -0800663 mFlags &= ~AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800664
665 seekAudioIfNecessary_l();
666
667 return OK;
668}
669
670void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Huber7085b6842010-02-03 16:02:02 -0800671 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800672 mAudioPlayer->seekTo(mSeekTimeUs);
673
Andreas Huber70d10c02010-02-03 11:37:29 -0800674 mWatchForAudioSeekComplete = true;
675 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800676 mSeeking = false;
677 }
678}
679
680status_t AwesomePlayer::getVideoDimensions(
681 int32_t *width, int32_t *height) const {
682 Mutex::Autolock autoLock(mLock);
683
684 if (mVideoWidth < 0 || mVideoHeight < 0) {
685 return UNKNOWN_ERROR;
686 }
687
688 *width = mVideoWidth;
689 *height = mVideoHeight;
690
691 return OK;
692}
693
Andreas Huberb9e63832010-01-26 16:20:10 -0800694status_t AwesomePlayer::setAudioSource(sp<MediaSource> source) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800695 if (source == NULL) {
696 return UNKNOWN_ERROR;
697 }
698
Andreas Huberb9e63832010-01-26 16:20:10 -0800699 if (mPrefetcher != NULL) {
700 source = mPrefetcher->addSource(source);
701 }
702
Andreas Huberc79827a2010-01-05 10:54:55 -0800703 sp<MetaData> meta = source->getFormat();
704
705 const char *mime;
706 CHECK(meta->findCString(kKeyMIMEType, &mime));
707
708 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
709 mAudioSource = source;
710 } else {
711 mAudioSource = OMXCodec::Create(
712 mClient.interface(), source->getFormat(),
713 false, // createEncoder
714 source);
715 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800716
717 if (mAudioSource != NULL) {
718 int64_t durationUs;
719 if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) {
720 if (mDurationUs < 0 || durationUs > mDurationUs) {
721 mDurationUs = durationUs;
722 }
723 }
724 }
725
726 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
727}
728
Andreas Huberb9e63832010-01-26 16:20:10 -0800729status_t AwesomePlayer::setVideoSource(sp<MediaSource> source) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800730 if (source == NULL) {
731 return UNKNOWN_ERROR;
732 }
733
Andreas Huberb9e63832010-01-26 16:20:10 -0800734 if (mPrefetcher != NULL) {
735 source = mPrefetcher->addSource(source);
736 }
737
Andreas Huber27366fc2009-11-20 09:32:46 -0800738 mVideoSource = OMXCodec::Create(
739 mClient.interface(), source->getFormat(),
740 false, // createEncoder
741 source);
742
743 if (mVideoSource != NULL) {
744 int64_t durationUs;
745 if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) {
746 if (mDurationUs < 0 || durationUs > mDurationUs) {
747 mDurationUs = durationUs;
748 }
749 }
750
751 CHECK(source->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
752 CHECK(source->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
753
754 mVideoSource->start();
755 }
756
757 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
758}
759
Andreas Huber6be780e2010-02-08 14:40:30 -0800760void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800761 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800762 if (!mVideoEventPending) {
763 // The event has been cancelled in reset_l() but had already
764 // been scheduled for execution at that time.
765 return;
766 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800767 mVideoEventPending = false;
768
769 if (mSeeking) {
770 if (mLastVideoBuffer) {
771 mLastVideoBuffer->release();
772 mLastVideoBuffer = NULL;
773 }
774
775 if (mVideoBuffer) {
776 mVideoBuffer->release();
777 mVideoBuffer = NULL;
778 }
779 }
780
781 if (!mVideoBuffer) {
782 MediaSource::ReadOptions options;
783 if (mSeeking) {
784 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
785
786 options.setSeekTo(mSeekTimeUs);
787 }
788 for (;;) {
789 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -0800790 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -0800791
792 if (err != OK) {
793 CHECK_EQ(mVideoBuffer, NULL);
794
795 if (err == INFO_FORMAT_CHANGED) {
796 LOGV("VideoSource signalled format change.");
797
Andreas Huber7085b6842010-02-03 16:02:02 -0800798 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800799 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -0800800 initRenderer_l();
801 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800802 continue;
803 }
804
805 postStreamDoneEvent_l();
806 return;
807 }
808
Andreas Hubera67d5382009-12-10 15:32:12 -0800809 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -0800810 // Some decoders, notably the PV AVC software decoder
811 // return spurious empty buffers that we just want to ignore.
812
Andreas Hubera67d5382009-12-10 15:32:12 -0800813 mVideoBuffer->release();
814 mVideoBuffer = NULL;
815 continue;
816 }
817
Andreas Huber27366fc2009-11-20 09:32:46 -0800818 break;
819 }
820 }
821
822 int64_t timeUs;
823 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
824
825 mVideoTimeUs = timeUs;
826
827 if (mSeeking) {
828 if (mAudioPlayer != NULL) {
829 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
830
831 mAudioPlayer->seekTo(timeUs);
Andreas Huber70d10c02010-02-03 11:37:29 -0800832 mWatchForAudioSeekComplete = true;
833 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800834 } else {
835 // If we're playing video only, report seek complete now,
836 // otherwise audio player will notify us later.
Andreas Hubera3f43842010-01-21 10:28:45 -0800837 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800838 }
839
840 mFlags |= FIRST_FRAME;
841 mSeeking = false;
842 }
843
844 if (mFlags & FIRST_FRAME) {
845 mFlags &= ~FIRST_FRAME;
846
847 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
848 }
849
850 int64_t realTimeUs, mediaTimeUs;
851 if (mAudioPlayer != NULL
852 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
853 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
854 }
855
856 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
857
858 int64_t latenessUs = nowUs - timeUs;
859
Andreas Huber24b0a952009-11-23 14:02:00 -0800860 if (latenessUs > 40000) {
861 // We're more than 40ms late.
Andreas Huber4a9375e2010-02-09 11:54:33 -0800862 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -0800863
864 mVideoBuffer->release();
865 mVideoBuffer = NULL;
866
867 postVideoEvent_l();
868 return;
869 }
870
871 if (latenessUs < -10000) {
872 // We're more than 10ms early.
873
874 postVideoEvent_l(10000);
875 return;
876 }
877
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800878 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
879 mVideoRendererIsPreview = false;
880
Andreas Huber7085b6842010-02-03 16:02:02 -0800881 initRenderer_l();
882 }
883
884 if (mVideoRenderer != NULL) {
885 mVideoRenderer->render(mVideoBuffer);
886 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800887
888 if (mLastVideoBuffer) {
889 mLastVideoBuffer->release();
890 mLastVideoBuffer = NULL;
891 }
892 mLastVideoBuffer = mVideoBuffer;
893 mVideoBuffer = NULL;
894
895 postVideoEvent_l();
896}
897
898void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
899 if (mVideoEventPending) {
900 return;
901 }
902
903 mVideoEventPending = true;
904 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
905}
906
907void AwesomePlayer::postStreamDoneEvent_l() {
908 if (mStreamDoneEventPending) {
909 return;
910 }
911 mStreamDoneEventPending = true;
912 mQueue.postEvent(mStreamDoneEvent);
913}
914
Andreas Huberb9e63832010-01-26 16:20:10 -0800915void AwesomePlayer::postBufferingEvent_l() {
916 if (mPrefetcher == NULL) {
917 return;
918 }
919
920 if (mBufferingEventPending) {
921 return;
922 }
923 mBufferingEventPending = true;
924 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
925}
926
Andreas Huber70d10c02010-02-03 11:37:29 -0800927void AwesomePlayer::postCheckAudioStatusEvent_l() {
928 if (mAudioStatusEventPending) {
929 return;
930 }
931 mAudioStatusEventPending = true;
932 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
933}
934
935void AwesomePlayer::onCheckAudioStatus() {
936 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800937 if (!mAudioStatusEventPending) {
938 // Event was dispatched and while we were blocking on the mutex,
939 // has already been cancelled.
940 return;
941 }
942
Andreas Huber70d10c02010-02-03 11:37:29 -0800943 mAudioStatusEventPending = false;
944
945 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
946 mWatchForAudioSeekComplete = false;
947 notifyListener_l(MEDIA_SEEK_COMPLETE);
948 }
949
950 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS()) {
951 mWatchForAudioEOS = false;
952 postStreamDoneEvent_l();
953 }
954
955 postCheckAudioStatusEvent_l();
956}
957
Andreas Huber6be780e2010-02-08 14:40:30 -0800958status_t AwesomePlayer::prepare() {
959 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -0800960 return prepare_l();
961}
Andreas Huber6be780e2010-02-08 14:40:30 -0800962
Andreas Huberffdf4782010-02-09 14:05:43 -0800963status_t AwesomePlayer::prepare_l() {
964 if (mFlags & PREPARED) {
965 return OK;
966 }
967
968 if (mFlags & PREPARING) {
969 return UNKNOWN_ERROR;
970 }
971
972 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800973 status_t err = prepareAsync_l();
974
975 if (err != OK) {
976 return err;
977 }
978
Andreas Huberffdf4782010-02-09 14:05:43 -0800979 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800980 mPreparedCondition.wait(mLock);
981 }
982
Andreas Huberffdf4782010-02-09 14:05:43 -0800983 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -0800984}
985
986status_t AwesomePlayer::prepareAsync() {
987 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -0800988
989 if (mFlags & PREPARING) {
990 return UNKNOWN_ERROR; // async prepare already pending
991 }
992
993 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -0800994 return prepareAsync_l();
995}
996
997status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -0800998 if (mFlags & PREPARING) {
999 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001000 }
1001
Andreas Huber406a18b2010-02-18 16:45:13 -08001002 if (!mQueueStarted) {
1003 mQueue.start();
1004 mQueueStarted = true;
1005 }
1006
Andreas Huberffdf4782010-02-09 14:05:43 -08001007 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -08001008 mAsyncPrepareEvent = new AwesomeEvent(
1009 this, &AwesomePlayer::onPrepareAsyncEvent);
1010
1011 mQueue.postEvent(mAsyncPrepareEvent);
1012
1013 return OK;
1014}
1015
Andreas Huberffdf4782010-02-09 14:05:43 -08001016status_t AwesomePlayer::finishSetDataSource_l() {
1017 sp<DataSource> dataSource =
1018 DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1019
1020 if (dataSource == NULL) {
1021 return UNKNOWN_ERROR;
1022 }
1023
1024 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1025
1026 if (extractor == NULL) {
1027 return UNKNOWN_ERROR;
1028 }
1029
1030 if (dataSource->flags() & DataSource::kWantsPrefetching) {
1031 mPrefetcher = new Prefetcher;
1032 }
1033
1034 return setDataSource_l(extractor);
1035}
1036
Andreas Huber6be780e2010-02-08 14:40:30 -08001037void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001038 {
1039 Mutex::Autolock autoLock(mLock);
1040
1041 if (mUri.size() > 0) {
1042 status_t err = finishSetDataSource_l();
1043
1044 if (err != OK) {
1045 if (mIsAsyncPrepare) {
1046 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1047 }
1048
1049 mPrepareResult = err;
1050 mFlags &= ~PREPARING;
1051 mAsyncPrepareEvent = NULL;
1052 mPreparedCondition.broadcast();
1053
1054 return;
1055 }
1056 }
1057 }
1058
Andreas Huber6be780e2010-02-08 14:40:30 -08001059 sp<Prefetcher> prefetcher;
1060
1061 {
1062 Mutex::Autolock autoLock(mLock);
1063 prefetcher = mPrefetcher;
1064 }
1065
1066 if (prefetcher != NULL) {
1067 prefetcher->prepare();
Andreas Huberba7ec912010-02-12 10:42:02 -08001068 prefetcher.clear();
Andreas Huber6be780e2010-02-08 14:40:30 -08001069 }
1070
1071 Mutex::Autolock autoLock(mLock);
1072
Andreas Huberffdf4782010-02-09 14:05:43 -08001073 if (mIsAsyncPrepare) {
1074 if (mVideoWidth < 0 || mVideoHeight < 0) {
1075 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1076 } else {
1077 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
1078 }
1079
1080 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08001081 }
1082
Andreas Huberffdf4782010-02-09 14:05:43 -08001083 mPrepareResult = OK;
1084 mFlags &= ~PREPARING;
1085 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -08001086 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08001087 mPreparedCondition.broadcast();
Andreas Huber6be780e2010-02-08 14:40:30 -08001088}
1089
Andreas Huberba7ec912010-02-12 10:42:02 -08001090status_t AwesomePlayer::suspend() {
1091 LOGI("suspend");
1092 Mutex::Autolock autoLock(mLock);
1093
1094 if (mSuspensionState != NULL) {
1095 return INVALID_OPERATION;
1096 }
1097
1098 while (mFlags & PREPARING) {
1099 mPreparedCondition.wait(mLock);
1100 }
1101
1102 SuspensionState *state = new SuspensionState;
1103 state->mUri = mUri;
1104 state->mUriHeaders = mUriHeaders;
1105 state->mFileSource = mFileSource;
1106
Andreas Huber406a18b2010-02-18 16:45:13 -08001107 state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS);
Andreas Huberba7ec912010-02-12 10:42:02 -08001108 getPosition_l(&state->mPositionUs);
1109
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001110 if (mLastVideoBuffer) {
1111 size_t size = mLastVideoBuffer->range_length();
1112 if (size) {
1113 state->mLastVideoFrameSize = size;
1114 state->mLastVideoFrame = malloc(size);
1115 memcpy(state->mLastVideoFrame,
1116 (const uint8_t *)mLastVideoBuffer->data()
1117 + mLastVideoBuffer->range_offset(),
1118 size);
1119
1120 state->mVideoWidth = mVideoWidth;
1121 state->mVideoHeight = mVideoHeight;
1122
1123 sp<MetaData> meta = mVideoSource->getFormat();
1124 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1125 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1126 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1127 }
1128 }
1129
Andreas Huberba7ec912010-02-12 10:42:02 -08001130 reset_l();
1131
1132 mSuspensionState = state;
1133
1134 return OK;
1135}
1136
1137status_t AwesomePlayer::resume() {
1138 LOGI("resume");
1139 Mutex::Autolock autoLock(mLock);
1140
1141 if (mSuspensionState == NULL) {
1142 return INVALID_OPERATION;
1143 }
1144
1145 SuspensionState *state = mSuspensionState;
1146 mSuspensionState = NULL;
1147
1148 status_t err;
1149 if (state->mFileSource != NULL) {
1150 err = setDataSource_l(state->mFileSource);
1151
1152 if (err == OK) {
1153 mFileSource = state->mFileSource;
1154 }
1155 } else {
1156 err = setDataSource_l(state->mUri, &state->mUriHeaders);
1157 }
1158
1159 if (err != OK) {
1160 delete state;
1161 state = NULL;
1162
1163 return err;
1164 }
1165
1166 seekTo_l(state->mPositionUs);
1167
Andreas Huber406a18b2010-02-18 16:45:13 -08001168 mFlags = state->mFlags & (LOOPING | AT_EOS);
Andreas Huberba7ec912010-02-12 10:42:02 -08001169
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001170 if (state->mLastVideoFrame && mISurface != NULL) {
1171 mVideoRenderer =
1172 new AwesomeLocalRenderer(
1173 true, // previewOnly
1174 "",
1175 (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1176 mISurface,
1177 state->mVideoWidth,
1178 state->mVideoHeight,
1179 state->mDecodedWidth,
1180 state->mDecodedHeight);
1181
1182 mVideoRendererIsPreview = true;
1183
1184 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render(
1185 state->mLastVideoFrame, state->mLastVideoFrameSize);
1186 }
1187
Andreas Huberba7ec912010-02-12 10:42:02 -08001188 if (state->mFlags & PLAYING) {
1189 play_l();
1190 }
1191
1192 delete state;
1193 state = NULL;
1194
1195 return OK;
1196}
1197
Andreas Huber27366fc2009-11-20 09:32:46 -08001198} // namespace android
1199