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