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