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