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