GenericSource.cpp revision 84f5278a36f2816cc38f64307b4a1ad8a6818507
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/* 220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2012 The Android Open Source Project 320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License. 620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at 720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software 1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and 1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License. 1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */ 1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//#define LOG_NDEBUG 0 1820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#define LOG_TAG "GenericSource" 1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include "GenericSource.h" 2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include "AnotherPacketSource.h" 2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24f89d780df70b7fbb8465bce4913c46cca019721fAndreas Huber#include <media/IMediaHTTPService.h> 25f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ABuffer.h> 2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/foundation/ADebug.h> 2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/foundation/AMessage.h> 2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/DataSource.h> 296a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis#include <media/stagefright/FileSource.h> 306a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis#include <media/stagefright/MediaBuffer.h> 3120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaDefs.h> 3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaExtractor.h> 3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h> 3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h> 3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include "../../libstagefright/include/DRMExtractor.h" 3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include "../../libstagefright/include/NuCachedSource2.h" 3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include "../../libstagefright/include/WVMExtractor.h" 3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberNuPlayer::GenericSource::GenericSource( 4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const sp<AMessage> ¬ify, 4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool uidValid, 4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uid_t uid) 4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : Source(notify), 4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFetchSubtitleDataGeneration(0), 4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFetchTimedTextDataGeneration(0), 4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDurationUs(0ll), 50b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen mAudioIsVorbis(false), 5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mIsWidevine(false), 5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mUIDValid(uidValid), 5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mUID(uid), 5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDrmManagerClient(NULL), 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mMetaDataSize(-1ll), 5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBitrate(-1ll), 57b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen mPollBufferingGeneration(0), 58b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen mPendingReadBufferTypes(0) { 59b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen resetDataSource(); 60b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen DataSource::RegisterDefaultSniffers(); 61b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen} 62b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen 63b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissenvoid NuPlayer::GenericSource::resetDataSource() { 64b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen mAudioTimeUs = 0; 65b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen mVideoTimeUs = 0; 66b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen mHTTPService.clear(); 67b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen mUri.clear(); 68b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen mUriHeaders.clear(); 69b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen mFd = -1; 70b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen mOffset = 0; 71b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen mLength = 0; 72b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen setDrmPlaybackStatusIfNeeded(Playback::STOP, 0); 7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDecryptHandle = NULL; 7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDrmManagerClient = NULL; 756a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis mStarted = false; 766a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis} 776a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis 786a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennisstatus_t NuPlayer::GenericSource::setDataSource( 796a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis const sp<IMediaHTTPService> &httpService, 806a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis const char *url, 816a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis const KeyedVector<String8, String8> *headers) { 826a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis resetDataSource(); 836a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis 846a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis mHTTPService = httpService; 856a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis mUri = url; 866a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis 876a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis if (headers) { 886a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis mUriHeaders = *headers; 89f89d780df70b7fbb8465bce4913c46cca019721fAndreas Huber } 90f89d780df70b7fbb8465bce4913c46cca019721fAndreas Huber 91f89d780df70b7fbb8465bce4913c46cca019721fAndreas Huber // delay data source creation to prepareAsync() to avoid blocking 92f89d780df70b7fbb8465bce4913c46cca019721fAndreas Huber // the calling thread in setDataSource for any significant time. 93f89d780df70b7fbb8465bce4913c46cca019721fAndreas Huber return OK; 94f89d780df70b7fbb8465bce4913c46cca019721fAndreas Huber} 95f89d780df70b7fbb8465bce4913c46cca019721fAndreas Huber 96f89d780df70b7fbb8465bce4913c46cca019721fAndreas Huberstatus_t NuPlayer::GenericSource::setDataSource( 97f89d780df70b7fbb8465bce4913c46cca019721fAndreas Huber int fd, int64_t offset, int64_t length) { 98f89d780df70b7fbb8465bce4913c46cca019721fAndreas Huber resetDataSource(); 99f89d780df70b7fbb8465bce4913c46cca019721fAndreas Huber 100f89d780df70b7fbb8465bce4913c46cca019721fAndreas Huber mFd = dup(fd); 101f89d780df70b7fbb8465bce4913c46cca019721fAndreas Huber mOffset = offset; 102f89d780df70b7fbb8465bce4913c46cca019721fAndreas Huber mLength = length; 10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // delay data source creation to prepareAsync() to avoid blocking 1050c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber // the calling thread in setDataSource for any significant time. 10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t NuPlayer::GenericSource::initFromDataSource() { 11063492411cf4abff452b47f59ec7ff6f3e9925c84Elliott Hughes sp<MediaExtractor> extractor; 11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber CHECK(mDataSource != NULL); 11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mIsWidevine) { 11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber String8 mimeType; 11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber float confidence; 11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<AMessage> dummy; 11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success; 1190c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber 12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = SniffWVM(mDataSource, &mimeType, &confidence, &dummy); 12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (!success 12220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber || strcasecmp( 1230c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) { 1240c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber ALOGE("unsupported widevine mime: %s", mimeType.string()); 12520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return UNKNOWN_ERROR; 12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mWVMExtractor = new WVMExtractor(mDataSource); 12920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mWVMExtractor->setAdaptiveStreamingMode(true); 13063492411cf4abff452b47f59ec7ff6f3e9925c84Elliott Hughes if (mUIDValid) { 13120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mWVMExtractor->setUID(mUID); 13220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 13320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber extractor = mWVMExtractor; 1346a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis } else { 13520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber extractor = MediaExtractor::Create(mDataSource, 13620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSniffedMIME.empty() ? NULL: mSniffedMIME.c_str()); 13720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 13820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1396a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis if (extractor == NULL) { 14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return UNKNOWN_ERROR; 14120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (extractor->getDrmFlag()) { 14420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber checkDrmStatus(mDataSource); 14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> fileMeta = extractor->getMetaData(); 14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (fileMeta != NULL) { 14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t duration; 15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (fileMeta->findInt64(kKeyDuration, &duration)) { 15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDurationUs = duration; 1526a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis } 153a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn } 15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1556a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis int32_t totalBitrate = 0; 15620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (size_t i = 0; i < extractor->countTracks(); ++i) { 15820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MediaSource> track = extractor->getTrack(i); 15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> meta = extractor->getTrackMetaData(i); 1616a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis 1626a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis const char *mime; 1636a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis CHECK(meta->findCString(kKeyMIMEType, &mime)); 1646a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis 16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Do the string compare immediately with "mime", 16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // we can't assume "mime" would stay valid after another 16720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // extractor operation, some extractors might modify meta 16820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // during getTrack() and make it invalid. 16920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (!strncasecmp(mime, "audio/", 6)) { 17020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mAudioTrack.mSource == NULL) { 17120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mAudioTrack.mIndex = i; 17220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mAudioTrack.mSource = track; 17320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { 175f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong mAudioIsVorbis = true; 17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 177b65990f4a0cf01db0b9f21c68fcf8824ae03a178Marco Nelissen mAudioIsVorbis = false; 17820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 17920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 18020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else if (!strncasecmp(mime, "video/", 6)) { 18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mVideoTrack.mSource == NULL) { 18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mVideoTrack.mIndex = i; 18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mVideoTrack.mSource = track; 18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 18520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // check if the source requires secure buffers 18620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t secure; 18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (meta->findInt32(kKeyRequiresSecureBuffers, &secure) 18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber && secure) { 1890c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber mIsWidevine = true; 19020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mUIDValid) { 19120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber extractor->setUID(mUID); 19220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 19320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 19420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 19520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 19620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 19720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (track != NULL) { 19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSources.push(track); 19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t durationUs; 20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (meta->findInt64(kKeyDuration, &durationUs)) { 20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (durationUs > mDurationUs) { 20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDurationUs = durationUs; 20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 206f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong int32_t bitrate; 2076a9da9fc558263548ebfbae2cbf177eb7454a41bJamie Gennis if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) { 20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber totalBitrate += bitrate; 20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber totalBitrate = -1; 21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBitrate = totalBitrate; 21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 219 220void NuPlayer::GenericSource::checkDrmStatus(const sp<DataSource>& dataSource) { 221 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient); 222 if (mDecryptHandle != NULL) { 223 CHECK(mDrmManagerClient); 224 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) { 225 sp<AMessage> msg = dupNotify(); 226 msg->setInt32("what", kWhatDrmNoLicense); 227 msg->post(); 228 } 229 } 230} 231 232int64_t NuPlayer::GenericSource::getLastReadPosition() { 233 if (mAudioTrack.mSource != NULL) { 234 return mAudioTimeUs; 235 } else if (mVideoTrack.mSource != NULL) { 236 return mVideoTimeUs; 237 } else { 238 return 0; 239 } 240} 241 242status_t NuPlayer::GenericSource::setBuffers( 243 bool audio, Vector<MediaBuffer *> &buffers) { 244 if (mIsWidevine && !audio) { 245 return mVideoTrack.mSource->setBuffers(buffers); 246 } 247 return INVALID_OPERATION; 248} 249 250NuPlayer::GenericSource::~GenericSource() { 251 if (mLooper != NULL) { 252 mLooper->unregisterHandler(id()); 253 mLooper->stop(); 254 } 255} 256 257void NuPlayer::GenericSource::prepareAsync() { 258 if (mLooper == NULL) { 259 mLooper = new ALooper; 260 mLooper->setName("generic"); 261 mLooper->start(); 262 263 mLooper->registerHandler(this); 264 } 265 266 sp<AMessage> msg = new AMessage(kWhatPrepareAsync, id()); 267 msg->post(); 268} 269 270void NuPlayer::GenericSource::onPrepareAsync() { 271 // delayed data source creation 272 if (mDataSource == NULL) { 273 if (!mUri.empty()) { 274 mIsWidevine = !strncasecmp(mUri.c_str(), "widevine://", 11); 275 276 mDataSource = DataSource::CreateFromURI( 277 mHTTPService, mUri.c_str(), &mUriHeaders, &mContentType); 278 } else { 279 // set to false first, if the extractor 280 // comes back as secure, set it to true then. 281 mIsWidevine = false; 282 283 mDataSource = new FileSource(mFd, mOffset, mLength); 284 } 285 286 if (mDataSource == NULL) { 287 ALOGE("Failed to create data source!"); 288 notifyPreparedAndCleanup(UNKNOWN_ERROR); 289 return; 290 } 291 292 if (mDataSource->flags() & DataSource::kIsCachingDataSource) { 293 mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get()); 294 } 295 296 if (mIsWidevine || mCachedSource != NULL) { 297 schedulePollBuffering(); 298 } 299 } 300 301 // check initial caching status 302 status_t err = prefillCacheIfNecessary(); 303 if (err != OK) { 304 if (err == -EAGAIN) { 305 (new AMessage(kWhatPrepareAsync, id()))->post(200000); 306 } else { 307 ALOGE("Failed to prefill data cache!"); 308 notifyPreparedAndCleanup(UNKNOWN_ERROR); 309 } 310 return; 311 } 312 313 // init extrator from data source 314 err = initFromDataSource(); 315 316 if (err != OK) { 317 ALOGE("Failed to init from data source!"); 318 notifyPreparedAndCleanup(err); 319 return; 320 } 321 322 if (mVideoTrack.mSource != NULL) { 323 sp<MetaData> meta = doGetFormatMeta(false /* audio */); 324 sp<AMessage> msg = new AMessage; 325 err = convertMetaDataToMessage(meta, &msg); 326 if(err != OK) { 327 notifyPreparedAndCleanup(err); 328 return; 329 } 330 notifyVideoSizeChanged(msg); 331 } 332 333 notifyFlagsChanged( 334 (mIsWidevine ? FLAG_SECURE : 0) 335 | FLAG_CAN_PAUSE 336 | FLAG_CAN_SEEK_BACKWARD 337 | FLAG_CAN_SEEK_FORWARD 338 | FLAG_CAN_SEEK); 339 340 notifyPrepared(); 341} 342 343void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) { 344 if (err != OK) { 345 mMetaDataSize = -1ll; 346 mContentType = ""; 347 mSniffedMIME = ""; 348 mDataSource.clear(); 349 mCachedSource.clear(); 350 351 cancelPollBuffering(); 352 } 353 notifyPrepared(err); 354} 355 356status_t NuPlayer::GenericSource::prefillCacheIfNecessary() { 357 CHECK(mDataSource != NULL); 358 359 if (mCachedSource == NULL) { 360 // no prefill if the data source is not cached 361 return OK; 362 } 363 364 // We're not doing this for streams that appear to be audio-only 365 // streams to ensure that even low bandwidth streams start 366 // playing back fairly instantly. 367 if (!strncasecmp(mContentType.string(), "audio/", 6)) { 368 return OK; 369 } 370 371 // We're going to prefill the cache before trying to instantiate 372 // the extractor below, as the latter is an operation that otherwise 373 // could block on the datasource for a significant amount of time. 374 // During that time we'd be unable to abort the preparation phase 375 // without this prefill. 376 377 // Initially make sure we have at least 192 KB for the sniff 378 // to complete without blocking. 379 static const size_t kMinBytesForSniffing = 192 * 1024; 380 static const size_t kDefaultMetaSize = 200000; 381 382 status_t finalStatus; 383 384 size_t cachedDataRemaining = 385 mCachedSource->approxDataRemaining(&finalStatus); 386 387 if (finalStatus != OK || (mMetaDataSize >= 0 388 && (off64_t)cachedDataRemaining >= mMetaDataSize)) { 389 ALOGV("stop caching, status %d, " 390 "metaDataSize %lld, cachedDataRemaining %zu", 391 finalStatus, mMetaDataSize, cachedDataRemaining); 392 return OK; 393 } 394 395 ALOGV("now cached %zu bytes of data", cachedDataRemaining); 396 397 if (mMetaDataSize < 0 398 && cachedDataRemaining >= kMinBytesForSniffing) { 399 String8 tmp; 400 float confidence; 401 sp<AMessage> meta; 402 if (!mCachedSource->sniff(&tmp, &confidence, &meta)) { 403 return UNKNOWN_ERROR; 404 } 405 406 // We successfully identified the file's extractor to 407 // be, remember this mime type so we don't have to 408 // sniff it again when we call MediaExtractor::Create() 409 mSniffedMIME = tmp.string(); 410 411 if (meta == NULL 412 || !meta->findInt64("meta-data-size", 413 reinterpret_cast<int64_t*>(&mMetaDataSize))) { 414 mMetaDataSize = kDefaultMetaSize; 415 } 416 417 if (mMetaDataSize < 0ll) { 418 ALOGE("invalid metaDataSize = %lld bytes", mMetaDataSize); 419 return UNKNOWN_ERROR; 420 } 421 } 422 423 return -EAGAIN; 424} 425 426void NuPlayer::GenericSource::start() { 427 ALOGI("start"); 428 429 if (mAudioTrack.mSource != NULL) { 430 CHECK_EQ(mAudioTrack.mSource->start(), (status_t)OK); 431 mAudioTrack.mPackets = 432 new AnotherPacketSource(mAudioTrack.mSource->getFormat()); 433 434 postReadBuffer(MEDIA_TRACK_TYPE_AUDIO); 435 } 436 437 if (mVideoTrack.mSource != NULL) { 438 CHECK_EQ(mVideoTrack.mSource->start(), (status_t)OK); 439 mVideoTrack.mPackets = 440 new AnotherPacketSource(mVideoTrack.mSource->getFormat()); 441 442 postReadBuffer(MEDIA_TRACK_TYPE_VIDEO); 443 } 444 445 setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000); 446 mStarted = true; 447} 448 449void NuPlayer::GenericSource::stop() { 450 // nothing to do, just account for DRM playback status 451 setDrmPlaybackStatusIfNeeded(Playback::STOP, 0); 452 mStarted = false; 453} 454 455void NuPlayer::GenericSource::pause() { 456 // nothing to do, just account for DRM playback status 457 setDrmPlaybackStatusIfNeeded(Playback::PAUSE, 0); 458 mStarted = false; 459} 460 461void NuPlayer::GenericSource::resume() { 462 // nothing to do, just account for DRM playback status 463 setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000); 464 mStarted = true; 465} 466 467void NuPlayer::GenericSource::setDrmPlaybackStatusIfNeeded(int playbackStatus, int64_t position) { 468 if (mDecryptHandle != NULL) { 469 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, playbackStatus, position); 470 } 471 mSubtitleTrack.mPackets = new AnotherPacketSource(NULL); 472 mTimedTextTrack.mPackets = new AnotherPacketSource(NULL); 473} 474 475status_t NuPlayer::GenericSource::feedMoreTSData() { 476 return OK; 477} 478 479void NuPlayer::GenericSource::schedulePollBuffering() { 480 sp<AMessage> msg = new AMessage(kWhatPollBuffering, id()); 481 msg->setInt32("generation", mPollBufferingGeneration); 482 msg->post(1000000ll); 483} 484 485void NuPlayer::GenericSource::cancelPollBuffering() { 486 ++mPollBufferingGeneration; 487} 488 489void NuPlayer::GenericSource::notifyBufferingUpdate(int percentage) { 490 sp<AMessage> msg = dupNotify(); 491 msg->setInt32("what", kWhatBufferingUpdate); 492 msg->setInt32("percentage", percentage); 493 msg->post(); 494} 495 496void NuPlayer::GenericSource::onPollBuffering() { 497 status_t finalStatus = UNKNOWN_ERROR; 498 int64_t cachedDurationUs = 0ll; 499 500 if (mCachedSource != NULL) { 501 size_t cachedDataRemaining = 502 mCachedSource->approxDataRemaining(&finalStatus); 503 504 if (finalStatus == OK) { 505 off64_t size; 506 int64_t bitrate = 0ll; 507 if (mDurationUs > 0 && mCachedSource->getSize(&size) == OK) { 508 bitrate = size * 8000000ll / mDurationUs; 509 } else if (mBitrate > 0) { 510 bitrate = mBitrate; 511 } 512 if (bitrate > 0) { 513 cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate; 514 } 515 } 516 } else if (mWVMExtractor != NULL) { 517 cachedDurationUs 518 = mWVMExtractor->getCachedDurationUs(&finalStatus); 519 } 520 521 if (finalStatus == ERROR_END_OF_STREAM) { 522 notifyBufferingUpdate(100); 523 cancelPollBuffering(); 524 return; 525 } else if (cachedDurationUs > 0ll && mDurationUs > 0ll) { 526 int percentage = 100.0 * cachedDurationUs / mDurationUs; 527 if (percentage > 100) { 528 percentage = 100; 529 } 530 531 notifyBufferingUpdate(percentage); 532 } 533 534 schedulePollBuffering(); 535} 536 537 538void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) { 539 switch (msg->what()) { 540 case kWhatPrepareAsync: 541 { 542 onPrepareAsync(); 543 break; 544 } 545 case kWhatFetchSubtitleData: 546 { 547 fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE, 548 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg); 549 break; 550 } 551 552 case kWhatFetchTimedTextData: 553 { 554 fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT, 555 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg); 556 break; 557 } 558 559 case kWhatSendSubtitleData: 560 { 561 sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE, 562 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg); 563 break; 564 } 565 566 case kWhatSendTimedTextData: 567 { 568 sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT, 569 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg); 570 break; 571 } 572 573 case kWhatChangeAVSource: 574 { 575 int32_t trackIndex; 576 CHECK(msg->findInt32("trackIndex", &trackIndex)); 577 const sp<MediaSource> source = mSources.itemAt(trackIndex); 578 579 Track* track; 580 const char *mime; 581 media_track_type trackType, counterpartType; 582 sp<MetaData> meta = source->getFormat(); 583 meta->findCString(kKeyMIMEType, &mime); 584 if (!strncasecmp(mime, "audio/", 6)) { 585 track = &mAudioTrack; 586 trackType = MEDIA_TRACK_TYPE_AUDIO; 587 counterpartType = MEDIA_TRACK_TYPE_VIDEO;; 588 } else { 589 CHECK(!strncasecmp(mime, "video/", 6)); 590 track = &mVideoTrack; 591 trackType = MEDIA_TRACK_TYPE_VIDEO; 592 counterpartType = MEDIA_TRACK_TYPE_AUDIO;; 593 } 594 595 596 if (track->mSource != NULL) { 597 track->mSource->stop(); 598 } 599 track->mSource = source; 600 track->mSource->start(); 601 track->mIndex = trackIndex; 602 603 status_t avail; 604 if (!track->mPackets->hasBufferAvailable(&avail)) { 605 // sync from other source 606 TRESPASS(); 607 break; 608 } 609 610 int64_t timeUs, actualTimeUs; 611 const bool formatChange = true; 612 sp<AMessage> latestMeta = track->mPackets->getLatestEnqueuedMeta(); 613 CHECK(latestMeta != NULL && latestMeta->findInt64("timeUs", &timeUs)); 614 readBuffer(trackType, timeUs, &actualTimeUs, formatChange); 615 readBuffer(counterpartType, -1, NULL, formatChange); 616 ALOGV("timeUs %lld actualTimeUs %lld", timeUs, actualTimeUs); 617 618 break; 619 } 620 case kWhatPollBuffering: 621 { 622 int32_t generation; 623 CHECK(msg->findInt32("generation", &generation)); 624 if (generation == mPollBufferingGeneration) { 625 onPollBuffering(); 626 } 627 break; 628 } 629 630 case kWhatGetFormat: 631 { 632 onGetFormatMeta(msg); 633 break; 634 } 635 636 case kWhatGetSelectedTrack: 637 { 638 onGetSelectedTrack(msg); 639 break; 640 } 641 642 case kWhatSelectTrack: 643 { 644 onSelectTrack(msg); 645 break; 646 } 647 648 case kWhatSeek: 649 { 650 onSeek(msg); 651 break; 652 } 653 654 case kWhatReadBuffer: 655 { 656 onReadBuffer(msg); 657 break; 658 } 659 660 default: 661 Source::onMessageReceived(msg); 662 break; 663 } 664} 665 666void NuPlayer::GenericSource::fetchTextData( 667 uint32_t sendWhat, 668 media_track_type type, 669 int32_t curGen, 670 sp<AnotherPacketSource> packets, 671 sp<AMessage> msg) { 672 int32_t msgGeneration; 673 CHECK(msg->findInt32("generation", &msgGeneration)); 674 if (msgGeneration != curGen) { 675 // stale 676 return; 677 } 678 679 int32_t avail; 680 if (packets->hasBufferAvailable(&avail)) { 681 return; 682 } 683 684 int64_t timeUs; 685 CHECK(msg->findInt64("timeUs", &timeUs)); 686 687 int64_t subTimeUs; 688 readBuffer(type, timeUs, &subTimeUs); 689 690 int64_t delayUs = subTimeUs - timeUs; 691 if (msg->what() == kWhatFetchSubtitleData) { 692 const int64_t oneSecUs = 1000000ll; 693 delayUs -= oneSecUs; 694 } 695 sp<AMessage> msg2 = new AMessage(sendWhat, id()); 696 msg2->setInt32("generation", msgGeneration); 697 msg2->post(delayUs < 0 ? 0 : delayUs); 698} 699 700void NuPlayer::GenericSource::sendTextData( 701 uint32_t what, 702 media_track_type type, 703 int32_t curGen, 704 sp<AnotherPacketSource> packets, 705 sp<AMessage> msg) { 706 int32_t msgGeneration; 707 CHECK(msg->findInt32("generation", &msgGeneration)); 708 if (msgGeneration != curGen) { 709 // stale 710 return; 711 } 712 713 int64_t subTimeUs; 714 if (packets->nextBufferTime(&subTimeUs) != OK) { 715 return; 716 } 717 718 int64_t nextSubTimeUs; 719 readBuffer(type, -1, &nextSubTimeUs); 720 721 sp<ABuffer> buffer; 722 status_t dequeueStatus = packets->dequeueAccessUnit(&buffer); 723 if (dequeueStatus == OK) { 724 sp<AMessage> notify = dupNotify(); 725 notify->setInt32("what", what); 726 notify->setBuffer("buffer", buffer); 727 notify->post(); 728 729 const int64_t delayUs = nextSubTimeUs - subTimeUs; 730 msg->post(delayUs < 0 ? 0 : delayUs); 731 } 732} 733 734sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) { 735 sp<AMessage> msg = new AMessage(kWhatGetFormat, id()); 736 msg->setInt32("audio", audio); 737 738 sp<AMessage> response; 739 void *format; 740 status_t err = msg->postAndAwaitResponse(&response); 741 if (err == OK && response != NULL) { 742 CHECK(response->findPointer("format", &format)); 743 return (MetaData *)format; 744 } else { 745 return NULL; 746 } 747} 748 749void NuPlayer::GenericSource::onGetFormatMeta(sp<AMessage> msg) const { 750 int32_t audio; 751 CHECK(msg->findInt32("audio", &audio)); 752 753 sp<AMessage> response = new AMessage; 754 sp<MetaData> format = doGetFormatMeta(audio); 755 response->setPointer("format", format.get()); 756 757 uint32_t replyID; 758 CHECK(msg->senderAwaitsResponse(&replyID)); 759 response->postReply(replyID); 760} 761 762sp<MetaData> NuPlayer::GenericSource::doGetFormatMeta(bool audio) const { 763 sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource; 764 765 if (source == NULL) { 766 return NULL; 767 } 768 769 return source->getFormat(); 770} 771 772status_t NuPlayer::GenericSource::dequeueAccessUnit( 773 bool audio, sp<ABuffer> *accessUnit) { 774 Track *track = audio ? &mAudioTrack : &mVideoTrack; 775 776 if (track->mSource == NULL) { 777 return -EWOULDBLOCK; 778 } 779 780 if (mIsWidevine && !audio) { 781 // try to read a buffer as we may not have been able to the last time 782 postReadBuffer(MEDIA_TRACK_TYPE_VIDEO); 783 } 784 785 status_t finalResult; 786 if (!track->mPackets->hasBufferAvailable(&finalResult)) { 787 return (finalResult == OK ? -EWOULDBLOCK : finalResult); 788 } 789 790 status_t result = track->mPackets->dequeueAccessUnit(accessUnit); 791 792 if (!track->mPackets->hasBufferAvailable(&finalResult)) { 793 postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO); 794 } 795 796 if (result != OK) { 797 if (mSubtitleTrack.mSource != NULL) { 798 mSubtitleTrack.mPackets->clear(); 799 mFetchSubtitleDataGeneration++; 800 } 801 if (mTimedTextTrack.mSource != NULL) { 802 mTimedTextTrack.mPackets->clear(); 803 mFetchTimedTextDataGeneration++; 804 } 805 return result; 806 } 807 808 int64_t timeUs; 809 status_t eosResult; // ignored 810 CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs)); 811 812 if (mSubtitleTrack.mSource != NULL 813 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) { 814 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, id()); 815 msg->setInt64("timeUs", timeUs); 816 msg->setInt32("generation", mFetchSubtitleDataGeneration); 817 msg->post(); 818 } 819 820 if (mTimedTextTrack.mSource != NULL 821 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) { 822 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, id()); 823 msg->setInt64("timeUs", timeUs); 824 msg->setInt32("generation", mFetchTimedTextDataGeneration); 825 msg->post(); 826 } 827 828 return result; 829} 830 831status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) { 832 *durationUs = mDurationUs; 833 return OK; 834} 835 836size_t NuPlayer::GenericSource::getTrackCount() const { 837 return mSources.size(); 838} 839 840sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const { 841 size_t trackCount = mSources.size(); 842 if (trackIndex >= trackCount) { 843 return NULL; 844 } 845 846 sp<AMessage> format = new AMessage(); 847 sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat(); 848 849 const char *mime; 850 CHECK(meta->findCString(kKeyMIMEType, &mime)); 851 852 int32_t trackType; 853 if (!strncasecmp(mime, "video/", 6)) { 854 trackType = MEDIA_TRACK_TYPE_VIDEO; 855 } else if (!strncasecmp(mime, "audio/", 6)) { 856 trackType = MEDIA_TRACK_TYPE_AUDIO; 857 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) { 858 trackType = MEDIA_TRACK_TYPE_TIMEDTEXT; 859 } else { 860 trackType = MEDIA_TRACK_TYPE_UNKNOWN; 861 } 862 format->setInt32("type", trackType); 863 864 const char *lang; 865 if (!meta->findCString(kKeyMediaLanguage, &lang)) { 866 lang = "und"; 867 } 868 format->setString("language", lang); 869 870 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) { 871 format->setString("mime", mime); 872 873 int32_t isAutoselect = 1, isDefault = 0, isForced = 0; 874 meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect); 875 meta->findInt32(kKeyTrackIsDefault, &isDefault); 876 meta->findInt32(kKeyTrackIsForced, &isForced); 877 878 format->setInt32("auto", !!isAutoselect); 879 format->setInt32("default", !!isDefault); 880 format->setInt32("forced", !!isForced); 881 } 882 883 return format; 884} 885 886ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const { 887 sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, id()); 888 msg->setInt32("type", type); 889 890 sp<AMessage> response; 891 int32_t index; 892 status_t err = msg->postAndAwaitResponse(&response); 893 if (err == OK && response != NULL) { 894 CHECK(response->findInt32("index", &index)); 895 return index; 896 } else { 897 return -1; 898 } 899} 900 901void NuPlayer::GenericSource::onGetSelectedTrack(sp<AMessage> msg) const { 902 int32_t tmpType; 903 CHECK(msg->findInt32("type", &tmpType)); 904 media_track_type type = (media_track_type)tmpType; 905 906 sp<AMessage> response = new AMessage; 907 ssize_t index = doGetSelectedTrack(type); 908 response->setInt32("index", index); 909 910 uint32_t replyID; 911 CHECK(msg->senderAwaitsResponse(&replyID)); 912 response->postReply(replyID); 913} 914 915ssize_t NuPlayer::GenericSource::doGetSelectedTrack(media_track_type type) const { 916 const Track *track = NULL; 917 switch (type) { 918 case MEDIA_TRACK_TYPE_VIDEO: 919 track = &mVideoTrack; 920 break; 921 case MEDIA_TRACK_TYPE_AUDIO: 922 track = &mAudioTrack; 923 break; 924 case MEDIA_TRACK_TYPE_TIMEDTEXT: 925 track = &mTimedTextTrack; 926 break; 927 case MEDIA_TRACK_TYPE_SUBTITLE: 928 track = &mSubtitleTrack; 929 break; 930 default: 931 break; 932 } 933 934 if (track != NULL && track->mSource != NULL) { 935 return track->mIndex; 936 } 937 938 return -1; 939} 940 941status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select) { 942 ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex); 943 sp<AMessage> msg = new AMessage(kWhatSelectTrack, id()); 944 msg->setInt32("trackIndex", trackIndex); 945 msg->setInt32("select", trackIndex); 946 947 sp<AMessage> response; 948 status_t err = msg->postAndAwaitResponse(&response); 949 if (err == OK && response != NULL) { 950 CHECK(response->findInt32("err", &err)); 951 } 952 953 return err; 954} 955 956void NuPlayer::GenericSource::onSelectTrack(sp<AMessage> msg) { 957 int32_t trackIndex, select; 958 CHECK(msg->findInt32("trackIndex", &trackIndex)); 959 CHECK(msg->findInt32("select", &select)); 960 961 sp<AMessage> response = new AMessage; 962 status_t err = doSelectTrack(trackIndex, select); 963 response->setInt32("err", err); 964 965 uint32_t replyID; 966 CHECK(msg->senderAwaitsResponse(&replyID)); 967 response->postReply(replyID); 968} 969 970status_t NuPlayer::GenericSource::doSelectTrack(size_t trackIndex, bool select) { 971 if (trackIndex >= mSources.size()) { 972 return BAD_INDEX; 973 } 974 975 if (!select) { 976 Track* track = NULL; 977 if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) { 978 track = &mSubtitleTrack; 979 mFetchSubtitleDataGeneration++; 980 } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) { 981 track = &mTimedTextTrack; 982 mFetchTimedTextDataGeneration++; 983 } 984 if (track == NULL) { 985 return INVALID_OPERATION; 986 } 987 track->mSource->stop(); 988 track->mSource = NULL; 989 track->mPackets->clear(); 990 return OK; 991 } 992 993 const sp<MediaSource> source = mSources.itemAt(trackIndex); 994 sp<MetaData> meta = source->getFormat(); 995 const char *mime; 996 CHECK(meta->findCString(kKeyMIMEType, &mime)); 997 if (!strncasecmp(mime, "text/", 5)) { 998 bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP); 999 Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack; 1000 if (track->mSource != NULL && track->mIndex == trackIndex) { 1001 return OK; 1002 } 1003 track->mIndex = trackIndex; 1004 if (track->mSource != NULL) { 1005 track->mSource->stop(); 1006 } 1007 track->mSource = mSources.itemAt(trackIndex); 1008 track->mSource->start(); 1009 if (track->mPackets == NULL) { 1010 track->mPackets = new AnotherPacketSource(track->mSource->getFormat()); 1011 } else { 1012 track->mPackets->clear(); 1013 track->mPackets->setFormat(track->mSource->getFormat()); 1014 1015 } 1016 1017 if (isSubtitle) { 1018 mFetchSubtitleDataGeneration++; 1019 } else { 1020 mFetchTimedTextDataGeneration++; 1021 } 1022 1023 return OK; 1024 } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) { 1025 bool audio = !strncasecmp(mime, "audio/", 6); 1026 Track *track = audio ? &mAudioTrack : &mVideoTrack; 1027 if (track->mSource != NULL && track->mIndex == trackIndex) { 1028 return OK; 1029 } 1030 1031 sp<AMessage> msg = new AMessage(kWhatChangeAVSource, id()); 1032 msg->setInt32("trackIndex", trackIndex); 1033 msg->post(); 1034 return OK; 1035 } 1036 1037 return INVALID_OPERATION; 1038} 1039 1040status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs) { 1041 sp<AMessage> msg = new AMessage(kWhatSeek, id()); 1042 msg->setInt64("seekTimeUs", seekTimeUs); 1043 1044 sp<AMessage> response; 1045 status_t err = msg->postAndAwaitResponse(&response); 1046 if (err == OK && response != NULL) { 1047 CHECK(response->findInt32("err", &err)); 1048 } 1049 1050 return err; 1051} 1052 1053void NuPlayer::GenericSource::onSeek(sp<AMessage> msg) { 1054 int64_t seekTimeUs; 1055 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs)); 1056 1057 sp<AMessage> response = new AMessage; 1058 status_t err = doSeek(seekTimeUs); 1059 response->setInt32("err", err); 1060 1061 uint32_t replyID; 1062 CHECK(msg->senderAwaitsResponse(&replyID)); 1063 response->postReply(replyID); 1064} 1065 1066status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs) { 1067 if (mVideoTrack.mSource != NULL) { 1068 int64_t actualTimeUs; 1069 readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, &actualTimeUs); 1070 1071 seekTimeUs = actualTimeUs; 1072 } 1073 1074 if (mAudioTrack.mSource != NULL) { 1075 readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs); 1076 } 1077 1078 setDrmPlaybackStatusIfNeeded(Playback::START, seekTimeUs / 1000); 1079 if (!mStarted) { 1080 setDrmPlaybackStatusIfNeeded(Playback::PAUSE, 0); 1081 } 1082 return OK; 1083} 1084 1085sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer( 1086 MediaBuffer* mb, 1087 media_track_type trackType, 1088 int64_t *actualTimeUs) { 1089 bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO; 1090 size_t outLength = mb->range_length(); 1091 1092 if (audio && mAudioIsVorbis) { 1093 outLength += sizeof(int32_t); 1094 } 1095 1096 sp<ABuffer> ab; 1097 if (mIsWidevine && !audio) { 1098 // data is already provided in the buffer 1099 ab = new ABuffer(NULL, mb->range_length()); 1100 ab->meta()->setPointer("mediaBuffer", mb); 1101 mb->add_ref(); 1102 } else { 1103 ab = new ABuffer(outLength); 1104 memcpy(ab->data(), 1105 (const uint8_t *)mb->data() + mb->range_offset(), 1106 mb->range_length()); 1107 } 1108 1109 if (audio && mAudioIsVorbis) { 1110 int32_t numPageSamples; 1111 if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) { 1112 numPageSamples = -1; 1113 } 1114 1115 uint8_t* abEnd = ab->data() + mb->range_length(); 1116 memcpy(abEnd, &numPageSamples, sizeof(numPageSamples)); 1117 } 1118 1119 sp<AMessage> meta = ab->meta(); 1120 1121 int64_t timeUs; 1122 CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs)); 1123 meta->setInt64("timeUs", timeUs); 1124 1125 if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) { 1126 const char *mime; 1127 CHECK(mTimedTextTrack.mSource != NULL 1128 && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime)); 1129 meta->setString("mime", mime); 1130 } 1131 1132 int64_t durationUs; 1133 if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) { 1134 meta->setInt64("durationUs", durationUs); 1135 } 1136 1137 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) { 1138 meta->setInt32("trackIndex", mSubtitleTrack.mIndex); 1139 } 1140 1141 if (actualTimeUs) { 1142 *actualTimeUs = timeUs; 1143 } 1144 1145 mb->release(); 1146 mb = NULL; 1147 1148 return ab; 1149} 1150 1151void NuPlayer::GenericSource::postReadBuffer(media_track_type trackType) { 1152 Mutex::Autolock _l(mReadBufferLock); 1153 1154 if ((mPendingReadBufferTypes & (1 << trackType)) == 0) { 1155 mPendingReadBufferTypes |= (1 << trackType); 1156 sp<AMessage> msg = new AMessage(kWhatReadBuffer, id()); 1157 msg->setInt32("trackType", trackType); 1158 msg->post(); 1159 } 1160} 1161 1162void NuPlayer::GenericSource::onReadBuffer(sp<AMessage> msg) { 1163 int32_t tmpType; 1164 CHECK(msg->findInt32("trackType", &tmpType)); 1165 media_track_type trackType = (media_track_type)tmpType; 1166 { 1167 // only protect the variable change, as readBuffer may 1168 // take considerable time. This may result in one extra 1169 // read being processed, but that is benign. 1170 Mutex::Autolock _l(mReadBufferLock); 1171 mPendingReadBufferTypes &= ~(1 << trackType); 1172 } 1173 readBuffer(trackType); 1174} 1175 1176void NuPlayer::GenericSource::readBuffer( 1177 media_track_type trackType, int64_t seekTimeUs, int64_t *actualTimeUs, bool formatChange) { 1178 Track *track; 1179 switch (trackType) { 1180 case MEDIA_TRACK_TYPE_VIDEO: 1181 track = &mVideoTrack; 1182 break; 1183 case MEDIA_TRACK_TYPE_AUDIO: 1184 track = &mAudioTrack; 1185 break; 1186 case MEDIA_TRACK_TYPE_SUBTITLE: 1187 track = &mSubtitleTrack; 1188 break; 1189 case MEDIA_TRACK_TYPE_TIMEDTEXT: 1190 track = &mTimedTextTrack; 1191 break; 1192 default: 1193 TRESPASS(); 1194 } 1195 1196 if (track->mSource == NULL) { 1197 return; 1198 } 1199 1200 if (actualTimeUs) { 1201 *actualTimeUs = seekTimeUs; 1202 } 1203 1204 MediaSource::ReadOptions options; 1205 1206 bool seeking = false; 1207 1208 if (seekTimeUs >= 0) { 1209 options.setSeekTo(seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC); 1210 seeking = true; 1211 } 1212 1213 if (mIsWidevine && trackType != MEDIA_TRACK_TYPE_AUDIO) { 1214 options.setNonBlocking(); 1215 } 1216 1217 for (;;) { 1218 MediaBuffer *mbuf; 1219 status_t err = track->mSource->read(&mbuf, &options); 1220 1221 options.clearSeekTo(); 1222 1223 if (err == OK) { 1224 int64_t timeUs; 1225 CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs)); 1226 if (trackType == MEDIA_TRACK_TYPE_AUDIO) { 1227 mAudioTimeUs = timeUs; 1228 } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) { 1229 mVideoTimeUs = timeUs; 1230 } 1231 1232 // formatChange && seeking: track whose source is changed during selection 1233 // formatChange && !seeking: track whose source is not changed during selection 1234 // !formatChange: normal seek 1235 if ((seeking || formatChange) 1236 && (trackType == MEDIA_TRACK_TYPE_AUDIO 1237 || trackType == MEDIA_TRACK_TYPE_VIDEO)) { 1238 ATSParser::DiscontinuityType type = formatChange 1239 ? (seeking 1240 ? ATSParser::DISCONTINUITY_FORMATCHANGE 1241 : ATSParser::DISCONTINUITY_NONE) 1242 : ATSParser::DISCONTINUITY_SEEK; 1243 track->mPackets->queueDiscontinuity( type, NULL, true /* discard */); 1244 } 1245 1246 sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType, actualTimeUs); 1247 track->mPackets->queueAccessUnit(buffer); 1248 break; 1249 } else if (err == WOULD_BLOCK) { 1250 break; 1251 } else if (err == INFO_FORMAT_CHANGED) { 1252#if 0 1253 track->mPackets->queueDiscontinuity( 1254 ATSParser::DISCONTINUITY_FORMATCHANGE, 1255 NULL, 1256 false /* discard */); 1257#endif 1258 } else { 1259 track->mPackets->signalEOS(err); 1260 break; 1261 } 1262 } 1263} 1264 1265} // namespace android 1266