AwesomePlayer.cpp revision fa090f541bb84a546af2ec834e91a032ff10e66e
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    mBufferingEventPending = false;
405
406    if (mDurationUs >= 0) {
407        int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs();
408        int64_t positionUs = 0;
409        if (mVideoSource != NULL) {
410            positionUs = mVideoTimeUs;
411        } else if (mAudioPlayer != NULL) {
412            positionUs = mAudioPlayer->getMediaTimeUs();
413        }
414
415        cachedDurationUs += positionUs;
416
417        double percentage = (double)cachedDurationUs / mDurationUs;
418        notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
419
420        postBufferingEvent_l();
421    }
422}
423
424void AwesomePlayer::onStreamDone() {
425    // Posted whenever any stream finishes playing.
426
427    Mutex::Autolock autoLock(mLock);
428    mStreamDoneEventPending = false;
429
430    if (mFlags & LOOPING) {
431        seekTo_l(0);
432
433        if (mVideoSource != NULL) {
434            postVideoEvent_l();
435        }
436    } else {
437        notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
438
439        pause_l();
440    }
441}
442
443status_t AwesomePlayer::play() {
444    Mutex::Autolock autoLock(mLock);
445    return play_l();
446}
447
448status_t AwesomePlayer::play_l() {
449    if (mFlags & PLAYING) {
450        return OK;
451    }
452
453    if (!(mFlags & PREPARED)) {
454        status_t err = prepare_l();
455
456        if (err != OK) {
457            return err;
458        }
459    }
460
461    mFlags |= PLAYING;
462    mFlags |= FIRST_FRAME;
463
464    bool deferredAudioSeek = false;
465
466    if (mAudioSource != NULL) {
467        if (mAudioPlayer == NULL) {
468            if (mAudioSink != NULL) {
469                mAudioPlayer = new AudioPlayer(mAudioSink);
470                mAudioPlayer->setSource(mAudioSource);
471                status_t err = mAudioPlayer->start();
472
473                if (err != OK) {
474                    delete mAudioPlayer;
475                    mAudioPlayer = NULL;
476
477                    mFlags &= ~(PLAYING | FIRST_FRAME);
478
479                    return err;
480                }
481
482                delete mTimeSource;
483                mTimeSource = mAudioPlayer;
484
485                deferredAudioSeek = true;
486
487                mWatchForAudioSeekComplete = false;
488                mWatchForAudioEOS = true;
489            }
490        } else {
491            mAudioPlayer->resume();
492        }
493
494        postCheckAudioStatusEvent_l();
495    }
496
497    if (mTimeSource == NULL && mAudioPlayer == NULL) {
498        mTimeSource = new SystemTimeSource;
499    }
500
501    if (mVideoSource != NULL) {
502        // Kick off video playback
503        postVideoEvent_l();
504    }
505
506    if (deferredAudioSeek) {
507        // If there was a seek request while we were paused
508        // and we're just starting up again, honor the request now.
509        seekAudioIfNecessary_l();
510    }
511
512    postBufferingEvent_l();
513
514    return OK;
515}
516
517void AwesomePlayer::initRenderer_l() {
518    if (mISurface != NULL) {
519        sp<MetaData> meta = mVideoSource->getFormat();
520
521        int32_t format;
522        const char *component;
523        int32_t decodedWidth, decodedHeight;
524        CHECK(meta->findInt32(kKeyColorFormat, &format));
525        CHECK(meta->findCString(kKeyDecoderComponent, &component));
526        CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
527        CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
528
529        mVideoRenderer.clear();
530
531        // Must ensure that mVideoRenderer's destructor is actually executed
532        // before creating a new one.
533        IPCThreadState::self()->flushCommands();
534
535        if (!strncmp("OMX.", component, 4)) {
536            // Our OMX codecs allocate buffers on the media_server side
537            // therefore they require a remote IOMXRenderer that knows how
538            // to display them.
539            mVideoRenderer = new AwesomeRemoteRenderer(
540                mClient.interface()->createRenderer(
541                        mISurface, component,
542                        (OMX_COLOR_FORMATTYPE)format,
543                        decodedWidth, decodedHeight,
544                        mVideoWidth, mVideoHeight));
545        } else {
546            // Other decoders are instantiated locally and as a consequence
547            // allocate their buffers in local address space.
548            mVideoRenderer = new AwesomeLocalRenderer(
549                false,  // previewOnly
550                component,
551                (OMX_COLOR_FORMATTYPE)format,
552                mISurface,
553                mVideoWidth, mVideoHeight,
554                decodedWidth, decodedHeight);
555        }
556    }
557}
558
559status_t AwesomePlayer::pause() {
560    Mutex::Autolock autoLock(mLock);
561    return pause_l();
562}
563
564status_t AwesomePlayer::pause_l() {
565    if (!(mFlags & PLAYING)) {
566        return OK;
567    }
568
569    cancelPlayerEvents(true /* keepBufferingGoing */);
570
571    if (mAudioPlayer != NULL) {
572        mAudioPlayer->pause();
573    }
574
575    mFlags &= ~PLAYING;
576
577    return OK;
578}
579
580bool AwesomePlayer::isPlaying() const {
581    Mutex::Autolock autoLock(mLock);
582
583    return mFlags & PLAYING;
584}
585
586void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
587    Mutex::Autolock autoLock(mLock);
588
589    mISurface = isurface;
590}
591
592void AwesomePlayer::setAudioSink(
593        const sp<MediaPlayerBase::AudioSink> &audioSink) {
594    Mutex::Autolock autoLock(mLock);
595
596    mAudioSink = audioSink;
597}
598
599status_t AwesomePlayer::setLooping(bool shouldLoop) {
600    Mutex::Autolock autoLock(mLock);
601
602    mFlags = mFlags & ~LOOPING;
603
604    if (shouldLoop) {
605        mFlags |= LOOPING;
606    }
607
608    return OK;
609}
610
611status_t AwesomePlayer::getDuration(int64_t *durationUs) {
612    Mutex::Autolock autoLock(mLock);
613
614    if (mDurationUs < 0) {
615        return UNKNOWN_ERROR;
616    }
617
618    *durationUs = mDurationUs;
619
620    return OK;
621}
622
623status_t AwesomePlayer::getPosition(int64_t *positionUs) {
624    Mutex::Autolock autoLock(mLock);
625    return getPosition_l(positionUs);
626}
627
628status_t AwesomePlayer::getPosition_l(int64_t *positionUs) {
629    if (mVideoSource != NULL) {
630        *positionUs = mVideoTimeUs;
631    } else if (mAudioPlayer != NULL) {
632        *positionUs = mAudioPlayer->getMediaTimeUs();
633    } else {
634        *positionUs = 0;
635    }
636
637    return OK;
638}
639
640status_t AwesomePlayer::seekTo(int64_t timeUs) {
641    Mutex::Autolock autoLock(mLock);
642    return seekTo_l(timeUs);
643}
644
645status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
646    mSeeking = true;
647    mSeekTimeUs = timeUs;
648
649    seekAudioIfNecessary_l();
650
651    return OK;
652}
653
654void AwesomePlayer::seekAudioIfNecessary_l() {
655    if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
656        mAudioPlayer->seekTo(mSeekTimeUs);
657
658        mWatchForAudioSeekComplete = true;
659        mWatchForAudioEOS = true;
660        mSeeking = false;
661    }
662}
663
664status_t AwesomePlayer::getVideoDimensions(
665        int32_t *width, int32_t *height) const {
666    Mutex::Autolock autoLock(mLock);
667
668    if (mVideoWidth < 0 || mVideoHeight < 0) {
669        return UNKNOWN_ERROR;
670    }
671
672    *width = mVideoWidth;
673    *height = mVideoHeight;
674
675    return OK;
676}
677
678status_t AwesomePlayer::setAudioSource(sp<MediaSource> source) {
679    if (source == NULL) {
680        return UNKNOWN_ERROR;
681    }
682
683    if (mPrefetcher != NULL) {
684        source = mPrefetcher->addSource(source);
685    }
686
687    sp<MetaData> meta = source->getFormat();
688
689    const char *mime;
690    CHECK(meta->findCString(kKeyMIMEType, &mime));
691
692    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
693        mAudioSource = source;
694    } else {
695        mAudioSource = OMXCodec::Create(
696                mClient.interface(), source->getFormat(),
697                false, // createEncoder
698                source);
699    }
700
701    if (mAudioSource != NULL) {
702        int64_t durationUs;
703        if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) {
704            if (mDurationUs < 0 || durationUs > mDurationUs) {
705                mDurationUs = durationUs;
706            }
707        }
708    }
709
710    return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
711}
712
713status_t AwesomePlayer::setVideoSource(sp<MediaSource> source) {
714    if (source == NULL) {
715        return UNKNOWN_ERROR;
716    }
717
718    if (mPrefetcher != NULL) {
719        source = mPrefetcher->addSource(source);
720    }
721
722    mVideoSource = OMXCodec::Create(
723            mClient.interface(), source->getFormat(),
724            false, // createEncoder
725            source);
726
727    if (mVideoSource != NULL) {
728        int64_t durationUs;
729        if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) {
730            if (mDurationUs < 0 || durationUs > mDurationUs) {
731                mDurationUs = durationUs;
732            }
733        }
734
735        CHECK(source->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
736        CHECK(source->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
737
738        mVideoSource->start();
739    }
740
741    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
742}
743
744void AwesomePlayer::onVideoEvent() {
745    Mutex::Autolock autoLock(mLock);
746    if (!mVideoEventPending) {
747        // The event has been cancelled in reset_l() but had already
748        // been scheduled for execution at that time.
749        return;
750    }
751    mVideoEventPending = false;
752
753    if (mSeeking) {
754        if (mLastVideoBuffer) {
755            mLastVideoBuffer->release();
756            mLastVideoBuffer = NULL;
757        }
758
759        if (mVideoBuffer) {
760            mVideoBuffer->release();
761            mVideoBuffer = NULL;
762        }
763    }
764
765    if (!mVideoBuffer) {
766        MediaSource::ReadOptions options;
767        if (mSeeking) {
768            LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
769
770            options.setSeekTo(mSeekTimeUs);
771        }
772        for (;;) {
773            status_t err = mVideoSource->read(&mVideoBuffer, &options);
774            options.clearSeekTo();
775
776            if (err != OK) {
777                CHECK_EQ(mVideoBuffer, NULL);
778
779                if (err == INFO_FORMAT_CHANGED) {
780                    LOGV("VideoSource signalled format change.");
781
782                    if (mVideoRenderer != NULL) {
783                        mVideoRendererIsPreview = false;
784                        initRenderer_l();
785                    }
786                    continue;
787                }
788
789                postStreamDoneEvent_l();
790                return;
791            }
792
793            if (mVideoBuffer->range_length() == 0) {
794                // Some decoders, notably the PV AVC software decoder
795                // return spurious empty buffers that we just want to ignore.
796
797                mVideoBuffer->release();
798                mVideoBuffer = NULL;
799                continue;
800            }
801
802            break;
803        }
804    }
805
806    int64_t timeUs;
807    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
808
809    mVideoTimeUs = timeUs;
810
811    if (mSeeking) {
812        if (mAudioPlayer != NULL) {
813            LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
814
815            mAudioPlayer->seekTo(timeUs);
816            mWatchForAudioSeekComplete = true;
817            mWatchForAudioEOS = true;
818        } else {
819            // If we're playing video only, report seek complete now,
820            // otherwise audio player will notify us later.
821            notifyListener_l(MEDIA_SEEK_COMPLETE);
822        }
823
824        mFlags |= FIRST_FRAME;
825        mSeeking = false;
826    }
827
828    if (mFlags & FIRST_FRAME) {
829        mFlags &= ~FIRST_FRAME;
830
831        mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
832    }
833
834    int64_t realTimeUs, mediaTimeUs;
835    if (mAudioPlayer != NULL
836        && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
837        mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
838    }
839
840    int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
841
842    int64_t latenessUs = nowUs - timeUs;
843
844    if (latenessUs > 40000) {
845        // We're more than 40ms late.
846        LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
847
848        mVideoBuffer->release();
849        mVideoBuffer = NULL;
850
851        postVideoEvent_l();
852        return;
853    }
854
855    if (latenessUs < -10000) {
856        // We're more than 10ms early.
857
858        postVideoEvent_l(10000);
859        return;
860    }
861
862    if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
863        mVideoRendererIsPreview = false;
864
865        initRenderer_l();
866    }
867
868    if (mVideoRenderer != NULL) {
869        mVideoRenderer->render(mVideoBuffer);
870    }
871
872    if (mLastVideoBuffer) {
873        mLastVideoBuffer->release();
874        mLastVideoBuffer = NULL;
875    }
876    mLastVideoBuffer = mVideoBuffer;
877    mVideoBuffer = NULL;
878
879    postVideoEvent_l();
880}
881
882void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
883    if (mVideoEventPending) {
884        return;
885    }
886
887    mVideoEventPending = true;
888    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
889}
890
891void AwesomePlayer::postStreamDoneEvent_l() {
892    if (mStreamDoneEventPending) {
893        return;
894    }
895    mStreamDoneEventPending = true;
896    mQueue.postEvent(mStreamDoneEvent);
897}
898
899void AwesomePlayer::postBufferingEvent_l() {
900    if (mPrefetcher == NULL) {
901        return;
902    }
903
904    if (mBufferingEventPending) {
905        return;
906    }
907    mBufferingEventPending = true;
908    mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
909}
910
911void AwesomePlayer::postCheckAudioStatusEvent_l() {
912    if (mAudioStatusEventPending) {
913        return;
914    }
915    mAudioStatusEventPending = true;
916    mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
917}
918
919void AwesomePlayer::onCheckAudioStatus() {
920    Mutex::Autolock autoLock(mLock);
921    mAudioStatusEventPending = false;
922
923    if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
924        mWatchForAudioSeekComplete = false;
925        notifyListener_l(MEDIA_SEEK_COMPLETE);
926    }
927
928    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS()) {
929        mWatchForAudioEOS = false;
930        postStreamDoneEvent_l();
931    }
932
933    postCheckAudioStatusEvent_l();
934}
935
936status_t AwesomePlayer::prepare() {
937    Mutex::Autolock autoLock(mLock);
938    return prepare_l();
939}
940
941status_t AwesomePlayer::prepare_l() {
942    if (mFlags & PREPARED) {
943        return OK;
944    }
945
946    if (mFlags & PREPARING) {
947        return UNKNOWN_ERROR;
948    }
949
950    mIsAsyncPrepare = false;
951    status_t err = prepareAsync_l();
952
953    if (err != OK) {
954        return err;
955    }
956
957    while (mFlags & PREPARING) {
958        mPreparedCondition.wait(mLock);
959    }
960
961    return mPrepareResult;
962}
963
964status_t AwesomePlayer::prepareAsync() {
965    Mutex::Autolock autoLock(mLock);
966
967    if (mFlags & PREPARING) {
968        return UNKNOWN_ERROR;  // async prepare already pending
969    }
970
971    mIsAsyncPrepare = true;
972    return prepareAsync_l();
973}
974
975status_t AwesomePlayer::prepareAsync_l() {
976    if (mFlags & PREPARING) {
977        return UNKNOWN_ERROR;  // async prepare already pending
978    }
979
980    mFlags |= PREPARING;
981    mAsyncPrepareEvent = new AwesomeEvent(
982            this, &AwesomePlayer::onPrepareAsyncEvent);
983
984    mQueue.postEvent(mAsyncPrepareEvent);
985
986    return OK;
987}
988
989status_t AwesomePlayer::finishSetDataSource_l() {
990    sp<DataSource> dataSource =
991        DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
992
993    if (dataSource == NULL) {
994        return UNKNOWN_ERROR;
995    }
996
997    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
998
999    if (extractor == NULL) {
1000        return UNKNOWN_ERROR;
1001    }
1002
1003    if (dataSource->flags() & DataSource::kWantsPrefetching) {
1004        mPrefetcher = new Prefetcher;
1005    }
1006
1007    return setDataSource_l(extractor);
1008}
1009
1010void AwesomePlayer::onPrepareAsyncEvent() {
1011    {
1012        Mutex::Autolock autoLock(mLock);
1013
1014        if (mUri.size() > 0) {
1015            status_t err = finishSetDataSource_l();
1016
1017            if (err != OK) {
1018                if (mIsAsyncPrepare) {
1019                    notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1020                }
1021
1022                mPrepareResult = err;
1023                mFlags &= ~PREPARING;
1024                mAsyncPrepareEvent = NULL;
1025                mPreparedCondition.broadcast();
1026
1027                return;
1028            }
1029        }
1030    }
1031
1032    sp<Prefetcher> prefetcher;
1033
1034    {
1035        Mutex::Autolock autoLock(mLock);
1036        prefetcher = mPrefetcher;
1037    }
1038
1039    if (prefetcher != NULL) {
1040        prefetcher->prepare();
1041        prefetcher.clear();
1042    }
1043
1044    Mutex::Autolock autoLock(mLock);
1045
1046    if (mIsAsyncPrepare) {
1047        if (mVideoWidth < 0 || mVideoHeight < 0) {
1048            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1049        } else {
1050            notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
1051        }
1052
1053        notifyListener_l(MEDIA_PREPARED);
1054    }
1055
1056    mPrepareResult = OK;
1057    mFlags &= ~PREPARING;
1058    mFlags |= PREPARED;
1059    mAsyncPrepareEvent = NULL;
1060    mPreparedCondition.broadcast();
1061}
1062
1063status_t AwesomePlayer::suspend() {
1064    LOGI("suspend");
1065    Mutex::Autolock autoLock(mLock);
1066
1067    if (mSuspensionState != NULL) {
1068        return INVALID_OPERATION;
1069    }
1070
1071    while (mFlags & PREPARING) {
1072        mPreparedCondition.wait(mLock);
1073    }
1074
1075    SuspensionState *state = new SuspensionState;
1076    state->mUri = mUri;
1077    state->mUriHeaders = mUriHeaders;
1078    state->mFileSource = mFileSource;
1079
1080    state->mFlags = mFlags & (PLAYING | LOOPING);
1081    getPosition_l(&state->mPositionUs);
1082
1083    if (mLastVideoBuffer) {
1084        size_t size = mLastVideoBuffer->range_length();
1085        if (size) {
1086            state->mLastVideoFrameSize = size;
1087            state->mLastVideoFrame = malloc(size);
1088            memcpy(state->mLastVideoFrame,
1089                   (const uint8_t *)mLastVideoBuffer->data()
1090                        + mLastVideoBuffer->range_offset(),
1091                   size);
1092
1093            state->mVideoWidth = mVideoWidth;
1094            state->mVideoHeight = mVideoHeight;
1095
1096            sp<MetaData> meta = mVideoSource->getFormat();
1097            CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1098            CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1099            CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1100        }
1101    }
1102
1103    reset_l();
1104
1105    mSuspensionState = state;
1106
1107    return OK;
1108}
1109
1110status_t AwesomePlayer::resume() {
1111    LOGI("resume");
1112    Mutex::Autolock autoLock(mLock);
1113
1114    if (mSuspensionState == NULL) {
1115        return INVALID_OPERATION;
1116    }
1117
1118    SuspensionState *state = mSuspensionState;
1119    mSuspensionState = NULL;
1120
1121    status_t err;
1122    if (state->mFileSource != NULL) {
1123        err = setDataSource_l(state->mFileSource);
1124
1125        if (err == OK) {
1126            mFileSource = state->mFileSource;
1127        }
1128    } else {
1129        err = setDataSource_l(state->mUri, &state->mUriHeaders);
1130    }
1131
1132    if (err != OK) {
1133        delete state;
1134        state = NULL;
1135
1136        return err;
1137    }
1138
1139    seekTo_l(state->mPositionUs);
1140
1141    mFlags = state->mFlags & LOOPING;
1142
1143    if (state->mLastVideoFrame && mISurface != NULL) {
1144        mVideoRenderer =
1145            new AwesomeLocalRenderer(
1146                    true,  // previewOnly
1147                    "",
1148                    (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1149                    mISurface,
1150                    state->mVideoWidth,
1151                    state->mVideoHeight,
1152                    state->mDecodedWidth,
1153                    state->mDecodedHeight);
1154
1155        mVideoRendererIsPreview = true;
1156
1157        ((AwesomeLocalRenderer *)mVideoRenderer.get())->render(
1158                state->mLastVideoFrame, state->mLastVideoFrameSize);
1159    }
1160
1161    if (state->mFlags & PLAYING) {
1162        play_l();
1163    }
1164
1165    delete state;
1166    state = NULL;
1167
1168    return OK;
1169}
1170
1171}  // namespace android
1172
1173