GenericSource.cpp revision 3b9912bcd428fcaeead1faf9297aee11b7fd1888
10c1bc742181ded4930842b46e9507372f0b1b963James Dong/* 278e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * Copyright (C) 2012 The Android Open Source Project 378e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * 478e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * Licensed under the Apache License, Version 2.0 (the "License"); 578e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * you may not use this file except in compliance with the License. 678e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * You may obtain a copy of the License at 778e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * 878e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * http://www.apache.org/licenses/LICENSE-2.0 978e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * 1078e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * Unless required by applicable law or agreed to in writing, software 1178e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * distributed under the License is distributed on an "AS IS" BASIS, 1278e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1378e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * See the License for the specific language governing permissions and 1478e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar * limitations under the License. 1578e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar */ 1678e52bfac041d71ce53b5b13c2abf78af742b09dLajos Molnar 170c1bc742181ded4930842b46e9507372f0b1b963James Dong//#define LOG_NDEBUG 0 180c1bc742181ded4930842b46e9507372f0b1b963James Dong#define LOG_TAG "GenericSource" 190c1bc742181ded4930842b46e9507372f0b1b963James Dong 200c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "GenericSource.h" 210c1bc742181ded4930842b46e9507372f0b1b963James Dong 220c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "AnotherPacketSource.h" 230c1bc742181ded4930842b46e9507372f0b1b963James Dong 240c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/IMediaHTTPService.h> 250c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/foundation/ABuffer.h> 260c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/foundation/ADebug.h> 270c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/foundation/AMessage.h> 280c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/DataSource.h> 290c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/FileSource.h> 300c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/MediaBuffer.h> 310c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/MediaDefs.h> 320c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/MediaExtractor.h> 330c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/MediaSource.h> 340c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/MetaData.h> 350c1bc742181ded4930842b46e9507372f0b1b963James Dong#include <media/stagefright/Utils.h> 360c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "../../libstagefright/include/DRMExtractor.h" 370c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "../../libstagefright/include/NuCachedSource2.h" 380c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "../../libstagefright/include/WVMExtractor.h" 390c1bc742181ded4930842b46e9507372f0b1b963James Dong#include "../../libstagefright/include/HTTPBase.h" 400c1bc742181ded4930842b46e9507372f0b1b963James Dong 410c1bc742181ded4930842b46e9507372f0b1b963James Dongnamespace android { 420c1bc742181ded4930842b46e9507372f0b1b963James Dong 430c1bc742181ded4930842b46e9507372f0b1b963James Dongstatic int64_t kLowWaterMarkUs = 2000000ll; // 2secs 440c1bc742181ded4930842b46e9507372f0b1b963James Dongstatic int64_t kHighWaterMarkUs = 5000000ll; // 5secs 450c1bc742181ded4930842b46e9507372f0b1b963James Dongstatic int64_t kHighWaterMarkRebufferUs = 15000000ll; // 15secs 460c1bc742181ded4930842b46e9507372f0b1b963James Dongstatic const ssize_t kLowWaterMarkBytes = 40000; 470c1bc742181ded4930842b46e9507372f0b1b963James Dongstatic const ssize_t kHighWaterMarkBytes = 200000; 480c1bc742181ded4930842b46e9507372f0b1b963James Dong 490c1bc742181ded4930842b46e9507372f0b1b963James DongNuPlayer::GenericSource::GenericSource( 500c1bc742181ded4930842b46e9507372f0b1b963James Dong const sp<AMessage> ¬ify, 510c1bc742181ded4930842b46e9507372f0b1b963James Dong bool uidValid, 520c1bc742181ded4930842b46e9507372f0b1b963James Dong uid_t uid) 530c1bc742181ded4930842b46e9507372f0b1b963James Dong : Source(notify), 540c1bc742181ded4930842b46e9507372f0b1b963James Dong mAudioTimeUs(0), 550c1bc742181ded4930842b46e9507372f0b1b963James Dong mAudioLastDequeueTimeUs(0), 560c1bc742181ded4930842b46e9507372f0b1b963James Dong mVideoTimeUs(0), 570c1bc742181ded4930842b46e9507372f0b1b963James Dong mVideoLastDequeueTimeUs(0), 580c1bc742181ded4930842b46e9507372f0b1b963James Dong mFetchSubtitleDataGeneration(0), 590c1bc742181ded4930842b46e9507372f0b1b963James Dong mFetchTimedTextDataGeneration(0), 600c1bc742181ded4930842b46e9507372f0b1b963James Dong mDurationUs(-1ll), 610c1bc742181ded4930842b46e9507372f0b1b963James Dong mAudioIsVorbis(false), 620c1bc742181ded4930842b46e9507372f0b1b963James Dong mIsWidevine(false), 630c1bc742181ded4930842b46e9507372f0b1b963James Dong mIsSecure(false), 640c1bc742181ded4930842b46e9507372f0b1b963James Dong mIsStreaming(false), 650c1bc742181ded4930842b46e9507372f0b1b963James Dong mUIDValid(uidValid), 660c1bc742181ded4930842b46e9507372f0b1b963James Dong mUID(uid), 670c1bc742181ded4930842b46e9507372f0b1b963James Dong mFd(-1), 680c1bc742181ded4930842b46e9507372f0b1b963James Dong mDrmManagerClient(NULL), 690c1bc742181ded4930842b46e9507372f0b1b963James Dong mBitrate(-1ll), 700c1bc742181ded4930842b46e9507372f0b1b963James Dong mPendingReadBufferTypes(0) { 710c1bc742181ded4930842b46e9507372f0b1b963James Dong mBufferingMonitor = new BufferingMonitor(notify); 720c1bc742181ded4930842b46e9507372f0b1b963James Dong resetDataSource(); 730c1bc742181ded4930842b46e9507372f0b1b963James Dong DataSource::RegisterDefaultSniffers(); 740c1bc742181ded4930842b46e9507372f0b1b963James Dong} 750c1bc742181ded4930842b46e9507372f0b1b963James Dong 760c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid NuPlayer::GenericSource::resetDataSource() { 770c1bc742181ded4930842b46e9507372f0b1b963James Dong mHTTPService.clear(); 780c1bc742181ded4930842b46e9507372f0b1b963James Dong mHttpSource.clear(); 790c1bc742181ded4930842b46e9507372f0b1b963James Dong mUri.clear(); 800c1bc742181ded4930842b46e9507372f0b1b963James Dong mUriHeaders.clear(); 810c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mFd >= 0) { 820c1bc742181ded4930842b46e9507372f0b1b963James Dong close(mFd); 830c1bc742181ded4930842b46e9507372f0b1b963James Dong mFd = -1; 840c1bc742181ded4930842b46e9507372f0b1b963James Dong } 850c1bc742181ded4930842b46e9507372f0b1b963James Dong mOffset = 0; 860c1bc742181ded4930842b46e9507372f0b1b963James Dong mLength = 0; 870c1bc742181ded4930842b46e9507372f0b1b963James Dong setDrmPlaybackStatusIfNeeded(Playback::STOP, 0); 880c1bc742181ded4930842b46e9507372f0b1b963James Dong mDecryptHandle = NULL; 890c1bc742181ded4930842b46e9507372f0b1b963James Dong mDrmManagerClient = NULL; 900c1bc742181ded4930842b46e9507372f0b1b963James Dong mStarted = false; 910c1bc742181ded4930842b46e9507372f0b1b963James Dong mStopRead = true; 920c1bc742181ded4930842b46e9507372f0b1b963James Dong 930c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mBufferingMonitorLooper != NULL) { 940c1bc742181ded4930842b46e9507372f0b1b963James Dong mBufferingMonitorLooper->unregisterHandler(mBufferingMonitor->id()); 950c1bc742181ded4930842b46e9507372f0b1b963James Dong mBufferingMonitorLooper->stop(); 960c1bc742181ded4930842b46e9507372f0b1b963James Dong mBufferingMonitorLooper = NULL; 970c1bc742181ded4930842b46e9507372f0b1b963James Dong } 980c1bc742181ded4930842b46e9507372f0b1b963James Dong mBufferingMonitor->stop(); 990c1bc742181ded4930842b46e9507372f0b1b963James Dong} 1000c1bc742181ded4930842b46e9507372f0b1b963James Dong 1010c1bc742181ded4930842b46e9507372f0b1b963James Dongstatus_t NuPlayer::GenericSource::setDataSource( 1020c1bc742181ded4930842b46e9507372f0b1b963James Dong const sp<IMediaHTTPService> &httpService, 1030c1bc742181ded4930842b46e9507372f0b1b963James Dong const char *url, 1040c1bc742181ded4930842b46e9507372f0b1b963James Dong const KeyedVector<String8, String8> *headers) { 1050c1bc742181ded4930842b46e9507372f0b1b963James Dong resetDataSource(); 1060c1bc742181ded4930842b46e9507372f0b1b963James Dong 1070c1bc742181ded4930842b46e9507372f0b1b963James Dong mHTTPService = httpService; 1080c1bc742181ded4930842b46e9507372f0b1b963James Dong mUri = url; 1090c1bc742181ded4930842b46e9507372f0b1b963James Dong 1100c1bc742181ded4930842b46e9507372f0b1b963James Dong if (headers) { 1110c1bc742181ded4930842b46e9507372f0b1b963James Dong mUriHeaders = *headers; 1120c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1130c1bc742181ded4930842b46e9507372f0b1b963James Dong 1140c1bc742181ded4930842b46e9507372f0b1b963James Dong // delay data source creation to prepareAsync() to avoid blocking 1150c1bc742181ded4930842b46e9507372f0b1b963James Dong // the calling thread in setDataSource for any significant time. 1160c1bc742181ded4930842b46e9507372f0b1b963James Dong return OK; 1170c1bc742181ded4930842b46e9507372f0b1b963James Dong} 1180c1bc742181ded4930842b46e9507372f0b1b963James Dong 1190c1bc742181ded4930842b46e9507372f0b1b963James Dongstatus_t NuPlayer::GenericSource::setDataSource( 1200c1bc742181ded4930842b46e9507372f0b1b963James Dong int fd, int64_t offset, int64_t length) { 1210c1bc742181ded4930842b46e9507372f0b1b963James Dong resetDataSource(); 1220c1bc742181ded4930842b46e9507372f0b1b963James Dong 1230c1bc742181ded4930842b46e9507372f0b1b963James Dong mFd = dup(fd); 1240c1bc742181ded4930842b46e9507372f0b1b963James Dong mOffset = offset; 1250c1bc742181ded4930842b46e9507372f0b1b963James Dong mLength = length; 1260c1bc742181ded4930842b46e9507372f0b1b963James Dong 1270c1bc742181ded4930842b46e9507372f0b1b963James Dong // delay data source creation to prepareAsync() to avoid blocking 1280c1bc742181ded4930842b46e9507372f0b1b963James Dong // the calling thread in setDataSource for any significant time. 1290c1bc742181ded4930842b46e9507372f0b1b963James Dong return OK; 1300c1bc742181ded4930842b46e9507372f0b1b963James Dong} 1310c1bc742181ded4930842b46e9507372f0b1b963James Dong 1320c1bc742181ded4930842b46e9507372f0b1b963James Dongstatus_t NuPlayer::GenericSource::setDataSource(const sp<DataSource>& source) { 1330c1bc742181ded4930842b46e9507372f0b1b963James Dong resetDataSource(); 1340c1bc742181ded4930842b46e9507372f0b1b963James Dong mDataSource = source; 1350c1bc742181ded4930842b46e9507372f0b1b963James Dong return OK; 1360c1bc742181ded4930842b46e9507372f0b1b963James Dong} 1370c1bc742181ded4930842b46e9507372f0b1b963James Dong 1380c1bc742181ded4930842b46e9507372f0b1b963James Dongsp<MetaData> NuPlayer::GenericSource::getFileFormatMeta() const { 1390c1bc742181ded4930842b46e9507372f0b1b963James Dong return mFileMeta; 1400c1bc742181ded4930842b46e9507372f0b1b963James Dong} 1410c1bc742181ded4930842b46e9507372f0b1b963James Dong 1420c1bc742181ded4930842b46e9507372f0b1b963James Dongstatus_t NuPlayer::GenericSource::initFromDataSource() { 1430c1bc742181ded4930842b46e9507372f0b1b963James Dong sp<IMediaExtractor> extractor; 1440c1bc742181ded4930842b46e9507372f0b1b963James Dong String8 mimeType; 1450c1bc742181ded4930842b46e9507372f0b1b963James Dong float confidence; 1460c1bc742181ded4930842b46e9507372f0b1b963James Dong sp<AMessage> dummy; 1470c1bc742181ded4930842b46e9507372f0b1b963James Dong bool isWidevineStreaming = false; 1480c1bc742181ded4930842b46e9507372f0b1b963James Dong 1490c1bc742181ded4930842b46e9507372f0b1b963James Dong CHECK(mDataSource != NULL); 1500c1bc742181ded4930842b46e9507372f0b1b963James Dong 1510c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mIsWidevine) { 1520c1bc742181ded4930842b46e9507372f0b1b963James Dong isWidevineStreaming = SniffWVM( 1530c1bc742181ded4930842b46e9507372f0b1b963James Dong mDataSource, &mimeType, &confidence, &dummy); 1540c1bc742181ded4930842b46e9507372f0b1b963James Dong if (!isWidevineStreaming || 1550c1bc742181ded4930842b46e9507372f0b1b963James Dong strcasecmp( 1560c1bc742181ded4930842b46e9507372f0b1b963James Dong mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) { 1570c1bc742181ded4930842b46e9507372f0b1b963James Dong ALOGE("unsupported widevine mime: %s", mimeType.string()); 1580c1bc742181ded4930842b46e9507372f0b1b963James Dong return UNKNOWN_ERROR; 1590c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1600c1bc742181ded4930842b46e9507372f0b1b963James Dong } else if (mIsStreaming) { 1610c1bc742181ded4930842b46e9507372f0b1b963James Dong if (!mDataSource->sniff(&mimeType, &confidence, &dummy)) { 1620c1bc742181ded4930842b46e9507372f0b1b963James Dong return UNKNOWN_ERROR; 1630c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1640c1bc742181ded4930842b46e9507372f0b1b963James Dong isWidevineStreaming = !strcasecmp( 1650c1bc742181ded4930842b46e9507372f0b1b963James Dong mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM); 1660c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1670c1bc742181ded4930842b46e9507372f0b1b963James Dong 1680c1bc742181ded4930842b46e9507372f0b1b963James Dong if (isWidevineStreaming) { 1690c1bc742181ded4930842b46e9507372f0b1b963James Dong // we don't want cached source for widevine streaming. 1700c1bc742181ded4930842b46e9507372f0b1b963James Dong mCachedSource.clear(); 1710c1bc742181ded4930842b46e9507372f0b1b963James Dong mDataSource = mHttpSource; 1720c1bc742181ded4930842b46e9507372f0b1b963James Dong mWVMExtractor = new WVMExtractor(mDataSource); 1730c1bc742181ded4930842b46e9507372f0b1b963James Dong mWVMExtractor->setAdaptiveStreamingMode(true); 1740c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mUIDValid) { 1750c1bc742181ded4930842b46e9507372f0b1b963James Dong mWVMExtractor->setUID(mUID); 1760c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1770c1bc742181ded4930842b46e9507372f0b1b963James Dong extractor = mWVMExtractor; 1780c1bc742181ded4930842b46e9507372f0b1b963James Dong } else { 1790c1bc742181ded4930842b46e9507372f0b1b963James Dong extractor = MediaExtractor::Create(mDataSource, 1800c1bc742181ded4930842b46e9507372f0b1b963James Dong mimeType.isEmpty() ? NULL : mimeType.string()); 1810c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1820c1bc742181ded4930842b46e9507372f0b1b963James Dong 1830c1bc742181ded4930842b46e9507372f0b1b963James Dong if (extractor == NULL) { 1840c1bc742181ded4930842b46e9507372f0b1b963James Dong return UNKNOWN_ERROR; 1850c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1860c1bc742181ded4930842b46e9507372f0b1b963James Dong 1870c1bc742181ded4930842b46e9507372f0b1b963James Dong if (extractor->getDrmFlag()) { 1880c1bc742181ded4930842b46e9507372f0b1b963James Dong checkDrmStatus(mDataSource); 1890c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1900c1bc742181ded4930842b46e9507372f0b1b963James Dong 1910c1bc742181ded4930842b46e9507372f0b1b963James Dong mFileMeta = extractor->getMetaData(); 1920c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mFileMeta != NULL) { 1930c1bc742181ded4930842b46e9507372f0b1b963James Dong int64_t duration; 1940c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mFileMeta->findInt64(kKeyDuration, &duration)) { 1950c1bc742181ded4930842b46e9507372f0b1b963James Dong mDurationUs = duration; 1960c1bc742181ded4930842b46e9507372f0b1b963James Dong } 1970c1bc742181ded4930842b46e9507372f0b1b963James Dong 1980c1bc742181ded4930842b46e9507372f0b1b963James Dong if (!mIsWidevine) { 1990c1bc742181ded4930842b46e9507372f0b1b963James Dong // Check mime to see if we actually have a widevine source. 2000c1bc742181ded4930842b46e9507372f0b1b963James Dong // If the data source is not URL-type (eg. file source), we 2010c1bc742181ded4930842b46e9507372f0b1b963James Dong // won't be able to tell until now. 2020c1bc742181ded4930842b46e9507372f0b1b963James Dong const char *fileMime; 2030c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mFileMeta->findCString(kKeyMIMEType, &fileMime) 2040c1bc742181ded4930842b46e9507372f0b1b963James Dong && !strncasecmp(fileMime, "video/wvm", 9)) { 2050c1bc742181ded4930842b46e9507372f0b1b963James Dong mIsWidevine = true; 2060c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2070c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2080c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2090c1bc742181ded4930842b46e9507372f0b1b963James Dong 2100c1bc742181ded4930842b46e9507372f0b1b963James Dong int32_t totalBitrate = 0; 2110c1bc742181ded4930842b46e9507372f0b1b963James Dong 2120c1bc742181ded4930842b46e9507372f0b1b963James Dong size_t numtracks = extractor->countTracks(); 2130c1bc742181ded4930842b46e9507372f0b1b963James Dong if (numtracks == 0) { 2140c1bc742181ded4930842b46e9507372f0b1b963James Dong return UNKNOWN_ERROR; 2150c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2160c1bc742181ded4930842b46e9507372f0b1b963James Dong 2170c1bc742181ded4930842b46e9507372f0b1b963James Dong for (size_t i = 0; i < numtracks; ++i) { 2180c1bc742181ded4930842b46e9507372f0b1b963James Dong sp<IMediaSource> track = extractor->getTrack(i); 2190c1bc742181ded4930842b46e9507372f0b1b963James Dong if (track == NULL) { 2200c1bc742181ded4930842b46e9507372f0b1b963James Dong continue; 2210c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2220c1bc742181ded4930842b46e9507372f0b1b963James Dong 2230c1bc742181ded4930842b46e9507372f0b1b963James Dong sp<MetaData> meta = extractor->getTrackMetaData(i); 2240c1bc742181ded4930842b46e9507372f0b1b963James Dong if (meta == NULL) { 2250c1bc742181ded4930842b46e9507372f0b1b963James Dong ALOGE("no metadata for track %zu", i); 2260c1bc742181ded4930842b46e9507372f0b1b963James Dong return UNKNOWN_ERROR; 2270c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2280c1bc742181ded4930842b46e9507372f0b1b963James Dong 2290c1bc742181ded4930842b46e9507372f0b1b963James Dong const char *mime; 2300c1bc742181ded4930842b46e9507372f0b1b963James Dong CHECK(meta->findCString(kKeyMIMEType, &mime)); 2310c1bc742181ded4930842b46e9507372f0b1b963James Dong 2320c1bc742181ded4930842b46e9507372f0b1b963James Dong // Do the string compare immediately with "mime", 2330c1bc742181ded4930842b46e9507372f0b1b963James Dong // we can't assume "mime" would stay valid after another 2340c1bc742181ded4930842b46e9507372f0b1b963James Dong // extractor operation, some extractors might modify meta 2350c1bc742181ded4930842b46e9507372f0b1b963James Dong // during getTrack() and make it invalid. 2360c1bc742181ded4930842b46e9507372f0b1b963James Dong if (!strncasecmp(mime, "audio/", 6)) { 2370c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mAudioTrack.mSource == NULL) { 2380c1bc742181ded4930842b46e9507372f0b1b963James Dong mAudioTrack.mIndex = i; 2390c1bc742181ded4930842b46e9507372f0b1b963James Dong mAudioTrack.mSource = track; 2400c1bc742181ded4930842b46e9507372f0b1b963James Dong mAudioTrack.mPackets = 2410c1bc742181ded4930842b46e9507372f0b1b963James Dong new AnotherPacketSource(mAudioTrack.mSource->getFormat()); 2420c1bc742181ded4930842b46e9507372f0b1b963James Dong 2430c1bc742181ded4930842b46e9507372f0b1b963James Dong if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { 2440c1bc742181ded4930842b46e9507372f0b1b963James Dong mAudioIsVorbis = true; 2450c1bc742181ded4930842b46e9507372f0b1b963James Dong } else { 2460c1bc742181ded4930842b46e9507372f0b1b963James Dong mAudioIsVorbis = false; 2470c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2480c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2490c1bc742181ded4930842b46e9507372f0b1b963James Dong } else if (!strncasecmp(mime, "video/", 6)) { 2500c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mVideoTrack.mSource == NULL) { 2510c1bc742181ded4930842b46e9507372f0b1b963James Dong mVideoTrack.mIndex = i; 2520c1bc742181ded4930842b46e9507372f0b1b963James Dong mVideoTrack.mSource = track; 2530c1bc742181ded4930842b46e9507372f0b1b963James Dong mVideoTrack.mPackets = 2540c1bc742181ded4930842b46e9507372f0b1b963James Dong new AnotherPacketSource(mVideoTrack.mSource->getFormat()); 2550c1bc742181ded4930842b46e9507372f0b1b963James Dong 2560c1bc742181ded4930842b46e9507372f0b1b963James Dong // check if the source requires secure buffers 2570c1bc742181ded4930842b46e9507372f0b1b963James Dong int32_t secure; 2580c1bc742181ded4930842b46e9507372f0b1b963James Dong if (meta->findInt32(kKeyRequiresSecureBuffers, &secure) 2590c1bc742181ded4930842b46e9507372f0b1b963James Dong && secure) { 2600c1bc742181ded4930842b46e9507372f0b1b963James Dong mIsSecure = true; 2610c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mUIDValid) { 2620c1bc742181ded4930842b46e9507372f0b1b963James Dong extractor->setUID(mUID); 2630c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2640c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2650c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2660c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2670c1bc742181ded4930842b46e9507372f0b1b963James Dong 2680c1bc742181ded4930842b46e9507372f0b1b963James Dong mSources.push(track); 2690c1bc742181ded4930842b46e9507372f0b1b963James Dong int64_t durationUs; 2700c1bc742181ded4930842b46e9507372f0b1b963James Dong if (meta->findInt64(kKeyDuration, &durationUs)) { 2710c1bc742181ded4930842b46e9507372f0b1b963James Dong if (durationUs > mDurationUs) { 2720c1bc742181ded4930842b46e9507372f0b1b963James Dong mDurationUs = durationUs; 2730c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2740c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2750c1bc742181ded4930842b46e9507372f0b1b963James Dong 2760c1bc742181ded4930842b46e9507372f0b1b963James Dong int32_t bitrate; 2770c1bc742181ded4930842b46e9507372f0b1b963James Dong if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) { 2780c1bc742181ded4930842b46e9507372f0b1b963James Dong totalBitrate += bitrate; 2790c1bc742181ded4930842b46e9507372f0b1b963James Dong } else { 2800c1bc742181ded4930842b46e9507372f0b1b963James Dong totalBitrate = -1; 2810c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2820c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2830c1bc742181ded4930842b46e9507372f0b1b963James Dong 2840c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mSources.size() == 0) { 2850c1bc742181ded4930842b46e9507372f0b1b963James Dong ALOGE("b/23705695"); 2860c1bc742181ded4930842b46e9507372f0b1b963James Dong return UNKNOWN_ERROR; 2870c1bc742181ded4930842b46e9507372f0b1b963James Dong } 2880c1bc742181ded4930842b46e9507372f0b1b963James Dong 2890c1bc742181ded4930842b46e9507372f0b1b963James Dong mBitrate = totalBitrate; 2900c1bc742181ded4930842b46e9507372f0b1b963James Dong 2910c1bc742181ded4930842b46e9507372f0b1b963James Dong return OK; 2920c1bc742181ded4930842b46e9507372f0b1b963James Dong} 2930c1bc742181ded4930842b46e9507372f0b1b963James Dong 2940c1bc742181ded4930842b46e9507372f0b1b963James Dongstatus_t NuPlayer::GenericSource::startSources() { 2950c1bc742181ded4930842b46e9507372f0b1b963James Dong // Start the selected A/V tracks now before we start buffering. 2960c1bc742181ded4930842b46e9507372f0b1b963James Dong // Widevine sources might re-initialize crypto when starting, if we delay 2970c1bc742181ded4930842b46e9507372f0b1b963James Dong // this to start(), all data buffered during prepare would be wasted. 2980c1bc742181ded4930842b46e9507372f0b1b963James Dong // (We don't actually start reading until start().) 2990c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) { 3000c1bc742181ded4930842b46e9507372f0b1b963James Dong ALOGE("failed to start audio track!"); 3010c1bc742181ded4930842b46e9507372f0b1b963James Dong return UNKNOWN_ERROR; 3020c1bc742181ded4930842b46e9507372f0b1b963James Dong } 3030c1bc742181ded4930842b46e9507372f0b1b963James Dong 3040c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mVideoTrack.mSource != NULL && mVideoTrack.mSource->start() != OK) { 3050c1bc742181ded4930842b46e9507372f0b1b963James Dong ALOGE("failed to start video track!"); 3060c1bc742181ded4930842b46e9507372f0b1b963James Dong return UNKNOWN_ERROR; 3070c1bc742181ded4930842b46e9507372f0b1b963James Dong } 3080c1bc742181ded4930842b46e9507372f0b1b963James Dong 3090c1bc742181ded4930842b46e9507372f0b1b963James Dong return OK; 3100c1bc742181ded4930842b46e9507372f0b1b963James Dong} 3110c1bc742181ded4930842b46e9507372f0b1b963James Dong 3120c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid NuPlayer::GenericSource::checkDrmStatus(const sp<DataSource>& dataSource) { 3130c1bc742181ded4930842b46e9507372f0b1b963James Dong dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient); 3140c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mDecryptHandle != NULL) { 3150c1bc742181ded4930842b46e9507372f0b1b963James Dong CHECK(mDrmManagerClient); 3160c1bc742181ded4930842b46e9507372f0b1b963James Dong if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) { 3170c1bc742181ded4930842b46e9507372f0b1b963James Dong sp<AMessage> msg = dupNotify(); 3180c1bc742181ded4930842b46e9507372f0b1b963James Dong msg->setInt32("what", kWhatDrmNoLicense); 3190c1bc742181ded4930842b46e9507372f0b1b963James Dong msg->post(); 3200c1bc742181ded4930842b46e9507372f0b1b963James Dong } 3210c1bc742181ded4930842b46e9507372f0b1b963James Dong } 3220c1bc742181ded4930842b46e9507372f0b1b963James Dong} 3230c1bc742181ded4930842b46e9507372f0b1b963James Dong 3240c1bc742181ded4930842b46e9507372f0b1b963James Dongint64_t NuPlayer::GenericSource::getLastReadPosition() { 3250c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mAudioTrack.mSource != NULL) { 3260c1bc742181ded4930842b46e9507372f0b1b963James Dong return mAudioTimeUs; 3270c1bc742181ded4930842b46e9507372f0b1b963James Dong } else if (mVideoTrack.mSource != NULL) { 3280c1bc742181ded4930842b46e9507372f0b1b963James Dong return mVideoTimeUs; 3290c1bc742181ded4930842b46e9507372f0b1b963James Dong } else { 3300c1bc742181ded4930842b46e9507372f0b1b963James Dong return 0; 3310c1bc742181ded4930842b46e9507372f0b1b963James Dong } 3320c1bc742181ded4930842b46e9507372f0b1b963James Dong} 3330c1bc742181ded4930842b46e9507372f0b1b963James Dong 3340c1bc742181ded4930842b46e9507372f0b1b963James Dongstatus_t NuPlayer::GenericSource::setBuffers( 3350c1bc742181ded4930842b46e9507372f0b1b963James Dong bool audio, Vector<MediaBuffer *> &buffers) { 3360c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mIsSecure && !audio && mVideoTrack.mSource != NULL) { 3370c1bc742181ded4930842b46e9507372f0b1b963James Dong return mVideoTrack.mSource->setBuffers(buffers); 3380c1bc742181ded4930842b46e9507372f0b1b963James Dong } 3390c1bc742181ded4930842b46e9507372f0b1b963James Dong return INVALID_OPERATION; 3400c1bc742181ded4930842b46e9507372f0b1b963James Dong} 3410c1bc742181ded4930842b46e9507372f0b1b963James Dong 3420c1bc742181ded4930842b46e9507372f0b1b963James Dongbool NuPlayer::GenericSource::isStreaming() const { 3430c1bc742181ded4930842b46e9507372f0b1b963James Dong return mIsStreaming; 3440c1bc742181ded4930842b46e9507372f0b1b963James Dong} 3450c1bc742181ded4930842b46e9507372f0b1b963James Dong 3460c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid NuPlayer::GenericSource::setOffloadAudio(bool offload) { 3470c1bc742181ded4930842b46e9507372f0b1b963James Dong mBufferingMonitor->setOffloadAudio(offload); 3480c1bc742181ded4930842b46e9507372f0b1b963James Dong} 3490c1bc742181ded4930842b46e9507372f0b1b963James Dong 3500c1bc742181ded4930842b46e9507372f0b1b963James DongNuPlayer::GenericSource::~GenericSource() { 3510c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mLooper != NULL) { 3520c1bc742181ded4930842b46e9507372f0b1b963James Dong mLooper->unregisterHandler(id()); 3530c1bc742181ded4930842b46e9507372f0b1b963James Dong mLooper->stop(); 3540c1bc742181ded4930842b46e9507372f0b1b963James Dong } 3550c1bc742181ded4930842b46e9507372f0b1b963James Dong resetDataSource(); 3560c1bc742181ded4930842b46e9507372f0b1b963James Dong} 3570c1bc742181ded4930842b46e9507372f0b1b963James Dong 3580c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid NuPlayer::GenericSource::prepareAsync() { 3590c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mLooper == NULL) { 3600c1bc742181ded4930842b46e9507372f0b1b963James Dong mLooper = new ALooper; 3610c1bc742181ded4930842b46e9507372f0b1b963James Dong mLooper->setName("generic"); 3620c1bc742181ded4930842b46e9507372f0b1b963James Dong mLooper->start(); 3630c1bc742181ded4930842b46e9507372f0b1b963James Dong 3640c1bc742181ded4930842b46e9507372f0b1b963James Dong mLooper->registerHandler(this); 3650c1bc742181ded4930842b46e9507372f0b1b963James Dong } 3660c1bc742181ded4930842b46e9507372f0b1b963James Dong 3670c1bc742181ded4930842b46e9507372f0b1b963James Dong sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this); 3680c1bc742181ded4930842b46e9507372f0b1b963James Dong msg->post(); 3690c1bc742181ded4930842b46e9507372f0b1b963James Dong} 3700c1bc742181ded4930842b46e9507372f0b1b963James Dong 3710c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid NuPlayer::GenericSource::onPrepareAsync() { 3720c1bc742181ded4930842b46e9507372f0b1b963James Dong // delayed data source creation 3730c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mDataSource == NULL) { 3740c1bc742181ded4930842b46e9507372f0b1b963James Dong // set to false first, if the extractor 3750c1bc742181ded4930842b46e9507372f0b1b963James Dong // comes back as secure, set it to true then. 3760c1bc742181ded4930842b46e9507372f0b1b963James Dong mIsSecure = false; 3770c1bc742181ded4930842b46e9507372f0b1b963James Dong 3780c1bc742181ded4930842b46e9507372f0b1b963James Dong if (!mUri.empty()) { 3790c1bc742181ded4930842b46e9507372f0b1b963James Dong const char* uri = mUri.c_str(); 3800c1bc742181ded4930842b46e9507372f0b1b963James Dong String8 contentType; 3810c1bc742181ded4930842b46e9507372f0b1b963James Dong mIsWidevine = !strncasecmp(uri, "widevine://", 11); 3820c1bc742181ded4930842b46e9507372f0b1b963James Dong 3830c1bc742181ded4930842b46e9507372f0b1b963James Dong if (!strncasecmp("http://", uri, 7) 3840c1bc742181ded4930842b46e9507372f0b1b963James Dong || !strncasecmp("https://", uri, 8) 3850c1bc742181ded4930842b46e9507372f0b1b963James Dong || mIsWidevine) { 3860c1bc742181ded4930842b46e9507372f0b1b963James Dong mHttpSource = DataSource::CreateMediaHTTP(mHTTPService); 3870c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mHttpSource == NULL) { 3880c1bc742181ded4930842b46e9507372f0b1b963James Dong ALOGE("Failed to create http source!"); 3890c1bc742181ded4930842b46e9507372f0b1b963James Dong notifyPreparedAndCleanup(UNKNOWN_ERROR); 3900c1bc742181ded4930842b46e9507372f0b1b963James Dong return; 3910c1bc742181ded4930842b46e9507372f0b1b963James Dong } 3920c1bc742181ded4930842b46e9507372f0b1b963James Dong } 3930c1bc742181ded4930842b46e9507372f0b1b963James Dong 3940c1bc742181ded4930842b46e9507372f0b1b963James Dong mDataSource = DataSource::CreateFromURI( 3950c1bc742181ded4930842b46e9507372f0b1b963James Dong mHTTPService, uri, &mUriHeaders, &contentType, 3960c1bc742181ded4930842b46e9507372f0b1b963James Dong static_cast<HTTPBase *>(mHttpSource.get())); 3970c1bc742181ded4930842b46e9507372f0b1b963James Dong } else { 3980c1bc742181ded4930842b46e9507372f0b1b963James Dong mIsWidevine = false; 3990c1bc742181ded4930842b46e9507372f0b1b963James Dong 4000c1bc742181ded4930842b46e9507372f0b1b963James Dong mDataSource = new FileSource(mFd, mOffset, mLength); 4010c1bc742181ded4930842b46e9507372f0b1b963James Dong mFd = -1; 4020c1bc742181ded4930842b46e9507372f0b1b963James Dong } 4030c1bc742181ded4930842b46e9507372f0b1b963James Dong 4040c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mDataSource == NULL) { 4050c1bc742181ded4930842b46e9507372f0b1b963James Dong ALOGE("Failed to create data source!"); 4060c1bc742181ded4930842b46e9507372f0b1b963James Dong notifyPreparedAndCleanup(UNKNOWN_ERROR); 4070c1bc742181ded4930842b46e9507372f0b1b963James Dong return; 4080c1bc742181ded4930842b46e9507372f0b1b963James Dong } 4090c1bc742181ded4930842b46e9507372f0b1b963James Dong } 4100c1bc742181ded4930842b46e9507372f0b1b963James Dong 4110c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mDataSource->flags() & DataSource::kIsCachingDataSource) { 4120c1bc742181ded4930842b46e9507372f0b1b963James Dong mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get()); 4130c1bc742181ded4930842b46e9507372f0b1b963James Dong } 4140c1bc742181ded4930842b46e9507372f0b1b963James Dong 4150c1bc742181ded4930842b46e9507372f0b1b963James Dong // For widevine or other cached streaming cases, we need to wait for 4160c1bc742181ded4930842b46e9507372f0b1b963James Dong // enough buffering before reporting prepared. 4170c1bc742181ded4930842b46e9507372f0b1b963James Dong // Note that even when URL doesn't start with widevine://, mIsWidevine 4180c1bc742181ded4930842b46e9507372f0b1b963James Dong // could still be set to true later, if the streaming or file source 4190c1bc742181ded4930842b46e9507372f0b1b963James Dong // is sniffed to be widevine. We don't want to buffer for file source 4200c1bc742181ded4930842b46e9507372f0b1b963James Dong // in that case, so must check the flag now. 4210c1bc742181ded4930842b46e9507372f0b1b963James Dong mIsStreaming = (mIsWidevine || mCachedSource != NULL); 4220c1bc742181ded4930842b46e9507372f0b1b963James Dong 4230c1bc742181ded4930842b46e9507372f0b1b963James Dong // init extractor from data source 4240c1bc742181ded4930842b46e9507372f0b1b963James Dong status_t err = initFromDataSource(); 4250c1bc742181ded4930842b46e9507372f0b1b963James Dong 4260c1bc742181ded4930842b46e9507372f0b1b963James Dong if (err != OK) { 4270c1bc742181ded4930842b46e9507372f0b1b963James Dong ALOGE("Failed to init from data source!"); 4280c1bc742181ded4930842b46e9507372f0b1b963James Dong notifyPreparedAndCleanup(err); 4290c1bc742181ded4930842b46e9507372f0b1b963James Dong return; 4300c1bc742181ded4930842b46e9507372f0b1b963James Dong } 4310c1bc742181ded4930842b46e9507372f0b1b963James Dong 4320c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mVideoTrack.mSource != NULL) { 4330c1bc742181ded4930842b46e9507372f0b1b963James Dong sp<MetaData> meta = doGetFormatMeta(false /* audio */); 4340c1bc742181ded4930842b46e9507372f0b1b963James Dong sp<AMessage> msg = new AMessage; 4350c1bc742181ded4930842b46e9507372f0b1b963James Dong err = convertMetaDataToMessage(meta, &msg); 4360c1bc742181ded4930842b46e9507372f0b1b963James Dong if(err != OK) { 4370c1bc742181ded4930842b46e9507372f0b1b963James Dong notifyPreparedAndCleanup(err); 4380c1bc742181ded4930842b46e9507372f0b1b963James Dong return; 4390c1bc742181ded4930842b46e9507372f0b1b963James Dong } 4400c1bc742181ded4930842b46e9507372f0b1b963James Dong notifyVideoSizeChanged(msg); 4410c1bc742181ded4930842b46e9507372f0b1b963James Dong } 4420c1bc742181ded4930842b46e9507372f0b1b963James Dong 4430c1bc742181ded4930842b46e9507372f0b1b963James Dong notifyFlagsChanged( 4440c1bc742181ded4930842b46e9507372f0b1b963James Dong (mIsSecure ? FLAG_SECURE : 0) 4450c1bc742181ded4930842b46e9507372f0b1b963James Dong | (mDecryptHandle != NULL ? FLAG_PROTECTED : 0) 4460c1bc742181ded4930842b46e9507372f0b1b963James Dong | FLAG_CAN_PAUSE 4470c1bc742181ded4930842b46e9507372f0b1b963James Dong | FLAG_CAN_SEEK_BACKWARD 4480c1bc742181ded4930842b46e9507372f0b1b963James Dong | FLAG_CAN_SEEK_FORWARD 4490c1bc742181ded4930842b46e9507372f0b1b963James Dong | FLAG_CAN_SEEK); 4500c1bc742181ded4930842b46e9507372f0b1b963James Dong 4510c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mIsSecure) { 4520c1bc742181ded4930842b46e9507372f0b1b963James Dong // secure decoders must be instantiated before starting widevine source 4530c1bc742181ded4930842b46e9507372f0b1b963James Dong sp<AMessage> reply = new AMessage(kWhatSecureDecodersInstantiated, this); 4540c1bc742181ded4930842b46e9507372f0b1b963James Dong notifyInstantiateSecureDecoders(reply); 4550c1bc742181ded4930842b46e9507372f0b1b963James Dong } else { 4560c1bc742181ded4930842b46e9507372f0b1b963James Dong finishPrepareAsync(); 4570c1bc742181ded4930842b46e9507372f0b1b963James Dong } 4580c1bc742181ded4930842b46e9507372f0b1b963James Dong} 4590c1bc742181ded4930842b46e9507372f0b1b963James Dong 4600c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid NuPlayer::GenericSource::onSecureDecodersInstantiated(status_t err) { 4610c1bc742181ded4930842b46e9507372f0b1b963James Dong if (err != OK) { 4620c1bc742181ded4930842b46e9507372f0b1b963James Dong ALOGE("Failed to instantiate secure decoders!"); 4630c1bc742181ded4930842b46e9507372f0b1b963James Dong notifyPreparedAndCleanup(err); 4640c1bc742181ded4930842b46e9507372f0b1b963James Dong return; 4650c1bc742181ded4930842b46e9507372f0b1b963James Dong } 4660c1bc742181ded4930842b46e9507372f0b1b963James Dong finishPrepareAsync(); 4670c1bc742181ded4930842b46e9507372f0b1b963James Dong} 4680c1bc742181ded4930842b46e9507372f0b1b963James Dong 4690c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid NuPlayer::GenericSource::finishPrepareAsync() { 4700c1bc742181ded4930842b46e9507372f0b1b963James Dong status_t err = startSources(); 4710c1bc742181ded4930842b46e9507372f0b1b963James Dong if (err != OK) { 4720c1bc742181ded4930842b46e9507372f0b1b963James Dong ALOGE("Failed to init start data source!"); 4730c1bc742181ded4930842b46e9507372f0b1b963James Dong notifyPreparedAndCleanup(err); 4740c1bc742181ded4930842b46e9507372f0b1b963James Dong return; 4750c1bc742181ded4930842b46e9507372f0b1b963James Dong } 4760c1bc742181ded4930842b46e9507372f0b1b963James Dong 4770c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mIsStreaming) { 4780c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mBufferingMonitorLooper == NULL) { 4790c1bc742181ded4930842b46e9507372f0b1b963James Dong mBufferingMonitor->prepare(mCachedSource, mWVMExtractor, mDurationUs, mBitrate, 4800c1bc742181ded4930842b46e9507372f0b1b963James Dong mIsStreaming); 4810c1bc742181ded4930842b46e9507372f0b1b963James Dong 4820c1bc742181ded4930842b46e9507372f0b1b963James Dong mBufferingMonitorLooper = new ALooper; 4830c1bc742181ded4930842b46e9507372f0b1b963James Dong mBufferingMonitorLooper->setName("GSBMonitor"); 4840c1bc742181ded4930842b46e9507372f0b1b963James Dong mBufferingMonitorLooper->start(); 4850c1bc742181ded4930842b46e9507372f0b1b963James Dong mBufferingMonitorLooper->registerHandler(mBufferingMonitor); 4860c1bc742181ded4930842b46e9507372f0b1b963James Dong } 4870c1bc742181ded4930842b46e9507372f0b1b963James Dong 4880c1bc742181ded4930842b46e9507372f0b1b963James Dong mBufferingMonitor->ensureCacheIsFetching(); 4890c1bc742181ded4930842b46e9507372f0b1b963James Dong mBufferingMonitor->restartPollBuffering(); 4900c1bc742181ded4930842b46e9507372f0b1b963James Dong } else { 4910c1bc742181ded4930842b46e9507372f0b1b963James Dong notifyPrepared(); 4920c1bc742181ded4930842b46e9507372f0b1b963James Dong } 4930c1bc742181ded4930842b46e9507372f0b1b963James Dong} 4940c1bc742181ded4930842b46e9507372f0b1b963James Dong 4950c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) { 4960c1bc742181ded4930842b46e9507372f0b1b963James Dong if (err != OK) { 4970c1bc742181ded4930842b46e9507372f0b1b963James Dong { 4980c1bc742181ded4930842b46e9507372f0b1b963James Dong sp<DataSource> dataSource = mDataSource; 4990c1bc742181ded4930842b46e9507372f0b1b963James Dong sp<NuCachedSource2> cachedSource = mCachedSource; 5000c1bc742181ded4930842b46e9507372f0b1b963James Dong sp<DataSource> httpSource = mHttpSource; 5010c1bc742181ded4930842b46e9507372f0b1b963James Dong { 5020c1bc742181ded4930842b46e9507372f0b1b963James Dong Mutex::Autolock _l(mDisconnectLock); 5030c1bc742181ded4930842b46e9507372f0b1b963James Dong mDataSource.clear(); 5040c1bc742181ded4930842b46e9507372f0b1b963James Dong mDecryptHandle = NULL; 5050c1bc742181ded4930842b46e9507372f0b1b963James Dong mDrmManagerClient = NULL; 5060c1bc742181ded4930842b46e9507372f0b1b963James Dong mCachedSource.clear(); 5070c1bc742181ded4930842b46e9507372f0b1b963James Dong mHttpSource.clear(); 5080c1bc742181ded4930842b46e9507372f0b1b963James Dong } 5090c1bc742181ded4930842b46e9507372f0b1b963James Dong } 5100c1bc742181ded4930842b46e9507372f0b1b963James Dong mBitrate = -1; 5110c1bc742181ded4930842b46e9507372f0b1b963James Dong 5120c1bc742181ded4930842b46e9507372f0b1b963James Dong mBufferingMonitor->cancelPollBuffering(); 5130c1bc742181ded4930842b46e9507372f0b1b963James Dong } 5140c1bc742181ded4930842b46e9507372f0b1b963James Dong notifyPrepared(err); 5150c1bc742181ded4930842b46e9507372f0b1b963James Dong} 5160c1bc742181ded4930842b46e9507372f0b1b963James Dong 5170c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid NuPlayer::GenericSource::start() { 5180c1bc742181ded4930842b46e9507372f0b1b963James Dong ALOGI("start"); 5190c1bc742181ded4930842b46e9507372f0b1b963James Dong 5200c1bc742181ded4930842b46e9507372f0b1b963James Dong mStopRead = false; 5210c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mAudioTrack.mSource != NULL) { 5220c1bc742181ded4930842b46e9507372f0b1b963James Dong postReadBuffer(MEDIA_TRACK_TYPE_AUDIO); 5230c1bc742181ded4930842b46e9507372f0b1b963James Dong } 5240c1bc742181ded4930842b46e9507372f0b1b963James Dong 5250c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mVideoTrack.mSource != NULL) { 5260c1bc742181ded4930842b46e9507372f0b1b963James Dong postReadBuffer(MEDIA_TRACK_TYPE_VIDEO); 5270c1bc742181ded4930842b46e9507372f0b1b963James Dong } 5280c1bc742181ded4930842b46e9507372f0b1b963James Dong 5290c1bc742181ded4930842b46e9507372f0b1b963James Dong setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000); 5300c1bc742181ded4930842b46e9507372f0b1b963James Dong mStarted = true; 5310c1bc742181ded4930842b46e9507372f0b1b963James Dong 5320c1bc742181ded4930842b46e9507372f0b1b963James Dong (new AMessage(kWhatStart, this))->post(); 5330c1bc742181ded4930842b46e9507372f0b1b963James Dong} 5340c1bc742181ded4930842b46e9507372f0b1b963James Dong 5350c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid NuPlayer::GenericSource::stop() { 5360c1bc742181ded4930842b46e9507372f0b1b963James Dong // nothing to do, just account for DRM playback status 5370c1bc742181ded4930842b46e9507372f0b1b963James Dong setDrmPlaybackStatusIfNeeded(Playback::STOP, 0); 5380c1bc742181ded4930842b46e9507372f0b1b963James Dong mStarted = false; 5390c1bc742181ded4930842b46e9507372f0b1b963James Dong if (mIsWidevine || mIsSecure) { 5400c1bc742181ded4930842b46e9507372f0b1b963James Dong // For widevine or secure sources we need to prevent any further reads. 5410c1bc742181ded4930842b46e9507372f0b1b963James Dong sp<AMessage> msg = new AMessage(kWhatStopWidevine, this); 5420c1bc742181ded4930842b46e9507372f0b1b963James Dong sp<AMessage> response; 5430c1bc742181ded4930842b46e9507372f0b1b963James Dong (void) msg->postAndAwaitResponse(&response); 5440c1bc742181ded4930842b46e9507372f0b1b963James Dong } 5450c1bc742181ded4930842b46e9507372f0b1b963James Dong} 5460c1bc742181ded4930842b46e9507372f0b1b963James Dong 5470c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid NuPlayer::GenericSource::pause() { 5480c1bc742181ded4930842b46e9507372f0b1b963James Dong // nothing to do, just account for DRM playback status 5490c1bc742181ded4930842b46e9507372f0b1b963James Dong setDrmPlaybackStatusIfNeeded(Playback::PAUSE, 0); 5500c1bc742181ded4930842b46e9507372f0b1b963James Dong mStarted = false; 5510c1bc742181ded4930842b46e9507372f0b1b963James Dong} 5520c1bc742181ded4930842b46e9507372f0b1b963James Dong 5530c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid NuPlayer::GenericSource::resume() { 5540c1bc742181ded4930842b46e9507372f0b1b963James Dong // nothing to do, just account for DRM playback status 5550c1bc742181ded4930842b46e9507372f0b1b963James Dong setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000); 5560c1bc742181ded4930842b46e9507372f0b1b963James Dong mStarted = true; 5570c1bc742181ded4930842b46e9507372f0b1b963James Dong 5580c1bc742181ded4930842b46e9507372f0b1b963James Dong (new AMessage(kWhatResume, this))->post(); 5590c1bc742181ded4930842b46e9507372f0b1b963James Dong} 5600c1bc742181ded4930842b46e9507372f0b1b963James Dong 5610c1bc742181ded4930842b46e9507372f0b1b963James Dongvoid NuPlayer::GenericSource::disconnect() { 5620c1bc742181ded4930842b46e9507372f0b1b963James Dong sp<DataSource> dataSource, httpSource; 5630c1bc742181ded4930842b46e9507372f0b1b963James Dong { 5640c1bc742181ded4930842b46e9507372f0b1b963James Dong Mutex::Autolock _l(mDisconnectLock); 5650c1bc742181ded4930842b46e9507372f0b1b963James Dong dataSource = mDataSource; 5660c1bc742181ded4930842b46e9507372f0b1b963James Dong httpSource = mHttpSource; 5670c1bc742181ded4930842b46e9507372f0b1b963James Dong } 568 569 if (dataSource != NULL) { 570 // disconnect data source 571 if (dataSource->flags() & DataSource::kIsCachingDataSource) { 572 static_cast<NuCachedSource2 *>(dataSource.get())->disconnect(); 573 } 574 } else if (httpSource != NULL) { 575 static_cast<HTTPBase *>(httpSource.get())->disconnect(); 576 } 577} 578 579void NuPlayer::GenericSource::setDrmPlaybackStatusIfNeeded(int playbackStatus, int64_t position) { 580 if (mDecryptHandle != NULL) { 581 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, playbackStatus, position); 582 } 583 mSubtitleTrack.mPackets = new AnotherPacketSource(NULL); 584 mTimedTextTrack.mPackets = new AnotherPacketSource(NULL); 585} 586 587status_t NuPlayer::GenericSource::feedMoreTSData() { 588 return OK; 589} 590 591void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) { 592 switch (msg->what()) { 593 case kWhatPrepareAsync: 594 { 595 onPrepareAsync(); 596 break; 597 } 598 case kWhatFetchSubtitleData: 599 { 600 fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE, 601 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg); 602 break; 603 } 604 605 case kWhatFetchTimedTextData: 606 { 607 fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT, 608 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg); 609 break; 610 } 611 612 case kWhatSendSubtitleData: 613 { 614 sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE, 615 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg); 616 break; 617 } 618 619 case kWhatSendGlobalTimedTextData: 620 { 621 sendGlobalTextData(kWhatTimedTextData, mFetchTimedTextDataGeneration, msg); 622 break; 623 } 624 case kWhatSendTimedTextData: 625 { 626 sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT, 627 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg); 628 break; 629 } 630 631 case kWhatChangeAVSource: 632 { 633 int32_t trackIndex; 634 CHECK(msg->findInt32("trackIndex", &trackIndex)); 635 const sp<IMediaSource> source = mSources.itemAt(trackIndex); 636 637 Track* track; 638 const char *mime; 639 media_track_type trackType, counterpartType; 640 sp<MetaData> meta = source->getFormat(); 641 meta->findCString(kKeyMIMEType, &mime); 642 if (!strncasecmp(mime, "audio/", 6)) { 643 track = &mAudioTrack; 644 trackType = MEDIA_TRACK_TYPE_AUDIO; 645 counterpartType = MEDIA_TRACK_TYPE_VIDEO;; 646 } else { 647 CHECK(!strncasecmp(mime, "video/", 6)); 648 track = &mVideoTrack; 649 trackType = MEDIA_TRACK_TYPE_VIDEO; 650 counterpartType = MEDIA_TRACK_TYPE_AUDIO;; 651 } 652 653 654 if (track->mSource != NULL) { 655 track->mSource->stop(); 656 } 657 track->mSource = source; 658 track->mSource->start(); 659 track->mIndex = trackIndex; 660 661 int64_t timeUs, actualTimeUs; 662 const bool formatChange = true; 663 if (trackType == MEDIA_TRACK_TYPE_AUDIO) { 664 timeUs = mAudioLastDequeueTimeUs; 665 } else { 666 timeUs = mVideoLastDequeueTimeUs; 667 } 668 readBuffer(trackType, timeUs, &actualTimeUs, formatChange); 669 readBuffer(counterpartType, -1, NULL, formatChange); 670 ALOGV("timeUs %lld actualTimeUs %lld", (long long)timeUs, (long long)actualTimeUs); 671 672 break; 673 } 674 675 case kWhatStart: 676 case kWhatResume: 677 { 678 mBufferingMonitor->restartPollBuffering(); 679 break; 680 } 681 682 case kWhatGetFormat: 683 { 684 onGetFormatMeta(msg); 685 break; 686 } 687 688 case kWhatGetSelectedTrack: 689 { 690 onGetSelectedTrack(msg); 691 break; 692 } 693 694 case kWhatSelectTrack: 695 { 696 onSelectTrack(msg); 697 break; 698 } 699 700 case kWhatSeek: 701 { 702 onSeek(msg); 703 break; 704 } 705 706 case kWhatReadBuffer: 707 { 708 onReadBuffer(msg); 709 break; 710 } 711 712 case kWhatSecureDecodersInstantiated: 713 { 714 int32_t err; 715 CHECK(msg->findInt32("err", &err)); 716 onSecureDecodersInstantiated(err); 717 break; 718 } 719 720 case kWhatStopWidevine: 721 { 722 // mStopRead is only used for Widevine to prevent the video source 723 // from being read while the associated video decoder is shutting down. 724 mStopRead = true; 725 if (mVideoTrack.mSource != NULL) { 726 mVideoTrack.mPackets->clear(); 727 } 728 sp<AMessage> response = new AMessage; 729 sp<AReplyToken> replyID; 730 CHECK(msg->senderAwaitsResponse(&replyID)); 731 response->postReply(replyID); 732 break; 733 } 734 default: 735 Source::onMessageReceived(msg); 736 break; 737 } 738} 739 740void NuPlayer::GenericSource::fetchTextData( 741 uint32_t sendWhat, 742 media_track_type type, 743 int32_t curGen, 744 sp<AnotherPacketSource> packets, 745 sp<AMessage> msg) { 746 int32_t msgGeneration; 747 CHECK(msg->findInt32("generation", &msgGeneration)); 748 if (msgGeneration != curGen) { 749 // stale 750 return; 751 } 752 753 int32_t avail; 754 if (packets->hasBufferAvailable(&avail)) { 755 return; 756 } 757 758 int64_t timeUs; 759 CHECK(msg->findInt64("timeUs", &timeUs)); 760 761 int64_t subTimeUs; 762 readBuffer(type, timeUs, &subTimeUs); 763 764 int64_t delayUs = subTimeUs - timeUs; 765 if (msg->what() == kWhatFetchSubtitleData) { 766 const int64_t oneSecUs = 1000000ll; 767 delayUs -= oneSecUs; 768 } 769 sp<AMessage> msg2 = new AMessage(sendWhat, this); 770 msg2->setInt32("generation", msgGeneration); 771 msg2->post(delayUs < 0 ? 0 : delayUs); 772} 773 774void NuPlayer::GenericSource::sendTextData( 775 uint32_t what, 776 media_track_type type, 777 int32_t curGen, 778 sp<AnotherPacketSource> packets, 779 sp<AMessage> msg) { 780 int32_t msgGeneration; 781 CHECK(msg->findInt32("generation", &msgGeneration)); 782 if (msgGeneration != curGen) { 783 // stale 784 return; 785 } 786 787 int64_t subTimeUs; 788 if (packets->nextBufferTime(&subTimeUs) != OK) { 789 return; 790 } 791 792 int64_t nextSubTimeUs; 793 readBuffer(type, -1, &nextSubTimeUs); 794 795 sp<ABuffer> buffer; 796 status_t dequeueStatus = packets->dequeueAccessUnit(&buffer); 797 if (dequeueStatus == OK) { 798 sp<AMessage> notify = dupNotify(); 799 notify->setInt32("what", what); 800 notify->setBuffer("buffer", buffer); 801 notify->post(); 802 803 const int64_t delayUs = nextSubTimeUs - subTimeUs; 804 msg->post(delayUs < 0 ? 0 : delayUs); 805 } 806} 807 808void NuPlayer::GenericSource::sendGlobalTextData( 809 uint32_t what, 810 int32_t curGen, 811 sp<AMessage> msg) { 812 int32_t msgGeneration; 813 CHECK(msg->findInt32("generation", &msgGeneration)); 814 if (msgGeneration != curGen) { 815 // stale 816 return; 817 } 818 819 uint32_t textType; 820 const void *data; 821 size_t size = 0; 822 if (mTimedTextTrack.mSource->getFormat()->findData( 823 kKeyTextFormatData, &textType, &data, &size)) { 824 mGlobalTimedText = new ABuffer(size); 825 if (mGlobalTimedText->data()) { 826 memcpy(mGlobalTimedText->data(), data, size); 827 sp<AMessage> globalMeta = mGlobalTimedText->meta(); 828 globalMeta->setInt64("timeUs", 0); 829 globalMeta->setString("mime", MEDIA_MIMETYPE_TEXT_3GPP); 830 globalMeta->setInt32("global", 1); 831 sp<AMessage> notify = dupNotify(); 832 notify->setInt32("what", what); 833 notify->setBuffer("buffer", mGlobalTimedText); 834 notify->post(); 835 } 836 } 837} 838 839sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) { 840 sp<AMessage> msg = new AMessage(kWhatGetFormat, this); 841 msg->setInt32("audio", audio); 842 843 sp<AMessage> response; 844 sp<RefBase> format; 845 status_t err = msg->postAndAwaitResponse(&response); 846 if (err == OK && response != NULL) { 847 CHECK(response->findObject("format", &format)); 848 return static_cast<MetaData*>(format.get()); 849 } else { 850 return NULL; 851 } 852} 853 854void NuPlayer::GenericSource::onGetFormatMeta(sp<AMessage> msg) const { 855 int32_t audio; 856 CHECK(msg->findInt32("audio", &audio)); 857 858 sp<AMessage> response = new AMessage; 859 sp<MetaData> format = doGetFormatMeta(audio); 860 response->setObject("format", format); 861 862 sp<AReplyToken> replyID; 863 CHECK(msg->senderAwaitsResponse(&replyID)); 864 response->postReply(replyID); 865} 866 867sp<MetaData> NuPlayer::GenericSource::doGetFormatMeta(bool audio) const { 868 sp<IMediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource; 869 870 if (source == NULL) { 871 return NULL; 872 } 873 874 return source->getFormat(); 875} 876 877status_t NuPlayer::GenericSource::dequeueAccessUnit( 878 bool audio, sp<ABuffer> *accessUnit) { 879 if (audio && !mStarted) { 880 return -EWOULDBLOCK; 881 } 882 883 Track *track = audio ? &mAudioTrack : &mVideoTrack; 884 885 if (track->mSource == NULL) { 886 return -EWOULDBLOCK; 887 } 888 889 if (mIsWidevine && !audio) { 890 // try to read a buffer as we may not have been able to the last time 891 postReadBuffer(MEDIA_TRACK_TYPE_VIDEO); 892 } 893 894 status_t finalResult; 895 if (!track->mPackets->hasBufferAvailable(&finalResult)) { 896 if (finalResult == OK) { 897 postReadBuffer( 898 audio ? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO); 899 return -EWOULDBLOCK; 900 } 901 return finalResult; 902 } 903 904 status_t result = track->mPackets->dequeueAccessUnit(accessUnit); 905 906 // start pulling in more buffers if we only have one (or no) buffer left 907 // so that decoder has less chance of being starved 908 if (track->mPackets->getAvailableBufferCount(&finalResult) < 2) { 909 postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO); 910 } 911 912 if (result != OK) { 913 if (mSubtitleTrack.mSource != NULL) { 914 mSubtitleTrack.mPackets->clear(); 915 mFetchSubtitleDataGeneration++; 916 } 917 if (mTimedTextTrack.mSource != NULL) { 918 mTimedTextTrack.mPackets->clear(); 919 mFetchTimedTextDataGeneration++; 920 } 921 return result; 922 } 923 924 int64_t timeUs; 925 status_t eosResult; // ignored 926 CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs)); 927 if (audio) { 928 mAudioLastDequeueTimeUs = timeUs; 929 mBufferingMonitor->updateDequeuedBufferTime(timeUs); 930 } else { 931 mVideoLastDequeueTimeUs = timeUs; 932 } 933 934 if (mSubtitleTrack.mSource != NULL 935 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) { 936 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this); 937 msg->setInt64("timeUs", timeUs); 938 msg->setInt32("generation", mFetchSubtitleDataGeneration); 939 msg->post(); 940 } 941 942 if (mTimedTextTrack.mSource != NULL 943 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) { 944 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this); 945 msg->setInt64("timeUs", timeUs); 946 msg->setInt32("generation", mFetchTimedTextDataGeneration); 947 msg->post(); 948 } 949 950 return result; 951} 952 953status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) { 954 *durationUs = mDurationUs; 955 return OK; 956} 957 958size_t NuPlayer::GenericSource::getTrackCount() const { 959 return mSources.size(); 960} 961 962sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const { 963 size_t trackCount = mSources.size(); 964 if (trackIndex >= trackCount) { 965 return NULL; 966 } 967 968 sp<AMessage> format = new AMessage(); 969 sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat(); 970 if (meta == NULL) { 971 ALOGE("no metadata for track %zu", trackIndex); 972 return NULL; 973 } 974 975 const char *mime; 976 CHECK(meta->findCString(kKeyMIMEType, &mime)); 977 format->setString("mime", mime); 978 979 int32_t trackType; 980 if (!strncasecmp(mime, "video/", 6)) { 981 trackType = MEDIA_TRACK_TYPE_VIDEO; 982 } else if (!strncasecmp(mime, "audio/", 6)) { 983 trackType = MEDIA_TRACK_TYPE_AUDIO; 984 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) { 985 trackType = MEDIA_TRACK_TYPE_TIMEDTEXT; 986 } else { 987 trackType = MEDIA_TRACK_TYPE_UNKNOWN; 988 } 989 format->setInt32("type", trackType); 990 991 const char *lang; 992 if (!meta->findCString(kKeyMediaLanguage, &lang)) { 993 lang = "und"; 994 } 995 format->setString("language", lang); 996 997 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) { 998 int32_t isAutoselect = 1, isDefault = 0, isForced = 0; 999 meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect); 1000 meta->findInt32(kKeyTrackIsDefault, &isDefault); 1001 meta->findInt32(kKeyTrackIsForced, &isForced); 1002 1003 format->setInt32("auto", !!isAutoselect); 1004 format->setInt32("default", !!isDefault); 1005 format->setInt32("forced", !!isForced); 1006 } 1007 1008 return format; 1009} 1010 1011ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const { 1012 sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, this); 1013 msg->setInt32("type", type); 1014 1015 sp<AMessage> response; 1016 int32_t index; 1017 status_t err = msg->postAndAwaitResponse(&response); 1018 if (err == OK && response != NULL) { 1019 CHECK(response->findInt32("index", &index)); 1020 return index; 1021 } else { 1022 return -1; 1023 } 1024} 1025 1026void NuPlayer::GenericSource::onGetSelectedTrack(sp<AMessage> msg) const { 1027 int32_t tmpType; 1028 CHECK(msg->findInt32("type", &tmpType)); 1029 media_track_type type = (media_track_type)tmpType; 1030 1031 sp<AMessage> response = new AMessage; 1032 ssize_t index = doGetSelectedTrack(type); 1033 response->setInt32("index", index); 1034 1035 sp<AReplyToken> replyID; 1036 CHECK(msg->senderAwaitsResponse(&replyID)); 1037 response->postReply(replyID); 1038} 1039 1040ssize_t NuPlayer::GenericSource::doGetSelectedTrack(media_track_type type) const { 1041 const Track *track = NULL; 1042 switch (type) { 1043 case MEDIA_TRACK_TYPE_VIDEO: 1044 track = &mVideoTrack; 1045 break; 1046 case MEDIA_TRACK_TYPE_AUDIO: 1047 track = &mAudioTrack; 1048 break; 1049 case MEDIA_TRACK_TYPE_TIMEDTEXT: 1050 track = &mTimedTextTrack; 1051 break; 1052 case MEDIA_TRACK_TYPE_SUBTITLE: 1053 track = &mSubtitleTrack; 1054 break; 1055 default: 1056 break; 1057 } 1058 1059 if (track != NULL && track->mSource != NULL) { 1060 return track->mIndex; 1061 } 1062 1063 return -1; 1064} 1065 1066status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select, int64_t timeUs) { 1067 ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex); 1068 sp<AMessage> msg = new AMessage(kWhatSelectTrack, this); 1069 msg->setInt32("trackIndex", trackIndex); 1070 msg->setInt32("select", select); 1071 msg->setInt64("timeUs", timeUs); 1072 1073 sp<AMessage> response; 1074 status_t err = msg->postAndAwaitResponse(&response); 1075 if (err == OK && response != NULL) { 1076 CHECK(response->findInt32("err", &err)); 1077 } 1078 1079 return err; 1080} 1081 1082void NuPlayer::GenericSource::onSelectTrack(sp<AMessage> msg) { 1083 int32_t trackIndex, select; 1084 int64_t timeUs; 1085 CHECK(msg->findInt32("trackIndex", &trackIndex)); 1086 CHECK(msg->findInt32("select", &select)); 1087 CHECK(msg->findInt64("timeUs", &timeUs)); 1088 1089 sp<AMessage> response = new AMessage; 1090 status_t err = doSelectTrack(trackIndex, select, timeUs); 1091 response->setInt32("err", err); 1092 1093 sp<AReplyToken> replyID; 1094 CHECK(msg->senderAwaitsResponse(&replyID)); 1095 response->postReply(replyID); 1096} 1097 1098status_t NuPlayer::GenericSource::doSelectTrack(size_t trackIndex, bool select, int64_t timeUs) { 1099 if (trackIndex >= mSources.size()) { 1100 return BAD_INDEX; 1101 } 1102 1103 if (!select) { 1104 Track* track = NULL; 1105 if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) { 1106 track = &mSubtitleTrack; 1107 mFetchSubtitleDataGeneration++; 1108 } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) { 1109 track = &mTimedTextTrack; 1110 mFetchTimedTextDataGeneration++; 1111 } 1112 if (track == NULL) { 1113 return INVALID_OPERATION; 1114 } 1115 track->mSource->stop(); 1116 track->mSource = NULL; 1117 track->mPackets->clear(); 1118 return OK; 1119 } 1120 1121 const sp<IMediaSource> source = mSources.itemAt(trackIndex); 1122 sp<MetaData> meta = source->getFormat(); 1123 const char *mime; 1124 CHECK(meta->findCString(kKeyMIMEType, &mime)); 1125 if (!strncasecmp(mime, "text/", 5)) { 1126 bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP); 1127 Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack; 1128 if (track->mSource != NULL && track->mIndex == trackIndex) { 1129 return OK; 1130 } 1131 track->mIndex = trackIndex; 1132 if (track->mSource != NULL) { 1133 track->mSource->stop(); 1134 } 1135 track->mSource = mSources.itemAt(trackIndex); 1136 track->mSource->start(); 1137 if (track->mPackets == NULL) { 1138 track->mPackets = new AnotherPacketSource(track->mSource->getFormat()); 1139 } else { 1140 track->mPackets->clear(); 1141 track->mPackets->setFormat(track->mSource->getFormat()); 1142 1143 } 1144 1145 if (isSubtitle) { 1146 mFetchSubtitleDataGeneration++; 1147 } else { 1148 mFetchTimedTextDataGeneration++; 1149 } 1150 1151 status_t eosResult; // ignored 1152 if (mSubtitleTrack.mSource != NULL 1153 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) { 1154 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this); 1155 msg->setInt64("timeUs", timeUs); 1156 msg->setInt32("generation", mFetchSubtitleDataGeneration); 1157 msg->post(); 1158 } 1159 1160 sp<AMessage> msg2 = new AMessage(kWhatSendGlobalTimedTextData, this); 1161 msg2->setInt32("generation", mFetchTimedTextDataGeneration); 1162 msg2->post(); 1163 1164 if (mTimedTextTrack.mSource != NULL 1165 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) { 1166 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this); 1167 msg->setInt64("timeUs", timeUs); 1168 msg->setInt32("generation", mFetchTimedTextDataGeneration); 1169 msg->post(); 1170 } 1171 1172 return OK; 1173 } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) { 1174 bool audio = !strncasecmp(mime, "audio/", 6); 1175 Track *track = audio ? &mAudioTrack : &mVideoTrack; 1176 if (track->mSource != NULL && track->mIndex == trackIndex) { 1177 return OK; 1178 } 1179 1180 sp<AMessage> msg = new AMessage(kWhatChangeAVSource, this); 1181 msg->setInt32("trackIndex", trackIndex); 1182 msg->post(); 1183 return OK; 1184 } 1185 1186 return INVALID_OPERATION; 1187} 1188 1189status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs) { 1190 sp<AMessage> msg = new AMessage(kWhatSeek, this); 1191 msg->setInt64("seekTimeUs", seekTimeUs); 1192 1193 sp<AMessage> response; 1194 status_t err = msg->postAndAwaitResponse(&response); 1195 if (err == OK && response != NULL) { 1196 CHECK(response->findInt32("err", &err)); 1197 } 1198 1199 return err; 1200} 1201 1202void NuPlayer::GenericSource::onSeek(sp<AMessage> msg) { 1203 int64_t seekTimeUs; 1204 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs)); 1205 1206 sp<AMessage> response = new AMessage; 1207 status_t err = doSeek(seekTimeUs); 1208 response->setInt32("err", err); 1209 1210 sp<AReplyToken> replyID; 1211 CHECK(msg->senderAwaitsResponse(&replyID)); 1212 response->postReply(replyID); 1213} 1214 1215status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs) { 1216 mBufferingMonitor->updateDequeuedBufferTime(-1ll); 1217 1218 // If the Widevine source is stopped, do not attempt to read any 1219 // more buffers. 1220 if (mStopRead) { 1221 return INVALID_OPERATION; 1222 } 1223 if (mVideoTrack.mSource != NULL) { 1224 int64_t actualTimeUs; 1225 readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, &actualTimeUs); 1226 1227 seekTimeUs = actualTimeUs; 1228 mVideoLastDequeueTimeUs = seekTimeUs; 1229 } 1230 1231 if (mAudioTrack.mSource != NULL) { 1232 readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs); 1233 mAudioLastDequeueTimeUs = seekTimeUs; 1234 } 1235 1236 setDrmPlaybackStatusIfNeeded(Playback::START, seekTimeUs / 1000); 1237 if (!mStarted) { 1238 setDrmPlaybackStatusIfNeeded(Playback::PAUSE, 0); 1239 } 1240 1241 // If currently buffering, post kWhatBufferingEnd first, so that 1242 // NuPlayer resumes. Otherwise, if cache hits high watermark 1243 // before new polling happens, no one will resume the playback. 1244 mBufferingMonitor->stopBufferingIfNecessary(); 1245 mBufferingMonitor->restartPollBuffering(); 1246 1247 return OK; 1248} 1249 1250sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer( 1251 MediaBuffer* mb, 1252 media_track_type trackType, 1253 int64_t /* seekTimeUs */, 1254 int64_t *actualTimeUs) { 1255 bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO; 1256 size_t outLength = mb->range_length(); 1257 1258 if (audio && mAudioIsVorbis) { 1259 outLength += sizeof(int32_t); 1260 } 1261 1262 sp<ABuffer> ab; 1263 if (mIsSecure && !audio) { 1264 // data is already provided in the buffer 1265 ab = new ABuffer(NULL, mb->range_length()); 1266 mb->add_ref(); 1267 ab->setMediaBufferBase(mb); 1268 } else { 1269 ab = new ABuffer(outLength); 1270 memcpy(ab->data(), 1271 (const uint8_t *)mb->data() + mb->range_offset(), 1272 mb->range_length()); 1273 } 1274 1275 if (audio && mAudioIsVorbis) { 1276 int32_t numPageSamples; 1277 if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) { 1278 numPageSamples = -1; 1279 } 1280 1281 uint8_t* abEnd = ab->data() + mb->range_length(); 1282 memcpy(abEnd, &numPageSamples, sizeof(numPageSamples)); 1283 } 1284 1285 sp<AMessage> meta = ab->meta(); 1286 1287 int64_t timeUs; 1288 CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs)); 1289 meta->setInt64("timeUs", timeUs); 1290 1291#if 0 1292 // Temporarily disable pre-roll till we have a full solution to handle 1293 // both single seek and continous seek gracefully. 1294 if (seekTimeUs > timeUs) { 1295 sp<AMessage> extra = new AMessage; 1296 extra->setInt64("resume-at-mediaTimeUs", seekTimeUs); 1297 meta->setMessage("extra", extra); 1298 } 1299#endif 1300 1301 if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) { 1302 const char *mime; 1303 CHECK(mTimedTextTrack.mSource != NULL 1304 && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime)); 1305 meta->setString("mime", mime); 1306 } 1307 1308 int64_t durationUs; 1309 if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) { 1310 meta->setInt64("durationUs", durationUs); 1311 } 1312 1313 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) { 1314 meta->setInt32("trackIndex", mSubtitleTrack.mIndex); 1315 } 1316 1317 uint32_t dataType; // unused 1318 const void *seiData; 1319 size_t seiLength; 1320 if (mb->meta_data()->findData(kKeySEI, &dataType, &seiData, &seiLength)) { 1321 sp<ABuffer> sei = ABuffer::CreateAsCopy(seiData, seiLength);; 1322 meta->setBuffer("sei", sei); 1323 } 1324 1325 const void *mpegUserDataPointer; 1326 size_t mpegUserDataLength; 1327 if (mb->meta_data()->findData( 1328 kKeyMpegUserData, &dataType, &mpegUserDataPointer, &mpegUserDataLength)) { 1329 sp<ABuffer> mpegUserData = ABuffer::CreateAsCopy(mpegUserDataPointer, mpegUserDataLength); 1330 meta->setBuffer("mpegUserData", mpegUserData); 1331 } 1332 1333 if (actualTimeUs) { 1334 *actualTimeUs = timeUs; 1335 } 1336 1337 mb->release(); 1338 mb = NULL; 1339 1340 return ab; 1341} 1342 1343void NuPlayer::GenericSource::postReadBuffer(media_track_type trackType) { 1344 Mutex::Autolock _l(mReadBufferLock); 1345 1346 if ((mPendingReadBufferTypes & (1 << trackType)) == 0) { 1347 mPendingReadBufferTypes |= (1 << trackType); 1348 sp<AMessage> msg = new AMessage(kWhatReadBuffer, this); 1349 msg->setInt32("trackType", trackType); 1350 msg->post(); 1351 } 1352} 1353 1354void NuPlayer::GenericSource::onReadBuffer(sp<AMessage> msg) { 1355 int32_t tmpType; 1356 CHECK(msg->findInt32("trackType", &tmpType)); 1357 media_track_type trackType = (media_track_type)tmpType; 1358 readBuffer(trackType); 1359 { 1360 // only protect the variable change, as readBuffer may 1361 // take considerable time. 1362 Mutex::Autolock _l(mReadBufferLock); 1363 mPendingReadBufferTypes &= ~(1 << trackType); 1364 } 1365} 1366 1367void NuPlayer::GenericSource::readBuffer( 1368 media_track_type trackType, int64_t seekTimeUs, int64_t *actualTimeUs, bool formatChange) { 1369 // Do not read data if Widevine source is stopped 1370 if (mStopRead) { 1371 return; 1372 } 1373 Track *track; 1374 size_t maxBuffers = 1; 1375 switch (trackType) { 1376 case MEDIA_TRACK_TYPE_VIDEO: 1377 track = &mVideoTrack; 1378 if (mIsWidevine) { 1379 maxBuffers = 2; 1380 } else { 1381 maxBuffers = 4; 1382 } 1383 break; 1384 case MEDIA_TRACK_TYPE_AUDIO: 1385 track = &mAudioTrack; 1386 if (mIsWidevine) { 1387 maxBuffers = 8; 1388 } else { 1389 maxBuffers = 64; 1390 } 1391 break; 1392 case MEDIA_TRACK_TYPE_SUBTITLE: 1393 track = &mSubtitleTrack; 1394 break; 1395 case MEDIA_TRACK_TYPE_TIMEDTEXT: 1396 track = &mTimedTextTrack; 1397 break; 1398 default: 1399 TRESPASS(); 1400 } 1401 1402 if (track->mSource == NULL) { 1403 return; 1404 } 1405 1406 if (actualTimeUs) { 1407 *actualTimeUs = seekTimeUs; 1408 } 1409 1410 MediaSource::ReadOptions options; 1411 1412 bool seeking = false; 1413 1414 if (seekTimeUs >= 0) { 1415 options.setSeekTo(seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC); 1416 seeking = true; 1417 } 1418 1419 if (mIsWidevine) { 1420 options.setNonBlocking(); 1421 } 1422 1423 for (size_t numBuffers = 0; numBuffers < maxBuffers; ) { 1424 MediaBuffer *mbuf; 1425 status_t err = track->mSource->read(&mbuf, &options); 1426 1427 options.clearSeekTo(); 1428 1429 if (err == OK) { 1430 int64_t timeUs; 1431 if (!mbuf->meta_data()->findInt64(kKeyTime, &timeUs)) { 1432 mbuf->meta_data()->dumpToLog(); 1433 track->mPackets->signalEOS(ERROR_MALFORMED); 1434 break; 1435 } 1436 if (trackType == MEDIA_TRACK_TYPE_AUDIO) { 1437 mAudioTimeUs = timeUs; 1438 mBufferingMonitor->updateQueuedTime(true /* isAudio */, timeUs); 1439 } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) { 1440 mVideoTimeUs = timeUs; 1441 mBufferingMonitor->updateQueuedTime(false /* isAudio */, timeUs); 1442 } 1443 1444 queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track); 1445 1446 sp<ABuffer> buffer = mediaBufferToABuffer( 1447 mbuf, trackType, seekTimeUs, 1448 numBuffers == 0 ? actualTimeUs : NULL); 1449 track->mPackets->queueAccessUnit(buffer); 1450 formatChange = false; 1451 seeking = false; 1452 ++numBuffers; 1453 } else if (err == WOULD_BLOCK) { 1454 break; 1455 } else if (err == INFO_FORMAT_CHANGED) { 1456#if 0 1457 track->mPackets->queueDiscontinuity( 1458 ATSParser::DISCONTINUITY_FORMATCHANGE, 1459 NULL, 1460 false /* discard */); 1461#endif 1462 } else { 1463 queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track); 1464 track->mPackets->signalEOS(err); 1465 break; 1466 } 1467 } 1468} 1469 1470void NuPlayer::GenericSource::queueDiscontinuityIfNeeded( 1471 bool seeking, bool formatChange, media_track_type trackType, Track *track) { 1472 // formatChange && seeking: track whose source is changed during selection 1473 // formatChange && !seeking: track whose source is not changed during selection 1474 // !formatChange: normal seek 1475 if ((seeking || formatChange) 1476 && (trackType == MEDIA_TRACK_TYPE_AUDIO 1477 || trackType == MEDIA_TRACK_TYPE_VIDEO)) { 1478 ATSParser::DiscontinuityType type = (formatChange && seeking) 1479 ? ATSParser::DISCONTINUITY_FORMATCHANGE 1480 : ATSParser::DISCONTINUITY_NONE; 1481 track->mPackets->queueDiscontinuity(type, NULL /* extra */, true /* discard */); 1482 } 1483} 1484 1485NuPlayer::GenericSource::BufferingMonitor::BufferingMonitor(const sp<AMessage> ¬ify) 1486 : mNotify(notify), 1487 mDurationUs(-1ll), 1488 mBitrate(-1ll), 1489 mIsStreaming(false), 1490 mAudioTimeUs(0), 1491 mVideoTimeUs(0), 1492 mPollBufferingGeneration(0), 1493 mPrepareBuffering(false), 1494 mBuffering(false), 1495 mPrevBufferPercentage(-1), 1496 mOffloadAudio(false), 1497 mFirstDequeuedBufferRealUs(-1ll), 1498 mFirstDequeuedBufferMediaUs(-1ll), 1499 mlastDequeuedBufferMediaUs(-1ll) { 1500} 1501 1502NuPlayer::GenericSource::BufferingMonitor::~BufferingMonitor() { 1503} 1504 1505void NuPlayer::GenericSource::BufferingMonitor::prepare( 1506 const sp<NuCachedSource2> &cachedSource, 1507 const sp<WVMExtractor> &wvmExtractor, 1508 int64_t durationUs, 1509 int64_t bitrate, 1510 bool isStreaming) { 1511 Mutex::Autolock _l(mLock); 1512 prepare_l(cachedSource, wvmExtractor, durationUs, bitrate, isStreaming); 1513} 1514 1515void NuPlayer::GenericSource::BufferingMonitor::stop() { 1516 Mutex::Autolock _l(mLock); 1517 prepare_l(NULL /* cachedSource */, NULL /* wvmExtractor */, -1 /* durationUs */, 1518 -1 /* bitrate */, false /* isStreaming */); 1519} 1520 1521void NuPlayer::GenericSource::BufferingMonitor::cancelPollBuffering() { 1522 Mutex::Autolock _l(mLock); 1523 cancelPollBuffering_l(); 1524} 1525 1526void NuPlayer::GenericSource::BufferingMonitor::restartPollBuffering() { 1527 Mutex::Autolock _l(mLock); 1528 if (mIsStreaming) { 1529 cancelPollBuffering_l(); 1530 onPollBuffering_l(); 1531 } 1532} 1533 1534void NuPlayer::GenericSource::BufferingMonitor::stopBufferingIfNecessary() { 1535 Mutex::Autolock _l(mLock); 1536 stopBufferingIfNecessary_l(); 1537} 1538 1539void NuPlayer::GenericSource::BufferingMonitor::ensureCacheIsFetching() { 1540 Mutex::Autolock _l(mLock); 1541 ensureCacheIsFetching_l(); 1542} 1543 1544void NuPlayer::GenericSource::BufferingMonitor::updateQueuedTime(bool isAudio, int64_t timeUs) { 1545 Mutex::Autolock _l(mLock); 1546 if (isAudio) { 1547 mAudioTimeUs = timeUs; 1548 } else { 1549 mVideoTimeUs = timeUs; 1550 } 1551} 1552 1553void NuPlayer::GenericSource::BufferingMonitor::setOffloadAudio(bool offload) { 1554 Mutex::Autolock _l(mLock); 1555 mOffloadAudio = offload; 1556} 1557 1558void NuPlayer::GenericSource::BufferingMonitor::updateDequeuedBufferTime(int64_t mediaUs) { 1559 Mutex::Autolock _l(mLock); 1560 if (mediaUs < 0) { 1561 mFirstDequeuedBufferRealUs = -1ll; 1562 mFirstDequeuedBufferMediaUs = -1ll; 1563 } else if (mFirstDequeuedBufferRealUs < 0) { 1564 mFirstDequeuedBufferRealUs = ALooper::GetNowUs(); 1565 mFirstDequeuedBufferMediaUs = mediaUs; 1566 } 1567 mlastDequeuedBufferMediaUs = mediaUs; 1568} 1569 1570void NuPlayer::GenericSource::BufferingMonitor::prepare_l( 1571 const sp<NuCachedSource2> &cachedSource, 1572 const sp<WVMExtractor> &wvmExtractor, 1573 int64_t durationUs, 1574 int64_t bitrate, 1575 bool isStreaming) { 1576 ALOGW_IF(wvmExtractor != NULL && cachedSource != NULL, 1577 "WVMExtractor and NuCachedSource are both present when " 1578 "BufferingMonitor::prepare_l is called, ignore NuCachedSource"); 1579 1580 mCachedSource = cachedSource; 1581 mWVMExtractor = wvmExtractor; 1582 mDurationUs = durationUs; 1583 mBitrate = bitrate; 1584 mIsStreaming = isStreaming; 1585 mAudioTimeUs = 0; 1586 mVideoTimeUs = 0; 1587 mPrepareBuffering = (cachedSource != NULL || wvmExtractor != NULL); 1588 cancelPollBuffering_l(); 1589 mOffloadAudio = false; 1590 mFirstDequeuedBufferRealUs = -1ll; 1591 mFirstDequeuedBufferMediaUs = -1ll; 1592 mlastDequeuedBufferMediaUs = -1ll; 1593} 1594 1595void NuPlayer::GenericSource::BufferingMonitor::cancelPollBuffering_l() { 1596 mBuffering = false; 1597 ++mPollBufferingGeneration; 1598 mPrevBufferPercentage = -1; 1599} 1600 1601void NuPlayer::GenericSource::BufferingMonitor::notifyBufferingUpdate_l(int32_t percentage) { 1602 // Buffering percent could go backward as it's estimated from remaining 1603 // data and last access time. This could cause the buffering position 1604 // drawn on media control to jitter slightly. Remember previously reported 1605 // percentage and don't allow it to go backward. 1606 if (percentage < mPrevBufferPercentage) { 1607 percentage = mPrevBufferPercentage; 1608 } else if (percentage > 100) { 1609 percentage = 100; 1610 } 1611 1612 mPrevBufferPercentage = percentage; 1613 1614 ALOGV("notifyBufferingUpdate_l: buffering %d%%", percentage); 1615 1616 sp<AMessage> msg = mNotify->dup(); 1617 msg->setInt32("what", kWhatBufferingUpdate); 1618 msg->setInt32("percentage", percentage); 1619 msg->post(); 1620} 1621 1622void NuPlayer::GenericSource::BufferingMonitor::startBufferingIfNecessary_l() { 1623 ALOGD("startBufferingIfNecessary_l: mPrepareBuffering=%d, mBuffering=%d", 1624 mPrepareBuffering, mBuffering); 1625 1626 if (mPrepareBuffering) { 1627 return; 1628 } 1629 1630 if (!mBuffering) { 1631 mBuffering = true; 1632 1633 ensureCacheIsFetching_l(); 1634 sendCacheStats_l(); 1635 1636 sp<AMessage> notify = mNotify->dup(); 1637 notify->setInt32("what", kWhatPauseOnBufferingStart); 1638 notify->post(); 1639 } 1640} 1641 1642void NuPlayer::GenericSource::BufferingMonitor::stopBufferingIfNecessary_l() { 1643 ALOGD("stopBufferingIfNecessary_l: mPrepareBuffering=%d, mBuffering=%d", 1644 mPrepareBuffering, mBuffering); 1645 1646 if (mPrepareBuffering) { 1647 mPrepareBuffering = false; 1648 1649 sp<AMessage> notify = mNotify->dup(); 1650 notify->setInt32("what", kWhatPrepared); 1651 notify->setInt32("err", OK); 1652 notify->post(); 1653 1654 return; 1655 } 1656 1657 if (mBuffering) { 1658 mBuffering = false; 1659 1660 sendCacheStats_l(); 1661 1662 sp<AMessage> notify = mNotify->dup(); 1663 notify->setInt32("what", kWhatResumeOnBufferingEnd); 1664 notify->post(); 1665 } 1666} 1667 1668void NuPlayer::GenericSource::BufferingMonitor::sendCacheStats_l() { 1669 int32_t kbps = 0; 1670 status_t err = UNKNOWN_ERROR; 1671 1672 if (mWVMExtractor != NULL) { 1673 err = mWVMExtractor->getEstimatedBandwidthKbps(&kbps); 1674 } else if (mCachedSource != NULL) { 1675 err = mCachedSource->getEstimatedBandwidthKbps(&kbps); 1676 } 1677 1678 if (err == OK) { 1679 sp<AMessage> notify = mNotify->dup(); 1680 notify->setInt32("what", kWhatCacheStats); 1681 notify->setInt32("bandwidth", kbps); 1682 notify->post(); 1683 } 1684} 1685 1686void NuPlayer::GenericSource::BufferingMonitor::ensureCacheIsFetching_l() { 1687 if (mCachedSource != NULL) { 1688 mCachedSource->resumeFetchingIfNecessary(); 1689 } 1690} 1691 1692void NuPlayer::GenericSource::BufferingMonitor::schedulePollBuffering_l() { 1693 sp<AMessage> msg = new AMessage(kWhatPollBuffering, this); 1694 msg->setInt32("generation", mPollBufferingGeneration); 1695 // Enquires buffering status every second. 1696 msg->post(1000000ll); 1697} 1698 1699int64_t NuPlayer::GenericSource::BufferingMonitor::getLastReadPosition_l() { 1700 if (mAudioTimeUs > 0) { 1701 return mAudioTimeUs; 1702 } else if (mVideoTimeUs > 0) { 1703 return mVideoTimeUs; 1704 } else { 1705 return 0; 1706 } 1707} 1708 1709void NuPlayer::GenericSource::BufferingMonitor::onPollBuffering_l() { 1710 status_t finalStatus = UNKNOWN_ERROR; 1711 int64_t cachedDurationUs = -1ll; 1712 ssize_t cachedDataRemaining = -1; 1713 1714 if (mWVMExtractor != NULL) { 1715 cachedDurationUs = 1716 mWVMExtractor->getCachedDurationUs(&finalStatus); 1717 } else if (mCachedSource != NULL) { 1718 cachedDataRemaining = 1719 mCachedSource->approxDataRemaining(&finalStatus); 1720 1721 if (finalStatus == OK) { 1722 off64_t size; 1723 int64_t bitrate = 0ll; 1724 if (mDurationUs > 0 && mCachedSource->getSize(&size) == OK) { 1725 // |bitrate| uses bits/second unit, while size is number of bytes. 1726 bitrate = size * 8000000ll / mDurationUs; 1727 } else if (mBitrate > 0) { 1728 bitrate = mBitrate; 1729 } 1730 if (bitrate > 0) { 1731 cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate; 1732 } 1733 } 1734 } 1735 1736 if (finalStatus != OK) { 1737 ALOGV("onPollBuffering_l: EOS (finalStatus = %d)", finalStatus); 1738 1739 if (finalStatus == ERROR_END_OF_STREAM) { 1740 notifyBufferingUpdate_l(100); 1741 } 1742 1743 stopBufferingIfNecessary_l(); 1744 return; 1745 } else if (cachedDurationUs >= 0ll) { 1746 if (mDurationUs > 0ll) { 1747 int64_t cachedPosUs = getLastReadPosition_l() + cachedDurationUs; 1748 int percentage = 100.0 * cachedPosUs / mDurationUs; 1749 if (percentage > 100) { 1750 percentage = 100; 1751 } 1752 1753 notifyBufferingUpdate_l(percentage); 1754 } 1755 1756 ALOGV("onPollBuffering_l: cachedDurationUs %.1f sec", 1757 cachedDurationUs / 1000000.0f); 1758 1759 if (cachedDurationUs < kLowWaterMarkUs) { 1760 // Take into account the data cached in downstream components to try to avoid 1761 // unnecessary pause. 1762 if (mOffloadAudio && mFirstDequeuedBufferRealUs >= 0) { 1763 int64_t downStreamCacheUs = mlastDequeuedBufferMediaUs - mFirstDequeuedBufferMediaUs 1764 - (ALooper::GetNowUs() - mFirstDequeuedBufferRealUs); 1765 if (downStreamCacheUs > 0) { 1766 cachedDurationUs += downStreamCacheUs; 1767 } 1768 } 1769 1770 if (cachedDurationUs < kLowWaterMarkUs) { 1771 startBufferingIfNecessary_l(); 1772 } 1773 } else { 1774 int64_t highWaterMark = mPrepareBuffering ? kHighWaterMarkUs : kHighWaterMarkRebufferUs; 1775 if (cachedDurationUs > highWaterMark) { 1776 stopBufferingIfNecessary_l(); 1777 } 1778 } 1779 } else if (cachedDataRemaining >= 0) { 1780 ALOGV("onPollBuffering_l: cachedDataRemaining %zd bytes", 1781 cachedDataRemaining); 1782 1783 if (cachedDataRemaining < kLowWaterMarkBytes) { 1784 startBufferingIfNecessary_l(); 1785 } else if (cachedDataRemaining > kHighWaterMarkBytes) { 1786 stopBufferingIfNecessary_l(); 1787 } 1788 } 1789 1790 schedulePollBuffering_l(); 1791} 1792 1793void NuPlayer::GenericSource::BufferingMonitor::onMessageReceived(const sp<AMessage> &msg) { 1794 switch (msg->what()) { 1795 case kWhatPollBuffering: 1796 { 1797 int32_t generation; 1798 CHECK(msg->findInt32("generation", &generation)); 1799 Mutex::Autolock _l(mLock); 1800 if (generation == mPollBufferingGeneration) { 1801 onPollBuffering_l(); 1802 } 1803 break; 1804 } 1805 default: 1806 TRESPASS(); 1807 break; 1808 } 1809} 1810 1811} // namespace android 1812