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