AwesomePlayer.cpp revision bd22c52280179b29eefac91ef7e7bbbc33d25904
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 "include/AwesomePlayer.h"
22#include "include/Prefetcher.h"
23#include "include/SoftwareRenderer.h"
24
25#include <binder/IPCThreadState.h>
26#include <media/stagefright/AudioPlayer.h>
27#include <media/stagefright/DataSource.h>
28#include <media/stagefright/FileSource.h>
29#include <media/stagefright/MediaBuffer.h>
30#include <media/stagefright/MediaDefs.h>
31#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>
36
37namespace android {
38
39struct AwesomeEvent : public TimedEventQueue::Event {
40    AwesomeEvent(
41            AwesomePlayer *player,
42            void (AwesomePlayer::*method)())
43        : mPlayer(player),
44          mMethod(method) {
45    }
46
47protected:
48    virtual ~AwesomeEvent() {}
49
50    virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
51        (mPlayer->*mMethod)();
52    }
53
54private:
55    AwesomePlayer *mPlayer;
56    void (AwesomePlayer::*mMethod)();
57
58    AwesomeEvent(const AwesomeEvent &);
59    AwesomeEvent &operator=(const AwesomeEvent &);
60};
61
62struct 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
111AwesomePlayer::AwesomePlayer()
112    : mTimeSource(NULL),
113      mAudioPlayer(NULL),
114      mFlags(0),
115      mLastVideoBuffer(NULL),
116      mVideoBuffer(NULL) {
117    CHECK_EQ(mClient.connect(), OK);
118
119    DataSource::RegisterDefaultSniffers();
120
121    mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
122    mVideoEventPending = false;
123    mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
124    mStreamDoneEventPending = false;
125    mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
126    mBufferingEventPending = false;
127
128    mCheckAudioStatusEvent = new AwesomeEvent(
129            this, &AwesomePlayer::onCheckAudioStatus);
130
131    mAudioStatusEventPending = false;
132
133    mQueue.start();
134
135    reset();
136}
137
138AwesomePlayer::~AwesomePlayer() {
139    mQueue.stop();
140
141    reset();
142
143    mClient.disconnect();
144}
145
146void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
147    mQueue.cancelEvent(mVideoEvent->eventID());
148    mVideoEventPending = false;
149    mQueue.cancelEvent(mStreamDoneEvent->eventID());
150    mStreamDoneEventPending = false;
151    mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
152    mAudioStatusEventPending = false;
153
154    if (!keepBufferingGoing) {
155        mQueue.cancelEvent(mBufferingEvent->eventID());
156        mBufferingEventPending = false;
157    }
158}
159
160void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
161    Mutex::Autolock autoLock(mLock);
162    mListener = listener;
163}
164
165status_t AwesomePlayer::setDataSource(
166        const char *uri, const KeyedVector<String8, String8> *headers) {
167    Mutex::Autolock autoLock(mLock);
168
169    reset_l();
170
171    mUri = uri;
172
173    if (headers) {
174        mUriHeaders = *headers;
175    }
176
177    // 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.
180
181    return OK;
182}
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) {
208    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() {
240    while (mFlags & PREPARING) {
241        mPreparedCondition.wait(mLock);
242    }
243
244    cancelPlayerEvents();
245
246    mVideoRenderer.clear();
247
248    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();
260
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;
265        mVideoSource.clear();
266        while (tmp.promote() != NULL) {
267            usleep(1000);
268        }
269        IPCThreadState::self()->flushCommands();
270    }
271
272    mAudioSource.clear();
273
274    if (mTimeSource != mAudioPlayer) {
275        delete mTimeSource;
276    }
277    mTimeSource = NULL;
278
279    delete mAudioPlayer;
280    mAudioPlayer = NULL;
281
282    mDurationUs = -1;
283    mFlags = 0;
284    mVideoWidth = mVideoHeight = -1;
285    mTimeSourceDeltaUs = 0;
286    mVideoTimeUs = 0;
287
288    mSeeking = false;
289    mSeekTimeUs = 0;
290
291    mPrefetcher.clear();
292
293    mUri.setTo("");
294    mUriHeaders.clear();
295}
296
297void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
298    if (mListener != NULL) {
299        sp<MediaPlayerBase> listener = mListener.promote();
300
301        if (listener != NULL) {
302            listener->sendEvent(msg, ext1, ext2);
303        }
304    }
305}
306
307void 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;
314        if (mVideoSource != NULL) {
315            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
329void 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
338        if (mVideoSource != NULL) {
339            postVideoEvent_l();
340        }
341    } else {
342        notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
343
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
355    if (!(mFlags & PREPARED)) {
356        status_t err = prepare_l();
357
358        if (err != OK) {
359            return err;
360        }
361    }
362
363    mFlags |= PLAYING;
364    mFlags |= FIRST_FRAME;
365
366    bool deferredAudioSeek = false;
367
368    if (mAudioSource != NULL) {
369        if (mAudioPlayer == NULL) {
370            if (mAudioSink != NULL) {
371                mAudioPlayer = new AudioPlayer(mAudioSink);
372                mAudioPlayer->setSource(mAudioSource);
373                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                }
383
384                delete mTimeSource;
385                mTimeSource = mAudioPlayer;
386
387                deferredAudioSeek = true;
388
389                mWatchForAudioSeekComplete = false;
390                mWatchForAudioEOS = true;
391            }
392        } else {
393            mAudioPlayer->resume();
394        }
395
396        postCheckAudioStatusEvent_l();
397    }
398
399    if (mTimeSource == NULL && mAudioPlayer == NULL) {
400        mTimeSource = new SystemTimeSource;
401    }
402
403    if (mVideoSource != NULL) {
404        // Kick off video playback
405        postVideoEvent_l();
406    }
407
408    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
414    postBufferingEvent_l();
415
416    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
431        mVideoRenderer.clear();
432
433        // Must ensure that mVideoRenderer's destructor is actually executed
434        // before creating a new one.
435        IPCThreadState::self()->flushCommands();
436
437        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        }
456    }
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
469    cancelPlayerEvents(true /* keepBufferingGoing */);
470
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
526    if (mVideoSource != NULL) {
527        *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() {
552    if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
553        mAudioPlayer->seekTo(mSeekTimeUs);
554
555        mWatchForAudioSeekComplete = true;
556        mWatchForAudioEOS = true;
557        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
575status_t AwesomePlayer::setAudioSource(sp<MediaSource> source) {
576    if (source == NULL) {
577        return UNKNOWN_ERROR;
578    }
579
580    if (mPrefetcher != NULL) {
581        source = mPrefetcher->addSource(source);
582    }
583
584    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    }
597
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
610status_t AwesomePlayer::setVideoSource(sp<MediaSource> source) {
611    if (source == NULL) {
612        return UNKNOWN_ERROR;
613    }
614
615    if (mPrefetcher != NULL) {
616        source = mPrefetcher->addSource(source);
617    }
618
619    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
641void AwesomePlayer::onVideoEvent() {
642    Mutex::Autolock autoLock(mLock);
643
644    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);
667            options.clearSeekTo();
668
669            if (err != OK) {
670                CHECK_EQ(mVideoBuffer, NULL);
671
672                if (err == INFO_FORMAT_CHANGED) {
673                    LOGV("VideoSource signalled format change.");
674
675                    if (mVideoRenderer != NULL) {
676                        initRenderer_l();
677                    }
678                    continue;
679                }
680
681                postStreamDoneEvent_l();
682                return;
683            }
684
685            if (mVideoBuffer->range_length() == 0) {
686                // Some decoders, notably the PV AVC software decoder
687                // return spurious empty buffers that we just want to ignore.
688
689                mVideoBuffer->release();
690                mVideoBuffer = NULL;
691                continue;
692            }
693
694            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);
708            mWatchForAudioSeekComplete = true;
709            mWatchForAudioEOS = true;
710        } else {
711            // If we're playing video only, report seek complete now,
712            // otherwise audio player will notify us later.
713            notifyListener_l(MEDIA_SEEK_COMPLETE);
714        }
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
736    if (latenessUs > 40000) {
737        // We're more than 40ms late.
738        LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
739
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
754    if (mVideoRenderer == NULL) {
755        initRenderer_l();
756    }
757
758    if (mVideoRenderer != NULL) {
759        mVideoRenderer->render(mVideoBuffer);
760    }
761
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
789void 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
801void 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
826status_t AwesomePlayer::prepare() {
827    Mutex::Autolock autoLock(mLock);
828    return prepare_l();
829}
830
831status_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;
841    status_t err = prepareAsync_l();
842
843    if (err != OK) {
844        return err;
845    }
846
847    while (mFlags & PREPARING) {
848        mPreparedCondition.wait(mLock);
849    }
850
851    return mPrepareResult;
852}
853
854status_t AwesomePlayer::prepareAsync() {
855    Mutex::Autolock autoLock(mLock);
856
857    if (mFlags & PREPARING) {
858        return UNKNOWN_ERROR;  // async prepare already pending
859    }
860
861    mIsAsyncPrepare = true;
862    return prepareAsync_l();
863}
864
865status_t AwesomePlayer::prepareAsync_l() {
866    if (mFlags & PREPARING) {
867        return UNKNOWN_ERROR;  // async prepare already pending
868    }
869
870    mFlags |= PREPARING;
871    mAsyncPrepareEvent = new AwesomeEvent(
872            this, &AwesomePlayer::onPrepareAsyncEvent);
873
874    mQueue.postEvent(mAsyncPrepareEvent);
875
876    return OK;
877}
878
879status_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
900void AwesomePlayer::onPrepareAsyncEvent() {
901    {
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
922    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
935    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);
943    }
944
945    mPrepareResult = OK;
946    mFlags &= ~PREPARING;
947    mFlags |= PREPARED;
948    mAsyncPrepareEvent = NULL;
949    mPreparedCondition.broadcast();
950}
951
952}  // namespace android
953
954