blob: 42b9acce1cfb7cd86049c3387549abf40d777522 [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 {
40 AwesomeEvent(AwesomePlayer *player, int32_t code)
41 : mPlayer(player),
42 mCode(code) {
43 }
44
45protected:
46 virtual ~AwesomeEvent() {}
47
48 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
49 mPlayer->onEvent(mCode);
50 }
51
52private:
53 AwesomePlayer *mPlayer;
54 int32_t mCode;
55
56 AwesomeEvent(const AwesomeEvent &);
57 AwesomeEvent &operator=(const AwesomeEvent &);
58};
59
Andreas Huber1314e732009-12-14 14:18:22 -080060struct AwesomeRemoteRenderer : public AwesomeRenderer {
61 AwesomeRemoteRenderer(const sp<IOMXRenderer> &target)
62 : mTarget(target) {
63 }
64
65 virtual void render(MediaBuffer *buffer) {
66 void *id;
67 if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) {
68 mTarget->render((IOMX::buffer_id)id);
69 }
70 }
71
72private:
73 sp<IOMXRenderer> mTarget;
74
75 AwesomeRemoteRenderer(const AwesomeRemoteRenderer &);
76 AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &);
77};
78
79struct AwesomeLocalRenderer : public AwesomeRenderer {
80 AwesomeLocalRenderer(
81 OMX_COLOR_FORMATTYPE colorFormat,
82 const sp<ISurface> &surface,
83 size_t displayWidth, size_t displayHeight,
84 size_t decodedWidth, size_t decodedHeight)
85 : mTarget(new SoftwareRenderer(
86 colorFormat, surface, displayWidth, displayHeight,
87 decodedWidth, decodedHeight)) {
88 }
89
90 virtual void render(MediaBuffer *buffer) {
91 mTarget->render(
92 (const uint8_t *)buffer->data() + buffer->range_offset(),
93 buffer->range_length(), NULL);
94 }
95
96protected:
97 virtual ~AwesomeLocalRenderer() {
98 delete mTarget;
99 mTarget = NULL;
100 }
101
102private:
103 SoftwareRenderer *mTarget;
104
105 AwesomeLocalRenderer(const AwesomeLocalRenderer &);
106 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
107};
108
Andreas Huber27366fc2009-11-20 09:32:46 -0800109AwesomePlayer::AwesomePlayer()
110 : mTimeSource(NULL),
111 mAudioPlayer(NULL),
112 mLastVideoBuffer(NULL),
113 mVideoBuffer(NULL) {
114 CHECK_EQ(mClient.connect(), OK);
115
116 DataSource::RegisterDefaultSniffers();
117
118 mVideoEvent = new AwesomeEvent(this, 0);
119 mVideoEventPending = false;
120 mStreamDoneEvent = new AwesomeEvent(this, 1);
121 mStreamDoneEventPending = false;
Andreas Huberb9e63832010-01-26 16:20:10 -0800122 mBufferingEvent = new AwesomeEvent(this, 2);
123 mBufferingEventPending = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800124
125 mQueue.start();
126
127 reset();
128}
129
130AwesomePlayer::~AwesomePlayer() {
131 mQueue.stop();
132
133 reset();
134
135 mClient.disconnect();
136}
137
Andreas Huberb9e63832010-01-26 16:20:10 -0800138void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800139 mQueue.cancelEvent(mVideoEvent->eventID());
140 mVideoEventPending = false;
141 mQueue.cancelEvent(mStreamDoneEvent->eventID());
142 mStreamDoneEventPending = false;
Andreas Huberb9e63832010-01-26 16:20:10 -0800143
144 if (!keepBufferingGoing) {
145 mQueue.cancelEvent(mBufferingEvent->eventID());
146 mBufferingEventPending = false;
147 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800148}
149
Andreas Hubera3f43842010-01-21 10:28:45 -0800150void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800151 Mutex::Autolock autoLock(mLock);
152 mListener = listener;
153}
154
155status_t AwesomePlayer::setDataSource(const char *uri) {
156 Mutex::Autolock autoLock(mLock);
157
158 reset_l();
159
Andreas Huberb9e63832010-01-26 16:20:10 -0800160 sp<DataSource> dataSource = DataSource::CreateFromURI(uri);
161
162 if (dataSource == NULL) {
163 return UNKNOWN_ERROR;
164 }
165
166 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
Andreas Huber27366fc2009-11-20 09:32:46 -0800167
168 if (extractor == NULL) {
169 return UNKNOWN_ERROR;
170 }
171
Andreas Huberb9e63832010-01-26 16:20:10 -0800172 if (dataSource->flags() & DataSource::kWantsPrefetching) {
173 mPrefetcher = new Prefetcher;
174 }
175
Andreas Huber27366fc2009-11-20 09:32:46 -0800176 return setDataSource_l(extractor);
177}
178
179status_t AwesomePlayer::setDataSource(
180 int fd, int64_t offset, int64_t length) {
181 Mutex::Autolock autoLock(mLock);
182
183 reset_l();
184
185 sp<DataSource> source = new FileSource(fd, offset, length);
186
187 status_t err = source->initCheck();
188
189 if (err != OK) {
190 return err;
191 }
192
193 sp<MediaExtractor> extractor = MediaExtractor::Create(source);
194
195 if (extractor == NULL) {
196 return UNKNOWN_ERROR;
197 }
198
199 return setDataSource_l(extractor);
200}
201
202status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800203 bool haveAudio = false;
204 bool haveVideo = false;
205 for (size_t i = 0; i < extractor->countTracks(); ++i) {
206 sp<MetaData> meta = extractor->getTrackMetaData(i);
207
208 const char *mime;
209 CHECK(meta->findCString(kKeyMIMEType, &mime));
210
211 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
212 if (setVideoSource(extractor->getTrack(i)) == OK) {
213 haveVideo = true;
214 }
215 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
216 if (setAudioSource(extractor->getTrack(i)) == OK) {
217 haveAudio = true;
218 }
219 }
220
221 if (haveAudio && haveVideo) {
222 break;
223 }
224 }
225
226 return !haveAudio && !haveVideo ? UNKNOWN_ERROR : OK;
227}
228
229void AwesomePlayer::reset() {
230 Mutex::Autolock autoLock(mLock);
231 reset_l();
232}
233
234void AwesomePlayer::reset_l() {
235 cancelPlayerEvents();
236
Andreas Huber3522b5a52010-01-22 14:36:53 -0800237 mVideoRenderer.clear();
238
Andreas Huber27366fc2009-11-20 09:32:46 -0800239 if (mLastVideoBuffer) {
240 mLastVideoBuffer->release();
241 mLastVideoBuffer = NULL;
242 }
243
244 if (mVideoBuffer) {
245 mVideoBuffer->release();
246 mVideoBuffer = NULL;
247 }
248
249 if (mVideoSource != NULL) {
250 mVideoSource->stop();
251 mVideoSource.clear();
252 }
253
254 mAudioSource.clear();
255
256 if (mTimeSource != mAudioPlayer) {
257 delete mTimeSource;
258 }
259 mTimeSource = NULL;
260
261 delete mAudioPlayer;
262 mAudioPlayer = NULL;
263
Andreas Huber27366fc2009-11-20 09:32:46 -0800264 mDurationUs = -1;
265 mFlags = 0;
266 mVideoWidth = mVideoHeight = -1;
267 mTimeSourceDeltaUs = 0;
268 mVideoTimeUs = 0;
269
270 mSeeking = false;
271 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800272
273 mPrefetcher.clear();
Andreas Huber27366fc2009-11-20 09:32:46 -0800274}
275
276// static
277void AwesomePlayer::AudioNotify(void *_me, int what) {
278 AwesomePlayer *me = (AwesomePlayer *)_me;
279
280 Mutex::Autolock autoLock(me->mLock);
281
282 switch (what) {
283 case AudioPlayer::REACHED_EOS:
284 me->postStreamDoneEvent_l();
285 break;
286
287 case AudioPlayer::SEEK_COMPLETE:
288 {
Andreas Hubera3f43842010-01-21 10:28:45 -0800289 me->notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800290 break;
291 }
292
293 default:
294 CHECK(!"should not be here.");
295 break;
296 }
297}
298
Andreas Huberb9e63832010-01-26 16:20:10 -0800299void AwesomePlayer::notifyListener_l(int msg, int ext1) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800300 if (mListener != NULL) {
301 sp<MediaPlayerBase> listener = mListener.promote();
302
303 if (listener != NULL) {
Andreas Huberb9e63832010-01-26 16:20:10 -0800304 listener->sendEvent(msg, ext1);
Andreas Hubera3f43842010-01-21 10:28:45 -0800305 }
306 }
307}
308
Andreas Huberb9e63832010-01-26 16:20:10 -0800309void AwesomePlayer::onBufferingUpdate() {
310 Mutex::Autolock autoLock(mLock);
311 mBufferingEventPending = false;
312
313 if (mDurationUs >= 0) {
314 int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs();
315 int64_t positionUs = 0;
316 if (mVideoRenderer != NULL) {
317 positionUs = mVideoTimeUs;
318 } else if (mAudioPlayer != NULL) {
319 positionUs = mAudioPlayer->getMediaTimeUs();
320 }
321
322 cachedDurationUs += positionUs;
323
324 double percentage = (double)cachedDurationUs / mDurationUs;
325 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
326
327 postBufferingEvent_l();
328 }
329}
330
Andreas Huber27366fc2009-11-20 09:32:46 -0800331void AwesomePlayer::onStreamDone() {
332 // Posted whenever any stream finishes playing.
333
334 Mutex::Autolock autoLock(mLock);
335 mStreamDoneEventPending = false;
336
337 if (mFlags & LOOPING) {
338 seekTo_l(0);
339
340 if (mVideoRenderer != NULL) {
341 postVideoEvent_l();
342 }
343 } else {
Andreas Hubera3f43842010-01-21 10:28:45 -0800344 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800345
346 pause_l();
347 }
348}
349
350status_t AwesomePlayer::play() {
351 Mutex::Autolock autoLock(mLock);
352
353 if (mFlags & PLAYING) {
354 return OK;
355 }
356
357 mFlags |= PLAYING;
358 mFlags |= FIRST_FRAME;
359
Andreas Huberc1d5c922009-12-10 15:49:04 -0800360 bool deferredAudioSeek = false;
361
Andreas Huber27366fc2009-11-20 09:32:46 -0800362 if (mAudioSource != NULL) {
363 if (mAudioPlayer == NULL) {
364 if (mAudioSink != NULL) {
365 mAudioPlayer = new AudioPlayer(mAudioSink);
366
367 mAudioPlayer->setListenerCallback(
368 &AwesomePlayer::AudioNotify, this);
369
370 mAudioPlayer->setSource(mAudioSource);
371 mAudioPlayer->start();
372
373 delete mTimeSource;
374 mTimeSource = mAudioPlayer;
375
Andreas Huberc1d5c922009-12-10 15:49:04 -0800376 deferredAudioSeek = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800377 }
378 } else {
379 mAudioPlayer->resume();
380 }
381 }
382
383 if (mTimeSource == NULL && mAudioPlayer == NULL) {
384 mTimeSource = new SystemTimeSource;
385 }
386
387 if (mVideoSource != NULL) {
388 if (mVideoRenderer == NULL) {
389 initRenderer_l();
390 }
391
392 if (mVideoRenderer != NULL) {
393 // Kick off video playback
394 postVideoEvent_l();
395 }
396 }
397
Andreas Huberc1d5c922009-12-10 15:49:04 -0800398 if (deferredAudioSeek) {
399 // If there was a seek request while we were paused
400 // and we're just starting up again, honor the request now.
401 seekAudioIfNecessary_l();
402 }
403
Andreas Huberb9e63832010-01-26 16:20:10 -0800404 postBufferingEvent_l();
405
Andreas Huber27366fc2009-11-20 09:32:46 -0800406 return OK;
407}
408
409void AwesomePlayer::initRenderer_l() {
410 if (mISurface != NULL) {
411 sp<MetaData> meta = mVideoSource->getFormat();
412
413 int32_t format;
414 const char *component;
415 int32_t decodedWidth, decodedHeight;
416 CHECK(meta->findInt32(kKeyColorFormat, &format));
417 CHECK(meta->findCString(kKeyDecoderComponent, &component));
418 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
419 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
420
Andreas Hubera67d5382009-12-10 15:32:12 -0800421 mVideoRenderer.clear();
422
423 // Must ensure that mVideoRenderer's destructor is actually executed
424 // before creating a new one.
425 IPCThreadState::self()->flushCommands();
426
Andreas Huber1314e732009-12-14 14:18:22 -0800427 if (!strncmp("OMX.", component, 4)) {
428 // Our OMX codecs allocate buffers on the media_server side
429 // therefore they require a remote IOMXRenderer that knows how
430 // to display them.
431 mVideoRenderer = new AwesomeRemoteRenderer(
432 mClient.interface()->createRenderer(
433 mISurface, component,
434 (OMX_COLOR_FORMATTYPE)format,
435 decodedWidth, decodedHeight,
436 mVideoWidth, mVideoHeight));
437 } else {
438 // Other decoders are instantiated locally and as a consequence
439 // allocate their buffers in local address space.
440 mVideoRenderer = new AwesomeLocalRenderer(
441 (OMX_COLOR_FORMATTYPE)format,
442 mISurface,
443 mVideoWidth, mVideoHeight,
444 decodedWidth, decodedHeight);
445 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800446 }
447}
448
449status_t AwesomePlayer::pause() {
450 Mutex::Autolock autoLock(mLock);
451 return pause_l();
452}
453
454status_t AwesomePlayer::pause_l() {
455 if (!(mFlags & PLAYING)) {
456 return OK;
457 }
458
Andreas Huberb9e63832010-01-26 16:20:10 -0800459 cancelPlayerEvents(true /* keepBufferingGoing */);
Andreas Huber27366fc2009-11-20 09:32:46 -0800460
461 if (mAudioPlayer != NULL) {
462 mAudioPlayer->pause();
463 }
464
465 mFlags &= ~PLAYING;
466
467 return OK;
468}
469
470bool AwesomePlayer::isPlaying() const {
471 Mutex::Autolock autoLock(mLock);
472
473 return mFlags & PLAYING;
474}
475
476void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
477 Mutex::Autolock autoLock(mLock);
478
479 mISurface = isurface;
480}
481
482void AwesomePlayer::setAudioSink(
483 const sp<MediaPlayerBase::AudioSink> &audioSink) {
484 Mutex::Autolock autoLock(mLock);
485
486 mAudioSink = audioSink;
487}
488
489status_t AwesomePlayer::setLooping(bool shouldLoop) {
490 Mutex::Autolock autoLock(mLock);
491
492 mFlags = mFlags & ~LOOPING;
493
494 if (shouldLoop) {
495 mFlags |= LOOPING;
496 }
497
498 return OK;
499}
500
501status_t AwesomePlayer::getDuration(int64_t *durationUs) {
502 Mutex::Autolock autoLock(mLock);
503
504 if (mDurationUs < 0) {
505 return UNKNOWN_ERROR;
506 }
507
508 *durationUs = mDurationUs;
509
510 return OK;
511}
512
513status_t AwesomePlayer::getPosition(int64_t *positionUs) {
514 Mutex::Autolock autoLock(mLock);
515
516 if (mVideoRenderer != NULL) {
517 *positionUs = mVideoTimeUs;
518 } else if (mAudioPlayer != NULL) {
519 *positionUs = mAudioPlayer->getMediaTimeUs();
520 } else {
521 *positionUs = 0;
522 }
523
524 return OK;
525}
526
527status_t AwesomePlayer::seekTo(int64_t timeUs) {
528 Mutex::Autolock autoLock(mLock);
529 return seekTo_l(timeUs);
530}
531
532status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
533 mSeeking = true;
534 mSeekTimeUs = timeUs;
535
536 seekAudioIfNecessary_l();
537
538 return OK;
539}
540
541void AwesomePlayer::seekAudioIfNecessary_l() {
542 if (mSeeking && mVideoRenderer == NULL && mAudioPlayer != NULL) {
543 mAudioPlayer->seekTo(mSeekTimeUs);
544
545 mSeeking = false;
546 }
547}
548
549status_t AwesomePlayer::getVideoDimensions(
550 int32_t *width, int32_t *height) const {
551 Mutex::Autolock autoLock(mLock);
552
553 if (mVideoWidth < 0 || mVideoHeight < 0) {
554 return UNKNOWN_ERROR;
555 }
556
557 *width = mVideoWidth;
558 *height = mVideoHeight;
559
560 return OK;
561}
562
Andreas Huberb9e63832010-01-26 16:20:10 -0800563status_t AwesomePlayer::setAudioSource(sp<MediaSource> source) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800564 if (source == NULL) {
565 return UNKNOWN_ERROR;
566 }
567
Andreas Huberb9e63832010-01-26 16:20:10 -0800568 if (mPrefetcher != NULL) {
569 source = mPrefetcher->addSource(source);
570 }
571
Andreas Huberc79827a2010-01-05 10:54:55 -0800572 sp<MetaData> meta = source->getFormat();
573
574 const char *mime;
575 CHECK(meta->findCString(kKeyMIMEType, &mime));
576
577 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
578 mAudioSource = source;
579 } else {
580 mAudioSource = OMXCodec::Create(
581 mClient.interface(), source->getFormat(),
582 false, // createEncoder
583 source);
584 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800585
586 if (mAudioSource != NULL) {
587 int64_t durationUs;
588 if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) {
589 if (mDurationUs < 0 || durationUs > mDurationUs) {
590 mDurationUs = durationUs;
591 }
592 }
593 }
594
595 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
596}
597
Andreas Huberb9e63832010-01-26 16:20:10 -0800598status_t AwesomePlayer::setVideoSource(sp<MediaSource> source) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800599 if (source == NULL) {
600 return UNKNOWN_ERROR;
601 }
602
Andreas Huberb9e63832010-01-26 16:20:10 -0800603 if (mPrefetcher != NULL) {
604 source = mPrefetcher->addSource(source);
605 }
606
Andreas Huber27366fc2009-11-20 09:32:46 -0800607 mVideoSource = OMXCodec::Create(
608 mClient.interface(), source->getFormat(),
609 false, // createEncoder
610 source);
611
612 if (mVideoSource != NULL) {
613 int64_t durationUs;
614 if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) {
615 if (mDurationUs < 0 || durationUs > mDurationUs) {
616 mDurationUs = durationUs;
617 }
618 }
619
620 CHECK(source->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
621 CHECK(source->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
622
623 mVideoSource->start();
624 }
625
626 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
627}
628
629void AwesomePlayer::onEvent(int32_t code) {
630 if (code == 1) {
631 onStreamDone();
632 return;
Andreas Huberb9e63832010-01-26 16:20:10 -0800633 } else if (code == 2) {
634 onBufferingUpdate();
635 return;
Andreas Huber27366fc2009-11-20 09:32:46 -0800636 }
637
638 Mutex::Autolock autoLock(mLock);
Andreas Huberb9e63832010-01-26 16:20:10 -0800639
Andreas Huber27366fc2009-11-20 09:32:46 -0800640 mVideoEventPending = false;
641
642 if (mSeeking) {
643 if (mLastVideoBuffer) {
644 mLastVideoBuffer->release();
645 mLastVideoBuffer = NULL;
646 }
647
648 if (mVideoBuffer) {
649 mVideoBuffer->release();
650 mVideoBuffer = NULL;
651 }
652 }
653
654 if (!mVideoBuffer) {
655 MediaSource::ReadOptions options;
656 if (mSeeking) {
657 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
658
659 options.setSeekTo(mSeekTimeUs);
660 }
661 for (;;) {
662 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -0800663 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -0800664
665 if (err != OK) {
666 CHECK_EQ(mVideoBuffer, NULL);
667
668 if (err == INFO_FORMAT_CHANGED) {
669 LOGV("VideoSource signalled format change.");
670
671 initRenderer_l();
672 continue;
673 }
674
675 postStreamDoneEvent_l();
676 return;
677 }
678
Andreas Hubera67d5382009-12-10 15:32:12 -0800679 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -0800680 // Some decoders, notably the PV AVC software decoder
681 // return spurious empty buffers that we just want to ignore.
682
Andreas Hubera67d5382009-12-10 15:32:12 -0800683 mVideoBuffer->release();
684 mVideoBuffer = NULL;
685 continue;
686 }
687
Andreas Huber27366fc2009-11-20 09:32:46 -0800688 break;
689 }
690 }
691
692 int64_t timeUs;
693 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
694
695 mVideoTimeUs = timeUs;
696
697 if (mSeeking) {
698 if (mAudioPlayer != NULL) {
699 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
700
701 mAudioPlayer->seekTo(timeUs);
702 } else {
703 // If we're playing video only, report seek complete now,
704 // otherwise audio player will notify us later.
Andreas Hubera3f43842010-01-21 10:28:45 -0800705 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800706 }
707
708 mFlags |= FIRST_FRAME;
709 mSeeking = false;
710 }
711
712 if (mFlags & FIRST_FRAME) {
713 mFlags &= ~FIRST_FRAME;
714
715 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
716 }
717
718 int64_t realTimeUs, mediaTimeUs;
719 if (mAudioPlayer != NULL
720 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
721 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
722 }
723
724 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
725
726 int64_t latenessUs = nowUs - timeUs;
727
Andreas Huber24b0a952009-11-23 14:02:00 -0800728 if (latenessUs > 40000) {
729 // We're more than 40ms late.
730 LOGI("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -0800731
732 mVideoBuffer->release();
733 mVideoBuffer = NULL;
734
735 postVideoEvent_l();
736 return;
737 }
738
739 if (latenessUs < -10000) {
740 // We're more than 10ms early.
741
742 postVideoEvent_l(10000);
743 return;
744 }
745
Andreas Huber1314e732009-12-14 14:18:22 -0800746 mVideoRenderer->render(mVideoBuffer);
Andreas Huber27366fc2009-11-20 09:32:46 -0800747
748 if (mLastVideoBuffer) {
749 mLastVideoBuffer->release();
750 mLastVideoBuffer = NULL;
751 }
752 mLastVideoBuffer = mVideoBuffer;
753 mVideoBuffer = NULL;
754
755 postVideoEvent_l();
756}
757
758void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
759 if (mVideoEventPending) {
760 return;
761 }
762
763 mVideoEventPending = true;
764 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
765}
766
767void AwesomePlayer::postStreamDoneEvent_l() {
768 if (mStreamDoneEventPending) {
769 return;
770 }
771 mStreamDoneEventPending = true;
772 mQueue.postEvent(mStreamDoneEvent);
773}
774
Andreas Huberb9e63832010-01-26 16:20:10 -0800775void AwesomePlayer::postBufferingEvent_l() {
776 if (mPrefetcher == NULL) {
777 return;
778 }
779
780 if (mBufferingEventPending) {
781 return;
782 }
783 mBufferingEventPending = true;
784 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
785}
786
Andreas Huber27366fc2009-11-20 09:32:46 -0800787} // namespace android
788