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