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