blob: b0c82f26c697e15177b890b1d588c6e734429298 [file] [log] [blame]
Andreas Huberafed0e12011-09-20 15:39:58 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Chong Zhang7e892182014-08-05 11:58:21 -070017//#define LOG_NDEBUG 0
18#define LOG_TAG "GenericSource"
19
Andreas Huberafed0e12011-09-20 15:39:58 -070020#include "GenericSource.h"
Hassan Shojaniacefac142017-02-06 21:02:02 -080021#include "NuPlayerDrm.h"
Andreas Huberafed0e12011-09-20 15:39:58 -070022
23#include "AnotherPacketSource.h"
Andy Hungd49dbd62016-07-07 14:20:35 -070024#include <binder/IServiceManager.h>
25#include <cutils/properties.h>
Dongwon Kangd91dc5a2017-10-10 00:07:09 -070026#include <media/DataSource.h>
Dongwon Kangbc8f53b2018-01-25 17:01:44 -080027#include <media/MediaBufferHolder.h>
Dongwon Kangd91dc5a2017-10-10 00:07:09 -070028#include <media/MediaExtractor.h>
29#include <media/MediaSource.h>
Chong Zhanga19f33e2014-08-07 15:35:07 -070030#include <media/IMediaHTTPService.h>
Andreas Huberafed0e12011-09-20 15:39:58 -070031#include <media/stagefright/foundation/ABuffer.h>
32#include <media/stagefright/foundation/ADebug.h>
33#include <media/stagefright/foundation/AMessage.h>
Dongwon Kangd91dc5a2017-10-10 00:07:09 -070034#include <media/stagefright/DataSourceFactory.h>
Andreas Huberafed0e12011-09-20 15:39:58 -070035#include <media/stagefright/FileSource.h>
Dongwon Kangd91dc5a2017-10-10 00:07:09 -070036#include <media/stagefright/InterfaceUtils.h>
Andreas Huberafed0e12011-09-20 15:39:58 -070037#include <media/stagefright/MediaBuffer.h>
Wei Jia992c5592017-09-01 14:20:23 -070038#include <media/stagefright/MediaClock.h>
Andreas Huberafed0e12011-09-20 15:39:58 -070039#include <media/stagefright/MediaDefs.h>
Dongwon Kangd91dc5a2017-10-10 00:07:09 -070040#include <media/stagefright/MediaExtractorFactory.h>
Andreas Huberafed0e12011-09-20 15:39:58 -070041#include <media/stagefright/MetaData.h>
Robert Shih17f6dd62014-08-20 17:00:21 -070042#include <media/stagefright/Utils.h>
Chong Zhangd354d8d2014-08-20 13:09:58 -070043#include "../../libstagefright/include/NuCachedSource2.h"
Robert Shih360d6d02014-09-29 14:42:35 -070044#include "../../libstagefright/include/HTTPBase.h"
Andreas Huberafed0e12011-09-20 15:39:58 -070045
46namespace android {
47
Wei Jia9bb38032017-03-23 18:00:38 -070048static const int kInitialMarkMs = 5000; // 5secs
49
50//static const int kPausePlaybackMarkMs = 2000; // 2secs
51static const int kResumePlaybackMarkMs = 15000; // 15secs
Wei Jia48fa06d2016-12-20 15:30:49 -080052
Andreas Huberafed0e12011-09-20 15:39:58 -070053NuPlayer::GenericSource::GenericSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080054 const sp<AMessage> &notify,
Lajos Molnarcc227032014-07-17 15:33:06 -070055 bool uidValid,
Wei Jia992c5592017-09-01 14:20:23 -070056 uid_t uid,
57 const sp<MediaClock> &mediaClock)
Andreas Huberb5f25f02013-02-05 10:14:26 -080058 : Source(notify),
Robert Shih5c67ddc2014-11-04 17:46:05 -080059 mAudioTimeUs(0),
60 mAudioLastDequeueTimeUs(0),
61 mVideoTimeUs(0),
62 mVideoLastDequeueTimeUs(0),
Wei Jia542a81a2017-10-16 10:31:29 -070063 mPrevBufferPercentage(-1),
64 mPollBufferingGeneration(0),
65 mSentPauseOnBuffering(false),
66 mAudioDataGeneration(0),
67 mVideoDataGeneration(0),
Robert Shih3423bbd2014-07-16 15:47:09 -070068 mFetchSubtitleDataGeneration(0),
Lajos Molnare26940f2014-07-31 10:31:26 -070069 mFetchTimedTextDataGeneration(0),
Marco Nelissen02fc5e32015-05-27 11:20:41 -070070 mDurationUs(-1ll),
Lajos Molnarcc227032014-07-17 15:33:06 -070071 mAudioIsVorbis(false),
Chong Zhang42e81532014-12-01 13:44:26 -080072 mIsSecure(false),
Chong Zhangefbb6192015-01-30 17:13:27 -080073 mIsStreaming(false),
Lajos Molnarcc227032014-07-17 15:33:06 -070074 mUIDValid(uidValid),
Chong Zhangd354d8d2014-08-20 13:09:58 -070075 mUID(uid),
Wei Jia992c5592017-09-01 14:20:23 -070076 mMediaClock(mediaClock),
Chong Zhanga6bf21f2014-11-19 20:26:34 -080077 mFd(-1),
Chong Zhang2a3cc9a2014-08-21 17:48:26 -070078 mBitrate(-1ll),
Wei Jia14532f22015-12-29 11:28:15 -080079 mPendingReadBufferTypes(0) {
Hassan Shojaniacefac142017-02-06 21:02:02 -080080 ALOGV("GenericSource");
Wei Jia992c5592017-09-01 14:20:23 -070081 CHECK(mediaClock != NULL);
Hassan Shojaniacefac142017-02-06 21:02:02 -080082
Wei Jia9bb38032017-03-23 18:00:38 -070083 mBufferingSettings.mInitialMarkMs = kInitialMarkMs;
84 mBufferingSettings.mResumePlaybackMarkMs = kResumePlaybackMarkMs;
Chong Zhanga19f33e2014-08-07 15:35:07 -070085 resetDataSource();
Chong Zhang3de157d2014-08-05 20:54:44 -070086}
87
Chong Zhanga19f33e2014-08-07 15:35:07 -070088void NuPlayer::GenericSource::resetDataSource() {
Hassan Shojaniacefac142017-02-06 21:02:02 -080089 ALOGV("resetDataSource");
90
Chong Zhanga19f33e2014-08-07 15:35:07 -070091 mHTTPService.clear();
Robert Shih360d6d02014-09-29 14:42:35 -070092 mHttpSource.clear();
Wei Jia67744bd2017-11-10 11:27:04 -080093 mDisconnected = false;
Chong Zhanga19f33e2014-08-07 15:35:07 -070094 mUri.clear();
95 mUriHeaders.clear();
Chong Zhanga6bf21f2014-11-19 20:26:34 -080096 if (mFd >= 0) {
97 close(mFd);
98 mFd = -1;
99 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700100 mOffset = 0;
101 mLength = 0;
Ronghua Wu80276872014-08-28 15:50:29 -0700102 mStarted = false;
Wei Jia542a81a2017-10-16 10:31:29 -0700103 mPreparing = false;
Hassan Shojaniacefac142017-02-06 21:02:02 -0800104
105 mIsDrmProtected = false;
Hassan Shojania355e8472017-05-12 10:33:16 -0700106 mIsDrmReleased = false;
Hassan Shojaniacefac142017-02-06 21:02:02 -0800107 mIsSecure = false;
108 mMimes.clear();
Chong Zhanga19f33e2014-08-07 15:35:07 -0700109}
110
111status_t NuPlayer::GenericSource::setDataSource(
Chong Zhang3de157d2014-08-05 20:54:44 -0700112 const sp<IMediaHTTPService> &httpService,
113 const char *url,
114 const KeyedVector<String8, String8> *headers) {
Wei Jia542a81a2017-10-16 10:31:29 -0700115 Mutex::Autolock _l(mLock);
Hassan Shojaniacefac142017-02-06 21:02:02 -0800116 ALOGV("setDataSource url: %s", url);
117
Chong Zhanga19f33e2014-08-07 15:35:07 -0700118 resetDataSource();
Chong Zhang3de157d2014-08-05 20:54:44 -0700119
Chong Zhanga19f33e2014-08-07 15:35:07 -0700120 mHTTPService = httpService;
121 mUri = url;
Andreas Huberafed0e12011-09-20 15:39:58 -0700122
Chong Zhanga19f33e2014-08-07 15:35:07 -0700123 if (headers) {
124 mUriHeaders = *headers;
Chong Zhang3de157d2014-08-05 20:54:44 -0700125 }
126
Chong Zhanga19f33e2014-08-07 15:35:07 -0700127 // delay data source creation to prepareAsync() to avoid blocking
128 // the calling thread in setDataSource for any significant time.
129 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700130}
131
Chong Zhanga19f33e2014-08-07 15:35:07 -0700132status_t NuPlayer::GenericSource::setDataSource(
Chong Zhang3de157d2014-08-05 20:54:44 -0700133 int fd, int64_t offset, int64_t length) {
Wei Jia542a81a2017-10-16 10:31:29 -0700134 Mutex::Autolock _l(mLock);
Hassan Shojaniacefac142017-02-06 21:02:02 -0800135 ALOGV("setDataSource %d/%lld/%lld", fd, (long long)offset, (long long)length);
136
Chong Zhanga19f33e2014-08-07 15:35:07 -0700137 resetDataSource();
Andreas Huberafed0e12011-09-20 15:39:58 -0700138
Chong Zhanga19f33e2014-08-07 15:35:07 -0700139 mFd = dup(fd);
140 mOffset = offset;
141 mLength = length;
142
143 // delay data source creation to prepareAsync() to avoid blocking
144 // the calling thread in setDataSource for any significant time.
145 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700146}
147
Chris Watkins99f31602015-03-20 13:06:33 -0700148status_t NuPlayer::GenericSource::setDataSource(const sp<DataSource>& source) {
Wei Jia542a81a2017-10-16 10:31:29 -0700149 Mutex::Autolock _l(mLock);
Hassan Shojaniacefac142017-02-06 21:02:02 -0800150 ALOGV("setDataSource (source: %p)", source.get());
151
Chris Watkins99f31602015-03-20 13:06:33 -0700152 resetDataSource();
153 mDataSource = source;
154 return OK;
155}
156
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700157sp<MetaData> NuPlayer::GenericSource::getFileFormatMeta() const {
Wei Jia542a81a2017-10-16 10:31:29 -0700158 Mutex::Autolock _l(mLock);
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700159 return mFileMeta;
160}
161
Chong Zhangd354d8d2014-08-20 13:09:58 -0700162status_t NuPlayer::GenericSource::initFromDataSource() {
Marco Nelissenb2487f02015-09-01 13:23:23 -0700163 sp<IMediaExtractor> extractor;
Dongwon Kang51467422017-12-08 06:07:16 -0800164 CHECK(mDataSource != NULL || mFd != -1);
Wei Jia67744bd2017-11-10 11:27:04 -0800165 sp<DataSource> dataSource = mDataSource;
Dongwon Kang51467422017-12-08 06:07:16 -0800166 const int fd = mFd;
167 const int64_t offset = mOffset;
168 const int64_t length = mLength;
Chong Zhangd354d8d2014-08-20 13:09:58 -0700169
Wei Jia67744bd2017-11-10 11:27:04 -0800170 mLock.unlock();
171 // This might take long time if data source is not reliable.
Dongwon Kang51467422017-12-08 06:07:16 -0800172 if (dataSource != nullptr) {
173 extractor = MediaExtractorFactory::Create(dataSource, NULL /* mime */);
174 } else {
175 extractor = MediaExtractorFactory::CreateFromFd(
176 fd, offset, length, NULL /* mime */, &dataSource);
177 }
178
179 if (dataSource == nullptr) {
180 ALOGE("initFromDataSource, failed to create data source!");
181 mLock.lock();
182 return UNKNOWN_ERROR;
183 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700184
Chong Zhang3de157d2014-08-05 20:54:44 -0700185 if (extractor == NULL) {
Wei Jia161dc692017-04-20 16:40:06 -0700186 ALOGE("initFromDataSource, cannot create extractor!");
Dongwon Kang51467422017-12-08 06:07:16 -0800187 mLock.lock();
Chong Zhang3de157d2014-08-05 20:54:44 -0700188 return UNKNOWN_ERROR;
189 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700190
Wei Jia67744bd2017-11-10 11:27:04 -0800191 sp<MetaData> fileMeta = extractor->getMetaData();
192
193 size_t numtracks = extractor->countTracks();
194 if (numtracks == 0) {
195 ALOGE("initFromDataSource, source has no track!");
Dongwon Kang51467422017-12-08 06:07:16 -0800196 mLock.lock();
Wei Jia67744bd2017-11-10 11:27:04 -0800197 return UNKNOWN_ERROR;
198 }
199
200 mLock.lock();
Dongwon Kang51467422017-12-08 06:07:16 -0800201 mFd = -1;
202 mDataSource = dataSource;
Wei Jia67744bd2017-11-10 11:27:04 -0800203 mFileMeta = fileMeta;
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700204 if (mFileMeta != NULL) {
Marco Nelissenc1f4b2b2014-06-17 14:48:32 -0700205 int64_t duration;
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700206 if (mFileMeta->findInt64(kKeyDuration, &duration)) {
Marco Nelissenc1f4b2b2014-06-17 14:48:32 -0700207 mDurationUs = duration;
208 }
209 }
210
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700211 int32_t totalBitrate = 0;
212
Hassan Shojaniacefac142017-02-06 21:02:02 -0800213 mMimes.clear();
214
Marco Nelissen705d3292014-09-19 15:14:37 -0700215 for (size_t i = 0; i < numtracks; ++i) {
Marco Nelissenb2487f02015-09-01 13:23:23 -0700216 sp<IMediaSource> track = extractor->getTrack(i);
Wei Jia0386c912015-08-28 10:35:35 -0700217 if (track == NULL) {
218 continue;
219 }
Chong Zhangafc0a872014-08-26 09:56:52 -0700220
Andreas Huberafed0e12011-09-20 15:39:58 -0700221 sp<MetaData> meta = extractor->getTrackMetaData(i);
Marco Nelissenc367ca12015-09-15 09:51:59 -0700222 if (meta == NULL) {
223 ALOGE("no metadata for track %zu", i);
224 return UNKNOWN_ERROR;
225 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700226
227 const char *mime;
228 CHECK(meta->findCString(kKeyMIMEType, &mime));
229
Hassan Shojania06a70812017-02-15 21:57:45 -0800230 ALOGV("initFromDataSource track[%zu]: %s", i, mime);
Hassan Shojaniacefac142017-02-06 21:02:02 -0800231
Chong Zhangafc0a872014-08-26 09:56:52 -0700232 // Do the string compare immediately with "mime",
233 // we can't assume "mime" would stay valid after another
234 // extractor operation, some extractors might modify meta
235 // during getTrack() and make it invalid.
Andreas Huberafed0e12011-09-20 15:39:58 -0700236 if (!strncasecmp(mime, "audio/", 6)) {
237 if (mAudioTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700238 mAudioTrack.mIndex = i;
239 mAudioTrack.mSource = track;
Robert Shihaf52c1a2014-09-11 15:38:54 -0700240 mAudioTrack.mPackets =
241 new AnotherPacketSource(mAudioTrack.mSource->getFormat());
Andreas Huberafed0e12011-09-20 15:39:58 -0700242
243 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
244 mAudioIsVorbis = true;
245 } else {
246 mAudioIsVorbis = false;
247 }
Hassan Shojaniacefac142017-02-06 21:02:02 -0800248
249 mMimes.add(String8(mime));
Andreas Huberafed0e12011-09-20 15:39:58 -0700250 }
251 } else if (!strncasecmp(mime, "video/", 6)) {
252 if (mVideoTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700253 mVideoTrack.mIndex = i;
254 mVideoTrack.mSource = track;
Robert Shihaf52c1a2014-09-11 15:38:54 -0700255 mVideoTrack.mPackets =
256 new AnotherPacketSource(mVideoTrack.mSource->getFormat());
Chong Zhang7e892182014-08-05 11:58:21 -0700257
Hassan Shojaniacefac142017-02-06 21:02:02 -0800258 // video always at the beginning
259 mMimes.insertAt(String8(mime), 0);
Andreas Huberafed0e12011-09-20 15:39:58 -0700260 }
261 }
262
Wei Jia0386c912015-08-28 10:35:35 -0700263 mSources.push(track);
264 int64_t durationUs;
265 if (meta->findInt64(kKeyDuration, &durationUs)) {
266 if (durationUs > mDurationUs) {
267 mDurationUs = durationUs;
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700268 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700269 }
Wei Jia0386c912015-08-28 10:35:35 -0700270
271 int32_t bitrate;
272 if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) {
273 totalBitrate += bitrate;
274 } else {
275 totalBitrate = -1;
276 }
277 }
278
Hassan Shojaniacefac142017-02-06 21:02:02 -0800279 ALOGV("initFromDataSource mSources.size(): %zu mIsSecure: %d mime[0]: %s", mSources.size(),
280 mIsSecure, (mMimes.isEmpty() ? "NONE" : mMimes[0].string()));
281
Wei Jia0386c912015-08-28 10:35:35 -0700282 if (mSources.size() == 0) {
283 ALOGE("b/23705695");
284 return UNKNOWN_ERROR;
Andreas Huberafed0e12011-09-20 15:39:58 -0700285 }
Chong Zhang3de157d2014-08-05 20:54:44 -0700286
Hassan Shojaniacefac142017-02-06 21:02:02 -0800287 // Modular DRM: The return value doesn't affect source initialization.
288 (void)checkDrmInfo();
289
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700290 mBitrate = totalBitrate;
291
292 return OK;
293}
294
Wei Jia9bb38032017-03-23 18:00:38 -0700295status_t NuPlayer::GenericSource::getBufferingSettings(
Wei Jia48fa06d2016-12-20 15:30:49 -0800296 BufferingSettings* buffering /* nonnull */) {
Wei Jia9bb38032017-03-23 18:00:38 -0700297 {
298 Mutex::Autolock _l(mLock);
299 *buffering = mBufferingSettings;
300 }
Wei Jia542a81a2017-10-16 10:31:29 -0700301
Wei Jia9bb38032017-03-23 18:00:38 -0700302 ALOGV("getBufferingSettings{%s}", buffering->toString().string());
Wei Jia48fa06d2016-12-20 15:30:49 -0800303 return OK;
304}
305
306status_t NuPlayer::GenericSource::setBufferingSettings(const BufferingSettings& buffering) {
Wei Jia542a81a2017-10-16 10:31:29 -0700307 ALOGV("setBufferingSettings{%s}", buffering.toString().string());
308
Wei Jia542a81a2017-10-16 10:31:29 -0700309 Mutex::Autolock _l(mLock);
310 mBufferingSettings = buffering;
Wei Jia542a81a2017-10-16 10:31:29 -0700311 return OK;
Wei Jia48fa06d2016-12-20 15:30:49 -0800312}
313
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700314status_t NuPlayer::GenericSource::startSources() {
Chong Zhangefbb6192015-01-30 17:13:27 -0800315 // Start the selected A/V tracks now before we start buffering.
316 // Widevine sources might re-initialize crypto when starting, if we delay
317 // this to start(), all data buffered during prepare would be wasted.
318 // (We don't actually start reading until start().)
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700319 //
320 // TODO: this logic may no longer be relevant after the removal of widevine
321 // support
Chong Zhangefbb6192015-01-30 17:13:27 -0800322 if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) {
323 ALOGE("failed to start audio track!");
324 return UNKNOWN_ERROR;
325 }
326
327 if (mVideoTrack.mSource != NULL && mVideoTrack.mSource->start() != OK) {
328 ALOGE("failed to start video track!");
329 return UNKNOWN_ERROR;
330 }
331
Chong Zhang3de157d2014-08-05 20:54:44 -0700332 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700333}
334
Ronghua Wu80276872014-08-28 15:50:29 -0700335int64_t NuPlayer::GenericSource::getLastReadPosition() {
336 if (mAudioTrack.mSource != NULL) {
337 return mAudioTimeUs;
338 } else if (mVideoTrack.mSource != NULL) {
339 return mVideoTimeUs;
340 } else {
341 return 0;
342 }
343}
344
Ronghua Wu02cb98d2015-05-27 11:02:54 -0700345bool NuPlayer::GenericSource::isStreaming() const {
Wei Jia542a81a2017-10-16 10:31:29 -0700346 Mutex::Autolock _l(mLock);
Ronghua Wu02cb98d2015-05-27 11:02:54 -0700347 return mIsStreaming;
348}
349
Andreas Huberafed0e12011-09-20 15:39:58 -0700350NuPlayer::GenericSource::~GenericSource() {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800351 ALOGV("~GenericSource");
Chong Zhang1228d6b2014-08-12 21:25:48 -0700352 if (mLooper != NULL) {
353 mLooper->unregisterHandler(id());
354 mLooper->stop();
355 }
Chong Zhanga6bf21f2014-11-19 20:26:34 -0800356 resetDataSource();
Andreas Huberafed0e12011-09-20 15:39:58 -0700357}
358
Andreas Huber9575c962013-02-05 13:59:56 -0800359void NuPlayer::GenericSource::prepareAsync() {
Wei Jia542a81a2017-10-16 10:31:29 -0700360 Mutex::Autolock _l(mLock);
Hassan Shojaniacefac142017-02-06 21:02:02 -0800361 ALOGV("prepareAsync: (looper: %d)", (mLooper != NULL));
362
Chong Zhang1228d6b2014-08-12 21:25:48 -0700363 if (mLooper == NULL) {
364 mLooper = new ALooper;
365 mLooper->setName("generic");
366 mLooper->start();
367
368 mLooper->registerHandler(this);
369 }
370
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800371 sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this);
Chong Zhang1228d6b2014-08-12 21:25:48 -0700372 msg->post();
373}
374
375void NuPlayer::GenericSource::onPrepareAsync() {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800376 ALOGV("onPrepareAsync: mDataSource: %d", (mDataSource != NULL));
377
Chong Zhanga19f33e2014-08-07 15:35:07 -0700378 // delayed data source creation
Chong Zhangd354d8d2014-08-20 13:09:58 -0700379 if (mDataSource == NULL) {
Chong Zhang42e81532014-12-01 13:44:26 -0800380 // set to false first, if the extractor
381 // comes back as secure, set it to true then.
382 mIsSecure = false;
383
Chong Zhangd354d8d2014-08-20 13:09:58 -0700384 if (!mUri.empty()) {
Robert Shih360d6d02014-09-29 14:42:35 -0700385 const char* uri = mUri.c_str();
Chong Zhangc287cad2015-02-19 18:30:30 -0800386 String8 contentType;
Robert Shih360d6d02014-09-29 14:42:35 -0700387
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700388 if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
Dongwon Kangd91dc5a2017-10-10 00:07:09 -0700389 mHttpSource = DataSourceFactory::CreateMediaHTTP(mHTTPService);
Robert Shih360d6d02014-09-29 14:42:35 -0700390 if (mHttpSource == NULL) {
391 ALOGE("Failed to create http source!");
392 notifyPreparedAndCleanup(UNKNOWN_ERROR);
393 return;
394 }
395 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700396
Wei Jia67744bd2017-11-10 11:27:04 -0800397 mLock.unlock();
398 // This might take long time if connection has some issue.
399 sp<DataSource> dataSource = DataSourceFactory::CreateFromURI(
Chong Zhangc287cad2015-02-19 18:30:30 -0800400 mHTTPService, uri, &mUriHeaders, &contentType,
Robert Shih360d6d02014-09-29 14:42:35 -0700401 static_cast<HTTPBase *>(mHttpSource.get()));
Wei Jia67744bd2017-11-10 11:27:04 -0800402 mLock.lock();
403 if (!mDisconnected) {
404 mDataSource = dataSource;
405 }
Chong Zhangd354d8d2014-08-20 13:09:58 -0700406 }
Dongwon Kang51467422017-12-08 06:07:16 -0800407 if (mFd == -1 && mDataSource == NULL) {
Chong Zhangd354d8d2014-08-20 13:09:58 -0700408 ALOGE("Failed to create data source!");
409 notifyPreparedAndCleanup(UNKNOWN_ERROR);
410 return;
411 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700412 }
413
Dongwon Kang51467422017-12-08 06:07:16 -0800414 if (mDataSource != nullptr && mDataSource->flags() & DataSource::kIsCachingDataSource) {
Chris Watkins99f31602015-03-20 13:06:33 -0700415 mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
416 }
417
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700418 // For cached streaming cases, we need to wait for enough
419 // buffering before reporting prepared.
420 mIsStreaming = (mCachedSource != NULL);
Chris Watkins99f31602015-03-20 13:06:33 -0700421
Chong Zhangc287cad2015-02-19 18:30:30 -0800422 // init extractor from data source
423 status_t err = initFromDataSource();
Chong Zhanga19f33e2014-08-07 15:35:07 -0700424
425 if (err != OK) {
426 ALOGE("Failed to init from data source!");
Chong Zhangd354d8d2014-08-20 13:09:58 -0700427 notifyPreparedAndCleanup(err);
Chong Zhanga19f33e2014-08-07 15:35:07 -0700428 return;
429 }
430
Andreas Huber9575c962013-02-05 13:59:56 -0800431 if (mVideoTrack.mSource != NULL) {
Wei Jia542a81a2017-10-16 10:31:29 -0700432 sp<MetaData> meta = getFormatMeta_l(false /* audio */);
Robert Shih17f6dd62014-08-20 17:00:21 -0700433 sp<AMessage> msg = new AMessage;
434 err = convertMetaDataToMessage(meta, &msg);
435 if(err != OK) {
436 notifyPreparedAndCleanup(err);
437 return;
438 }
439 notifyVideoSizeChanged(msg);
Andreas Huber9575c962013-02-05 13:59:56 -0800440 }
441
442 notifyFlagsChanged(
Hassan Shojaniacefac142017-02-06 21:02:02 -0800443 // FLAG_SECURE will be known if/when prepareDrm is called by the app
444 // FLAG_PROTECTED will be known if/when prepareDrm is called by the app
445 FLAG_CAN_PAUSE |
446 FLAG_CAN_SEEK_BACKWARD |
447 FLAG_CAN_SEEK_FORWARD |
448 FLAG_CAN_SEEK);
Andreas Huber9575c962013-02-05 13:59:56 -0800449
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700450 finishPrepareAsync();
Hassan Shojaniacefac142017-02-06 21:02:02 -0800451
452 ALOGV("onPrepareAsync: Done");
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700453}
454
455void NuPlayer::GenericSource::finishPrepareAsync() {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800456 ALOGV("finishPrepareAsync");
457
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700458 status_t err = startSources();
459 if (err != OK) {
460 ALOGE("Failed to init start data source!");
461 notifyPreparedAndCleanup(err);
462 return;
463 }
464
Chong Zhangefbb6192015-01-30 17:13:27 -0800465 if (mIsStreaming) {
Wei Jia542a81a2017-10-16 10:31:29 -0700466 mCachedSource->resumeFetchingIfNecessary();
467 mPreparing = true;
468 schedulePollBuffering();
Chong Zhangefbb6192015-01-30 17:13:27 -0800469 } else {
470 notifyPrepared();
471 }
Wei Jia542a81a2017-10-16 10:31:29 -0700472
473 if (mAudioTrack.mSource != NULL) {
474 postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
475 }
476
477 if (mVideoTrack.mSource != NULL) {
478 postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
479 }
Andreas Huber9575c962013-02-05 13:59:56 -0800480}
481
Chong Zhangd354d8d2014-08-20 13:09:58 -0700482void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
483 if (err != OK) {
Wei Jia542a81a2017-10-16 10:31:29 -0700484 mDataSource.clear();
485 mCachedSource.clear();
486 mHttpSource.clear();
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700487
Wei Jia542a81a2017-10-16 10:31:29 -0700488 mBitrate = -1;
489 mPrevBufferPercentage = -1;
490 ++mPollBufferingGeneration;
Chong Zhangd354d8d2014-08-20 13:09:58 -0700491 }
492 notifyPrepared(err);
493}
494
Andreas Huberafed0e12011-09-20 15:39:58 -0700495void NuPlayer::GenericSource::start() {
Wei Jia542a81a2017-10-16 10:31:29 -0700496 Mutex::Autolock _l(mLock);
Andreas Huberafed0e12011-09-20 15:39:58 -0700497 ALOGI("start");
498
499 if (mAudioTrack.mSource != NULL) {
Robert Shih17f6dd62014-08-20 17:00:21 -0700500 postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700501 }
502
503 if (mVideoTrack.mSource != NULL) {
Robert Shih17f6dd62014-08-20 17:00:21 -0700504 postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700505 }
Ronghua Wu80276872014-08-28 15:50:29 -0700506
Ronghua Wu80276872014-08-28 15:50:29 -0700507 mStarted = true;
508}
509
510void NuPlayer::GenericSource::stop() {
Wei Jia542a81a2017-10-16 10:31:29 -0700511 Mutex::Autolock _l(mLock);
Ronghua Wu80276872014-08-28 15:50:29 -0700512 mStarted = false;
513}
514
515void NuPlayer::GenericSource::pause() {
Wei Jia542a81a2017-10-16 10:31:29 -0700516 Mutex::Autolock _l(mLock);
Ronghua Wu80276872014-08-28 15:50:29 -0700517 mStarted = false;
518}
519
520void NuPlayer::GenericSource::resume() {
Wei Jia542a81a2017-10-16 10:31:29 -0700521 Mutex::Autolock _l(mLock);
Ronghua Wu80276872014-08-28 15:50:29 -0700522 mStarted = true;
523}
524
Chong Zhang48296b72014-09-14 14:28:45 -0700525void NuPlayer::GenericSource::disconnect() {
Robert Shihebc27122015-09-02 14:02:47 -0700526 sp<DataSource> dataSource, httpSource;
527 {
Wei Jia542a81a2017-10-16 10:31:29 -0700528 Mutex::Autolock _l(mLock);
Robert Shihebc27122015-09-02 14:02:47 -0700529 dataSource = mDataSource;
530 httpSource = mHttpSource;
Wei Jia67744bd2017-11-10 11:27:04 -0800531 mDisconnected = true;
Robert Shihebc27122015-09-02 14:02:47 -0700532 }
533
534 if (dataSource != NULL) {
Chong Zhang48296b72014-09-14 14:28:45 -0700535 // disconnect data source
Robert Shihebc27122015-09-02 14:02:47 -0700536 if (dataSource->flags() & DataSource::kIsCachingDataSource) {
537 static_cast<NuCachedSource2 *>(dataSource.get())->disconnect();
Chong Zhang48296b72014-09-14 14:28:45 -0700538 }
Robert Shihebc27122015-09-02 14:02:47 -0700539 } else if (httpSource != NULL) {
540 static_cast<HTTPBase *>(httpSource.get())->disconnect();
Chong Zhang48296b72014-09-14 14:28:45 -0700541 }
542}
543
Andreas Huberafed0e12011-09-20 15:39:58 -0700544status_t NuPlayer::GenericSource::feedMoreTSData() {
545 return OK;
546}
547
Wei Jia542a81a2017-10-16 10:31:29 -0700548void NuPlayer::GenericSource::sendCacheStats() {
549 int32_t kbps = 0;
550 status_t err = UNKNOWN_ERROR;
551
552 if (mCachedSource != NULL) {
553 err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
554 }
555
556 if (err == OK) {
557 sp<AMessage> notify = dupNotify();
558 notify->setInt32("what", kWhatCacheStats);
559 notify->setInt32("bandwidth", kbps);
560 notify->post();
561 }
562}
563
Robert Shih3423bbd2014-07-16 15:47:09 -0700564void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
Wei Jia542a81a2017-10-16 10:31:29 -0700565 Mutex::Autolock _l(mLock);
Robert Shih3423bbd2014-07-16 15:47:09 -0700566 switch (msg->what()) {
Chong Zhang1228d6b2014-08-12 21:25:48 -0700567 case kWhatPrepareAsync:
568 {
569 onPrepareAsync();
570 break;
571 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700572 case kWhatFetchSubtitleData:
573 {
Lajos Molnare26940f2014-07-31 10:31:26 -0700574 fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
575 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
576 break;
577 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700578
Lajos Molnare26940f2014-07-31 10:31:26 -0700579 case kWhatFetchTimedTextData:
580 {
581 fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
582 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih3423bbd2014-07-16 15:47:09 -0700583 break;
584 }
585
586 case kWhatSendSubtitleData:
587 {
Lajos Molnare26940f2014-07-31 10:31:26 -0700588 sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
589 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
590 break;
591 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700592
Marco Nelissen55e2f4c2015-09-04 15:57:15 -0700593 case kWhatSendGlobalTimedTextData:
594 {
595 sendGlobalTextData(kWhatTimedTextData, mFetchTimedTextDataGeneration, msg);
596 break;
597 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700598 case kWhatSendTimedTextData:
599 {
600 sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
601 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih3423bbd2014-07-16 15:47:09 -0700602 break;
603 }
604
605 case kWhatChangeAVSource:
606 {
607 int32_t trackIndex;
608 CHECK(msg->findInt32("trackIndex", &trackIndex));
Marco Nelissenb2487f02015-09-01 13:23:23 -0700609 const sp<IMediaSource> source = mSources.itemAt(trackIndex);
Robert Shih3423bbd2014-07-16 15:47:09 -0700610
611 Track* track;
612 const char *mime;
613 media_track_type trackType, counterpartType;
614 sp<MetaData> meta = source->getFormat();
615 meta->findCString(kKeyMIMEType, &mime);
616 if (!strncasecmp(mime, "audio/", 6)) {
617 track = &mAudioTrack;
618 trackType = MEDIA_TRACK_TYPE_AUDIO;
619 counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
620 } else {
621 CHECK(!strncasecmp(mime, "video/", 6));
622 track = &mVideoTrack;
623 trackType = MEDIA_TRACK_TYPE_VIDEO;
624 counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
625 }
626
627
628 if (track->mSource != NULL) {
629 track->mSource->stop();
630 }
631 track->mSource = source;
632 track->mSource->start();
633 track->mIndex = trackIndex;
Wei Jia542a81a2017-10-16 10:31:29 -0700634 ++mAudioDataGeneration;
635 ++mVideoDataGeneration;
Robert Shih3423bbd2014-07-16 15:47:09 -0700636
Robert Shih3423bbd2014-07-16 15:47:09 -0700637 int64_t timeUs, actualTimeUs;
638 const bool formatChange = true;
Robert Shih5c67ddc2014-11-04 17:46:05 -0800639 if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
640 timeUs = mAudioLastDequeueTimeUs;
641 } else {
642 timeUs = mVideoLastDequeueTimeUs;
643 }
Wei Jiac5de0912016-11-18 10:22:14 -0800644 readBuffer(trackType, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
645 &actualTimeUs, formatChange);
646 readBuffer(counterpartType, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
647 NULL, !formatChange);
Lajos Molnar6d339f12015-04-17 16:15:53 -0700648 ALOGV("timeUs %lld actualTimeUs %lld", (long long)timeUs, (long long)actualTimeUs);
Robert Shih3423bbd2014-07-16 15:47:09 -0700649
650 break;
651 }
Chong Zhangefbb6192015-01-30 17:13:27 -0800652
Wei Jiac899fc02017-11-15 17:28:53 -0800653 case kWhatSeek:
654 {
655 onSeek(msg);
656 break;
657 }
658
Robert Shih17f6dd62014-08-20 17:00:21 -0700659 case kWhatReadBuffer:
660 {
661 onReadBuffer(msg);
662 break;
663 }
664
Wei Jia542a81a2017-10-16 10:31:29 -0700665 case kWhatPollBuffering:
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700666 {
Wei Jia542a81a2017-10-16 10:31:29 -0700667 int32_t generation;
668 CHECK(msg->findInt32("generation", &generation));
669 if (generation == mPollBufferingGeneration) {
670 onPollBuffering();
671 }
Hassan Shojania355e8472017-05-12 10:33:16 -0700672 break;
673 }
674
Robert Shih3423bbd2014-07-16 15:47:09 -0700675 default:
676 Source::onMessageReceived(msg);
677 break;
678 }
679}
680
Lajos Molnare26940f2014-07-31 10:31:26 -0700681void NuPlayer::GenericSource::fetchTextData(
682 uint32_t sendWhat,
683 media_track_type type,
684 int32_t curGen,
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -0700685 const sp<AnotherPacketSource>& packets,
686 const sp<AMessage>& msg) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700687 int32_t msgGeneration;
688 CHECK(msg->findInt32("generation", &msgGeneration));
689 if (msgGeneration != curGen) {
690 // stale
691 return;
692 }
693
694 int32_t avail;
695 if (packets->hasBufferAvailable(&avail)) {
696 return;
697 }
698
699 int64_t timeUs;
700 CHECK(msg->findInt64("timeUs", &timeUs));
701
Wei Jia992c5592017-09-01 14:20:23 -0700702 int64_t subTimeUs = 0;
Wei Jiac5de0912016-11-18 10:22:14 -0800703 readBuffer(type, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &subTimeUs);
Lajos Molnare26940f2014-07-31 10:31:26 -0700704
Wei Jia992c5592017-09-01 14:20:23 -0700705 status_t eosResult;
706 if (!packets->hasBufferAvailable(&eosResult)) {
707 return;
708 }
709
Lajos Molnare26940f2014-07-31 10:31:26 -0700710 if (msg->what() == kWhatFetchSubtitleData) {
Wei Jia992c5592017-09-01 14:20:23 -0700711 subTimeUs -= 1000000ll; // send subtile data one second earlier
Lajos Molnare26940f2014-07-31 10:31:26 -0700712 }
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800713 sp<AMessage> msg2 = new AMessage(sendWhat, this);
Lajos Molnare26940f2014-07-31 10:31:26 -0700714 msg2->setInt32("generation", msgGeneration);
Wei Jia992c5592017-09-01 14:20:23 -0700715 mMediaClock->addTimer(msg2, subTimeUs);
Lajos Molnare26940f2014-07-31 10:31:26 -0700716}
717
718void NuPlayer::GenericSource::sendTextData(
719 uint32_t what,
720 media_track_type type,
721 int32_t curGen,
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -0700722 const sp<AnotherPacketSource>& packets,
723 const sp<AMessage>& msg) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700724 int32_t msgGeneration;
725 CHECK(msg->findInt32("generation", &msgGeneration));
726 if (msgGeneration != curGen) {
727 // stale
728 return;
729 }
730
731 int64_t subTimeUs;
732 if (packets->nextBufferTime(&subTimeUs) != OK) {
733 return;
734 }
735
736 int64_t nextSubTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -0800737 readBuffer(type, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &nextSubTimeUs);
Lajos Molnare26940f2014-07-31 10:31:26 -0700738
739 sp<ABuffer> buffer;
740 status_t dequeueStatus = packets->dequeueAccessUnit(&buffer);
741 if (dequeueStatus == OK) {
742 sp<AMessage> notify = dupNotify();
743 notify->setInt32("what", what);
744 notify->setBuffer("buffer", buffer);
745 notify->post();
746
Wei Jia992c5592017-09-01 14:20:23 -0700747 if (msg->what() == kWhatSendSubtitleData) {
748 nextSubTimeUs -= 1000000ll; // send subtile data one second earlier
749 }
750 mMediaClock->addTimer(msg, nextSubTimeUs);
Lajos Molnare26940f2014-07-31 10:31:26 -0700751 }
752}
753
Marco Nelissen55e2f4c2015-09-04 15:57:15 -0700754void NuPlayer::GenericSource::sendGlobalTextData(
755 uint32_t what,
756 int32_t curGen,
757 sp<AMessage> msg) {
758 int32_t msgGeneration;
759 CHECK(msg->findInt32("generation", &msgGeneration));
760 if (msgGeneration != curGen) {
761 // stale
762 return;
763 }
764
765 uint32_t textType;
766 const void *data;
767 size_t size = 0;
768 if (mTimedTextTrack.mSource->getFormat()->findData(
769 kKeyTextFormatData, &textType, &data, &size)) {
770 mGlobalTimedText = new ABuffer(size);
771 if (mGlobalTimedText->data()) {
772 memcpy(mGlobalTimedText->data(), data, size);
773 sp<AMessage> globalMeta = mGlobalTimedText->meta();
774 globalMeta->setInt64("timeUs", 0);
775 globalMeta->setString("mime", MEDIA_MIMETYPE_TEXT_3GPP);
776 globalMeta->setInt32("global", 1);
777 sp<AMessage> notify = dupNotify();
778 notify->setInt32("what", what);
779 notify->setBuffer("buffer", mGlobalTimedText);
780 notify->post();
781 }
782 }
783}
784
Andreas Huber84066782011-08-16 09:34:26 -0700785sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
Wei Jia542a81a2017-10-16 10:31:29 -0700786 Mutex::Autolock _l(mLock);
787 return getFormatMeta_l(audio);
Robert Shih17f6dd62014-08-20 17:00:21 -0700788}
789
Wei Jia542a81a2017-10-16 10:31:29 -0700790sp<MetaData> NuPlayer::GenericSource::getFormatMeta_l(bool audio) {
Marco Nelissenb2487f02015-09-01 13:23:23 -0700791 sp<IMediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
Andreas Huberafed0e12011-09-20 15:39:58 -0700792
793 if (source == NULL) {
794 return NULL;
795 }
796
797 return source->getFormat();
798}
799
800status_t NuPlayer::GenericSource::dequeueAccessUnit(
801 bool audio, sp<ABuffer> *accessUnit) {
Wei Jia542a81a2017-10-16 10:31:29 -0700802 Mutex::Autolock _l(mLock);
Hassan Shojania355e8472017-05-12 10:33:16 -0700803 // If has gone through stop/releaseDrm sequence, we no longer send down any buffer b/c
804 // the codec's crypto object has gone away (b/37960096).
805 // Note: This will be unnecessary when stop() changes behavior and releases codec (b/35248283).
806 if (!mStarted && mIsDrmReleased) {
807 return -EWOULDBLOCK;
808 }
809
Andreas Huberafed0e12011-09-20 15:39:58 -0700810 Track *track = audio ? &mAudioTrack : &mVideoTrack;
811
812 if (track->mSource == NULL) {
813 return -EWOULDBLOCK;
814 }
815
816 status_t finalResult;
817 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
Chong Zhang42e81532014-12-01 13:44:26 -0800818 if (finalResult == OK) {
819 postReadBuffer(
820 audio ? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
821 return -EWOULDBLOCK;
822 }
823 return finalResult;
Andreas Huberafed0e12011-09-20 15:39:58 -0700824 }
825
826 status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
827
Wei Jia542a81a2017-10-16 10:31:29 -0700828 // start pulling in more buffers if cache is running low
Chong Zhangfcf044a2015-07-14 15:58:51 -0700829 // so that decoder has less chance of being starved
Wei Jia542a81a2017-10-16 10:31:29 -0700830 if (!mIsStreaming) {
831 if (track->mPackets->getAvailableBufferCount(&finalResult) < 2) {
832 postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
833 }
834 } else {
835 int64_t durationUs = track->mPackets->getBufferedDurationUs(&finalResult);
Wei Jia9bb38032017-03-23 18:00:38 -0700836 // TODO: maxRebufferingMarkMs could be larger than
837 // mBufferingSettings.mResumePlaybackMarkMs
Wei Jia542a81a2017-10-16 10:31:29 -0700838 int64_t restartBufferingMarkUs =
Wei Jia9bb38032017-03-23 18:00:38 -0700839 mBufferingSettings.mResumePlaybackMarkMs * 1000ll / 2;
Wei Jia542a81a2017-10-16 10:31:29 -0700840 if (finalResult == OK) {
841 if (durationUs < restartBufferingMarkUs) {
842 postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
843 }
844 if (track->mPackets->getAvailableBufferCount(&finalResult) < 2
845 && !mSentPauseOnBuffering && !mPreparing) {
846 mCachedSource->resumeFetchingIfNecessary();
847 sendCacheStats();
848 mSentPauseOnBuffering = true;
849 sp<AMessage> notify = dupNotify();
850 notify->setInt32("what", kWhatPauseOnBufferingStart);
851 notify->post();
852 }
853 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700854 }
855
Robert Shih3423bbd2014-07-16 15:47:09 -0700856 if (result != OK) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700857 if (mSubtitleTrack.mSource != NULL) {
858 mSubtitleTrack.mPackets->clear();
859 mFetchSubtitleDataGeneration++;
860 }
861 if (mTimedTextTrack.mSource != NULL) {
862 mTimedTextTrack.mPackets->clear();
863 mFetchTimedTextDataGeneration++;
864 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700865 return result;
866 }
867
868 int64_t timeUs;
869 status_t eosResult; // ignored
870 CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
Robert Shih5c67ddc2014-11-04 17:46:05 -0800871 if (audio) {
872 mAudioLastDequeueTimeUs = timeUs;
873 } else {
874 mVideoLastDequeueTimeUs = timeUs;
875 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700876
877 if (mSubtitleTrack.mSource != NULL
878 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800879 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
Robert Shih3423bbd2014-07-16 15:47:09 -0700880 msg->setInt64("timeUs", timeUs);
881 msg->setInt32("generation", mFetchSubtitleDataGeneration);
882 msg->post();
883 }
Robert Shiheb1735e2014-07-23 15:53:14 -0700884
Lajos Molnare26940f2014-07-31 10:31:26 -0700885 if (mTimedTextTrack.mSource != NULL
886 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800887 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
Lajos Molnare26940f2014-07-31 10:31:26 -0700888 msg->setInt64("timeUs", timeUs);
889 msg->setInt32("generation", mFetchTimedTextDataGeneration);
890 msg->post();
891 }
892
Andreas Huberafed0e12011-09-20 15:39:58 -0700893 return result;
894}
895
896status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
Wei Jia542a81a2017-10-16 10:31:29 -0700897 Mutex::Autolock _l(mLock);
Andreas Huberafed0e12011-09-20 15:39:58 -0700898 *durationUs = mDurationUs;
899 return OK;
900}
901
Robert Shihdd235722014-06-12 14:49:23 -0700902size_t NuPlayer::GenericSource::getTrackCount() const {
Wei Jia542a81a2017-10-16 10:31:29 -0700903 Mutex::Autolock _l(mLock);
Robert Shihdd235722014-06-12 14:49:23 -0700904 return mSources.size();
905}
906
907sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const {
Wei Jia542a81a2017-10-16 10:31:29 -0700908 Mutex::Autolock _l(mLock);
Robert Shihdd235722014-06-12 14:49:23 -0700909 size_t trackCount = mSources.size();
910 if (trackIndex >= trackCount) {
911 return NULL;
912 }
913
914 sp<AMessage> format = new AMessage();
915 sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat();
Marco Nelissenc367ca12015-09-15 09:51:59 -0700916 if (meta == NULL) {
917 ALOGE("no metadata for track %zu", trackIndex);
918 return NULL;
919 }
Robert Shihdd235722014-06-12 14:49:23 -0700920
921 const char *mime;
922 CHECK(meta->findCString(kKeyMIMEType, &mime));
Robert Shih755106e2015-04-30 14:36:45 -0700923 format->setString("mime", mime);
Robert Shihdd235722014-06-12 14:49:23 -0700924
925 int32_t trackType;
926 if (!strncasecmp(mime, "video/", 6)) {
927 trackType = MEDIA_TRACK_TYPE_VIDEO;
928 } else if (!strncasecmp(mime, "audio/", 6)) {
929 trackType = MEDIA_TRACK_TYPE_AUDIO;
930 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
931 trackType = MEDIA_TRACK_TYPE_TIMEDTEXT;
932 } else {
933 trackType = MEDIA_TRACK_TYPE_UNKNOWN;
934 }
935 format->setInt32("type", trackType);
936
937 const char *lang;
938 if (!meta->findCString(kKeyMediaLanguage, &lang)) {
939 lang = "und";
940 }
941 format->setString("language", lang);
942
943 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
Robert Shihdd235722014-06-12 14:49:23 -0700944 int32_t isAutoselect = 1, isDefault = 0, isForced = 0;
945 meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect);
946 meta->findInt32(kKeyTrackIsDefault, &isDefault);
947 meta->findInt32(kKeyTrackIsForced, &isForced);
948
949 format->setInt32("auto", !!isAutoselect);
950 format->setInt32("default", !!isDefault);
951 format->setInt32("forced", !!isForced);
952 }
953
954 return format;
955}
956
Lajos Molnare26940f2014-07-31 10:31:26 -0700957ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const {
Wei Jia542a81a2017-10-16 10:31:29 -0700958 Mutex::Autolock _l(mLock);
Lajos Molnare26940f2014-07-31 10:31:26 -0700959 const Track *track = NULL;
960 switch (type) {
961 case MEDIA_TRACK_TYPE_VIDEO:
962 track = &mVideoTrack;
963 break;
964 case MEDIA_TRACK_TYPE_AUDIO:
965 track = &mAudioTrack;
966 break;
967 case MEDIA_TRACK_TYPE_TIMEDTEXT:
968 track = &mTimedTextTrack;
969 break;
970 case MEDIA_TRACK_TYPE_SUBTITLE:
971 track = &mSubtitleTrack;
972 break;
973 default:
974 break;
975 }
976
977 if (track != NULL && track->mSource != NULL) {
978 return track->mIndex;
979 }
980
981 return -1;
982}
983
Robert Shih6ffb1fd2014-10-29 16:24:32 -0700984status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
Wei Jia542a81a2017-10-16 10:31:29 -0700985 Mutex::Autolock _l(mLock);
Lajos Molnare26940f2014-07-31 10:31:26 -0700986 ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
Robert Shih17f6dd62014-08-20 17:00:21 -0700987
Robert Shih3423bbd2014-07-16 15:47:09 -0700988 if (trackIndex >= mSources.size()) {
989 return BAD_INDEX;
990 }
991
992 if (!select) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700993 Track* track = NULL;
994 if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) {
995 track = &mSubtitleTrack;
996 mFetchSubtitleDataGeneration++;
997 } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) {
998 track = &mTimedTextTrack;
999 mFetchTimedTextDataGeneration++;
1000 }
1001 if (track == NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001002 return INVALID_OPERATION;
1003 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001004 track->mSource->stop();
1005 track->mSource = NULL;
1006 track->mPackets->clear();
Robert Shih3423bbd2014-07-16 15:47:09 -07001007 return OK;
1008 }
1009
Marco Nelissenb2487f02015-09-01 13:23:23 -07001010 const sp<IMediaSource> source = mSources.itemAt(trackIndex);
Robert Shih3423bbd2014-07-16 15:47:09 -07001011 sp<MetaData> meta = source->getFormat();
1012 const char *mime;
1013 CHECK(meta->findCString(kKeyMIMEType, &mime));
1014 if (!strncasecmp(mime, "text/", 5)) {
Lajos Molnare26940f2014-07-31 10:31:26 -07001015 bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP);
1016 Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack;
1017 if (track->mSource != NULL && track->mIndex == trackIndex) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001018 return OK;
1019 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001020 track->mIndex = trackIndex;
1021 if (track->mSource != NULL) {
1022 track->mSource->stop();
Robert Shih3423bbd2014-07-16 15:47:09 -07001023 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001024 track->mSource = mSources.itemAt(trackIndex);
1025 track->mSource->start();
1026 if (track->mPackets == NULL) {
1027 track->mPackets = new AnotherPacketSource(track->mSource->getFormat());
Robert Shih3423bbd2014-07-16 15:47:09 -07001028 } else {
Lajos Molnare26940f2014-07-31 10:31:26 -07001029 track->mPackets->clear();
1030 track->mPackets->setFormat(track->mSource->getFormat());
Robert Shih3423bbd2014-07-16 15:47:09 -07001031
1032 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001033
1034 if (isSubtitle) {
1035 mFetchSubtitleDataGeneration++;
1036 } else {
1037 mFetchTimedTextDataGeneration++;
1038 }
1039
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001040 status_t eosResult; // ignored
1041 if (mSubtitleTrack.mSource != NULL
1042 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001043 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001044 msg->setInt64("timeUs", timeUs);
1045 msg->setInt32("generation", mFetchSubtitleDataGeneration);
1046 msg->post();
1047 }
1048
Marco Nelissen55e2f4c2015-09-04 15:57:15 -07001049 sp<AMessage> msg2 = new AMessage(kWhatSendGlobalTimedTextData, this);
1050 msg2->setInt32("generation", mFetchTimedTextDataGeneration);
1051 msg2->post();
1052
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001053 if (mTimedTextTrack.mSource != NULL
1054 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001055 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001056 msg->setInt64("timeUs", timeUs);
1057 msg->setInt32("generation", mFetchTimedTextDataGeneration);
1058 msg->post();
1059 }
1060
Robert Shih3423bbd2014-07-16 15:47:09 -07001061 return OK;
1062 } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
1063 bool audio = !strncasecmp(mime, "audio/", 6);
1064 Track *track = audio ? &mAudioTrack : &mVideoTrack;
1065 if (track->mSource != NULL && track->mIndex == trackIndex) {
1066 return OK;
1067 }
1068
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001069 sp<AMessage> msg = new AMessage(kWhatChangeAVSource, this);
Robert Shih3423bbd2014-07-16 15:47:09 -07001070 msg->setInt32("trackIndex", trackIndex);
1071 msg->post();
1072 return OK;
1073 }
1074
1075 return INVALID_OPERATION;
1076}
1077
Wei Jiac5de0912016-11-18 10:22:14 -08001078status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
Wei Jia542a81a2017-10-16 10:31:29 -07001079 ALOGV("seekTo: %lld, %d", (long long)seekTimeUs, mode);
Wei Jiac899fc02017-11-15 17:28:53 -08001080 sp<AMessage> msg = new AMessage(kWhatSeek, this);
1081 msg->setInt64("seekTimeUs", seekTimeUs);
1082 msg->setInt32("mode", mode);
1083
1084 // Need to call readBuffer on |mLooper| to ensure the calls to
1085 // IMediaSource::read* are serialized. Note that IMediaSource::read*
1086 // is called without |mLock| acquired and MediaSource is not thread safe.
1087 sp<AMessage> response;
1088 status_t err = msg->postAndAwaitResponse(&response);
1089 if (err == OK && response != NULL) {
1090 CHECK(response->findInt32("err", &err));
1091 }
1092
1093 return err;
1094}
1095
1096void NuPlayer::GenericSource::onSeek(const sp<AMessage>& msg) {
1097 int64_t seekTimeUs;
1098 int32_t mode;
1099 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
1100 CHECK(msg->findInt32("mode", &mode));
1101
1102 sp<AMessage> response = new AMessage;
1103 status_t err = doSeek(seekTimeUs, (MediaPlayerSeekMode)mode);
1104 response->setInt32("err", err);
1105
1106 sp<AReplyToken> replyID;
1107 CHECK(msg->senderAwaitsResponse(&replyID));
1108 response->postReply(replyID);
1109}
1110
1111status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
Andreas Huberafed0e12011-09-20 15:39:58 -07001112 if (mVideoTrack.mSource != NULL) {
Wei Jia542a81a2017-10-16 10:31:29 -07001113 ++mVideoDataGeneration;
1114
Andreas Huberafed0e12011-09-20 15:39:58 -07001115 int64_t actualTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -08001116 readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, mode, &actualTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -07001117
Wei Jiac5de0912016-11-18 10:22:14 -08001118 if (mode != MediaPlayerSeekMode::SEEK_CLOSEST) {
Wei Jia5ec347f2016-11-01 17:07:54 -07001119 seekTimeUs = actualTimeUs;
1120 }
1121 mVideoLastDequeueTimeUs = actualTimeUs;
Andreas Huberafed0e12011-09-20 15:39:58 -07001122 }
1123
1124 if (mAudioTrack.mSource != NULL) {
Wei Jia542a81a2017-10-16 10:31:29 -07001125 ++mAudioDataGeneration;
Wei Jiaaec8d822017-08-25 15:27:57 -07001126 readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs, MediaPlayerSeekMode::SEEK_CLOSEST);
Robert Shih5c67ddc2014-11-04 17:46:05 -08001127 mAudioLastDequeueTimeUs = seekTimeUs;
Andreas Huberafed0e12011-09-20 15:39:58 -07001128 }
1129
Robert Shih40296722017-07-31 16:44:39 -07001130 if (mSubtitleTrack.mSource != NULL) {
1131 mSubtitleTrack.mPackets->clear();
1132 mFetchSubtitleDataGeneration++;
1133 }
1134
1135 if (mTimedTextTrack.mSource != NULL) {
1136 mTimedTextTrack.mPackets->clear();
1137 mFetchTimedTextDataGeneration++;
1138 }
1139
Wei Jia542a81a2017-10-16 10:31:29 -07001140 ++mPollBufferingGeneration;
1141 schedulePollBuffering();
Andreas Huberafed0e12011-09-20 15:39:58 -07001142 return OK;
1143}
1144
Robert Shih3423bbd2014-07-16 15:47:09 -07001145sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
Dongwon Kang1889c3e2018-02-01 13:44:57 -08001146 MediaBufferBase* mb,
Wei Jia14486822016-11-02 17:51:30 -07001147 media_track_type trackType) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001148 bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
1149 size_t outLength = mb->range_length();
1150
1151 if (audio && mAudioIsVorbis) {
1152 outLength += sizeof(int32_t);
1153 }
1154
1155 sp<ABuffer> ab;
Hassan Shojaniacefac142017-02-06 21:02:02 -08001156
1157 if (mIsDrmProtected) {
1158 // Modular DRM
1159 // Enabled for both video/audio so 1) media buffer is reused without extra copying
1160 // 2) meta data can be retrieved in onInputBufferFetched for calling queueSecureInputBuffer.
1161
Robert Shih3423bbd2014-07-16 15:47:09 -07001162 // data is already provided in the buffer
1163 ab = new ABuffer(NULL, mb->range_length());
Dongwon Kangbc8f53b2018-01-25 17:01:44 -08001164 ab->meta()->setObject("mediaBufferHolder", new MediaBufferHolder(mb));
Hassan Shojaniacefac142017-02-06 21:02:02 -08001165
1166 // Modular DRM: Required b/c of the above add_ref.
1167 // If ref>0, there must be an observer, or it'll crash at release().
1168 // TODO: MediaBuffer might need to be revised to ease such need.
1169 mb->setObserver(this);
Hassan Shojaniacefac142017-02-06 21:02:02 -08001170 // Extra increment (since we want to keep mb alive and attached to ab beyond this function
1171 // call. This is to counter the effect of mb->release() towards the end.
1172 mb->add_ref();
1173
Robert Shih3423bbd2014-07-16 15:47:09 -07001174 } else {
1175 ab = new ABuffer(outLength);
1176 memcpy(ab->data(),
1177 (const uint8_t *)mb->data() + mb->range_offset(),
1178 mb->range_length());
1179 }
1180
1181 if (audio && mAudioIsVorbis) {
1182 int32_t numPageSamples;
1183 if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
1184 numPageSamples = -1;
1185 }
1186
1187 uint8_t* abEnd = ab->data() + mb->range_length();
1188 memcpy(abEnd, &numPageSamples, sizeof(numPageSamples));
1189 }
1190
Lajos Molnare26940f2014-07-31 10:31:26 -07001191 sp<AMessage> meta = ab->meta();
1192
Robert Shih3423bbd2014-07-16 15:47:09 -07001193 int64_t timeUs;
1194 CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs));
Robert Shih3423bbd2014-07-16 15:47:09 -07001195 meta->setInt64("timeUs", timeUs);
1196
Praveen Chavanbbaa1442016-04-08 13:33:49 -07001197 if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
1198 int32_t layerId;
1199 if (mb->meta_data()->findInt32(kKeyTemporalLayerId, &layerId)) {
1200 meta->setInt32("temporal-layer-id", layerId);
1201 }
1202 }
1203
Lajos Molnare26940f2014-07-31 10:31:26 -07001204 if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
1205 const char *mime;
1206 CHECK(mTimedTextTrack.mSource != NULL
1207 && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime));
1208 meta->setString("mime", mime);
1209 }
1210
Robert Shih3423bbd2014-07-16 15:47:09 -07001211 int64_t durationUs;
1212 if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) {
1213 meta->setInt64("durationUs", durationUs);
1214 }
1215
1216 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
1217 meta->setInt32("trackIndex", mSubtitleTrack.mIndex);
1218 }
1219
Robert Shihf8bd8512015-04-23 16:39:18 -07001220 uint32_t dataType; // unused
1221 const void *seiData;
1222 size_t seiLength;
1223 if (mb->meta_data()->findData(kKeySEI, &dataType, &seiData, &seiLength)) {
1224 sp<ABuffer> sei = ABuffer::CreateAsCopy(seiData, seiLength);;
1225 meta->setBuffer("sei", sei);
1226 }
1227
Jaesung Chung3694d7c2015-10-21 11:41:38 +09001228 const void *mpegUserDataPointer;
1229 size_t mpegUserDataLength;
1230 if (mb->meta_data()->findData(
1231 kKeyMpegUserData, &dataType, &mpegUserDataPointer, &mpegUserDataLength)) {
1232 sp<ABuffer> mpegUserData = ABuffer::CreateAsCopy(mpegUserDataPointer, mpegUserDataLength);
1233 meta->setBuffer("mpegUserData", mpegUserData);
1234 }
1235
Robert Shih3423bbd2014-07-16 15:47:09 -07001236 mb->release();
1237 mb = NULL;
1238
1239 return ab;
1240}
1241
Wei Jia542a81a2017-10-16 10:31:29 -07001242int32_t NuPlayer::GenericSource::getDataGeneration(media_track_type type) const {
1243 int32_t generation = -1;
1244 switch (type) {
1245 case MEDIA_TRACK_TYPE_VIDEO:
1246 generation = mVideoDataGeneration;
1247 break;
1248 case MEDIA_TRACK_TYPE_AUDIO:
1249 generation = mAudioDataGeneration;
1250 break;
1251 case MEDIA_TRACK_TYPE_TIMEDTEXT:
1252 generation = mFetchTimedTextDataGeneration;
1253 break;
1254 case MEDIA_TRACK_TYPE_SUBTITLE:
1255 generation = mFetchSubtitleDataGeneration;
1256 break;
1257 default:
1258 break;
1259 }
Lajos Molnar84f52782014-09-11 10:01:55 -07001260
Wei Jia542a81a2017-10-16 10:31:29 -07001261 return generation;
1262}
1263
1264void NuPlayer::GenericSource::postReadBuffer(media_track_type trackType) {
Lajos Molnar84f52782014-09-11 10:01:55 -07001265 if ((mPendingReadBufferTypes & (1 << trackType)) == 0) {
1266 mPendingReadBufferTypes |= (1 << trackType);
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001267 sp<AMessage> msg = new AMessage(kWhatReadBuffer, this);
Lajos Molnar84f52782014-09-11 10:01:55 -07001268 msg->setInt32("trackType", trackType);
1269 msg->post();
1270 }
Robert Shih17f6dd62014-08-20 17:00:21 -07001271}
1272
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -07001273void NuPlayer::GenericSource::onReadBuffer(const sp<AMessage>& msg) {
Robert Shih17f6dd62014-08-20 17:00:21 -07001274 int32_t tmpType;
1275 CHECK(msg->findInt32("trackType", &tmpType));
1276 media_track_type trackType = (media_track_type)tmpType;
Wei Jia542a81a2017-10-16 10:31:29 -07001277 mPendingReadBufferTypes &= ~(1 << trackType);
Chong Zhang42e81532014-12-01 13:44:26 -08001278 readBuffer(trackType);
Robert Shih17f6dd62014-08-20 17:00:21 -07001279}
1280
Andreas Huberafed0e12011-09-20 15:39:58 -07001281void NuPlayer::GenericSource::readBuffer(
Wei Jiac5de0912016-11-18 10:22:14 -08001282 media_track_type trackType, int64_t seekTimeUs, MediaPlayerSeekMode mode,
Wei Jia5ec347f2016-11-01 17:07:54 -07001283 int64_t *actualTimeUs, bool formatChange) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001284 Track *track;
Phil Burkc5cc2e22014-09-09 20:08:39 -07001285 size_t maxBuffers = 1;
Robert Shih3423bbd2014-07-16 15:47:09 -07001286 switch (trackType) {
1287 case MEDIA_TRACK_TYPE_VIDEO:
1288 track = &mVideoTrack;
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001289 maxBuffers = 8; // too large of a number may influence seeks
Robert Shih3423bbd2014-07-16 15:47:09 -07001290 break;
1291 case MEDIA_TRACK_TYPE_AUDIO:
1292 track = &mAudioTrack;
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001293 maxBuffers = 64;
Robert Shih3423bbd2014-07-16 15:47:09 -07001294 break;
1295 case MEDIA_TRACK_TYPE_SUBTITLE:
1296 track = &mSubtitleTrack;
1297 break;
Lajos Molnare26940f2014-07-31 10:31:26 -07001298 case MEDIA_TRACK_TYPE_TIMEDTEXT:
1299 track = &mTimedTextTrack;
1300 break;
Robert Shih3423bbd2014-07-16 15:47:09 -07001301 default:
1302 TRESPASS();
1303 }
1304
1305 if (track->mSource == NULL) {
1306 return;
1307 }
Andreas Huberafed0e12011-09-20 15:39:58 -07001308
1309 if (actualTimeUs) {
1310 *actualTimeUs = seekTimeUs;
1311 }
1312
1313 MediaSource::ReadOptions options;
1314
1315 bool seeking = false;
Andreas Huberafed0e12011-09-20 15:39:58 -07001316 if (seekTimeUs >= 0) {
Wei Jiac5de0912016-11-18 10:22:14 -08001317 options.setSeekTo(seekTimeUs, mode);
Andreas Huberafed0e12011-09-20 15:39:58 -07001318 seeking = true;
1319 }
1320
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001321 const bool couldReadMultiple = (track->mSource->supportReadMultiple());
Andy Hungcdeb6602016-06-28 17:21:44 -07001322
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001323 if (couldReadMultiple) {
Lajos Molnarcc227032014-07-17 15:33:06 -07001324 options.setNonBlocking();
1325 }
1326
Wei Jia542a81a2017-10-16 10:31:29 -07001327 int32_t generation = getDataGeneration(trackType);
Phil Burkc5cc2e22014-09-09 20:08:39 -07001328 for (size_t numBuffers = 0; numBuffers < maxBuffers; ) {
Dongwon Kang1889c3e2018-02-01 13:44:57 -08001329 Vector<MediaBufferBase *> mediaBuffers;
Wei Jia1f1fc452016-05-11 16:17:22 -07001330 status_t err = NO_ERROR;
1331
Wei Jiac899fc02017-11-15 17:28:53 -08001332 sp<IMediaSource> source = track->mSource;
Wei Jia542a81a2017-10-16 10:31:29 -07001333 mLock.unlock();
Andy Hungcdeb6602016-06-28 17:21:44 -07001334 if (couldReadMultiple) {
Wei Jiac899fc02017-11-15 17:28:53 -08001335 err = source->readMultiple(
Andy Hungcdeb6602016-06-28 17:21:44 -07001336 &mediaBuffers, maxBuffers - numBuffers, &options);
Wei Jia1f1fc452016-05-11 16:17:22 -07001337 } else {
Dongwon Kang1889c3e2018-02-01 13:44:57 -08001338 MediaBufferBase *mbuf = NULL;
Wei Jiac899fc02017-11-15 17:28:53 -08001339 err = source->read(&mbuf, &options);
Wei Jia1f1fc452016-05-11 16:17:22 -07001340 if (err == OK && mbuf != NULL) {
1341 mediaBuffers.push_back(mbuf);
1342 }
1343 }
Wei Jia542a81a2017-10-16 10:31:29 -07001344 mLock.lock();
Andreas Huberafed0e12011-09-20 15:39:58 -07001345
Andy Hungf59c0ba2016-06-15 17:59:30 -07001346 options.clearNonPersistent();
Andreas Huberafed0e12011-09-20 15:39:58 -07001347
Wei Jia1f1fc452016-05-11 16:17:22 -07001348 size_t id = 0;
1349 size_t count = mediaBuffers.size();
Wei Jia542a81a2017-10-16 10:31:29 -07001350
1351 // in case track has been changed since we don't have lock for some time.
1352 if (generation != getDataGeneration(trackType)) {
1353 for (; id < count; ++id) {
1354 mediaBuffers[id]->release();
1355 }
1356 break;
1357 }
1358
Wei Jia1f1fc452016-05-11 16:17:22 -07001359 for (; id < count; ++id) {
Ronghua Wu80276872014-08-28 15:50:29 -07001360 int64_t timeUs;
Dongwon Kang1889c3e2018-02-01 13:44:57 -08001361 MediaBufferBase *mbuf = mediaBuffers[id];
Robert Shih3b9912b2016-04-07 16:56:54 -07001362 if (!mbuf->meta_data()->findInt64(kKeyTime, &timeUs)) {
1363 mbuf->meta_data()->dumpToLog();
1364 track->mPackets->signalEOS(ERROR_MALFORMED);
1365 break;
1366 }
Ronghua Wu80276872014-08-28 15:50:29 -07001367 if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
1368 mAudioTimeUs = timeUs;
1369 } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
1370 mVideoTimeUs = timeUs;
1371 }
1372
Ronghua Wu8f291bc2015-05-19 10:11:53 -07001373 queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
Andreas Huberafed0e12011-09-20 15:39:58 -07001374
Wei Jia14486822016-11-02 17:51:30 -07001375 sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType);
1376 if (numBuffers == 0 && actualTimeUs != nullptr) {
1377 *actualTimeUs = timeUs;
1378 }
1379 if (seeking && buffer != nullptr) {
1380 sp<AMessage> meta = buffer->meta();
Wei Jiac5de0912016-11-18 10:22:14 -08001381 if (meta != nullptr && mode == MediaPlayerSeekMode::SEEK_CLOSEST
1382 && seekTimeUs > timeUs) {
Wei Jia14486822016-11-02 17:51:30 -07001383 sp<AMessage> extra = new AMessage;
1384 extra->setInt64("resume-at-mediaTimeUs", seekTimeUs);
1385 meta->setMessage("extra", extra);
1386 }
1387 }
1388
Andreas Huberafed0e12011-09-20 15:39:58 -07001389 track->mPackets->queueAccessUnit(buffer);
Marco Nelissen317a49a2014-09-16 21:32:33 -07001390 formatChange = false;
1391 seeking = false;
Phil Burkc5cc2e22014-09-09 20:08:39 -07001392 ++numBuffers;
Wei Jia1f1fc452016-05-11 16:17:22 -07001393 }
1394 if (id < count) {
1395 // Error, some mediaBuffer doesn't have kKeyTime.
1396 for (; id < count; ++id) {
1397 mediaBuffers[id]->release();
1398 }
1399 break;
1400 }
1401
1402 if (err == WOULD_BLOCK) {
Lajos Molnarcc227032014-07-17 15:33:06 -07001403 break;
Andreas Huberafed0e12011-09-20 15:39:58 -07001404 } else if (err == INFO_FORMAT_CHANGED) {
1405#if 0
1406 track->mPackets->queueDiscontinuity(
Chong Zhang632740c2014-06-26 13:03:47 -07001407 ATSParser::DISCONTINUITY_FORMATCHANGE,
1408 NULL,
1409 false /* discard */);
Andreas Huberafed0e12011-09-20 15:39:58 -07001410#endif
Wei Jia1f1fc452016-05-11 16:17:22 -07001411 } else if (err != OK) {
Ronghua Wu8f291bc2015-05-19 10:11:53 -07001412 queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
Andreas Huberafed0e12011-09-20 15:39:58 -07001413 track->mPackets->signalEOS(err);
1414 break;
1415 }
1416 }
Wei Jia542a81a2017-10-16 10:31:29 -07001417
1418 if (mIsStreaming
1419 && (trackType == MEDIA_TRACK_TYPE_VIDEO || trackType == MEDIA_TRACK_TYPE_AUDIO)) {
1420 status_t finalResult;
1421 int64_t durationUs = track->mPackets->getBufferedDurationUs(&finalResult);
1422
Wei Jia9bb38032017-03-23 18:00:38 -07001423 // TODO: maxRebufferingMarkMs could be larger than
1424 // mBufferingSettings.mResumePlaybackMarkMs
1425 int64_t markUs = (mPreparing ? mBufferingSettings.mInitialMarkMs
1426 : mBufferingSettings.mResumePlaybackMarkMs) * 1000ll;
Wei Jia542a81a2017-10-16 10:31:29 -07001427 if (finalResult == ERROR_END_OF_STREAM || durationUs >= markUs) {
1428 if (mPreparing || mSentPauseOnBuffering) {
1429 Track *counterTrack =
1430 (trackType == MEDIA_TRACK_TYPE_VIDEO ? &mAudioTrack : &mVideoTrack);
1431 if (counterTrack->mSource != NULL) {
1432 durationUs = counterTrack->mPackets->getBufferedDurationUs(&finalResult);
1433 }
1434 if (finalResult == ERROR_END_OF_STREAM || durationUs >= markUs) {
1435 if (mPreparing) {
1436 notifyPrepared();
1437 mPreparing = false;
1438 } else {
1439 sendCacheStats();
1440 mSentPauseOnBuffering = false;
1441 sp<AMessage> notify = dupNotify();
1442 notify->setInt32("what", kWhatResumeOnBufferingEnd);
1443 notify->post();
1444 }
1445 }
1446 }
1447 return;
1448 }
1449
1450 postReadBuffer(trackType);
1451 }
Andreas Huberafed0e12011-09-20 15:39:58 -07001452}
1453
Ronghua Wu8f291bc2015-05-19 10:11:53 -07001454void NuPlayer::GenericSource::queueDiscontinuityIfNeeded(
1455 bool seeking, bool formatChange, media_track_type trackType, Track *track) {
1456 // formatChange && seeking: track whose source is changed during selection
1457 // formatChange && !seeking: track whose source is not changed during selection
1458 // !formatChange: normal seek
1459 if ((seeking || formatChange)
1460 && (trackType == MEDIA_TRACK_TYPE_AUDIO
1461 || trackType == MEDIA_TRACK_TYPE_VIDEO)) {
1462 ATSParser::DiscontinuityType type = (formatChange && seeking)
1463 ? ATSParser::DISCONTINUITY_FORMATCHANGE
1464 : ATSParser::DISCONTINUITY_NONE;
1465 track->mPackets->queueDiscontinuity(type, NULL /* extra */, true /* discard */);
1466 }
1467}
1468
Wei Jia542a81a2017-10-16 10:31:29 -07001469void NuPlayer::GenericSource::notifyBufferingUpdate(int32_t percentage) {
Wei Jia14532f22015-12-29 11:28:15 -08001470 // Buffering percent could go backward as it's estimated from remaining
1471 // data and last access time. This could cause the buffering position
1472 // drawn on media control to jitter slightly. Remember previously reported
1473 // percentage and don't allow it to go backward.
1474 if (percentage < mPrevBufferPercentage) {
1475 percentage = mPrevBufferPercentage;
1476 } else if (percentage > 100) {
1477 percentage = 100;
1478 }
1479
1480 mPrevBufferPercentage = percentage;
1481
Wei Jia542a81a2017-10-16 10:31:29 -07001482 ALOGV("notifyBufferingUpdate: buffering %d%%", percentage);
Wei Jia14532f22015-12-29 11:28:15 -08001483
Wei Jia542a81a2017-10-16 10:31:29 -07001484 sp<AMessage> notify = dupNotify();
1485 notify->setInt32("what", kWhatBufferingUpdate);
1486 notify->setInt32("percentage", percentage);
1487 notify->post();
Wei Jia14532f22015-12-29 11:28:15 -08001488}
1489
Wei Jia542a81a2017-10-16 10:31:29 -07001490void NuPlayer::GenericSource::schedulePollBuffering() {
Wei Jia14532f22015-12-29 11:28:15 -08001491 sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
1492 msg->setInt32("generation", mPollBufferingGeneration);
1493 // Enquires buffering status every second.
1494 msg->post(1000000ll);
1495}
1496
Wei Jia542a81a2017-10-16 10:31:29 -07001497void NuPlayer::GenericSource::onPollBuffering() {
Wei Jia14532f22015-12-29 11:28:15 -08001498 status_t finalStatus = UNKNOWN_ERROR;
1499 int64_t cachedDurationUs = -1ll;
1500 ssize_t cachedDataRemaining = -1;
1501
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001502 if (mCachedSource != NULL) {
Wei Jia542a81a2017-10-16 10:31:29 -07001503 cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
Wei Jia14532f22015-12-29 11:28:15 -08001504
1505 if (finalStatus == OK) {
1506 off64_t size;
1507 int64_t bitrate = 0ll;
1508 if (mDurationUs > 0 && mCachedSource->getSize(&size) == OK) {
1509 // |bitrate| uses bits/second unit, while size is number of bytes.
1510 bitrate = size * 8000000ll / mDurationUs;
1511 } else if (mBitrate > 0) {
1512 bitrate = mBitrate;
1513 }
1514 if (bitrate > 0) {
1515 cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate;
1516 }
1517 }
1518 }
1519
1520 if (finalStatus != OK) {
Wei Jia542a81a2017-10-16 10:31:29 -07001521 ALOGV("onPollBuffering: EOS (finalStatus = %d)", finalStatus);
Wei Jia14532f22015-12-29 11:28:15 -08001522
1523 if (finalStatus == ERROR_END_OF_STREAM) {
Wei Jia542a81a2017-10-16 10:31:29 -07001524 notifyBufferingUpdate(100);
Wei Jia14532f22015-12-29 11:28:15 -08001525 }
1526
Wei Jia14532f22015-12-29 11:28:15 -08001527 return;
Wei Jia48fa06d2016-12-20 15:30:49 -08001528 }
1529
1530 if (cachedDurationUs >= 0ll) {
Wei Jia14532f22015-12-29 11:28:15 -08001531 if (mDurationUs > 0ll) {
Wei Jia542a81a2017-10-16 10:31:29 -07001532 int64_t cachedPosUs = getLastReadPosition() + cachedDurationUs;
Wei Jia14532f22015-12-29 11:28:15 -08001533 int percentage = 100.0 * cachedPosUs / mDurationUs;
1534 if (percentage > 100) {
1535 percentage = 100;
1536 }
1537
Wei Jia542a81a2017-10-16 10:31:29 -07001538 notifyBufferingUpdate(percentage);
Wei Jia14532f22015-12-29 11:28:15 -08001539 }
1540
Wei Jia542a81a2017-10-16 10:31:29 -07001541 ALOGV("onPollBuffering: cachedDurationUs %.1f sec", cachedDurationUs / 1000000.0f);
Wei Jia14532f22015-12-29 11:28:15 -08001542 }
1543
Wei Jia542a81a2017-10-16 10:31:29 -07001544 schedulePollBuffering();
Wei Jia14532f22015-12-29 11:28:15 -08001545}
1546
Hassan Shojaniacefac142017-02-06 21:02:02 -08001547// Modular DRM
1548status_t NuPlayer::GenericSource::prepareDrm(
Wei Jia542a81a2017-10-16 10:31:29 -07001549 const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId, sp<ICrypto> *outCrypto) {
1550 Mutex::Autolock _l(mLock);
Hassan Shojaniacefac142017-02-06 21:02:02 -08001551 ALOGV("prepareDrm");
1552
Hassan Shojaniacefac142017-02-06 21:02:02 -08001553 mIsDrmProtected = false;
Hassan Shojania355e8472017-05-12 10:33:16 -07001554 mIsDrmReleased = false;
Hassan Shojaniacefac142017-02-06 21:02:02 -08001555 mIsSecure = false;
1556
Hassan Shojaniacefac142017-02-06 21:02:02 -08001557 status_t status = OK;
Wei Jia542a81a2017-10-16 10:31:29 -07001558 sp<ICrypto> crypto = NuPlayerDrm::createCryptoAndPlugin(uuid, drmSessionId, status);
Hassan Shojaniacefac142017-02-06 21:02:02 -08001559 if (crypto == NULL) {
Wei Jia542a81a2017-10-16 10:31:29 -07001560 ALOGE("prepareDrm: createCrypto failed. status: %d", status);
Hassan Shojaniacefac142017-02-06 21:02:02 -08001561 return status;
1562 }
Wei Jia542a81a2017-10-16 10:31:29 -07001563 ALOGV("prepareDrm: createCryptoAndPlugin succeeded for uuid: %s",
Hassan Shojaniacefac142017-02-06 21:02:02 -08001564 DrmUUID::toHexString(uuid).string());
1565
1566 *outCrypto = crypto;
1567 // as long a there is an active crypto
1568 mIsDrmProtected = true;
1569
1570 if (mMimes.size() == 0) {
1571 status = UNKNOWN_ERROR;
Wei Jia542a81a2017-10-16 10:31:29 -07001572 ALOGE("prepareDrm: Unexpected. Must have at least one track. status: %d", status);
Hassan Shojaniacefac142017-02-06 21:02:02 -08001573 return status;
1574 }
1575
1576 // first mime in this list is either the video track, or the first audio track
1577 const char *mime = mMimes[0].string();
1578 mIsSecure = crypto->requiresSecureDecoderComponent(mime);
Wei Jia542a81a2017-10-16 10:31:29 -07001579 ALOGV("prepareDrm: requiresSecureDecoderComponent mime: %s isSecure: %d",
Hassan Shojaniacefac142017-02-06 21:02:02 -08001580 mime, mIsSecure);
1581
1582 // Checking the member flags while in the looper to send out the notification.
1583 // The legacy mDecryptHandle!=NULL check (for FLAG_PROTECTED) is equivalent to mIsDrmProtected.
1584 notifyFlagsChanged(
1585 (mIsSecure ? FLAG_SECURE : 0) |
Hassan Shojania838be392017-05-23 14:14:24 -07001586 // Setting "protected screen" only for L1: b/38390836
1587 (mIsSecure ? FLAG_PROTECTED : 0) |
Hassan Shojaniacefac142017-02-06 21:02:02 -08001588 FLAG_CAN_PAUSE |
1589 FLAG_CAN_SEEK_BACKWARD |
1590 FLAG_CAN_SEEK_FORWARD |
1591 FLAG_CAN_SEEK);
1592
Wei Jia542a81a2017-10-16 10:31:29 -07001593 if (status == OK) {
1594 ALOGV("prepareDrm: mCrypto: %p (%d)", outCrypto->get(),
1595 (*outCrypto != NULL ? (*outCrypto)->getStrongCount() : 0));
1596 ALOGD("prepareDrm ret: %d ", status);
1597 } else {
1598 ALOGE("prepareDrm err: %d", status);
1599 }
Hassan Shojaniacefac142017-02-06 21:02:02 -08001600 return status;
1601}
1602
Wei Jia542a81a2017-10-16 10:31:29 -07001603status_t NuPlayer::GenericSource::releaseDrm() {
1604 Mutex::Autolock _l(mLock);
1605 ALOGV("releaseDrm");
1606
Hassan Shojania355e8472017-05-12 10:33:16 -07001607 if (mIsDrmProtected) {
1608 mIsDrmProtected = false;
1609 // to prevent returning any more buffer after stop/releaseDrm (b/37960096)
1610 mIsDrmReleased = true;
Wei Jia542a81a2017-10-16 10:31:29 -07001611 ALOGV("releaseDrm: mIsDrmProtected is reset.");
Hassan Shojania355e8472017-05-12 10:33:16 -07001612 } else {
Wei Jia542a81a2017-10-16 10:31:29 -07001613 ALOGE("releaseDrm: mIsDrmProtected is already false.");
Hassan Shojania355e8472017-05-12 10:33:16 -07001614 }
1615
1616 return OK;
1617}
1618
Hassan Shojaniacefac142017-02-06 21:02:02 -08001619status_t NuPlayer::GenericSource::checkDrmInfo()
1620{
Hassan Shojania355e8472017-05-12 10:33:16 -07001621 // clearing the flag at prepare in case the player is reused after stop/releaseDrm with the
1622 // same source without being reset (called by prepareAsync/initFromDataSource)
1623 mIsDrmReleased = false;
1624
Hassan Shojaniacefac142017-02-06 21:02:02 -08001625 if (mFileMeta == NULL) {
Hassan Shojaniae7a1f6c2017-03-14 09:24:28 -07001626 ALOGI("checkDrmInfo: No metadata");
Hassan Shojaniacefac142017-02-06 21:02:02 -08001627 return OK; // letting the caller responds accordingly
1628 }
1629
1630 uint32_t type;
1631 const void *pssh;
1632 size_t psshsize;
1633
1634 if (!mFileMeta->findData(kKeyPssh, &type, &pssh, &psshsize)) {
Hassan Shojaniadd4ce182017-04-20 15:25:39 -07001635 ALOGV("checkDrmInfo: No PSSH");
Hassan Shojaniacefac142017-02-06 21:02:02 -08001636 return OK; // source without DRM info
1637 }
1638
1639 Parcel parcel;
Hassan Shojaniadd4ce182017-04-20 15:25:39 -07001640 NuPlayerDrm::retrieveDrmInfo(pssh, psshsize, &parcel);
Hassan Shojaniacefac142017-02-06 21:02:02 -08001641 ALOGV("checkDrmInfo: MEDIA_DRM_INFO PSSH size: %d Parcel size: %d objects#: %d",
Hassan Shojania06a70812017-02-15 21:57:45 -08001642 (int)psshsize, (int)parcel.dataSize(), (int)parcel.objectsCount());
Hassan Shojaniacefac142017-02-06 21:02:02 -08001643
1644 if (parcel.dataSize() == 0) {
1645 ALOGE("checkDrmInfo: Unexpected parcel size: 0");
1646 return UNKNOWN_ERROR;
1647 }
1648
1649 // Can't pass parcel as a message to the player. Converting Parcel->ABuffer to pass it
1650 // to the Player's onSourceNotify then back to Parcel for calling driver's notifyListener.
1651 sp<ABuffer> drmInfoBuffer = ABuffer::CreateAsCopy(parcel.data(), parcel.dataSize());
1652 notifyDrmInfo(drmInfoBuffer);
1653
1654 return OK;
1655}
1656
Dongwon Kang1889c3e2018-02-01 13:44:57 -08001657void NuPlayer::GenericSource::signalBufferReturned(MediaBufferBase *buffer)
Hassan Shojaniacefac142017-02-06 21:02:02 -08001658{
1659 //ALOGV("signalBufferReturned %p refCount: %d", buffer, buffer->localRefcount());
1660
1661 buffer->setObserver(NULL);
1662 buffer->release(); // this leads to delete since that there is no observor
1663}
1664
Andreas Huberafed0e12011-09-20 15:39:58 -07001665} // namespace android