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