AwesomePlayer.cpp revision 85704836f33a199d7e442a23db82abbd5620d35d
10f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang/*
20f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * Copyright (C) 2009 The Android Open Source Project
30f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang *
40f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License");
50f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * you may not use this file except in compliance with the License.
60f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * You may obtain a copy of the License at
70f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang *
80f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang *      http://www.apache.org/licenses/LICENSE-2.0
90f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang *
100f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * Unless required by applicable law or agreed to in writing, software
110f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS,
120f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * See the License for the specific language governing permissions and
140f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * limitations under the License.
150f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang */
160f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
170f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang//#define LOG_NDEBUG 0
180f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#define LOG_TAG "AwesomePlayer"
190f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include <utils/Log.h>
200f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
210f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include <dlfcn.h>
220f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
230f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include "include/ARTSPController.h"
240f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include "include/AwesomePlayer.h"
250f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include "include/SoftwareRenderer.h"
260f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include "include/NuCachedSource2.h"
27c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "include/ThrottledSource.h"
28ef73a242762bcd8113b9b65ceccbe7d909b5acbcZonr Chang#include "include/MPEG2TSExtractor.h"
290f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
300f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include "ARTPSession.h"
310f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include "APacketSource.h"
320f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include "ASessionDescription.h"
330f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include "UDPPusher.h"
340f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
350f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include <binder/IPCThreadState.h>
36e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang#include <media/stagefright/foundation/hexdump.h>
37e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang#include <media/stagefright/foundation/ADebug.h>
38e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang#include <media/stagefright/AudioPlayer.h>
390f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include <media/stagefright/DataSource.h>
40e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang#include <media/stagefright/FileSource.h>
410f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include <media/stagefright/MediaBuffer.h>
420f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include <media/stagefright/MediaDefs.h>
430f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include <media/stagefright/MediaExtractor.h>
440f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include <media/stagefright/MediaSource.h>
450f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include <media/stagefright/MetaData.h>
460f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include <media/stagefright/OMXCodec.h>
47e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang
48e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang#include <surfaceflinger/Surface.h>
49c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray
50e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang#include <media/stagefright/foundation/ALooper.h>
51e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang#include <media/stagefright/foundation/AMessage.h>
52e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang#include "include/LiveSession.h"
53e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang
540f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#define USE_SURFACE_ALLOC 1
550f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
560f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Changnamespace android {
570f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
580f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Changstatic int64_t kLowWaterMarkUs = 2000000ll;  // 2secs
590f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Changstatic int64_t kHighWaterMarkUs = 10000000ll;  // 10secs
600f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
610f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Changstruct AwesomeEvent : public TimedEventQueue::Event {
620f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    AwesomeEvent(
630f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang            AwesomePlayer *player,
640f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang            void (AwesomePlayer::*method)())
650f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang        : mPlayer(player),
660f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang          mMethod(method) {
670f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    }
680f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
690f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Changprotected:
700f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    virtual ~AwesomeEvent() {}
710f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
720f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
730f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang        (mPlayer->*mMethod)();
740f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    }
750f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
76e524a6fede773ad8ea7d4a3ca11976585002387aWeiTangprivate:
77e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang    AwesomePlayer *mPlayer;
78e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang    void (AwesomePlayer::*mMethod)();
79e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang
800f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    AwesomeEvent(const AwesomeEvent &);
81e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang    AwesomeEvent &operator=(const AwesomeEvent &);
82e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang};
830f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
840f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Changstruct AwesomeLocalRenderer : public AwesomeRenderer {
85e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang    AwesomeLocalRenderer(
86e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang            const sp<Surface> &surface, const sp<MetaData> &meta)
87e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang        : mTarget(new SoftwareRenderer(surface, meta)) {
88e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang    }
890f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
900f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    virtual void render(MediaBuffer *buffer) {
91e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang        render((const uint8_t *)buffer->data() + buffer->range_offset(),
920f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang               buffer->range_length());
930f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    }
940f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
950f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    void render(const void *data, size_t size) {
960f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang        mTarget->render(data, size, NULL);
97e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang    }
98e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang
99e524a6fede773ad8ea7d4a3ca11976585002387aWeiTangprotected:
100e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang    virtual ~AwesomeLocalRenderer() {
101e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang        delete mTarget;
1020f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang        mTarget = NULL;
1030f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    }
1040f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
105e524a6fede773ad8ea7d4a3ca11976585002387aWeiTangprivate:
1060f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    SoftwareRenderer *mTarget;
1070f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
1080f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    AwesomeLocalRenderer(const AwesomeLocalRenderer &);
109e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang    AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
110e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang};
111e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang
112e524a6fede773ad8ea7d4a3ca11976585002387aWeiTangstruct AwesomeNativeWindowRenderer : public AwesomeRenderer {
113e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang    AwesomeNativeWindowRenderer(
1140f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang            const sp<ANativeWindow> &nativeWindow,
1150f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang            int32_t rotationDegrees)
1160f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang        : mNativeWindow(nativeWindow) {
117e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang        applyRotation(rotationDegrees);
1180f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    }
1190f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
1200f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    virtual void render(MediaBuffer *buffer) {
121e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang        status_t err = mNativeWindow->queueBuffer(
122e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang                mNativeWindow.get(), buffer->graphicBuffer().get());
123e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang        if (err != 0) {
124e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang            LOGE("queueBuffer failed with error %s (%d)", strerror(-err),
1250f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang                    -err);
1260f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang            return;
127e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang        }
1280f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
129be07e239b10f91169f795cbe602552792d4d0415Ian Rogers        sp<MetaData> metaData = buffer->meta_data();
130e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang        metaData->setInt32(kKeyRendered, 1);
131e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang    }
132e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang
133e524a6fede773ad8ea7d4a3ca11976585002387aWeiTangprotected:
134be07e239b10f91169f795cbe602552792d4d0415Ian Rogers    virtual ~AwesomeNativeWindowRenderer() {}
135be07e239b10f91169f795cbe602552792d4d0415Ian Rogers
136e524a6fede773ad8ea7d4a3ca11976585002387aWeiTangprivate:
1370f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    sp<ANativeWindow> mNativeWindow;
1380f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
1390f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    void applyRotation(int32_t rotationDegrees) {
1400f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang        uint32_t transform;
1410f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang        switch (rotationDegrees) {
1420f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang            case 0: transform = 0; break;
1430f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang            case 90: transform = HAL_TRANSFORM_ROT_90; break;
1440f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang            case 180: transform = HAL_TRANSFORM_ROT_180; break;
1450f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang            case 270: transform = HAL_TRANSFORM_ROT_270; break;
1460f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang            default: transform = 0; break;
1470f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang        }
1480f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
149e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang        if (transform) {
150e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang            CHECK_EQ(0, native_window_set_buffers_transform(
151e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang                        mNativeWindow.get(), transform));
1529795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao        }
153e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang    }
1540f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
1550f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &);
1560f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    AwesomeNativeWindowRenderer &operator=(
1570f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang            const AwesomeNativeWindowRenderer &);
1580f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang};
1590f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
1600f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang////////////////////////////////////////////////////////////////////////////////
1610f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
1620f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr ChangAwesomePlayer::AwesomePlayer()
1639795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    : mQueueStarted(false),
1649795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao      mTimeSource(NULL),
1659795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao      mVideoRendererIsPreview(false),
1669795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao      mAudioPlayer(NULL),
1679795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao      mFlags(0),
168e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang      mExtractorFlags(0),
169e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang      mVideoBuffer(NULL),
170e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang      mDecryptHandle(NULL) {
1719795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    CHECK_EQ(mClient.connect(), (status_t)OK);
172e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang
1739795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    DataSource::RegisterDefaultSniffers();
1749795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1759795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
1769795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    mVideoEventPending = false;
1779795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
1789795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    mStreamDoneEventPending = false;
1799795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
1809795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    mBufferingEventPending = false;
1819795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1829795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    mCheckAudioStatusEvent = new AwesomeEvent(
1839795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao            this, &AwesomePlayer::onCheckAudioStatus);
1849795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1859795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    mAudioStatusEventPending = false;
1869795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1879795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    reset();
1889795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao}
1899795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1909795754a34648d962f00ced51183b759b9eaf2b2Shih-wei LiaoAwesomePlayer::~AwesomePlayer() {
1919795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    if (mQueueStarted) {
1929795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao        mQueue.stop();
1939795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    }
1949795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1959795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    reset();
1969795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1979795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    mClient.disconnect();
1989795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao}
1999795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
2009795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liaovoid AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
2019795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    mQueue.cancelEvent(mVideoEvent->eventID());
2029795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    mVideoEventPending = false;
2039795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    mQueue.cancelEvent(mStreamDoneEvent->eventID());
2049795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    mStreamDoneEventPending = false;
2059795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
206e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang    mAudioStatusEventPending = false;
207e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang
208e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang    if (!keepBufferingGoing) {
2099795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao        mQueue.cancelEvent(mBufferingEvent->eventID());
210e524a6fede773ad8ea7d4a3ca11976585002387aWeiTang        mBufferingEventPending = false;
2119795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    }
2129795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao}
2139795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
2149795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liaovoid AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
2159795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    Mutex::Autolock autoLock(mLock);
2169795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    mListener = listener;
2179795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao}
2189795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
2199795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liaostatus_t AwesomePlayer::setDataSource(
2209795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao        const char *uri, const KeyedVector<String8, String8> *headers) {
2219795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    Mutex::Autolock autoLock(mLock);
2229795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    return setDataSource_l(uri, headers);
2239795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao}
2249795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
2259795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liaostatus_t AwesomePlayer::setDataSource_l(
2269795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao        const char *uri, const KeyedVector<String8, String8> *headers) {
2270f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    reset_l();
2280f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
2290f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    mUri = uri;
2300f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
231    if (!strncmp("http://", uri, 7)) {
232        // Hack to support http live.
233
234        size_t len = strlen(uri);
235        if (!strcasecmp(&uri[len - 5], ".m3u8")
236                || strstr(&uri[7], "m3u8") != NULL) {
237            mUri = "httplive://";
238            mUri.append(&uri[7]);
239        }
240    }
241
242    if (headers) {
243        mUriHeaders = *headers;
244    }
245
246    // The actual work will be done during preparation in the call to
247    // ::finishSetDataSource_l to avoid blocking the calling thread in
248    // setDataSource for any significant time.
249
250    return OK;
251}
252
253status_t AwesomePlayer::setDataSource(
254        int fd, int64_t offset, int64_t length) {
255    Mutex::Autolock autoLock(mLock);
256
257    reset_l();
258
259    sp<DataSource> dataSource = new FileSource(fd, offset, length);
260
261    status_t err = dataSource->initCheck();
262
263    if (err != OK) {
264        return err;
265    }
266
267    mFileSource = dataSource;
268
269    return setDataSource_l(dataSource);
270}
271
272status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) {
273    return INVALID_OPERATION;
274}
275
276status_t AwesomePlayer::setDataSource_l(
277        const sp<DataSource> &dataSource) {
278    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
279
280    if (extractor == NULL) {
281        return UNKNOWN_ERROR;
282    }
283
284    dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
285    if (mDecryptHandle != NULL
286            && RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
287        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
288    }
289
290    return setDataSource_l(extractor);
291}
292
293status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
294    // Attempt to approximate overall stream bitrate by summing all
295    // tracks' individual bitrates, if not all of them advertise bitrate,
296    // we have to fail.
297
298    int64_t totalBitRate = 0;
299
300    for (size_t i = 0; i < extractor->countTracks(); ++i) {
301        sp<MetaData> meta = extractor->getTrackMetaData(i);
302
303        int32_t bitrate;
304        if (!meta->findInt32(kKeyBitRate, &bitrate)) {
305            totalBitRate = -1;
306            break;
307        }
308
309        totalBitRate += bitrate;
310    }
311
312    mBitrate = totalBitRate;
313
314    LOGV("mBitrate = %lld bits/sec", mBitrate);
315
316    bool haveAudio = false;
317    bool haveVideo = false;
318    for (size_t i = 0; i < extractor->countTracks(); ++i) {
319        sp<MetaData> meta = extractor->getTrackMetaData(i);
320
321        const char *mime;
322        CHECK(meta->findCString(kKeyMIMEType, &mime));
323
324        if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
325            setVideoSource(extractor->getTrack(i));
326            haveVideo = true;
327        } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
328            setAudioSource(extractor->getTrack(i));
329            haveAudio = true;
330
331            if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
332                // Only do this for vorbis audio, none of the other audio
333                // formats even support this ringtone specific hack and
334                // retrieving the metadata on some extractors may turn out
335                // to be very expensive.
336                sp<MetaData> fileMeta = extractor->getMetaData();
337                int32_t loop;
338                if (fileMeta != NULL
339                        && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
340                    mFlags |= AUTO_LOOPING;
341                }
342            }
343        }
344
345        if (haveAudio && haveVideo) {
346            break;
347        }
348    }
349
350    if (!haveAudio && !haveVideo) {
351        return UNKNOWN_ERROR;
352    }
353
354    mExtractorFlags = extractor->flags();
355
356    return OK;
357}
358
359void AwesomePlayer::reset() {
360    Mutex::Autolock autoLock(mLock);
361    reset_l();
362}
363
364void AwesomePlayer::reset_l() {
365    if (mDecryptHandle != NULL) {
366            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
367                    Playback::STOP, 0);
368            mDrmManagerClient->closeDecryptSession(mDecryptHandle);
369            mDecryptHandle = NULL;
370            mDrmManagerClient = NULL;
371    }
372
373    if (mFlags & PREPARING) {
374        mFlags |= PREPARE_CANCELLED;
375        if (mConnectingDataSource != NULL) {
376            LOGI("interrupting the connection process");
377            mConnectingDataSource->disconnect();
378        }
379
380        if (mFlags & PREPARING_CONNECTED) {
381            // We are basically done preparing, we're just buffering
382            // enough data to start playback, we can safely interrupt that.
383            finishAsyncPrepare_l();
384        }
385    }
386
387    while (mFlags & PREPARING) {
388        mPreparedCondition.wait(mLock);
389    }
390
391    cancelPlayerEvents();
392
393    mCachedSource.clear();
394    mAudioTrack.clear();
395    mVideoTrack.clear();
396
397    // Shutdown audio first, so that the respone to the reset request
398    // appears to happen instantaneously as far as the user is concerned
399    // If we did this later, audio would continue playing while we
400    // shutdown the video-related resources and the player appear to
401    // not be as responsive to a reset request.
402    if (mAudioPlayer == NULL && mAudioSource != NULL) {
403        // If we had an audio player, it would have effectively
404        // taken possession of the audio source and stopped it when
405        // _it_ is stopped. Otherwise this is still our responsibility.
406        mAudioSource->stop();
407    }
408    mAudioSource.clear();
409
410    mTimeSource = NULL;
411
412    delete mAudioPlayer;
413    mAudioPlayer = NULL;
414
415    mVideoRenderer.clear();
416
417    if (mVideoBuffer) {
418        mVideoBuffer->release();
419        mVideoBuffer = NULL;
420    }
421
422    if (mRTSPController != NULL) {
423        mRTSPController->disconnect();
424        mRTSPController.clear();
425    }
426
427    if (mLiveSession != NULL) {
428        mLiveSession->disconnect();
429        mLiveSession.clear();
430    }
431
432    mRTPPusher.clear();
433    mRTCPPusher.clear();
434    mRTPSession.clear();
435
436    if (mVideoSource != NULL) {
437        mVideoSource->stop();
438
439        // The following hack is necessary to ensure that the OMX
440        // component is completely released by the time we may try
441        // to instantiate it again.
442        wp<MediaSource> tmp = mVideoSource;
443        mVideoSource.clear();
444        while (tmp.promote() != NULL) {
445            usleep(1000);
446        }
447        IPCThreadState::self()->flushCommands();
448    }
449
450    mDurationUs = -1;
451    mFlags = 0;
452    mExtractorFlags = 0;
453    mTimeSourceDeltaUs = 0;
454    mVideoTimeUs = 0;
455
456    mSeeking = false;
457    mSeekNotificationSent = false;
458    mSeekTimeUs = 0;
459
460    mUri.setTo("");
461    mUriHeaders.clear();
462
463    mFileSource.clear();
464
465    mBitrate = -1;
466}
467
468void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
469    if (mListener != NULL) {
470        sp<MediaPlayerBase> listener = mListener.promote();
471
472        if (listener != NULL) {
473            listener->sendEvent(msg, ext1, ext2);
474        }
475    }
476}
477
478bool AwesomePlayer::getBitrate(int64_t *bitrate) {
479    off64_t size;
480    if (mDurationUs >= 0 && mCachedSource != NULL
481            && mCachedSource->getSize(&size) == OK) {
482        *bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
483        return true;
484    }
485
486    if (mBitrate >= 0) {
487        *bitrate = mBitrate;
488        return true;
489    }
490
491    *bitrate = 0;
492
493    return false;
494}
495
496// Returns true iff cached duration is available/applicable.
497bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
498    int64_t bitrate;
499
500    if (mRTSPController != NULL) {
501        *durationUs = mRTSPController->getQueueDurationUs(eos);
502        return true;
503    } else if (mCachedSource != NULL && getBitrate(&bitrate)) {
504        size_t cachedDataRemaining = mCachedSource->approxDataRemaining(eos);
505        *durationUs = cachedDataRemaining * 8000000ll / bitrate;
506        return true;
507    }
508
509    return false;
510}
511
512void AwesomePlayer::ensureCacheIsFetching_l() {
513    if (mCachedSource != NULL) {
514        mCachedSource->resumeFetchingIfNecessary();
515    }
516}
517
518void AwesomePlayer::onBufferingUpdate() {
519    Mutex::Autolock autoLock(mLock);
520    if (!mBufferingEventPending) {
521        return;
522    }
523    mBufferingEventPending = false;
524
525    if (mCachedSource != NULL) {
526        bool eos;
527        size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos);
528
529        if (eos) {
530            notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
531            if (mFlags & PREPARING) {
532                LOGV("cache has reached EOS, prepare is done.");
533                finishAsyncPrepare_l();
534            }
535        } else {
536            int64_t bitrate;
537            if (getBitrate(&bitrate)) {
538                size_t cachedSize = mCachedSource->cachedSize();
539                int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
540
541                int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
542                if (percentage > 100) {
543                    percentage = 100;
544                }
545
546                notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
547            } else {
548                // We don't know the bitrate of the stream, use absolute size
549                // limits to maintain the cache.
550
551                const size_t kLowWaterMarkBytes = 40000;
552                const size_t kHighWaterMarkBytes = 200000;
553
554                if ((mFlags & PLAYING) && !eos
555                        && (cachedDataRemaining < kLowWaterMarkBytes)) {
556                    LOGI("cache is running low (< %d) , pausing.",
557                         kLowWaterMarkBytes);
558                    mFlags |= CACHE_UNDERRUN;
559                    pause_l();
560                    ensureCacheIsFetching_l();
561                    notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
562                } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
563                    if (mFlags & CACHE_UNDERRUN) {
564                        LOGI("cache has filled up (> %d), resuming.",
565                             kHighWaterMarkBytes);
566                        mFlags &= ~CACHE_UNDERRUN;
567                        play_l();
568                        notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
569                    } else if (mFlags & PREPARING) {
570                        LOGV("cache has filled up (> %d), prepare is done",
571                             kHighWaterMarkBytes);
572                        finishAsyncPrepare_l();
573                    }
574                }
575            }
576        }
577    }
578
579    int64_t cachedDurationUs;
580    bool eos;
581    if (getCachedDuration_l(&cachedDurationUs, &eos)) {
582        LOGV("cachedDurationUs = %.2f secs, eos=%d",
583             cachedDurationUs / 1E6, eos);
584
585        if ((mFlags & PLAYING) && !eos
586                && (cachedDurationUs < kLowWaterMarkUs)) {
587            LOGI("cache is running low (%.2f secs) , pausing.",
588                 cachedDurationUs / 1E6);
589            mFlags |= CACHE_UNDERRUN;
590            pause_l();
591            ensureCacheIsFetching_l();
592            notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
593        } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
594            if (mFlags & CACHE_UNDERRUN) {
595                LOGI("cache has filled up (%.2f secs), resuming.",
596                     cachedDurationUs / 1E6);
597                mFlags &= ~CACHE_UNDERRUN;
598                play_l();
599                notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
600            } else if (mFlags & PREPARING) {
601                LOGV("cache has filled up (%.2f secs), prepare is done",
602                     cachedDurationUs / 1E6);
603                finishAsyncPrepare_l();
604            }
605        }
606    }
607
608    postBufferingEvent_l();
609}
610
611void AwesomePlayer::partial_reset_l() {
612    // Only reset the video renderer and shut down the video decoder.
613    // Then instantiate a new video decoder and resume video playback.
614
615    mVideoRenderer.clear();
616
617    if (mVideoBuffer) {
618        mVideoBuffer->release();
619        mVideoBuffer = NULL;
620    }
621
622    {
623        mVideoSource->stop();
624
625        // The following hack is necessary to ensure that the OMX
626        // component is completely released by the time we may try
627        // to instantiate it again.
628        wp<MediaSource> tmp = mVideoSource;
629        mVideoSource.clear();
630        while (tmp.promote() != NULL) {
631            usleep(1000);
632        }
633        IPCThreadState::self()->flushCommands();
634    }
635
636    CHECK_EQ((status_t)OK,
637             initVideoDecoder(OMXCodec::kIgnoreCodecSpecificData));
638}
639
640void AwesomePlayer::onStreamDone() {
641    // Posted whenever any stream finishes playing.
642
643    Mutex::Autolock autoLock(mLock);
644    if (!mStreamDoneEventPending) {
645        return;
646    }
647    mStreamDoneEventPending = false;
648
649    if (mStreamDoneStatus == INFO_DISCONTINUITY) {
650        // This special status is returned because an http live stream's
651        // video stream switched to a different bandwidth at this point
652        // and future data may have been encoded using different parameters.
653        // This requires us to shutdown the video decoder and reinstantiate
654        // a fresh one.
655
656        LOGV("INFO_DISCONTINUITY");
657
658        CHECK(mVideoSource != NULL);
659
660        partial_reset_l();
661        postVideoEvent_l();
662        return;
663    } else if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
664        LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
665
666        notifyListener_l(
667                MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
668
669        pause_l(true /* at eos */);
670
671        mFlags |= AT_EOS;
672        return;
673    }
674
675    const bool allDone =
676        (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
677            && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
678
679    if (!allDone) {
680        return;
681    }
682
683    if (mFlags & (LOOPING | AUTO_LOOPING)) {
684        seekTo_l(0);
685
686        if (mVideoSource != NULL) {
687            postVideoEvent_l();
688        }
689    } else {
690        LOGV("MEDIA_PLAYBACK_COMPLETE");
691        notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
692
693        pause_l(true /* at eos */);
694
695        mFlags |= AT_EOS;
696    }
697}
698
699status_t AwesomePlayer::play() {
700    Mutex::Autolock autoLock(mLock);
701
702    mFlags &= ~CACHE_UNDERRUN;
703
704    return play_l();
705}
706
707status_t AwesomePlayer::play_l() {
708    if (mFlags & PLAYING) {
709        return OK;
710    }
711
712    if (!(mFlags & PREPARED)) {
713        status_t err = prepare_l();
714
715        if (err != OK) {
716            return err;
717        }
718    }
719
720    mFlags |= PLAYING;
721    mFlags |= FIRST_FRAME;
722
723    bool deferredAudioSeek = false;
724
725    if (mDecryptHandle != NULL) {
726        int64_t position;
727        getPosition(&position);
728        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
729                Playback::START, position / 1000);
730    }
731
732    if (mAudioSource != NULL) {
733        if (mAudioPlayer == NULL) {
734            if (mAudioSink != NULL) {
735                mAudioPlayer = new AudioPlayer(mAudioSink, this);
736                mAudioPlayer->setSource(mAudioSource);
737
738                // We've already started the MediaSource in order to enable
739                // the prefetcher to read its data.
740                status_t err = mAudioPlayer->start(
741                        true /* sourceAlreadyStarted */);
742
743                if (err != OK) {
744                    delete mAudioPlayer;
745                    mAudioPlayer = NULL;
746
747                    mFlags &= ~(PLAYING | FIRST_FRAME);
748
749                    if (mDecryptHandle != NULL) {
750                        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
751                                 Playback::STOP, 0);
752                    }
753
754                    return err;
755                }
756
757                mTimeSource = mAudioPlayer;
758
759                deferredAudioSeek = true;
760
761                mWatchForAudioSeekComplete = false;
762                mWatchForAudioEOS = true;
763            }
764        } else {
765            mAudioPlayer->resume();
766        }
767    }
768
769    if (mTimeSource == NULL && mAudioPlayer == NULL) {
770        mTimeSource = &mSystemTimeSource;
771    }
772
773    if (mVideoSource != NULL) {
774        // Kick off video playback
775        postVideoEvent_l();
776    }
777
778    if (deferredAudioSeek) {
779        // If there was a seek request while we were paused
780        // and we're just starting up again, honor the request now.
781        seekAudioIfNecessary_l();
782    }
783
784    if (mFlags & AT_EOS) {
785        // Legacy behaviour, if a stream finishes playing and then
786        // is started again, we play from the start...
787        seekTo_l(0);
788    }
789
790    return OK;
791}
792
793void AwesomePlayer::notifyVideoSize_l() {
794    sp<MetaData> meta = mVideoSource->getFormat();
795
796    int32_t cropLeft, cropTop, cropRight, cropBottom;
797    if (!meta->findRect(
798                kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
799        int32_t width, height;
800        CHECK(meta->findInt32(kKeyWidth, &width));
801        CHECK(meta->findInt32(kKeyHeight, &height));
802
803        cropLeft = cropTop = 0;
804        cropRight = width - 1;
805        cropBottom = height - 1;
806
807        LOGV("got dimensions only %d x %d", width, height);
808    } else {
809        LOGV("got crop rect %d, %d, %d, %d",
810             cropLeft, cropTop, cropRight, cropBottom);
811    }
812
813    int32_t usableWidth = cropRight - cropLeft + 1;
814    int32_t usableHeight = cropBottom - cropTop + 1;
815
816    int32_t rotationDegrees;
817    if (!mVideoTrack->getFormat()->findInt32(
818                kKeyRotation, &rotationDegrees)) {
819        rotationDegrees = 0;
820    }
821
822    if (rotationDegrees == 90 || rotationDegrees == 270) {
823        notifyListener_l(
824                MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
825    } else {
826        notifyListener_l(
827                MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
828    }
829}
830
831void AwesomePlayer::initRenderer_l() {
832    if (mSurface == NULL) {
833        return;
834    }
835
836    sp<MetaData> meta = mVideoSource->getFormat();
837
838    int32_t format;
839    const char *component;
840    int32_t decodedWidth, decodedHeight;
841    CHECK(meta->findInt32(kKeyColorFormat, &format));
842    CHECK(meta->findCString(kKeyDecoderComponent, &component));
843    CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
844    CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
845
846    int32_t rotationDegrees;
847    if (!mVideoTrack->getFormat()->findInt32(
848                kKeyRotation, &rotationDegrees)) {
849        rotationDegrees = 0;
850    }
851
852    mVideoRenderer.clear();
853
854    // Must ensure that mVideoRenderer's destructor is actually executed
855    // before creating a new one.
856    IPCThreadState::self()->flushCommands();
857
858    if (USE_SURFACE_ALLOC && strncmp(component, "OMX.", 4) == 0) {
859        // Hardware decoders avoid the CPU color conversion by decoding
860        // directly to ANativeBuffers, so we must use a renderer that
861        // just pushes those buffers to the ANativeWindow.
862        mVideoRenderer =
863            new AwesomeNativeWindowRenderer(mSurface, rotationDegrees);
864    } else {
865        // Other decoders are instantiated locally and as a consequence
866        // allocate their buffers in local address space.  This renderer
867        // then performs a color conversion and copy to get the data
868        // into the ANativeBuffer.
869        mVideoRenderer = new AwesomeLocalRenderer(mSurface, meta);
870    }
871}
872
873status_t AwesomePlayer::pause() {
874    Mutex::Autolock autoLock(mLock);
875
876    mFlags &= ~CACHE_UNDERRUN;
877
878    return pause_l();
879}
880
881status_t AwesomePlayer::pause_l(bool at_eos) {
882    if (!(mFlags & PLAYING)) {
883        return OK;
884    }
885
886    cancelPlayerEvents(true /* keepBufferingGoing */);
887
888    if (mAudioPlayer != NULL) {
889        if (at_eos) {
890            // If we played the audio stream to completion we
891            // want to make sure that all samples remaining in the audio
892            // track's queue are played out.
893            mAudioPlayer->pause(true /* playPendingSamples */);
894        } else {
895            mAudioPlayer->pause();
896        }
897    }
898
899    mFlags &= ~PLAYING;
900
901    if (mDecryptHandle != NULL) {
902        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
903                Playback::PAUSE, 0);
904    }
905
906    return OK;
907}
908
909bool AwesomePlayer::isPlaying() const {
910    return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
911}
912
913void AwesomePlayer::setSurface(const sp<Surface> &surface) {
914    Mutex::Autolock autoLock(mLock);
915
916    mSurface = surface;
917}
918
919void AwesomePlayer::setAudioSink(
920        const sp<MediaPlayerBase::AudioSink> &audioSink) {
921    Mutex::Autolock autoLock(mLock);
922
923    mAudioSink = audioSink;
924}
925
926status_t AwesomePlayer::setLooping(bool shouldLoop) {
927    Mutex::Autolock autoLock(mLock);
928
929    mFlags = mFlags & ~LOOPING;
930
931    if (shouldLoop) {
932        mFlags |= LOOPING;
933    }
934
935    return OK;
936}
937
938status_t AwesomePlayer::getDuration(int64_t *durationUs) {
939    Mutex::Autolock autoLock(mMiscStateLock);
940
941    if (mDurationUs < 0) {
942        return UNKNOWN_ERROR;
943    }
944
945    *durationUs = mDurationUs;
946
947    return OK;
948}
949
950status_t AwesomePlayer::getPosition(int64_t *positionUs) {
951    if (mRTSPController != NULL) {
952        *positionUs = mRTSPController->getNormalPlayTimeUs();
953    }
954    else if (mSeeking) {
955        *positionUs = mSeekTimeUs;
956    } else if (mVideoSource != NULL) {
957        Mutex::Autolock autoLock(mMiscStateLock);
958        *positionUs = mVideoTimeUs;
959    } else if (mAudioPlayer != NULL) {
960        *positionUs = mAudioPlayer->getMediaTimeUs();
961    } else {
962        *positionUs = 0;
963    }
964
965    return OK;
966}
967
968status_t AwesomePlayer::seekTo(int64_t timeUs) {
969    if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
970        Mutex::Autolock autoLock(mLock);
971        return seekTo_l(timeUs);
972    }
973
974    return OK;
975}
976
977// static
978void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) {
979    static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone();
980}
981
982void AwesomePlayer::onRTSPSeekDone() {
983    notifyListener_l(MEDIA_SEEK_COMPLETE);
984    mSeekNotificationSent = true;
985}
986
987status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
988    if (mRTSPController != NULL) {
989        mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
990        return OK;
991    }
992
993    if (mFlags & CACHE_UNDERRUN) {
994        mFlags &= ~CACHE_UNDERRUN;
995        play_l();
996    }
997
998    mSeeking = true;
999    mSeekNotificationSent = false;
1000    mSeekTimeUs = timeUs;
1001    mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
1002
1003    seekAudioIfNecessary_l();
1004
1005    if (!(mFlags & PLAYING)) {
1006        LOGV("seeking while paused, sending SEEK_COMPLETE notification"
1007             " immediately.");
1008
1009        notifyListener_l(MEDIA_SEEK_COMPLETE);
1010        mSeekNotificationSent = true;
1011    }
1012
1013    return OK;
1014}
1015
1016void AwesomePlayer::seekAudioIfNecessary_l() {
1017    if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
1018        mAudioPlayer->seekTo(mSeekTimeUs);
1019
1020        mWatchForAudioSeekComplete = true;
1021        mWatchForAudioEOS = true;
1022        mSeekNotificationSent = false;
1023
1024        if (mDecryptHandle != NULL) {
1025            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1026                    Playback::PAUSE, 0);
1027            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1028                    Playback::START, mSeekTimeUs / 1000);
1029        }
1030    }
1031}
1032
1033void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1034    CHECK(source != NULL);
1035
1036    mAudioTrack = source;
1037}
1038
1039status_t AwesomePlayer::initAudioDecoder() {
1040    sp<MetaData> meta = mAudioTrack->getFormat();
1041
1042    const char *mime;
1043    CHECK(meta->findCString(kKeyMIMEType, &mime));
1044
1045    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
1046        mAudioSource = mAudioTrack;
1047    } else {
1048        mAudioSource = OMXCodec::Create(
1049                mClient.interface(), mAudioTrack->getFormat(),
1050                false, // createEncoder
1051                mAudioTrack);
1052    }
1053
1054    if (mAudioSource != NULL) {
1055        int64_t durationUs;
1056        if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1057            Mutex::Autolock autoLock(mMiscStateLock);
1058            if (mDurationUs < 0 || durationUs > mDurationUs) {
1059                mDurationUs = durationUs;
1060            }
1061        }
1062
1063        status_t err = mAudioSource->start();
1064
1065        if (err != OK) {
1066            mAudioSource.clear();
1067            return err;
1068        }
1069    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1070        // For legacy reasons we're simply going to ignore the absence
1071        // of an audio decoder for QCELP instead of aborting playback
1072        // altogether.
1073        return OK;
1074    }
1075
1076    return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1077}
1078
1079void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1080    CHECK(source != NULL);
1081
1082    mVideoTrack = source;
1083}
1084
1085status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
1086    mVideoSource = OMXCodec::Create(
1087            mClient.interface(), mVideoTrack->getFormat(),
1088            false, // createEncoder
1089            mVideoTrack,
1090            NULL, flags, USE_SURFACE_ALLOC ? mSurface : NULL);
1091
1092    if (mVideoSource != NULL) {
1093        int64_t durationUs;
1094        if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1095            Mutex::Autolock autoLock(mMiscStateLock);
1096            if (mDurationUs < 0 || durationUs > mDurationUs) {
1097                mDurationUs = durationUs;
1098            }
1099        }
1100
1101        status_t err = mVideoSource->start();
1102
1103        if (err != OK) {
1104            mVideoSource.clear();
1105            return err;
1106        }
1107    }
1108
1109    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1110}
1111
1112void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
1113    if (!mSeeking) {
1114        return;
1115    }
1116
1117    if (mAudioPlayer != NULL) {
1118        LOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
1119
1120        // If we don't have a video time, seek audio to the originally
1121        // requested seek time instead.
1122
1123        mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
1124        mAudioPlayer->resume();
1125        mWatchForAudioSeekComplete = true;
1126        mWatchForAudioEOS = true;
1127    } else if (!mSeekNotificationSent) {
1128        // If we're playing video only, report seek complete now,
1129        // otherwise audio player will notify us later.
1130        notifyListener_l(MEDIA_SEEK_COMPLETE);
1131    }
1132
1133    mFlags |= FIRST_FRAME;
1134    mSeeking = false;
1135    mSeekNotificationSent = false;
1136
1137    if (mDecryptHandle != NULL) {
1138        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1139                Playback::PAUSE, 0);
1140        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1141                Playback::START, videoTimeUs / 1000);
1142    }
1143}
1144
1145void AwesomePlayer::onVideoEvent() {
1146    Mutex::Autolock autoLock(mLock);
1147    if (!mVideoEventPending) {
1148        // The event has been cancelled in reset_l() but had already
1149        // been scheduled for execution at that time.
1150        return;
1151    }
1152    mVideoEventPending = false;
1153
1154    if (mSeeking) {
1155        if (mVideoBuffer) {
1156            mVideoBuffer->release();
1157            mVideoBuffer = NULL;
1158        }
1159
1160        if (mCachedSource != NULL && mAudioSource != NULL) {
1161            // We're going to seek the video source first, followed by
1162            // the audio source.
1163            // In order to avoid jumps in the DataSource offset caused by
1164            // the audio codec prefetching data from the old locations
1165            // while the video codec is already reading data from the new
1166            // locations, we'll "pause" the audio source, causing it to
1167            // stop reading input data until a subsequent seek.
1168
1169            if (mAudioPlayer != NULL) {
1170                mAudioPlayer->pause();
1171            }
1172            mAudioSource->pause();
1173        }
1174    }
1175
1176    if (!mVideoBuffer) {
1177        MediaSource::ReadOptions options;
1178        if (mSeeking) {
1179            LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
1180
1181            options.setSeekTo(
1182                    mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
1183        }
1184        for (;;) {
1185            status_t err = mVideoSource->read(&mVideoBuffer, &options);
1186            options.clearSeekTo();
1187
1188            if (err != OK) {
1189                CHECK(mVideoBuffer == NULL);
1190
1191                if (err == INFO_FORMAT_CHANGED) {
1192                    LOGV("VideoSource signalled format change.");
1193
1194                    notifyVideoSize_l();
1195
1196                    if (mVideoRenderer != NULL) {
1197                        mVideoRendererIsPreview = false;
1198                        initRenderer_l();
1199                    }
1200                    continue;
1201                }
1202
1203                // So video playback is complete, but we may still have
1204                // a seek request pending that needs to be applied
1205                // to the audio track.
1206                if (mSeeking) {
1207                    LOGV("video stream ended while seeking!");
1208                }
1209                finishSeekIfNecessary(-1);
1210
1211                mFlags |= VIDEO_AT_EOS;
1212                postStreamDoneEvent_l(err);
1213                return;
1214            }
1215
1216            if (mVideoBuffer->range_length() == 0) {
1217                // Some decoders, notably the PV AVC software decoder
1218                // return spurious empty buffers that we just want to ignore.
1219
1220                mVideoBuffer->release();
1221                mVideoBuffer = NULL;
1222                continue;
1223            }
1224
1225            break;
1226        }
1227    }
1228
1229    int64_t timeUs;
1230    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1231
1232    {
1233        Mutex::Autolock autoLock(mMiscStateLock);
1234        mVideoTimeUs = timeUs;
1235    }
1236
1237    bool wasSeeking = mSeeking;
1238    finishSeekIfNecessary(timeUs);
1239
1240    TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
1241
1242    if (mFlags & FIRST_FRAME) {
1243        mFlags &= ~FIRST_FRAME;
1244
1245        mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
1246    }
1247
1248    int64_t realTimeUs, mediaTimeUs;
1249    if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
1250        && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1251        mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1252    }
1253
1254    int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1255
1256    int64_t latenessUs = nowUs - timeUs;
1257
1258    if (wasSeeking) {
1259        // Let's display the first frame after seeking right away.
1260        latenessUs = 0;
1261    }
1262
1263    if (mRTPSession != NULL) {
1264        // We'll completely ignore timestamps for gtalk videochat
1265        // and we'll play incoming video as fast as we get it.
1266        latenessUs = 0;
1267    }
1268
1269    if (latenessUs > 40000) {
1270        // We're more than 40ms late.
1271        LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
1272
1273        mVideoBuffer->release();
1274        mVideoBuffer = NULL;
1275
1276        postVideoEvent_l();
1277        return;
1278    }
1279
1280    if (latenessUs < -10000) {
1281        // We're more than 10ms early.
1282
1283        postVideoEvent_l(10000);
1284        return;
1285    }
1286
1287    if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
1288        mVideoRendererIsPreview = false;
1289
1290        initRenderer_l();
1291    }
1292
1293    if (mVideoRenderer != NULL) {
1294        mVideoRenderer->render(mVideoBuffer);
1295    }
1296
1297    mVideoBuffer->release();
1298    mVideoBuffer = NULL;
1299
1300    postVideoEvent_l();
1301}
1302
1303void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1304    if (mVideoEventPending) {
1305        return;
1306    }
1307
1308    mVideoEventPending = true;
1309    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1310}
1311
1312void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
1313    if (mStreamDoneEventPending) {
1314        return;
1315    }
1316    mStreamDoneEventPending = true;
1317
1318    mStreamDoneStatus = status;
1319    mQueue.postEvent(mStreamDoneEvent);
1320}
1321
1322void AwesomePlayer::postBufferingEvent_l() {
1323    if (mBufferingEventPending) {
1324        return;
1325    }
1326    mBufferingEventPending = true;
1327    mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1328}
1329
1330void AwesomePlayer::postCheckAudioStatusEvent_l() {
1331    if (mAudioStatusEventPending) {
1332        return;
1333    }
1334    mAudioStatusEventPending = true;
1335    mQueue.postEvent(mCheckAudioStatusEvent);
1336}
1337
1338void AwesomePlayer::onCheckAudioStatus() {
1339    Mutex::Autolock autoLock(mLock);
1340    if (!mAudioStatusEventPending) {
1341        // Event was dispatched and while we were blocking on the mutex,
1342        // has already been cancelled.
1343        return;
1344    }
1345
1346    mAudioStatusEventPending = false;
1347
1348    if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1349        mWatchForAudioSeekComplete = false;
1350
1351        if (!mSeekNotificationSent) {
1352            notifyListener_l(MEDIA_SEEK_COMPLETE);
1353            mSeekNotificationSent = true;
1354        }
1355
1356        mSeeking = false;
1357    }
1358
1359    status_t finalStatus;
1360    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
1361        mWatchForAudioEOS = false;
1362        mFlags |= AUDIO_AT_EOS;
1363        mFlags |= FIRST_FRAME;
1364        postStreamDoneEvent_l(finalStatus);
1365    }
1366}
1367
1368status_t AwesomePlayer::prepare() {
1369    Mutex::Autolock autoLock(mLock);
1370    return prepare_l();
1371}
1372
1373status_t AwesomePlayer::prepare_l() {
1374    if (mFlags & PREPARED) {
1375        return OK;
1376    }
1377
1378    if (mFlags & PREPARING) {
1379        return UNKNOWN_ERROR;
1380    }
1381
1382    mIsAsyncPrepare = false;
1383    status_t err = prepareAsync_l();
1384
1385    if (err != OK) {
1386        return err;
1387    }
1388
1389    while (mFlags & PREPARING) {
1390        mPreparedCondition.wait(mLock);
1391    }
1392
1393    return mPrepareResult;
1394}
1395
1396status_t AwesomePlayer::prepareAsync() {
1397    Mutex::Autolock autoLock(mLock);
1398
1399    if (mFlags & PREPARING) {
1400        return UNKNOWN_ERROR;  // async prepare already pending
1401    }
1402
1403    mIsAsyncPrepare = true;
1404    return prepareAsync_l();
1405}
1406
1407status_t AwesomePlayer::prepareAsync_l() {
1408    if (mFlags & PREPARING) {
1409        return UNKNOWN_ERROR;  // async prepare already pending
1410    }
1411
1412    if (!mQueueStarted) {
1413        mQueue.start();
1414        mQueueStarted = true;
1415    }
1416
1417    mFlags |= PREPARING;
1418    mAsyncPrepareEvent = new AwesomeEvent(
1419            this, &AwesomePlayer::onPrepareAsyncEvent);
1420
1421    mQueue.postEvent(mAsyncPrepareEvent);
1422
1423    return OK;
1424}
1425
1426status_t AwesomePlayer::finishSetDataSource_l() {
1427    sp<DataSource> dataSource;
1428
1429    if (!strncasecmp("http://", mUri.string(), 7)) {
1430        mConnectingDataSource = new NuHTTPDataSource;
1431
1432        mLock.unlock();
1433        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
1434        mLock.lock();
1435
1436        if (err != OK) {
1437            mConnectingDataSource.clear();
1438
1439            LOGI("mConnectingDataSource->connect() returned %d", err);
1440            return err;
1441        }
1442
1443#if 0
1444        mCachedSource = new NuCachedSource2(
1445                new ThrottledSource(
1446                    mConnectingDataSource, 50 * 1024 /* bytes/sec */));
1447#else
1448        mCachedSource = new NuCachedSource2(mConnectingDataSource);
1449#endif
1450        mConnectingDataSource.clear();
1451
1452        dataSource = mCachedSource;
1453    } else if (!strncasecmp(mUri.string(), "httplive://", 11)) {
1454        String8 uri("http://");
1455        uri.append(mUri.string() + 11);
1456
1457        if (mLooper == NULL) {
1458            mLooper = new ALooper;
1459            mLooper->setName("httplive");
1460            mLooper->start();
1461        }
1462
1463        mLiveSession = new LiveSession;
1464        mLooper->registerHandler(mLiveSession);
1465
1466        mLiveSession->connect(uri.string());
1467        dataSource = mLiveSession->getDataSource();
1468
1469        sp<MediaExtractor> extractor =
1470            MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
1471
1472        static_cast<MPEG2TSExtractor *>(extractor.get())
1473            ->setLiveSession(mLiveSession);
1474
1475        return setDataSource_l(extractor);
1476    } else if (!strncmp("rtsp://gtalk/", mUri.string(), 13)) {
1477        if (mLooper == NULL) {
1478            mLooper = new ALooper;
1479            mLooper->setName("gtalk rtp");
1480            mLooper->start(
1481                    false /* runOnCallingThread */,
1482                    false /* canCallJava */,
1483                    PRIORITY_HIGHEST);
1484        }
1485
1486        const char *startOfCodecString = &mUri.string()[13];
1487        const char *startOfSlash1 = strchr(startOfCodecString, '/');
1488        if (startOfSlash1 == NULL) {
1489            return BAD_VALUE;
1490        }
1491        const char *startOfWidthString = &startOfSlash1[1];
1492        const char *startOfSlash2 = strchr(startOfWidthString, '/');
1493        if (startOfSlash2 == NULL) {
1494            return BAD_VALUE;
1495        }
1496        const char *startOfHeightString = &startOfSlash2[1];
1497
1498        String8 codecString(startOfCodecString, startOfSlash1 - startOfCodecString);
1499        String8 widthString(startOfWidthString, startOfSlash2 - startOfWidthString);
1500        String8 heightString(startOfHeightString);
1501
1502#if 0
1503        mRTPPusher = new UDPPusher("/data/misc/rtpout.bin", 5434);
1504        mLooper->registerHandler(mRTPPusher);
1505
1506        mRTCPPusher = new UDPPusher("/data/misc/rtcpout.bin", 5435);
1507        mLooper->registerHandler(mRTCPPusher);
1508#endif
1509
1510        mRTPSession = new ARTPSession;
1511        mLooper->registerHandler(mRTPSession);
1512
1513#if 0
1514        // My AMR SDP
1515        static const char *raw =
1516            "v=0\r\n"
1517            "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
1518            "s=QuickTime\r\n"
1519            "t=0 0\r\n"
1520            "a=range:npt=0-315\r\n"
1521            "a=isma-compliance:2,2.0,2\r\n"
1522            "m=audio 5434 RTP/AVP 97\r\n"
1523            "c=IN IP4 127.0.0.1\r\n"
1524            "b=AS:30\r\n"
1525            "a=rtpmap:97 AMR/8000/1\r\n"
1526            "a=fmtp:97 octet-align\r\n";
1527#elif 1
1528        String8 sdp;
1529        sdp.appendFormat(
1530            "v=0\r\n"
1531            "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
1532            "s=QuickTime\r\n"
1533            "t=0 0\r\n"
1534            "a=range:npt=0-315\r\n"
1535            "a=isma-compliance:2,2.0,2\r\n"
1536            "m=video 5434 RTP/AVP 97\r\n"
1537            "c=IN IP4 127.0.0.1\r\n"
1538            "b=AS:30\r\n"
1539            "a=rtpmap:97 %s/90000\r\n"
1540            "a=cliprect:0,0,%s,%s\r\n"
1541            "a=framesize:97 %s-%s\r\n",
1542
1543            codecString.string(),
1544            heightString.string(), widthString.string(),
1545            widthString.string(), heightString.string()
1546            );
1547        const char *raw = sdp.string();
1548
1549#endif
1550
1551        sp<ASessionDescription> desc = new ASessionDescription;
1552        CHECK(desc->setTo(raw, strlen(raw)));
1553
1554        CHECK_EQ(mRTPSession->setup(desc), (status_t)OK);
1555
1556        if (mRTPPusher != NULL) {
1557            mRTPPusher->start();
1558        }
1559
1560        if (mRTCPPusher != NULL) {
1561            mRTCPPusher->start();
1562        }
1563
1564        CHECK_EQ(mRTPSession->countTracks(), 1u);
1565        sp<MediaSource> source = mRTPSession->trackAt(0);
1566
1567#if 0
1568        bool eos;
1569        while (((APacketSource *)source.get())
1570                ->getQueuedDuration(&eos) < 5000000ll && !eos) {
1571            usleep(100000ll);
1572        }
1573#endif
1574
1575        const char *mime;
1576        CHECK(source->getFormat()->findCString(kKeyMIMEType, &mime));
1577
1578        if (!strncasecmp("video/", mime, 6)) {
1579            setVideoSource(source);
1580        } else {
1581            CHECK(!strncasecmp("audio/", mime, 6));
1582            setAudioSource(source);
1583        }
1584
1585        mExtractorFlags = MediaExtractor::CAN_PAUSE;
1586
1587        return OK;
1588    } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
1589        if (mLooper == NULL) {
1590            mLooper = new ALooper;
1591            mLooper->setName("rtsp");
1592            mLooper->start();
1593        }
1594        mRTSPController = new ARTSPController(mLooper);
1595        status_t err = mRTSPController->connect(mUri.string());
1596
1597        LOGI("ARTSPController::connect returned %d", err);
1598
1599        if (err != OK) {
1600            mRTSPController.clear();
1601            return err;
1602        }
1603
1604        sp<MediaExtractor> extractor = mRTSPController.get();
1605        return setDataSource_l(extractor);
1606    } else {
1607        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1608    }
1609
1610    if (dataSource == NULL) {
1611        return UNKNOWN_ERROR;
1612    }
1613
1614    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1615
1616    if (extractor == NULL) {
1617        return UNKNOWN_ERROR;
1618    }
1619
1620    dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
1621    if (mDecryptHandle != NULL) {
1622        if (RightsStatus::RIGHTS_VALID == mDecryptHandle->status) {
1623            if (DecryptApiType::WV_BASED == mDecryptHandle->decryptApiType) {
1624                LOGD("Setting mCachedSource to NULL for WVM\n");
1625                mCachedSource.clear();
1626            }
1627        } else {
1628            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
1629        }
1630    }
1631
1632    return setDataSource_l(extractor);
1633}
1634
1635void AwesomePlayer::abortPrepare(status_t err) {
1636    CHECK(err != OK);
1637
1638    if (mIsAsyncPrepare) {
1639        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1640    }
1641
1642    mPrepareResult = err;
1643    mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
1644    mAsyncPrepareEvent = NULL;
1645    mPreparedCondition.broadcast();
1646}
1647
1648// static
1649bool AwesomePlayer::ContinuePreparation(void *cookie) {
1650    AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1651
1652    return (me->mFlags & PREPARE_CANCELLED) == 0;
1653}
1654
1655void AwesomePlayer::onPrepareAsyncEvent() {
1656    Mutex::Autolock autoLock(mLock);
1657
1658    if (mFlags & PREPARE_CANCELLED) {
1659        LOGI("prepare was cancelled before doing anything");
1660        abortPrepare(UNKNOWN_ERROR);
1661        return;
1662    }
1663
1664    if (mUri.size() > 0) {
1665        status_t err = finishSetDataSource_l();
1666
1667        if (err != OK) {
1668            abortPrepare(err);
1669            return;
1670        }
1671    }
1672
1673    if (mVideoTrack != NULL && mVideoSource == NULL) {
1674        status_t err = initVideoDecoder();
1675
1676        if (err != OK) {
1677            abortPrepare(err);
1678            return;
1679        }
1680    }
1681
1682    if (mAudioTrack != NULL && mAudioSource == NULL) {
1683        status_t err = initAudioDecoder();
1684
1685        if (err != OK) {
1686            abortPrepare(err);
1687            return;
1688        }
1689    }
1690
1691    mFlags |= PREPARING_CONNECTED;
1692
1693    if (mCachedSource != NULL || mRTSPController != NULL) {
1694        postBufferingEvent_l();
1695    } else {
1696        finishAsyncPrepare_l();
1697    }
1698}
1699
1700void AwesomePlayer::finishAsyncPrepare_l() {
1701    if (mIsAsyncPrepare) {
1702        if (mVideoSource == NULL) {
1703            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1704        } else {
1705            notifyVideoSize_l();
1706        }
1707
1708        notifyListener_l(MEDIA_PREPARED);
1709    }
1710
1711    mPrepareResult = OK;
1712    mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
1713    mFlags |= PREPARED;
1714    mAsyncPrepareEvent = NULL;
1715    mPreparedCondition.broadcast();
1716}
1717
1718uint32_t AwesomePlayer::flags() const {
1719    return mExtractorFlags;
1720}
1721
1722void AwesomePlayer::postAudioEOS() {
1723    postCheckAudioStatusEvent_l();
1724}
1725
1726void AwesomePlayer::postAudioSeekComplete() {
1727    postCheckAudioStatusEvent_l();
1728}
1729
1730}  // namespace android
1731