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