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