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