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