AwesomePlayer.cpp revision 988e3f0b2c74095deae580157c57935a98573052
1/*
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 <dlfcn.h>
22
23#include "include/AwesomePlayer.h"
24#include "include/Prefetcher.h"
25#include "include/SoftwareRenderer.h"
26
27#include <binder/IPCThreadState.h>
28#include <media/stagefright/AudioPlayer.h>
29#include <media/stagefright/DataSource.h>
30#include <media/stagefright/FileSource.h>
31#include <media/stagefright/MediaBuffer.h>
32#include <media/stagefright/MediaDefs.h>
33#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>
38
39namespace android {
40
41struct AwesomeEvent : public TimedEventQueue::Event {
42    AwesomeEvent(
43            AwesomePlayer *player,
44            void (AwesomePlayer::*method)())
45        : mPlayer(player),
46          mMethod(method) {
47    }
48
49protected:
50    virtual ~AwesomeEvent() {}
51
52    virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
53        (mPlayer->*mMethod)();
54    }
55
56private:
57    AwesomePlayer *mPlayer;
58    void (AwesomePlayer::*mMethod)();
59
60    AwesomeEvent(const AwesomeEvent &);
61    AwesomeEvent &operator=(const AwesomeEvent &);
62};
63
64struct AwesomeRemoteRenderer : public AwesomeRenderer {
65    AwesomeRemoteRenderer(const sp<IOMXRenderer> &target)
66        : mTarget(target) {
67    }
68
69    virtual void render(MediaBuffer *buffer) {
70        void *id;
71        if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) {
72            mTarget->render((IOMX::buffer_id)id);
73        }
74    }
75
76private:
77    sp<IOMXRenderer> mTarget;
78
79    AwesomeRemoteRenderer(const AwesomeRemoteRenderer &);
80    AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &);
81};
82
83struct AwesomeLocalRenderer : public AwesomeRenderer {
84    AwesomeLocalRenderer(
85            const char *componentName,
86            OMX_COLOR_FORMATTYPE colorFormat,
87            const sp<ISurface> &surface,
88            size_t displayWidth, size_t displayHeight,
89            size_t decodedWidth, size_t decodedHeight)
90        : mTarget(NULL),
91          mLibHandle(NULL) {
92            init(componentName,
93                 colorFormat, surface, displayWidth,
94                 displayHeight, decodedWidth, decodedHeight);
95    }
96
97    virtual void render(MediaBuffer *buffer) {
98        mTarget->render(
99                (const uint8_t *)buffer->data() + buffer->range_offset(),
100                buffer->range_length(), NULL);
101    }
102
103protected:
104    virtual ~AwesomeLocalRenderer() {
105        delete mTarget;
106        mTarget = NULL;
107
108        if (mLibHandle) {
109            dlclose(mLibHandle);
110            mLibHandle = NULL;
111        }
112    }
113
114private:
115    VideoRenderer *mTarget;
116    void *mLibHandle;
117
118    void init(
119            const char *componentName,
120            OMX_COLOR_FORMATTYPE colorFormat,
121            const sp<ISurface> &surface,
122            size_t displayWidth, size_t displayHeight,
123            size_t decodedWidth, size_t decodedHeight);
124
125    AwesomeLocalRenderer(const AwesomeLocalRenderer &);
126    AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
127};
128
129void AwesomeLocalRenderer::init(
130        const char *componentName,
131        OMX_COLOR_FORMATTYPE colorFormat,
132        const sp<ISurface> &surface,
133        size_t displayWidth, size_t displayHeight,
134        size_t decodedWidth, size_t decodedHeight) {
135    mLibHandle = dlopen("libstagefrighthw.so", RTLD_NOW);
136
137    if (mLibHandle) {
138        typedef VideoRenderer *(*CreateRendererFunc)(
139                const sp<ISurface> &surface,
140                const char *componentName,
141                OMX_COLOR_FORMATTYPE colorFormat,
142                size_t displayWidth, size_t displayHeight,
143                size_t decodedWidth, size_t decodedHeight);
144
145        CreateRendererFunc func =
146            (CreateRendererFunc)dlsym(
147                    mLibHandle,
148                    "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20"
149                    "OMX_COLOR_FORMATTYPEjjjj");
150
151        if (func) {
152            mTarget =
153                (*func)(surface, componentName, colorFormat,
154                    displayWidth, displayHeight, decodedWidth, decodedHeight);
155        }
156    }
157
158    if (mTarget == NULL) {
159        mTarget = new SoftwareRenderer(
160                colorFormat, surface, displayWidth, displayHeight,
161                decodedWidth, decodedHeight);
162    }
163}
164
165AwesomePlayer::AwesomePlayer()
166    : mTimeSource(NULL),
167      mAudioPlayer(NULL),
168      mFlags(0),
169      mLastVideoBuffer(NULL),
170      mVideoBuffer(NULL) {
171    CHECK_EQ(mClient.connect(), OK);
172
173    DataSource::RegisterDefaultSniffers();
174
175    mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
176    mVideoEventPending = false;
177    mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
178    mStreamDoneEventPending = false;
179    mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
180    mBufferingEventPending = false;
181
182    mCheckAudioStatusEvent = new AwesomeEvent(
183            this, &AwesomePlayer::onCheckAudioStatus);
184
185    mAudioStatusEventPending = false;
186
187    mQueue.start();
188
189    reset();
190}
191
192AwesomePlayer::~AwesomePlayer() {
193    mQueue.stop();
194
195    reset();
196
197    mClient.disconnect();
198}
199
200void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
201    mQueue.cancelEvent(mVideoEvent->eventID());
202    mVideoEventPending = false;
203    mQueue.cancelEvent(mStreamDoneEvent->eventID());
204    mStreamDoneEventPending = false;
205    mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
206    mAudioStatusEventPending = false;
207
208    if (!keepBufferingGoing) {
209        mQueue.cancelEvent(mBufferingEvent->eventID());
210        mBufferingEventPending = false;
211    }
212}
213
214void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
215    Mutex::Autolock autoLock(mLock);
216    mListener = listener;
217}
218
219status_t AwesomePlayer::setDataSource(
220        const char *uri, const KeyedVector<String8, String8> *headers) {
221    Mutex::Autolock autoLock(mLock);
222
223    reset_l();
224
225    mUri = uri;
226
227    if (headers) {
228        mUriHeaders = *headers;
229    }
230
231    // The actual work will be done during preparation in the call to
232    // ::finishSetDataSource_l to avoid blocking the calling thread in
233    // setDataSource for any significant time.
234
235    return OK;
236}
237
238status_t AwesomePlayer::setDataSource(
239        int fd, int64_t offset, int64_t length) {
240    Mutex::Autolock autoLock(mLock);
241
242    reset_l();
243
244    sp<DataSource> source = new FileSource(fd, offset, length);
245
246    status_t err = source->initCheck();
247
248    if (err != OK) {
249        return err;
250    }
251
252    sp<MediaExtractor> extractor = MediaExtractor::Create(source);
253
254    if (extractor == NULL) {
255        return UNKNOWN_ERROR;
256    }
257
258    return setDataSource_l(extractor);
259}
260
261status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
262    bool haveAudio = false;
263    bool haveVideo = false;
264    for (size_t i = 0; i < extractor->countTracks(); ++i) {
265        sp<MetaData> meta = extractor->getTrackMetaData(i);
266
267        const char *mime;
268        CHECK(meta->findCString(kKeyMIMEType, &mime));
269
270        if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
271            if (setVideoSource(extractor->getTrack(i)) == OK) {
272                haveVideo = true;
273            }
274        } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
275            if (setAudioSource(extractor->getTrack(i)) == OK) {
276                haveAudio = true;
277            }
278        }
279
280        if (haveAudio && haveVideo) {
281            break;
282        }
283    }
284
285    return !haveAudio && !haveVideo ? UNKNOWN_ERROR : OK;
286}
287
288void AwesomePlayer::reset() {
289    Mutex::Autolock autoLock(mLock);
290    reset_l();
291}
292
293void AwesomePlayer::reset_l() {
294    while (mFlags & PREPARING) {
295        mPreparedCondition.wait(mLock);
296    }
297
298    cancelPlayerEvents();
299
300    mVideoRenderer.clear();
301
302    if (mLastVideoBuffer) {
303        mLastVideoBuffer->release();
304        mLastVideoBuffer = NULL;
305    }
306
307    if (mVideoBuffer) {
308        mVideoBuffer->release();
309        mVideoBuffer = NULL;
310    }
311
312    if (mVideoSource != NULL) {
313        mVideoSource->stop();
314
315        // The following hack is necessary to ensure that the OMX
316        // component is completely released by the time we may try
317        // to instantiate it again.
318        wp<MediaSource> tmp = mVideoSource;
319        mVideoSource.clear();
320        while (tmp.promote() != NULL) {
321            usleep(1000);
322        }
323        IPCThreadState::self()->flushCommands();
324    }
325
326    mAudioSource.clear();
327
328    if (mTimeSource != mAudioPlayer) {
329        delete mTimeSource;
330    }
331    mTimeSource = NULL;
332
333    delete mAudioPlayer;
334    mAudioPlayer = NULL;
335
336    mDurationUs = -1;
337    mFlags = 0;
338    mVideoWidth = mVideoHeight = -1;
339    mTimeSourceDeltaUs = 0;
340    mVideoTimeUs = 0;
341
342    mSeeking = false;
343    mSeekTimeUs = 0;
344
345    mPrefetcher.clear();
346
347    mUri.setTo("");
348    mUriHeaders.clear();
349}
350
351void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
352    if (mListener != NULL) {
353        sp<MediaPlayerBase> listener = mListener.promote();
354
355        if (listener != NULL) {
356            listener->sendEvent(msg, ext1, ext2);
357        }
358    }
359}
360
361void AwesomePlayer::onBufferingUpdate() {
362    Mutex::Autolock autoLock(mLock);
363    mBufferingEventPending = false;
364
365    if (mDurationUs >= 0) {
366        int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs();
367        int64_t positionUs = 0;
368        if (mVideoSource != NULL) {
369            positionUs = mVideoTimeUs;
370        } else if (mAudioPlayer != NULL) {
371            positionUs = mAudioPlayer->getMediaTimeUs();
372        }
373
374        cachedDurationUs += positionUs;
375
376        double percentage = (double)cachedDurationUs / mDurationUs;
377        notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
378
379        postBufferingEvent_l();
380    }
381}
382
383void AwesomePlayer::onStreamDone() {
384    // Posted whenever any stream finishes playing.
385
386    Mutex::Autolock autoLock(mLock);
387    mStreamDoneEventPending = false;
388
389    if (mFlags & LOOPING) {
390        seekTo_l(0);
391
392        if (mVideoSource != NULL) {
393            postVideoEvent_l();
394        }
395    } else {
396        notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
397
398        pause_l();
399    }
400}
401
402status_t AwesomePlayer::play() {
403    Mutex::Autolock autoLock(mLock);
404
405    if (mFlags & PLAYING) {
406        return OK;
407    }
408
409    if (!(mFlags & PREPARED)) {
410        status_t err = prepare_l();
411
412        if (err != OK) {
413            return err;
414        }
415    }
416
417    mFlags |= PLAYING;
418    mFlags |= FIRST_FRAME;
419
420    bool deferredAudioSeek = false;
421
422    if (mAudioSource != NULL) {
423        if (mAudioPlayer == NULL) {
424            if (mAudioSink != NULL) {
425                mAudioPlayer = new AudioPlayer(mAudioSink);
426                mAudioPlayer->setSource(mAudioSource);
427                status_t err = mAudioPlayer->start();
428
429                if (err != OK) {
430                    delete mAudioPlayer;
431                    mAudioPlayer = NULL;
432
433                    mFlags &= ~(PLAYING | FIRST_FRAME);
434
435                    return err;
436                }
437
438                delete mTimeSource;
439                mTimeSource = mAudioPlayer;
440
441                deferredAudioSeek = true;
442
443                mWatchForAudioSeekComplete = false;
444                mWatchForAudioEOS = true;
445            }
446        } else {
447            mAudioPlayer->resume();
448        }
449
450        postCheckAudioStatusEvent_l();
451    }
452
453    if (mTimeSource == NULL && mAudioPlayer == NULL) {
454        mTimeSource = new SystemTimeSource;
455    }
456
457    if (mVideoSource != NULL) {
458        // Kick off video playback
459        postVideoEvent_l();
460    }
461
462    if (deferredAudioSeek) {
463        // If there was a seek request while we were paused
464        // and we're just starting up again, honor the request now.
465        seekAudioIfNecessary_l();
466    }
467
468    postBufferingEvent_l();
469
470    return OK;
471}
472
473void AwesomePlayer::initRenderer_l() {
474    if (mISurface != NULL) {
475        sp<MetaData> meta = mVideoSource->getFormat();
476
477        int32_t format;
478        const char *component;
479        int32_t decodedWidth, decodedHeight;
480        CHECK(meta->findInt32(kKeyColorFormat, &format));
481        CHECK(meta->findCString(kKeyDecoderComponent, &component));
482        CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
483        CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
484
485        mVideoRenderer.clear();
486
487        // Must ensure that mVideoRenderer's destructor is actually executed
488        // before creating a new one.
489        IPCThreadState::self()->flushCommands();
490
491        if (!strncmp("OMX.", component, 4)) {
492            // Our OMX codecs allocate buffers on the media_server side
493            // therefore they require a remote IOMXRenderer that knows how
494            // to display them.
495            mVideoRenderer = new AwesomeRemoteRenderer(
496                mClient.interface()->createRenderer(
497                        mISurface, component,
498                        (OMX_COLOR_FORMATTYPE)format,
499                        decodedWidth, decodedHeight,
500                        mVideoWidth, mVideoHeight));
501        } else {
502            // Other decoders are instantiated locally and as a consequence
503            // allocate their buffers in local address space.
504            mVideoRenderer = new AwesomeLocalRenderer(
505                component,
506                (OMX_COLOR_FORMATTYPE)format,
507                mISurface,
508                mVideoWidth, mVideoHeight,
509                decodedWidth, decodedHeight);
510        }
511    }
512}
513
514status_t AwesomePlayer::pause() {
515    Mutex::Autolock autoLock(mLock);
516    return pause_l();
517}
518
519status_t AwesomePlayer::pause_l() {
520    if (!(mFlags & PLAYING)) {
521        return OK;
522    }
523
524    cancelPlayerEvents(true /* keepBufferingGoing */);
525
526    if (mAudioPlayer != NULL) {
527        mAudioPlayer->pause();
528    }
529
530    mFlags &= ~PLAYING;
531
532    return OK;
533}
534
535bool AwesomePlayer::isPlaying() const {
536    Mutex::Autolock autoLock(mLock);
537
538    return mFlags & PLAYING;
539}
540
541void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
542    Mutex::Autolock autoLock(mLock);
543
544    mISurface = isurface;
545}
546
547void AwesomePlayer::setAudioSink(
548        const sp<MediaPlayerBase::AudioSink> &audioSink) {
549    Mutex::Autolock autoLock(mLock);
550
551    mAudioSink = audioSink;
552}
553
554status_t AwesomePlayer::setLooping(bool shouldLoop) {
555    Mutex::Autolock autoLock(mLock);
556
557    mFlags = mFlags & ~LOOPING;
558
559    if (shouldLoop) {
560        mFlags |= LOOPING;
561    }
562
563    return OK;
564}
565
566status_t AwesomePlayer::getDuration(int64_t *durationUs) {
567    Mutex::Autolock autoLock(mLock);
568
569    if (mDurationUs < 0) {
570        return UNKNOWN_ERROR;
571    }
572
573    *durationUs = mDurationUs;
574
575    return OK;
576}
577
578status_t AwesomePlayer::getPosition(int64_t *positionUs) {
579    Mutex::Autolock autoLock(mLock);
580
581    if (mVideoSource != NULL) {
582        *positionUs = mVideoTimeUs;
583    } else if (mAudioPlayer != NULL) {
584        *positionUs = mAudioPlayer->getMediaTimeUs();
585    } else {
586        *positionUs = 0;
587    }
588
589    return OK;
590}
591
592status_t AwesomePlayer::seekTo(int64_t timeUs) {
593    Mutex::Autolock autoLock(mLock);
594    return seekTo_l(timeUs);
595}
596
597status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
598    mSeeking = true;
599    mSeekTimeUs = timeUs;
600
601    seekAudioIfNecessary_l();
602
603    return OK;
604}
605
606void AwesomePlayer::seekAudioIfNecessary_l() {
607    if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
608        mAudioPlayer->seekTo(mSeekTimeUs);
609
610        mWatchForAudioSeekComplete = true;
611        mWatchForAudioEOS = true;
612        mSeeking = false;
613    }
614}
615
616status_t AwesomePlayer::getVideoDimensions(
617        int32_t *width, int32_t *height) const {
618    Mutex::Autolock autoLock(mLock);
619
620    if (mVideoWidth < 0 || mVideoHeight < 0) {
621        return UNKNOWN_ERROR;
622    }
623
624    *width = mVideoWidth;
625    *height = mVideoHeight;
626
627    return OK;
628}
629
630status_t AwesomePlayer::setAudioSource(sp<MediaSource> source) {
631    if (source == NULL) {
632        return UNKNOWN_ERROR;
633    }
634
635    if (mPrefetcher != NULL) {
636        source = mPrefetcher->addSource(source);
637    }
638
639    sp<MetaData> meta = source->getFormat();
640
641    const char *mime;
642    CHECK(meta->findCString(kKeyMIMEType, &mime));
643
644    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
645        mAudioSource = source;
646    } else {
647        mAudioSource = OMXCodec::Create(
648                mClient.interface(), source->getFormat(),
649                false, // createEncoder
650                source);
651    }
652
653    if (mAudioSource != NULL) {
654        int64_t durationUs;
655        if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) {
656            if (mDurationUs < 0 || durationUs > mDurationUs) {
657                mDurationUs = durationUs;
658            }
659        }
660    }
661
662    return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
663}
664
665status_t AwesomePlayer::setVideoSource(sp<MediaSource> source) {
666    if (source == NULL) {
667        return UNKNOWN_ERROR;
668    }
669
670    if (mPrefetcher != NULL) {
671        source = mPrefetcher->addSource(source);
672    }
673
674    mVideoSource = OMXCodec::Create(
675            mClient.interface(), source->getFormat(),
676            false, // createEncoder
677            source);
678
679    if (mVideoSource != NULL) {
680        int64_t durationUs;
681        if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) {
682            if (mDurationUs < 0 || durationUs > mDurationUs) {
683                mDurationUs = durationUs;
684            }
685        }
686
687        CHECK(source->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
688        CHECK(source->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
689
690        mVideoSource->start();
691    }
692
693    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
694}
695
696void AwesomePlayer::onVideoEvent() {
697    Mutex::Autolock autoLock(mLock);
698
699    mVideoEventPending = false;
700
701    if (mSeeking) {
702        if (mLastVideoBuffer) {
703            mLastVideoBuffer->release();
704            mLastVideoBuffer = NULL;
705        }
706
707        if (mVideoBuffer) {
708            mVideoBuffer->release();
709            mVideoBuffer = NULL;
710        }
711    }
712
713    if (!mVideoBuffer) {
714        MediaSource::ReadOptions options;
715        if (mSeeking) {
716            LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
717
718            options.setSeekTo(mSeekTimeUs);
719        }
720        for (;;) {
721            status_t err = mVideoSource->read(&mVideoBuffer, &options);
722            options.clearSeekTo();
723
724            if (err != OK) {
725                CHECK_EQ(mVideoBuffer, NULL);
726
727                if (err == INFO_FORMAT_CHANGED) {
728                    LOGV("VideoSource signalled format change.");
729
730                    if (mVideoRenderer != NULL) {
731                        initRenderer_l();
732                    }
733                    continue;
734                }
735
736                postStreamDoneEvent_l();
737                return;
738            }
739
740            if (mVideoBuffer->range_length() == 0) {
741                // Some decoders, notably the PV AVC software decoder
742                // return spurious empty buffers that we just want to ignore.
743
744                mVideoBuffer->release();
745                mVideoBuffer = NULL;
746                continue;
747            }
748
749            break;
750        }
751    }
752
753    int64_t timeUs;
754    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
755
756    mVideoTimeUs = timeUs;
757
758    if (mSeeking) {
759        if (mAudioPlayer != NULL) {
760            LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
761
762            mAudioPlayer->seekTo(timeUs);
763            mWatchForAudioSeekComplete = true;
764            mWatchForAudioEOS = true;
765        } else {
766            // If we're playing video only, report seek complete now,
767            // otherwise audio player will notify us later.
768            notifyListener_l(MEDIA_SEEK_COMPLETE);
769        }
770
771        mFlags |= FIRST_FRAME;
772        mSeeking = false;
773    }
774
775    if (mFlags & FIRST_FRAME) {
776        mFlags &= ~FIRST_FRAME;
777
778        mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
779    }
780
781    int64_t realTimeUs, mediaTimeUs;
782    if (mAudioPlayer != NULL
783        && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
784        mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
785    }
786
787    int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
788
789    int64_t latenessUs = nowUs - timeUs;
790
791    if (latenessUs > 40000) {
792        // We're more than 40ms late.
793        LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
794
795        mVideoBuffer->release();
796        mVideoBuffer = NULL;
797
798        postVideoEvent_l();
799        return;
800    }
801
802    if (latenessUs < -10000) {
803        // We're more than 10ms early.
804
805        postVideoEvent_l(10000);
806        return;
807    }
808
809    if (mVideoRenderer == NULL) {
810        initRenderer_l();
811    }
812
813    if (mVideoRenderer != NULL) {
814        mVideoRenderer->render(mVideoBuffer);
815    }
816
817    if (mLastVideoBuffer) {
818        mLastVideoBuffer->release();
819        mLastVideoBuffer = NULL;
820    }
821    mLastVideoBuffer = mVideoBuffer;
822    mVideoBuffer = NULL;
823
824    postVideoEvent_l();
825}
826
827void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
828    if (mVideoEventPending) {
829        return;
830    }
831
832    mVideoEventPending = true;
833    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
834}
835
836void AwesomePlayer::postStreamDoneEvent_l() {
837    if (mStreamDoneEventPending) {
838        return;
839    }
840    mStreamDoneEventPending = true;
841    mQueue.postEvent(mStreamDoneEvent);
842}
843
844void AwesomePlayer::postBufferingEvent_l() {
845    if (mPrefetcher == NULL) {
846        return;
847    }
848
849    if (mBufferingEventPending) {
850        return;
851    }
852    mBufferingEventPending = true;
853    mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
854}
855
856void AwesomePlayer::postCheckAudioStatusEvent_l() {
857    if (mAudioStatusEventPending) {
858        return;
859    }
860    mAudioStatusEventPending = true;
861    mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
862}
863
864void AwesomePlayer::onCheckAudioStatus() {
865    Mutex::Autolock autoLock(mLock);
866    mAudioStatusEventPending = false;
867
868    if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
869        mWatchForAudioSeekComplete = false;
870        notifyListener_l(MEDIA_SEEK_COMPLETE);
871    }
872
873    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS()) {
874        mWatchForAudioEOS = false;
875        postStreamDoneEvent_l();
876    }
877
878    postCheckAudioStatusEvent_l();
879}
880
881status_t AwesomePlayer::prepare() {
882    Mutex::Autolock autoLock(mLock);
883    return prepare_l();
884}
885
886status_t AwesomePlayer::prepare_l() {
887    if (mFlags & PREPARED) {
888        return OK;
889    }
890
891    if (mFlags & PREPARING) {
892        return UNKNOWN_ERROR;
893    }
894
895    mIsAsyncPrepare = false;
896    status_t err = prepareAsync_l();
897
898    if (err != OK) {
899        return err;
900    }
901
902    while (mFlags & PREPARING) {
903        mPreparedCondition.wait(mLock);
904    }
905
906    return mPrepareResult;
907}
908
909status_t AwesomePlayer::prepareAsync() {
910    Mutex::Autolock autoLock(mLock);
911
912    if (mFlags & PREPARING) {
913        return UNKNOWN_ERROR;  // async prepare already pending
914    }
915
916    mIsAsyncPrepare = true;
917    return prepareAsync_l();
918}
919
920status_t AwesomePlayer::prepareAsync_l() {
921    if (mFlags & PREPARING) {
922        return UNKNOWN_ERROR;  // async prepare already pending
923    }
924
925    mFlags |= PREPARING;
926    mAsyncPrepareEvent = new AwesomeEvent(
927            this, &AwesomePlayer::onPrepareAsyncEvent);
928
929    mQueue.postEvent(mAsyncPrepareEvent);
930
931    return OK;
932}
933
934status_t AwesomePlayer::finishSetDataSource_l() {
935    sp<DataSource> dataSource =
936        DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
937
938    if (dataSource == NULL) {
939        return UNKNOWN_ERROR;
940    }
941
942    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
943
944    if (extractor == NULL) {
945        return UNKNOWN_ERROR;
946    }
947
948    if (dataSource->flags() & DataSource::kWantsPrefetching) {
949        mPrefetcher = new Prefetcher;
950    }
951
952    return setDataSource_l(extractor);
953}
954
955void AwesomePlayer::onPrepareAsyncEvent() {
956    {
957        Mutex::Autolock autoLock(mLock);
958
959        if (mUri.size() > 0) {
960            status_t err = finishSetDataSource_l();
961
962            if (err != OK) {
963                if (mIsAsyncPrepare) {
964                    notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
965                }
966
967                mPrepareResult = err;
968                mFlags &= ~PREPARING;
969                mAsyncPrepareEvent = NULL;
970                mPreparedCondition.broadcast();
971
972                return;
973            }
974        }
975    }
976
977    sp<Prefetcher> prefetcher;
978
979    {
980        Mutex::Autolock autoLock(mLock);
981        prefetcher = mPrefetcher;
982    }
983
984    if (prefetcher != NULL) {
985        prefetcher->prepare();
986    }
987
988    Mutex::Autolock autoLock(mLock);
989
990    if (mIsAsyncPrepare) {
991        if (mVideoWidth < 0 || mVideoHeight < 0) {
992            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
993        } else {
994            notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
995        }
996
997        notifyListener_l(MEDIA_PREPARED);
998    }
999
1000    mPrepareResult = OK;
1001    mFlags &= ~PREPARING;
1002    mFlags |= PREPARED;
1003    mAsyncPrepareEvent = NULL;
1004    mPreparedCondition.broadcast();
1005}
1006
1007}  // namespace android
1008
1009