blob: a13b2421f31642c24d4d34197f02a11d64b2f172 [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
21#include "include/AwesomePlayer.h"
Andreas Huberb9e63832010-01-26 16:20:10 -080022#include "include/Prefetcher.h"
Andreas Huber1314e732009-12-14 14:18:22 -080023#include "include/SoftwareRenderer.h"
Andreas Huber27366fc2009-11-20 09:32:46 -080024
Andreas Hubera67d5382009-12-10 15:32:12 -080025#include <binder/IPCThreadState.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080026#include <media/stagefright/AudioPlayer.h>
27#include <media/stagefright/DataSource.h>
28#include <media/stagefright/FileSource.h>
29#include <media/stagefright/MediaBuffer.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080030#include <media/stagefright/MediaDefs.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080031#include <media/stagefright/MediaExtractor.h>
32#include <media/stagefright/MediaDebug.h>
33#include <media/stagefright/MediaSource.h>
34#include <media/stagefright/MetaData.h>
35#include <media/stagefright/OMXCodec.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080036
Andreas Huber27366fc2009-11-20 09:32:46 -080037namespace android {
38
39struct AwesomeEvent : public TimedEventQueue::Event {
Andreas Huber6be780e2010-02-08 14:40:30 -080040 AwesomeEvent(
41 AwesomePlayer *player,
42 void (AwesomePlayer::*method)())
Andreas Huber27366fc2009-11-20 09:32:46 -080043 : mPlayer(player),
Andreas Huber6be780e2010-02-08 14:40:30 -080044 mMethod(method) {
Andreas Huber27366fc2009-11-20 09:32:46 -080045 }
46
47protected:
48 virtual ~AwesomeEvent() {}
49
50 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
Andreas Huber6be780e2010-02-08 14:40:30 -080051 (mPlayer->*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080052 }
53
54private:
55 AwesomePlayer *mPlayer;
Andreas Huber6be780e2010-02-08 14:40:30 -080056 void (AwesomePlayer::*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080057
58 AwesomeEvent(const AwesomeEvent &);
59 AwesomeEvent &operator=(const AwesomeEvent &);
60};
61
Andreas Huber1314e732009-12-14 14:18:22 -080062struct AwesomeRemoteRenderer : public AwesomeRenderer {
63 AwesomeRemoteRenderer(const sp<IOMXRenderer> &target)
64 : mTarget(target) {
65 }
66
67 virtual void render(MediaBuffer *buffer) {
68 void *id;
69 if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) {
70 mTarget->render((IOMX::buffer_id)id);
71 }
72 }
73
74private:
75 sp<IOMXRenderer> mTarget;
76
77 AwesomeRemoteRenderer(const AwesomeRemoteRenderer &);
78 AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &);
79};
80
81struct AwesomeLocalRenderer : public AwesomeRenderer {
82 AwesomeLocalRenderer(
83 OMX_COLOR_FORMATTYPE colorFormat,
84 const sp<ISurface> &surface,
85 size_t displayWidth, size_t displayHeight,
86 size_t decodedWidth, size_t decodedHeight)
87 : mTarget(new SoftwareRenderer(
88 colorFormat, surface, displayWidth, displayHeight,
89 decodedWidth, decodedHeight)) {
90 }
91
92 virtual void render(MediaBuffer *buffer) {
93 mTarget->render(
94 (const uint8_t *)buffer->data() + buffer->range_offset(),
95 buffer->range_length(), NULL);
96 }
97
98protected:
99 virtual ~AwesomeLocalRenderer() {
100 delete mTarget;
101 mTarget = NULL;
102 }
103
104private:
105 SoftwareRenderer *mTarget;
106
107 AwesomeLocalRenderer(const AwesomeLocalRenderer &);
108 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
109};
110
Andreas Huber27366fc2009-11-20 09:32:46 -0800111AwesomePlayer::AwesomePlayer()
112 : mTimeSource(NULL),
113 mAudioPlayer(NULL),
Andreas Huberffdf4782010-02-09 14:05:43 -0800114 mFlags(0),
Andreas Huber27366fc2009-11-20 09:32:46 -0800115 mLastVideoBuffer(NULL),
116 mVideoBuffer(NULL) {
117 CHECK_EQ(mClient.connect(), OK);
118
119 DataSource::RegisterDefaultSniffers();
120
Andreas Huber6be780e2010-02-08 14:40:30 -0800121 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
Andreas Huber27366fc2009-11-20 09:32:46 -0800122 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800123 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
Andreas Huber27366fc2009-11-20 09:32:46 -0800124 mStreamDoneEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800125 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
Andreas Huberb9e63832010-01-26 16:20:10 -0800126 mBufferingEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800127
128 mCheckAudioStatusEvent = new AwesomeEvent(
129 this, &AwesomePlayer::onCheckAudioStatus);
130
Andreas Huber70d10c02010-02-03 11:37:29 -0800131 mAudioStatusEventPending = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800132
133 mQueue.start();
134
135 reset();
136}
137
138AwesomePlayer::~AwesomePlayer() {
139 mQueue.stop();
140
141 reset();
142
143 mClient.disconnect();
144}
145
Andreas Huberb9e63832010-01-26 16:20:10 -0800146void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800147 mQueue.cancelEvent(mVideoEvent->eventID());
148 mVideoEventPending = false;
149 mQueue.cancelEvent(mStreamDoneEvent->eventID());
150 mStreamDoneEventPending = false;
Andreas Huber70d10c02010-02-03 11:37:29 -0800151 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
152 mAudioStatusEventPending = false;
Andreas Huberb9e63832010-01-26 16:20:10 -0800153
154 if (!keepBufferingGoing) {
155 mQueue.cancelEvent(mBufferingEvent->eventID());
156 mBufferingEventPending = false;
157 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800158}
159
Andreas Hubera3f43842010-01-21 10:28:45 -0800160void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800161 Mutex::Autolock autoLock(mLock);
162 mListener = listener;
163}
164
Andreas Huber433c9ac2010-01-27 16:49:05 -0800165status_t AwesomePlayer::setDataSource(
166 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800167 Mutex::Autolock autoLock(mLock);
168
169 reset_l();
170
Andreas Huberffdf4782010-02-09 14:05:43 -0800171 mUri = uri;
Andreas Huberb9e63832010-01-26 16:20:10 -0800172
Andreas Huberffdf4782010-02-09 14:05:43 -0800173 if (headers) {
174 mUriHeaders = *headers;
Andreas Huberb9e63832010-01-26 16:20:10 -0800175 }
176
Andreas Huberffdf4782010-02-09 14:05:43 -0800177 // The actual work will be done during preparation in the call to
178 // ::finishSetDataSource_l to avoid blocking the calling thread in
179 // setDataSource for any significant time.
Andreas Huber27366fc2009-11-20 09:32:46 -0800180
Andreas Huberffdf4782010-02-09 14:05:43 -0800181 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800182}
183
184status_t AwesomePlayer::setDataSource(
185 int fd, int64_t offset, int64_t length) {
186 Mutex::Autolock autoLock(mLock);
187
188 reset_l();
189
190 sp<DataSource> source = new FileSource(fd, offset, length);
191
192 status_t err = source->initCheck();
193
194 if (err != OK) {
195 return err;
196 }
197
198 sp<MediaExtractor> extractor = MediaExtractor::Create(source);
199
200 if (extractor == NULL) {
201 return UNKNOWN_ERROR;
202 }
203
204 return setDataSource_l(extractor);
205}
206
207status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800208 bool haveAudio = false;
209 bool haveVideo = false;
210 for (size_t i = 0; i < extractor->countTracks(); ++i) {
211 sp<MetaData> meta = extractor->getTrackMetaData(i);
212
213 const char *mime;
214 CHECK(meta->findCString(kKeyMIMEType, &mime));
215
216 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
217 if (setVideoSource(extractor->getTrack(i)) == OK) {
218 haveVideo = true;
219 }
220 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
221 if (setAudioSource(extractor->getTrack(i)) == OK) {
222 haveAudio = true;
223 }
224 }
225
226 if (haveAudio && haveVideo) {
227 break;
228 }
229 }
230
231 return !haveAudio && !haveVideo ? UNKNOWN_ERROR : OK;
232}
233
234void AwesomePlayer::reset() {
235 Mutex::Autolock autoLock(mLock);
236 reset_l();
237}
238
239void AwesomePlayer::reset_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -0800240 while (mFlags & PREPARING) {
241 mPreparedCondition.wait(mLock);
242 }
243
Andreas Huber27366fc2009-11-20 09:32:46 -0800244 cancelPlayerEvents();
245
Andreas Huber3522b5a52010-01-22 14:36:53 -0800246 mVideoRenderer.clear();
247
Andreas Huber27366fc2009-11-20 09:32:46 -0800248 if (mLastVideoBuffer) {
249 mLastVideoBuffer->release();
250 mLastVideoBuffer = NULL;
251 }
252
253 if (mVideoBuffer) {
254 mVideoBuffer->release();
255 mVideoBuffer = NULL;
256 }
257
258 if (mVideoSource != NULL) {
259 mVideoSource->stop();
Andreas Huber98b48de2010-01-29 10:10:22 -0800260
261 // The following hack is necessary to ensure that the OMX
262 // component is completely released by the time we may try
263 // to instantiate it again.
264 wp<MediaSource> tmp = mVideoSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800265 mVideoSource.clear();
Andreas Huber98b48de2010-01-29 10:10:22 -0800266 while (tmp.promote() != NULL) {
267 usleep(1000);
268 }
269 IPCThreadState::self()->flushCommands();
Andreas Huber27366fc2009-11-20 09:32:46 -0800270 }
271
272 mAudioSource.clear();
273
274 if (mTimeSource != mAudioPlayer) {
275 delete mTimeSource;
276 }
277 mTimeSource = NULL;
278
279 delete mAudioPlayer;
280 mAudioPlayer = NULL;
281
Andreas Huber27366fc2009-11-20 09:32:46 -0800282 mDurationUs = -1;
283 mFlags = 0;
284 mVideoWidth = mVideoHeight = -1;
285 mTimeSourceDeltaUs = 0;
286 mVideoTimeUs = 0;
287
288 mSeeking = false;
289 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800290
291 mPrefetcher.clear();
Andreas Huberffdf4782010-02-09 14:05:43 -0800292
293 mUri.setTo("");
294 mUriHeaders.clear();
Andreas Huber27366fc2009-11-20 09:32:46 -0800295}
296
Andreas Huber6be780e2010-02-08 14:40:30 -0800297void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800298 if (mListener != NULL) {
299 sp<MediaPlayerBase> listener = mListener.promote();
300
301 if (listener != NULL) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800302 listener->sendEvent(msg, ext1, ext2);
Andreas Hubera3f43842010-01-21 10:28:45 -0800303 }
304 }
305}
306
Andreas Huberb9e63832010-01-26 16:20:10 -0800307void AwesomePlayer::onBufferingUpdate() {
308 Mutex::Autolock autoLock(mLock);
309 mBufferingEventPending = false;
310
311 if (mDurationUs >= 0) {
312 int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs();
313 int64_t positionUs = 0;
Andreas Huber7085b6842010-02-03 16:02:02 -0800314 if (mVideoSource != NULL) {
Andreas Huberb9e63832010-01-26 16:20:10 -0800315 positionUs = mVideoTimeUs;
316 } else if (mAudioPlayer != NULL) {
317 positionUs = mAudioPlayer->getMediaTimeUs();
318 }
319
320 cachedDurationUs += positionUs;
321
322 double percentage = (double)cachedDurationUs / mDurationUs;
323 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
324
325 postBufferingEvent_l();
326 }
327}
328
Andreas Huber27366fc2009-11-20 09:32:46 -0800329void AwesomePlayer::onStreamDone() {
330 // Posted whenever any stream finishes playing.
331
332 Mutex::Autolock autoLock(mLock);
333 mStreamDoneEventPending = false;
334
335 if (mFlags & LOOPING) {
336 seekTo_l(0);
337
Andreas Huber7085b6842010-02-03 16:02:02 -0800338 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800339 postVideoEvent_l();
340 }
341 } else {
Andreas Hubera3f43842010-01-21 10:28:45 -0800342 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800343
344 pause_l();
345 }
346}
347
348status_t AwesomePlayer::play() {
349 Mutex::Autolock autoLock(mLock);
350
351 if (mFlags & PLAYING) {
352 return OK;
353 }
354
Andreas Huberffdf4782010-02-09 14:05:43 -0800355 if (!(mFlags & PREPARED)) {
356 status_t err = prepare_l();
357
358 if (err != OK) {
359 return err;
360 }
361 }
362
Andreas Huber27366fc2009-11-20 09:32:46 -0800363 mFlags |= PLAYING;
364 mFlags |= FIRST_FRAME;
365
Andreas Huberc1d5c922009-12-10 15:49:04 -0800366 bool deferredAudioSeek = false;
367
Andreas Huber27366fc2009-11-20 09:32:46 -0800368 if (mAudioSource != NULL) {
369 if (mAudioPlayer == NULL) {
370 if (mAudioSink != NULL) {
371 mAudioPlayer = new AudioPlayer(mAudioSink);
Andreas Huber27366fc2009-11-20 09:32:46 -0800372 mAudioPlayer->setSource(mAudioSource);
Andreas Huber62eac002010-01-29 13:24:58 -0800373 status_t err = mAudioPlayer->start();
374
375 if (err != OK) {
376 delete mAudioPlayer;
377 mAudioPlayer = NULL;
378
379 mFlags &= ~(PLAYING | FIRST_FRAME);
380
381 return err;
382 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800383
384 delete mTimeSource;
385 mTimeSource = mAudioPlayer;
386
Andreas Huberc1d5c922009-12-10 15:49:04 -0800387 deferredAudioSeek = true;
Andreas Huber70d10c02010-02-03 11:37:29 -0800388
389 mWatchForAudioSeekComplete = false;
390 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800391 }
392 } else {
393 mAudioPlayer->resume();
394 }
Andreas Huber70d10c02010-02-03 11:37:29 -0800395
396 postCheckAudioStatusEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800397 }
398
399 if (mTimeSource == NULL && mAudioPlayer == NULL) {
400 mTimeSource = new SystemTimeSource;
401 }
402
403 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800404 // Kick off video playback
405 postVideoEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800406 }
407
Andreas Huberc1d5c922009-12-10 15:49:04 -0800408 if (deferredAudioSeek) {
409 // If there was a seek request while we were paused
410 // and we're just starting up again, honor the request now.
411 seekAudioIfNecessary_l();
412 }
413
Andreas Huberb9e63832010-01-26 16:20:10 -0800414 postBufferingEvent_l();
415
Andreas Huber27366fc2009-11-20 09:32:46 -0800416 return OK;
417}
418
419void AwesomePlayer::initRenderer_l() {
420 if (mISurface != NULL) {
421 sp<MetaData> meta = mVideoSource->getFormat();
422
423 int32_t format;
424 const char *component;
425 int32_t decodedWidth, decodedHeight;
426 CHECK(meta->findInt32(kKeyColorFormat, &format));
427 CHECK(meta->findCString(kKeyDecoderComponent, &component));
428 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
429 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
430
Andreas Hubera67d5382009-12-10 15:32:12 -0800431 mVideoRenderer.clear();
432
433 // Must ensure that mVideoRenderer's destructor is actually executed
434 // before creating a new one.
435 IPCThreadState::self()->flushCommands();
436
Andreas Huber1314e732009-12-14 14:18:22 -0800437 if (!strncmp("OMX.", component, 4)) {
438 // Our OMX codecs allocate buffers on the media_server side
439 // therefore they require a remote IOMXRenderer that knows how
440 // to display them.
441 mVideoRenderer = new AwesomeRemoteRenderer(
442 mClient.interface()->createRenderer(
443 mISurface, component,
444 (OMX_COLOR_FORMATTYPE)format,
445 decodedWidth, decodedHeight,
446 mVideoWidth, mVideoHeight));
447 } else {
448 // Other decoders are instantiated locally and as a consequence
449 // allocate their buffers in local address space.
450 mVideoRenderer = new AwesomeLocalRenderer(
451 (OMX_COLOR_FORMATTYPE)format,
452 mISurface,
453 mVideoWidth, mVideoHeight,
454 decodedWidth, decodedHeight);
455 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800456 }
457}
458
459status_t AwesomePlayer::pause() {
460 Mutex::Autolock autoLock(mLock);
461 return pause_l();
462}
463
464status_t AwesomePlayer::pause_l() {
465 if (!(mFlags & PLAYING)) {
466 return OK;
467 }
468
Andreas Huberb9e63832010-01-26 16:20:10 -0800469 cancelPlayerEvents(true /* keepBufferingGoing */);
Andreas Huber27366fc2009-11-20 09:32:46 -0800470
471 if (mAudioPlayer != NULL) {
472 mAudioPlayer->pause();
473 }
474
475 mFlags &= ~PLAYING;
476
477 return OK;
478}
479
480bool AwesomePlayer::isPlaying() const {
481 Mutex::Autolock autoLock(mLock);
482
483 return mFlags & PLAYING;
484}
485
486void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
487 Mutex::Autolock autoLock(mLock);
488
489 mISurface = isurface;
490}
491
492void AwesomePlayer::setAudioSink(
493 const sp<MediaPlayerBase::AudioSink> &audioSink) {
494 Mutex::Autolock autoLock(mLock);
495
496 mAudioSink = audioSink;
497}
498
499status_t AwesomePlayer::setLooping(bool shouldLoop) {
500 Mutex::Autolock autoLock(mLock);
501
502 mFlags = mFlags & ~LOOPING;
503
504 if (shouldLoop) {
505 mFlags |= LOOPING;
506 }
507
508 return OK;
509}
510
511status_t AwesomePlayer::getDuration(int64_t *durationUs) {
512 Mutex::Autolock autoLock(mLock);
513
514 if (mDurationUs < 0) {
515 return UNKNOWN_ERROR;
516 }
517
518 *durationUs = mDurationUs;
519
520 return OK;
521}
522
523status_t AwesomePlayer::getPosition(int64_t *positionUs) {
524 Mutex::Autolock autoLock(mLock);
525
Andreas Huber7085b6842010-02-03 16:02:02 -0800526 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800527 *positionUs = mVideoTimeUs;
528 } else if (mAudioPlayer != NULL) {
529 *positionUs = mAudioPlayer->getMediaTimeUs();
530 } else {
531 *positionUs = 0;
532 }
533
534 return OK;
535}
536
537status_t AwesomePlayer::seekTo(int64_t timeUs) {
538 Mutex::Autolock autoLock(mLock);
539 return seekTo_l(timeUs);
540}
541
542status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
543 mSeeking = true;
544 mSeekTimeUs = timeUs;
545
546 seekAudioIfNecessary_l();
547
548 return OK;
549}
550
551void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Huber7085b6842010-02-03 16:02:02 -0800552 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800553 mAudioPlayer->seekTo(mSeekTimeUs);
554
Andreas Huber70d10c02010-02-03 11:37:29 -0800555 mWatchForAudioSeekComplete = true;
556 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800557 mSeeking = false;
558 }
559}
560
561status_t AwesomePlayer::getVideoDimensions(
562 int32_t *width, int32_t *height) const {
563 Mutex::Autolock autoLock(mLock);
564
565 if (mVideoWidth < 0 || mVideoHeight < 0) {
566 return UNKNOWN_ERROR;
567 }
568
569 *width = mVideoWidth;
570 *height = mVideoHeight;
571
572 return OK;
573}
574
Andreas Huberb9e63832010-01-26 16:20:10 -0800575status_t AwesomePlayer::setAudioSource(sp<MediaSource> source) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800576 if (source == NULL) {
577 return UNKNOWN_ERROR;
578 }
579
Andreas Huberb9e63832010-01-26 16:20:10 -0800580 if (mPrefetcher != NULL) {
581 source = mPrefetcher->addSource(source);
582 }
583
Andreas Huberc79827a2010-01-05 10:54:55 -0800584 sp<MetaData> meta = source->getFormat();
585
586 const char *mime;
587 CHECK(meta->findCString(kKeyMIMEType, &mime));
588
589 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
590 mAudioSource = source;
591 } else {
592 mAudioSource = OMXCodec::Create(
593 mClient.interface(), source->getFormat(),
594 false, // createEncoder
595 source);
596 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800597
598 if (mAudioSource != NULL) {
599 int64_t durationUs;
600 if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) {
601 if (mDurationUs < 0 || durationUs > mDurationUs) {
602 mDurationUs = durationUs;
603 }
604 }
605 }
606
607 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
608}
609
Andreas Huberb9e63832010-01-26 16:20:10 -0800610status_t AwesomePlayer::setVideoSource(sp<MediaSource> source) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800611 if (source == NULL) {
612 return UNKNOWN_ERROR;
613 }
614
Andreas Huberb9e63832010-01-26 16:20:10 -0800615 if (mPrefetcher != NULL) {
616 source = mPrefetcher->addSource(source);
617 }
618
Andreas Huber27366fc2009-11-20 09:32:46 -0800619 mVideoSource = OMXCodec::Create(
620 mClient.interface(), source->getFormat(),
621 false, // createEncoder
622 source);
623
624 if (mVideoSource != NULL) {
625 int64_t durationUs;
626 if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) {
627 if (mDurationUs < 0 || durationUs > mDurationUs) {
628 mDurationUs = durationUs;
629 }
630 }
631
632 CHECK(source->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
633 CHECK(source->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
634
635 mVideoSource->start();
636 }
637
638 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
639}
640
Andreas Huber6be780e2010-02-08 14:40:30 -0800641void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800642 Mutex::Autolock autoLock(mLock);
Andreas Huberb9e63832010-01-26 16:20:10 -0800643
Andreas Huber27366fc2009-11-20 09:32:46 -0800644 mVideoEventPending = false;
645
646 if (mSeeking) {
647 if (mLastVideoBuffer) {
648 mLastVideoBuffer->release();
649 mLastVideoBuffer = NULL;
650 }
651
652 if (mVideoBuffer) {
653 mVideoBuffer->release();
654 mVideoBuffer = NULL;
655 }
656 }
657
658 if (!mVideoBuffer) {
659 MediaSource::ReadOptions options;
660 if (mSeeking) {
661 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
662
663 options.setSeekTo(mSeekTimeUs);
664 }
665 for (;;) {
666 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -0800667 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -0800668
669 if (err != OK) {
670 CHECK_EQ(mVideoBuffer, NULL);
671
672 if (err == INFO_FORMAT_CHANGED) {
673 LOGV("VideoSource signalled format change.");
674
Andreas Huber7085b6842010-02-03 16:02:02 -0800675 if (mVideoRenderer != NULL) {
676 initRenderer_l();
677 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800678 continue;
679 }
680
681 postStreamDoneEvent_l();
682 return;
683 }
684
Andreas Hubera67d5382009-12-10 15:32:12 -0800685 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -0800686 // Some decoders, notably the PV AVC software decoder
687 // return spurious empty buffers that we just want to ignore.
688
Andreas Hubera67d5382009-12-10 15:32:12 -0800689 mVideoBuffer->release();
690 mVideoBuffer = NULL;
691 continue;
692 }
693
Andreas Huber27366fc2009-11-20 09:32:46 -0800694 break;
695 }
696 }
697
698 int64_t timeUs;
699 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
700
701 mVideoTimeUs = timeUs;
702
703 if (mSeeking) {
704 if (mAudioPlayer != NULL) {
705 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
706
707 mAudioPlayer->seekTo(timeUs);
Andreas Huber70d10c02010-02-03 11:37:29 -0800708 mWatchForAudioSeekComplete = true;
709 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800710 } else {
711 // If we're playing video only, report seek complete now,
712 // otherwise audio player will notify us later.
Andreas Hubera3f43842010-01-21 10:28:45 -0800713 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800714 }
715
716 mFlags |= FIRST_FRAME;
717 mSeeking = false;
718 }
719
720 if (mFlags & FIRST_FRAME) {
721 mFlags &= ~FIRST_FRAME;
722
723 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
724 }
725
726 int64_t realTimeUs, mediaTimeUs;
727 if (mAudioPlayer != NULL
728 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
729 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
730 }
731
732 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
733
734 int64_t latenessUs = nowUs - timeUs;
735
Andreas Huber24b0a952009-11-23 14:02:00 -0800736 if (latenessUs > 40000) {
737 // We're more than 40ms late.
Andreas Huber4a9375e2010-02-09 11:54:33 -0800738 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -0800739
740 mVideoBuffer->release();
741 mVideoBuffer = NULL;
742
743 postVideoEvent_l();
744 return;
745 }
746
747 if (latenessUs < -10000) {
748 // We're more than 10ms early.
749
750 postVideoEvent_l(10000);
751 return;
752 }
753
Andreas Huber7085b6842010-02-03 16:02:02 -0800754 if (mVideoRenderer == NULL) {
755 initRenderer_l();
756 }
757
758 if (mVideoRenderer != NULL) {
759 mVideoRenderer->render(mVideoBuffer);
760 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800761
762 if (mLastVideoBuffer) {
763 mLastVideoBuffer->release();
764 mLastVideoBuffer = NULL;
765 }
766 mLastVideoBuffer = mVideoBuffer;
767 mVideoBuffer = NULL;
768
769 postVideoEvent_l();
770}
771
772void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
773 if (mVideoEventPending) {
774 return;
775 }
776
777 mVideoEventPending = true;
778 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
779}
780
781void AwesomePlayer::postStreamDoneEvent_l() {
782 if (mStreamDoneEventPending) {
783 return;
784 }
785 mStreamDoneEventPending = true;
786 mQueue.postEvent(mStreamDoneEvent);
787}
788
Andreas Huberb9e63832010-01-26 16:20:10 -0800789void AwesomePlayer::postBufferingEvent_l() {
790 if (mPrefetcher == NULL) {
791 return;
792 }
793
794 if (mBufferingEventPending) {
795 return;
796 }
797 mBufferingEventPending = true;
798 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
799}
800
Andreas Huber70d10c02010-02-03 11:37:29 -0800801void AwesomePlayer::postCheckAudioStatusEvent_l() {
802 if (mAudioStatusEventPending) {
803 return;
804 }
805 mAudioStatusEventPending = true;
806 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
807}
808
809void AwesomePlayer::onCheckAudioStatus() {
810 Mutex::Autolock autoLock(mLock);
811 mAudioStatusEventPending = false;
812
813 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
814 mWatchForAudioSeekComplete = false;
815 notifyListener_l(MEDIA_SEEK_COMPLETE);
816 }
817
818 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS()) {
819 mWatchForAudioEOS = false;
820 postStreamDoneEvent_l();
821 }
822
823 postCheckAudioStatusEvent_l();
824}
825
Andreas Huber6be780e2010-02-08 14:40:30 -0800826status_t AwesomePlayer::prepare() {
827 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -0800828 return prepare_l();
829}
Andreas Huber6be780e2010-02-08 14:40:30 -0800830
Andreas Huberffdf4782010-02-09 14:05:43 -0800831status_t AwesomePlayer::prepare_l() {
832 if (mFlags & PREPARED) {
833 return OK;
834 }
835
836 if (mFlags & PREPARING) {
837 return UNKNOWN_ERROR;
838 }
839
840 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800841 status_t err = prepareAsync_l();
842
843 if (err != OK) {
844 return err;
845 }
846
Andreas Huberffdf4782010-02-09 14:05:43 -0800847 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800848 mPreparedCondition.wait(mLock);
849 }
850
Andreas Huberffdf4782010-02-09 14:05:43 -0800851 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -0800852}
853
854status_t AwesomePlayer::prepareAsync() {
855 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -0800856
857 if (mFlags & PREPARING) {
858 return UNKNOWN_ERROR; // async prepare already pending
859 }
860
861 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -0800862 return prepareAsync_l();
863}
864
865status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -0800866 if (mFlags & PREPARING) {
867 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -0800868 }
869
Andreas Huberffdf4782010-02-09 14:05:43 -0800870 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -0800871 mAsyncPrepareEvent = new AwesomeEvent(
872 this, &AwesomePlayer::onPrepareAsyncEvent);
873
874 mQueue.postEvent(mAsyncPrepareEvent);
875
876 return OK;
877}
878
Andreas Huberffdf4782010-02-09 14:05:43 -0800879status_t AwesomePlayer::finishSetDataSource_l() {
880 sp<DataSource> dataSource =
881 DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
882
883 if (dataSource == NULL) {
884 return UNKNOWN_ERROR;
885 }
886
887 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
888
889 if (extractor == NULL) {
890 return UNKNOWN_ERROR;
891 }
892
893 if (dataSource->flags() & DataSource::kWantsPrefetching) {
894 mPrefetcher = new Prefetcher;
895 }
896
897 return setDataSource_l(extractor);
898}
899
Andreas Huber6be780e2010-02-08 14:40:30 -0800900void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huberffdf4782010-02-09 14:05:43 -0800901 {
902 Mutex::Autolock autoLock(mLock);
903
904 if (mUri.size() > 0) {
905 status_t err = finishSetDataSource_l();
906
907 if (err != OK) {
908 if (mIsAsyncPrepare) {
909 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
910 }
911
912 mPrepareResult = err;
913 mFlags &= ~PREPARING;
914 mAsyncPrepareEvent = NULL;
915 mPreparedCondition.broadcast();
916
917 return;
918 }
919 }
920 }
921
Andreas Huber6be780e2010-02-08 14:40:30 -0800922 sp<Prefetcher> prefetcher;
923
924 {
925 Mutex::Autolock autoLock(mLock);
926 prefetcher = mPrefetcher;
927 }
928
929 if (prefetcher != NULL) {
930 prefetcher->prepare();
931 }
932
933 Mutex::Autolock autoLock(mLock);
934
Andreas Huberffdf4782010-02-09 14:05:43 -0800935 if (mIsAsyncPrepare) {
936 if (mVideoWidth < 0 || mVideoHeight < 0) {
937 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
938 } else {
939 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
940 }
941
942 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -0800943 }
944
Andreas Huberffdf4782010-02-09 14:05:43 -0800945 mPrepareResult = OK;
946 mFlags &= ~PREPARING;
947 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -0800948 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -0800949 mPreparedCondition.broadcast();
Andreas Huber6be780e2010-02-08 14:40:30 -0800950}
951
Andreas Huber27366fc2009-11-20 09:32:46 -0800952} // namespace android
953