blob: 8378d24b48245c99e16cd7506a873eb4f0b4ce9d [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"
24
Chong Zhanga19f33e2014-08-07 15:35:07 -070025#include <media/IMediaHTTPService.h>
Andreas Huberafed0e12011-09-20 15:39:58 -070026#include <media/stagefright/foundation/ABuffer.h>
27#include <media/stagefright/foundation/ADebug.h>
28#include <media/stagefright/foundation/AMessage.h>
29#include <media/stagefright/DataSource.h>
30#include <media/stagefright/FileSource.h>
31#include <media/stagefright/MediaBuffer.h>
32#include <media/stagefright/MediaDefs.h>
33#include <media/stagefright/MediaExtractor.h>
34#include <media/stagefright/MediaSource.h>
35#include <media/stagefright/MetaData.h>
Robert Shih17f6dd62014-08-20 17:00:21 -070036#include <media/stagefright/Utils.h>
Chong Zhangd354d8d2014-08-20 13:09:58 -070037#include "../../libstagefright/include/NuCachedSource2.h"
Robert Shih360d6d02014-09-29 14:42:35 -070038#include "../../libstagefright/include/HTTPBase.h"
Andreas Huberafed0e12011-09-20 15:39:58 -070039
40namespace android {
41
Wei Jia48fa06d2016-12-20 15:30:49 -080042static const int kLowWaterMarkMs = 2000; // 2secs
43static const int kHighWaterMarkMs = 5000; // 5secs
44static const int kHighWaterMarkRebufferMs = 15000; // 15secs
45
46static const int kLowWaterMarkKB = 40;
47static const int kHighWaterMarkKB = 200;
Chong Zhangefbb6192015-01-30 17:13:27 -080048
Andreas Huberafed0e12011-09-20 15:39:58 -070049NuPlayer::GenericSource::GenericSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080050 const sp<AMessage> &notify,
Lajos Molnarcc227032014-07-17 15:33:06 -070051 bool uidValid,
52 uid_t uid)
Andreas Huberb5f25f02013-02-05 10:14:26 -080053 : Source(notify),
Robert Shih5c67ddc2014-11-04 17:46:05 -080054 mAudioTimeUs(0),
55 mAudioLastDequeueTimeUs(0),
56 mVideoTimeUs(0),
57 mVideoLastDequeueTimeUs(0),
Robert Shih3423bbd2014-07-16 15:47:09 -070058 mFetchSubtitleDataGeneration(0),
Lajos Molnare26940f2014-07-31 10:31:26 -070059 mFetchTimedTextDataGeneration(0),
Marco Nelissen02fc5e32015-05-27 11:20:41 -070060 mDurationUs(-1ll),
Lajos Molnarcc227032014-07-17 15:33:06 -070061 mAudioIsVorbis(false),
Chong Zhang42e81532014-12-01 13:44:26 -080062 mIsSecure(false),
Chong Zhangefbb6192015-01-30 17:13:27 -080063 mIsStreaming(false),
Lajos Molnarcc227032014-07-17 15:33:06 -070064 mUIDValid(uidValid),
Chong Zhangd354d8d2014-08-20 13:09:58 -070065 mUID(uid),
Chong Zhanga6bf21f2014-11-19 20:26:34 -080066 mFd(-1),
Chong Zhang2a3cc9a2014-08-21 17:48:26 -070067 mBitrate(-1ll),
Wei Jia14532f22015-12-29 11:28:15 -080068 mPendingReadBufferTypes(0) {
Hassan Shojaniacefac142017-02-06 21:02:02 -080069 ALOGV("GenericSource");
70
Wei Jia14532f22015-12-29 11:28:15 -080071 mBufferingMonitor = new BufferingMonitor(notify);
Chong Zhanga19f33e2014-08-07 15:35:07 -070072 resetDataSource();
Chong Zhang3de157d2014-08-05 20:54:44 -070073}
74
Chong Zhanga19f33e2014-08-07 15:35:07 -070075void NuPlayer::GenericSource::resetDataSource() {
Hassan Shojaniacefac142017-02-06 21:02:02 -080076 ALOGV("resetDataSource");
77
Chong Zhanga19f33e2014-08-07 15:35:07 -070078 mHTTPService.clear();
Robert Shih360d6d02014-09-29 14:42:35 -070079 mHttpSource.clear();
Chong Zhanga19f33e2014-08-07 15:35:07 -070080 mUri.clear();
81 mUriHeaders.clear();
Chong Zhanga6bf21f2014-11-19 20:26:34 -080082 if (mFd >= 0) {
83 close(mFd);
84 mFd = -1;
85 }
Chong Zhanga19f33e2014-08-07 15:35:07 -070086 mOffset = 0;
87 mLength = 0;
Ronghua Wu80276872014-08-28 15:50:29 -070088 mStarted = false;
Andy Hung2abde2c2014-09-30 14:40:32 -070089 mStopRead = true;
Wei Jia14532f22015-12-29 11:28:15 -080090
91 if (mBufferingMonitorLooper != NULL) {
92 mBufferingMonitorLooper->unregisterHandler(mBufferingMonitor->id());
93 mBufferingMonitorLooper->stop();
94 mBufferingMonitorLooper = NULL;
95 }
96 mBufferingMonitor->stop();
Hassan Shojaniacefac142017-02-06 21:02:02 -080097
98 mIsDrmProtected = false;
99 mIsSecure = false;
100 mMimes.clear();
Chong Zhanga19f33e2014-08-07 15:35:07 -0700101}
102
103status_t NuPlayer::GenericSource::setDataSource(
Chong Zhang3de157d2014-08-05 20:54:44 -0700104 const sp<IMediaHTTPService> &httpService,
105 const char *url,
106 const KeyedVector<String8, String8> *headers) {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800107 ALOGV("setDataSource url: %s", url);
108
Chong Zhanga19f33e2014-08-07 15:35:07 -0700109 resetDataSource();
Chong Zhang3de157d2014-08-05 20:54:44 -0700110
Chong Zhanga19f33e2014-08-07 15:35:07 -0700111 mHTTPService = httpService;
112 mUri = url;
Andreas Huberafed0e12011-09-20 15:39:58 -0700113
Chong Zhanga19f33e2014-08-07 15:35:07 -0700114 if (headers) {
115 mUriHeaders = *headers;
Chong Zhang3de157d2014-08-05 20:54:44 -0700116 }
117
Chong Zhanga19f33e2014-08-07 15:35:07 -0700118 // delay data source creation to prepareAsync() to avoid blocking
119 // the calling thread in setDataSource for any significant time.
120 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700121}
122
Chong Zhanga19f33e2014-08-07 15:35:07 -0700123status_t NuPlayer::GenericSource::setDataSource(
Chong Zhang3de157d2014-08-05 20:54:44 -0700124 int fd, int64_t offset, int64_t length) {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800125 ALOGV("setDataSource %d/%lld/%lld", fd, (long long)offset, (long long)length);
126
Chong Zhanga19f33e2014-08-07 15:35:07 -0700127 resetDataSource();
Andreas Huberafed0e12011-09-20 15:39:58 -0700128
Chong Zhanga19f33e2014-08-07 15:35:07 -0700129 mFd = dup(fd);
130 mOffset = offset;
131 mLength = length;
132
133 // delay data source creation to prepareAsync() to avoid blocking
134 // the calling thread in setDataSource for any significant time.
135 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700136}
137
Chris Watkins99f31602015-03-20 13:06:33 -0700138status_t NuPlayer::GenericSource::setDataSource(const sp<DataSource>& source) {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800139 ALOGV("setDataSource (source: %p)", source.get());
140
Chris Watkins99f31602015-03-20 13:06:33 -0700141 resetDataSource();
142 mDataSource = source;
143 return OK;
144}
145
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700146sp<MetaData> NuPlayer::GenericSource::getFileFormatMeta() const {
147 return mFileMeta;
148}
149
Chong Zhangd354d8d2014-08-20 13:09:58 -0700150status_t NuPlayer::GenericSource::initFromDataSource() {
Marco Nelissenb2487f02015-09-01 13:23:23 -0700151 sp<IMediaExtractor> extractor;
Chong Zhangd354d8d2014-08-20 13:09:58 -0700152 CHECK(mDataSource != NULL);
153
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700154 extractor = MediaExtractor::Create(mDataSource, NULL);
Andreas Huberafed0e12011-09-20 15:39:58 -0700155
Chong Zhang3de157d2014-08-05 20:54:44 -0700156 if (extractor == NULL) {
157 return UNKNOWN_ERROR;
158 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700159
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700160 mFileMeta = extractor->getMetaData();
161 if (mFileMeta != NULL) {
Marco Nelissenc1f4b2b2014-06-17 14:48:32 -0700162 int64_t duration;
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700163 if (mFileMeta->findInt64(kKeyDuration, &duration)) {
Marco Nelissenc1f4b2b2014-06-17 14:48:32 -0700164 mDurationUs = duration;
165 }
166 }
167
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700168 int32_t totalBitrate = 0;
169
Marco Nelissen705d3292014-09-19 15:14:37 -0700170 size_t numtracks = extractor->countTracks();
171 if (numtracks == 0) {
172 return UNKNOWN_ERROR;
173 }
174
Hassan Shojaniacefac142017-02-06 21:02:02 -0800175 mMimes.clear();
176
Marco Nelissen705d3292014-09-19 15:14:37 -0700177 for (size_t i = 0; i < numtracks; ++i) {
Marco Nelissenb2487f02015-09-01 13:23:23 -0700178 sp<IMediaSource> track = extractor->getTrack(i);
Wei Jia0386c912015-08-28 10:35:35 -0700179 if (track == NULL) {
180 continue;
181 }
Chong Zhangafc0a872014-08-26 09:56:52 -0700182
Andreas Huberafed0e12011-09-20 15:39:58 -0700183 sp<MetaData> meta = extractor->getTrackMetaData(i);
Marco Nelissenc367ca12015-09-15 09:51:59 -0700184 if (meta == NULL) {
185 ALOGE("no metadata for track %zu", i);
186 return UNKNOWN_ERROR;
187 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700188
189 const char *mime;
190 CHECK(meta->findCString(kKeyMIMEType, &mime));
191
Hassan Shojania06a70812017-02-15 21:57:45 -0800192 ALOGV("initFromDataSource track[%zu]: %s", i, mime);
Hassan Shojaniacefac142017-02-06 21:02:02 -0800193
Chong Zhangafc0a872014-08-26 09:56:52 -0700194 // Do the string compare immediately with "mime",
195 // we can't assume "mime" would stay valid after another
196 // extractor operation, some extractors might modify meta
197 // during getTrack() and make it invalid.
Andreas Huberafed0e12011-09-20 15:39:58 -0700198 if (!strncasecmp(mime, "audio/", 6)) {
199 if (mAudioTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700200 mAudioTrack.mIndex = i;
201 mAudioTrack.mSource = track;
Robert Shihaf52c1a2014-09-11 15:38:54 -0700202 mAudioTrack.mPackets =
203 new AnotherPacketSource(mAudioTrack.mSource->getFormat());
Andreas Huberafed0e12011-09-20 15:39:58 -0700204
205 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
206 mAudioIsVorbis = true;
207 } else {
208 mAudioIsVorbis = false;
209 }
Hassan Shojaniacefac142017-02-06 21:02:02 -0800210
211 mMimes.add(String8(mime));
Andreas Huberafed0e12011-09-20 15:39:58 -0700212 }
213 } else if (!strncasecmp(mime, "video/", 6)) {
214 if (mVideoTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700215 mVideoTrack.mIndex = i;
216 mVideoTrack.mSource = track;
Robert Shihaf52c1a2014-09-11 15:38:54 -0700217 mVideoTrack.mPackets =
218 new AnotherPacketSource(mVideoTrack.mSource->getFormat());
Chong Zhang7e892182014-08-05 11:58:21 -0700219
Hassan Shojaniacefac142017-02-06 21:02:02 -0800220 // video always at the beginning
221 mMimes.insertAt(String8(mime), 0);
Andreas Huberafed0e12011-09-20 15:39:58 -0700222 }
223 }
224
Wei Jia0386c912015-08-28 10:35:35 -0700225 mSources.push(track);
226 int64_t durationUs;
227 if (meta->findInt64(kKeyDuration, &durationUs)) {
228 if (durationUs > mDurationUs) {
229 mDurationUs = durationUs;
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700230 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700231 }
Wei Jia0386c912015-08-28 10:35:35 -0700232
233 int32_t bitrate;
234 if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) {
235 totalBitrate += bitrate;
236 } else {
237 totalBitrate = -1;
238 }
239 }
240
Hassan Shojaniacefac142017-02-06 21:02:02 -0800241 ALOGV("initFromDataSource mSources.size(): %zu mIsSecure: %d mime[0]: %s", mSources.size(),
242 mIsSecure, (mMimes.isEmpty() ? "NONE" : mMimes[0].string()));
243
Wei Jia0386c912015-08-28 10:35:35 -0700244 if (mSources.size() == 0) {
245 ALOGE("b/23705695");
246 return UNKNOWN_ERROR;
Andreas Huberafed0e12011-09-20 15:39:58 -0700247 }
Chong Zhang3de157d2014-08-05 20:54:44 -0700248
Hassan Shojaniacefac142017-02-06 21:02:02 -0800249 // Modular DRM: The return value doesn't affect source initialization.
250 (void)checkDrmInfo();
251
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700252 mBitrate = totalBitrate;
253
254 return OK;
255}
256
Wei Jia48fa06d2016-12-20 15:30:49 -0800257status_t NuPlayer::GenericSource::getDefaultBufferingSettings(
258 BufferingSettings* buffering /* nonnull */) {
259 mBufferingMonitor->getDefaultBufferingSettings(buffering);
260 return OK;
261}
262
263status_t NuPlayer::GenericSource::setBufferingSettings(const BufferingSettings& buffering) {
264 return mBufferingMonitor->setBufferingSettings(buffering);
265}
266
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700267status_t NuPlayer::GenericSource::startSources() {
Chong Zhangefbb6192015-01-30 17:13:27 -0800268 // Start the selected A/V tracks now before we start buffering.
269 // Widevine sources might re-initialize crypto when starting, if we delay
270 // this to start(), all data buffered during prepare would be wasted.
271 // (We don't actually start reading until start().)
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700272 //
273 // TODO: this logic may no longer be relevant after the removal of widevine
274 // support
Chong Zhangefbb6192015-01-30 17:13:27 -0800275 if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) {
276 ALOGE("failed to start audio track!");
277 return UNKNOWN_ERROR;
278 }
279
280 if (mVideoTrack.mSource != NULL && mVideoTrack.mSource->start() != OK) {
281 ALOGE("failed to start video track!");
282 return UNKNOWN_ERROR;
283 }
284
Chong Zhang3de157d2014-08-05 20:54:44 -0700285 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700286}
287
Ronghua Wu80276872014-08-28 15:50:29 -0700288int64_t NuPlayer::GenericSource::getLastReadPosition() {
289 if (mAudioTrack.mSource != NULL) {
290 return mAudioTimeUs;
291 } else if (mVideoTrack.mSource != NULL) {
292 return mVideoTimeUs;
293 } else {
294 return 0;
295 }
296}
297
Chong Zhanga19f33e2014-08-07 15:35:07 -0700298status_t NuPlayer::GenericSource::setBuffers(
299 bool audio, Vector<MediaBuffer *> &buffers) {
Wei Jia0386c912015-08-28 10:35:35 -0700300 if (mIsSecure && !audio && mVideoTrack.mSource != NULL) {
Lajos Molnarcc227032014-07-17 15:33:06 -0700301 return mVideoTrack.mSource->setBuffers(buffers);
302 }
303 return INVALID_OPERATION;
304}
305
Ronghua Wu02cb98d2015-05-27 11:02:54 -0700306bool NuPlayer::GenericSource::isStreaming() const {
307 return mIsStreaming;
308}
309
Wei Jia14532f22015-12-29 11:28:15 -0800310void NuPlayer::GenericSource::setOffloadAudio(bool offload) {
311 mBufferingMonitor->setOffloadAudio(offload);
312}
313
Andreas Huberafed0e12011-09-20 15:39:58 -0700314NuPlayer::GenericSource::~GenericSource() {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800315 ALOGV("~GenericSource");
Chong Zhang1228d6b2014-08-12 21:25:48 -0700316 if (mLooper != NULL) {
317 mLooper->unregisterHandler(id());
318 mLooper->stop();
319 }
Chong Zhanga6bf21f2014-11-19 20:26:34 -0800320 resetDataSource();
Andreas Huberafed0e12011-09-20 15:39:58 -0700321}
322
Andreas Huber9575c962013-02-05 13:59:56 -0800323void NuPlayer::GenericSource::prepareAsync() {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800324 ALOGV("prepareAsync: (looper: %d)", (mLooper != NULL));
325
Chong Zhang1228d6b2014-08-12 21:25:48 -0700326 if (mLooper == NULL) {
327 mLooper = new ALooper;
328 mLooper->setName("generic");
329 mLooper->start();
330
331 mLooper->registerHandler(this);
332 }
333
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800334 sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this);
Chong Zhang1228d6b2014-08-12 21:25:48 -0700335 msg->post();
336}
337
338void NuPlayer::GenericSource::onPrepareAsync() {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800339 ALOGV("onPrepareAsync: mDataSource: %d", (mDataSource != NULL));
340
Chong Zhanga19f33e2014-08-07 15:35:07 -0700341 // delayed data source creation
Chong Zhangd354d8d2014-08-20 13:09:58 -0700342 if (mDataSource == NULL) {
Chong Zhang42e81532014-12-01 13:44:26 -0800343 // set to false first, if the extractor
344 // comes back as secure, set it to true then.
345 mIsSecure = false;
346
Chong Zhangd354d8d2014-08-20 13:09:58 -0700347 if (!mUri.empty()) {
Robert Shih360d6d02014-09-29 14:42:35 -0700348 const char* uri = mUri.c_str();
Chong Zhangc287cad2015-02-19 18:30:30 -0800349 String8 contentType;
Robert Shih360d6d02014-09-29 14:42:35 -0700350
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700351 if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
Robert Shih360d6d02014-09-29 14:42:35 -0700352 mHttpSource = DataSource::CreateMediaHTTP(mHTTPService);
353 if (mHttpSource == NULL) {
354 ALOGE("Failed to create http source!");
355 notifyPreparedAndCleanup(UNKNOWN_ERROR);
356 return;
357 }
358 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700359
Chong Zhangd354d8d2014-08-20 13:09:58 -0700360 mDataSource = DataSource::CreateFromURI(
Chong Zhangc287cad2015-02-19 18:30:30 -0800361 mHTTPService, uri, &mUriHeaders, &contentType,
Robert Shih360d6d02014-09-29 14:42:35 -0700362 static_cast<HTTPBase *>(mHttpSource.get()));
Chong Zhangd354d8d2014-08-20 13:09:58 -0700363 } else {
Chong Zhangd354d8d2014-08-20 13:09:58 -0700364 mDataSource = new FileSource(mFd, mOffset, mLength);
Chong Zhanga6bf21f2014-11-19 20:26:34 -0800365 mFd = -1;
Chong Zhangd354d8d2014-08-20 13:09:58 -0700366 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700367
Chong Zhangd354d8d2014-08-20 13:09:58 -0700368 if (mDataSource == NULL) {
369 ALOGE("Failed to create data source!");
370 notifyPreparedAndCleanup(UNKNOWN_ERROR);
371 return;
372 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700373 }
374
Chris Watkins99f31602015-03-20 13:06:33 -0700375 if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
376 mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
377 }
378
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700379 // For cached streaming cases, we need to wait for enough
380 // buffering before reporting prepared.
381 mIsStreaming = (mCachedSource != NULL);
Chris Watkins99f31602015-03-20 13:06:33 -0700382
Chong Zhangc287cad2015-02-19 18:30:30 -0800383 // init extractor from data source
384 status_t err = initFromDataSource();
Chong Zhanga19f33e2014-08-07 15:35:07 -0700385
386 if (err != OK) {
387 ALOGE("Failed to init from data source!");
Chong Zhangd354d8d2014-08-20 13:09:58 -0700388 notifyPreparedAndCleanup(err);
Chong Zhanga19f33e2014-08-07 15:35:07 -0700389 return;
390 }
391
Andreas Huber9575c962013-02-05 13:59:56 -0800392 if (mVideoTrack.mSource != NULL) {
Robert Shih17f6dd62014-08-20 17:00:21 -0700393 sp<MetaData> meta = doGetFormatMeta(false /* audio */);
394 sp<AMessage> msg = new AMessage;
395 err = convertMetaDataToMessage(meta, &msg);
396 if(err != OK) {
397 notifyPreparedAndCleanup(err);
398 return;
399 }
400 notifyVideoSizeChanged(msg);
Andreas Huber9575c962013-02-05 13:59:56 -0800401 }
402
403 notifyFlagsChanged(
Hassan Shojaniacefac142017-02-06 21:02:02 -0800404 // FLAG_SECURE will be known if/when prepareDrm is called by the app
405 // FLAG_PROTECTED will be known if/when prepareDrm is called by the app
406 FLAG_CAN_PAUSE |
407 FLAG_CAN_SEEK_BACKWARD |
408 FLAG_CAN_SEEK_FORWARD |
409 FLAG_CAN_SEEK);
Andreas Huber9575c962013-02-05 13:59:56 -0800410
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700411 finishPrepareAsync();
Hassan Shojaniacefac142017-02-06 21:02:02 -0800412
413 ALOGV("onPrepareAsync: Done");
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700414}
415
416void NuPlayer::GenericSource::finishPrepareAsync() {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800417 ALOGV("finishPrepareAsync");
418
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700419 status_t err = startSources();
420 if (err != OK) {
421 ALOGE("Failed to init start data source!");
422 notifyPreparedAndCleanup(err);
423 return;
424 }
425
Chong Zhangefbb6192015-01-30 17:13:27 -0800426 if (mIsStreaming) {
Wei Jia14532f22015-12-29 11:28:15 -0800427 if (mBufferingMonitorLooper == NULL) {
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700428 mBufferingMonitor->prepare(mCachedSource, mDurationUs, mBitrate,
Wei Jia14532f22015-12-29 11:28:15 -0800429 mIsStreaming);
Chong Zhangefbb6192015-01-30 17:13:27 -0800430
Wei Jia14532f22015-12-29 11:28:15 -0800431 mBufferingMonitorLooper = new ALooper;
432 mBufferingMonitorLooper->setName("GSBMonitor");
433 mBufferingMonitorLooper->start();
434 mBufferingMonitorLooper->registerHandler(mBufferingMonitor);
435 }
436
437 mBufferingMonitor->ensureCacheIsFetching();
438 mBufferingMonitor->restartPollBuffering();
Chong Zhangefbb6192015-01-30 17:13:27 -0800439 } else {
440 notifyPrepared();
441 }
Andreas Huber9575c962013-02-05 13:59:56 -0800442}
443
Chong Zhangd354d8d2014-08-20 13:09:58 -0700444void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
445 if (err != OK) {
Robert Shihebc27122015-09-02 14:02:47 -0700446 {
447 sp<DataSource> dataSource = mDataSource;
448 sp<NuCachedSource2> cachedSource = mCachedSource;
449 sp<DataSource> httpSource = mHttpSource;
450 {
451 Mutex::Autolock _l(mDisconnectLock);
452 mDataSource.clear();
453 mCachedSource.clear();
454 mHttpSource.clear();
455 }
456 }
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700457 mBitrate = -1;
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700458
Wei Jia14532f22015-12-29 11:28:15 -0800459 mBufferingMonitor->cancelPollBuffering();
Chong Zhangd354d8d2014-08-20 13:09:58 -0700460 }
461 notifyPrepared(err);
462}
463
Andreas Huberafed0e12011-09-20 15:39:58 -0700464void NuPlayer::GenericSource::start() {
465 ALOGI("start");
466
Andy Hung2abde2c2014-09-30 14:40:32 -0700467 mStopRead = false;
Andreas Huberafed0e12011-09-20 15:39:58 -0700468 if (mAudioTrack.mSource != NULL) {
Robert Shih17f6dd62014-08-20 17:00:21 -0700469 postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700470 }
471
472 if (mVideoTrack.mSource != NULL) {
Robert Shih17f6dd62014-08-20 17:00:21 -0700473 postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700474 }
Ronghua Wu80276872014-08-28 15:50:29 -0700475
Ronghua Wu80276872014-08-28 15:50:29 -0700476 mStarted = true;
Chong Zhangefbb6192015-01-30 17:13:27 -0800477
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800478 (new AMessage(kWhatStart, this))->post();
Ronghua Wu80276872014-08-28 15:50:29 -0700479}
480
481void NuPlayer::GenericSource::stop() {
Ronghua Wu80276872014-08-28 15:50:29 -0700482 mStarted = false;
483}
484
485void NuPlayer::GenericSource::pause() {
Ronghua Wu80276872014-08-28 15:50:29 -0700486 mStarted = false;
487}
488
489void NuPlayer::GenericSource::resume() {
Ronghua Wu80276872014-08-28 15:50:29 -0700490 mStarted = true;
Chong Zhangefbb6192015-01-30 17:13:27 -0800491
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800492 (new AMessage(kWhatResume, this))->post();
Ronghua Wu80276872014-08-28 15:50:29 -0700493}
494
Chong Zhang48296b72014-09-14 14:28:45 -0700495void NuPlayer::GenericSource::disconnect() {
Robert Shihebc27122015-09-02 14:02:47 -0700496 sp<DataSource> dataSource, httpSource;
497 {
498 Mutex::Autolock _l(mDisconnectLock);
499 dataSource = mDataSource;
500 httpSource = mHttpSource;
501 }
502
503 if (dataSource != NULL) {
Chong Zhang48296b72014-09-14 14:28:45 -0700504 // disconnect data source
Robert Shihebc27122015-09-02 14:02:47 -0700505 if (dataSource->flags() & DataSource::kIsCachingDataSource) {
506 static_cast<NuCachedSource2 *>(dataSource.get())->disconnect();
Chong Zhang48296b72014-09-14 14:28:45 -0700507 }
Robert Shihebc27122015-09-02 14:02:47 -0700508 } else if (httpSource != NULL) {
509 static_cast<HTTPBase *>(httpSource.get())->disconnect();
Chong Zhang48296b72014-09-14 14:28:45 -0700510 }
511}
512
Andreas Huberafed0e12011-09-20 15:39:58 -0700513status_t NuPlayer::GenericSource::feedMoreTSData() {
514 return OK;
515}
516
Robert Shih3423bbd2014-07-16 15:47:09 -0700517void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
518 switch (msg->what()) {
Chong Zhang1228d6b2014-08-12 21:25:48 -0700519 case kWhatPrepareAsync:
520 {
521 onPrepareAsync();
522 break;
523 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700524 case kWhatFetchSubtitleData:
525 {
Lajos Molnare26940f2014-07-31 10:31:26 -0700526 fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
527 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
528 break;
529 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700530
Lajos Molnare26940f2014-07-31 10:31:26 -0700531 case kWhatFetchTimedTextData:
532 {
533 fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
534 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih3423bbd2014-07-16 15:47:09 -0700535 break;
536 }
537
538 case kWhatSendSubtitleData:
539 {
Lajos Molnare26940f2014-07-31 10:31:26 -0700540 sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
541 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
542 break;
543 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700544
Marco Nelissen55e2f4c2015-09-04 15:57:15 -0700545 case kWhatSendGlobalTimedTextData:
546 {
547 sendGlobalTextData(kWhatTimedTextData, mFetchTimedTextDataGeneration, msg);
548 break;
549 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700550 case kWhatSendTimedTextData:
551 {
552 sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
553 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih3423bbd2014-07-16 15:47:09 -0700554 break;
555 }
556
557 case kWhatChangeAVSource:
558 {
559 int32_t trackIndex;
560 CHECK(msg->findInt32("trackIndex", &trackIndex));
Marco Nelissenb2487f02015-09-01 13:23:23 -0700561 const sp<IMediaSource> source = mSources.itemAt(trackIndex);
Robert Shih3423bbd2014-07-16 15:47:09 -0700562
563 Track* track;
564 const char *mime;
565 media_track_type trackType, counterpartType;
566 sp<MetaData> meta = source->getFormat();
567 meta->findCString(kKeyMIMEType, &mime);
568 if (!strncasecmp(mime, "audio/", 6)) {
569 track = &mAudioTrack;
570 trackType = MEDIA_TRACK_TYPE_AUDIO;
571 counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
572 } else {
573 CHECK(!strncasecmp(mime, "video/", 6));
574 track = &mVideoTrack;
575 trackType = MEDIA_TRACK_TYPE_VIDEO;
576 counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
577 }
578
579
580 if (track->mSource != NULL) {
581 track->mSource->stop();
582 }
583 track->mSource = source;
584 track->mSource->start();
585 track->mIndex = trackIndex;
586
Robert Shih3423bbd2014-07-16 15:47:09 -0700587 int64_t timeUs, actualTimeUs;
588 const bool formatChange = true;
Robert Shih5c67ddc2014-11-04 17:46:05 -0800589 if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
590 timeUs = mAudioLastDequeueTimeUs;
591 } else {
592 timeUs = mVideoLastDequeueTimeUs;
593 }
Wei Jiac5de0912016-11-18 10:22:14 -0800594 readBuffer(trackType, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
595 &actualTimeUs, formatChange);
596 readBuffer(counterpartType, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
597 NULL, !formatChange);
Lajos Molnar6d339f12015-04-17 16:15:53 -0700598 ALOGV("timeUs %lld actualTimeUs %lld", (long long)timeUs, (long long)actualTimeUs);
Robert Shih3423bbd2014-07-16 15:47:09 -0700599
600 break;
601 }
Chong Zhangefbb6192015-01-30 17:13:27 -0800602
603 case kWhatStart:
604 case kWhatResume:
605 {
Wei Jia14532f22015-12-29 11:28:15 -0800606 mBufferingMonitor->restartPollBuffering();
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700607 break;
608 }
Robert Shih17f6dd62014-08-20 17:00:21 -0700609
610 case kWhatGetFormat:
611 {
612 onGetFormatMeta(msg);
613 break;
614 }
615
616 case kWhatGetSelectedTrack:
617 {
618 onGetSelectedTrack(msg);
619 break;
620 }
621
qinzhichao9935bd42016-12-31 15:36:18 +0800622 case kWhatGetTrackInfo:
623 {
624 onGetTrackInfo(msg);
625 break;
626 }
627
Robert Shih17f6dd62014-08-20 17:00:21 -0700628 case kWhatSelectTrack:
629 {
630 onSelectTrack(msg);
631 break;
632 }
633
634 case kWhatSeek:
635 {
636 onSeek(msg);
637 break;
638 }
639
640 case kWhatReadBuffer:
641 {
642 onReadBuffer(msg);
643 break;
644 }
645
Hassan Shojaniacefac142017-02-06 21:02:02 -0800646 case kWhatPrepareDrm:
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700647 {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800648 status_t status = onPrepareDrm(msg);
649 sp<AMessage> response = new AMessage;
650 response->setInt32("status", status);
651 sp<AReplyToken> replyID;
652 CHECK(msg->senderAwaitsResponse(&replyID));
653 response->postReply(replyID);
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700654 break;
655 }
656
Robert Shih3423bbd2014-07-16 15:47:09 -0700657 default:
658 Source::onMessageReceived(msg);
659 break;
660 }
661}
662
Lajos Molnare26940f2014-07-31 10:31:26 -0700663void NuPlayer::GenericSource::fetchTextData(
664 uint32_t sendWhat,
665 media_track_type type,
666 int32_t curGen,
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -0700667 const sp<AnotherPacketSource>& packets,
668 const sp<AMessage>& msg) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700669 int32_t msgGeneration;
670 CHECK(msg->findInt32("generation", &msgGeneration));
671 if (msgGeneration != curGen) {
672 // stale
673 return;
674 }
675
676 int32_t avail;
677 if (packets->hasBufferAvailable(&avail)) {
678 return;
679 }
680
681 int64_t timeUs;
682 CHECK(msg->findInt64("timeUs", &timeUs));
683
684 int64_t subTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -0800685 readBuffer(type, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &subTimeUs);
Lajos Molnare26940f2014-07-31 10:31:26 -0700686
687 int64_t delayUs = subTimeUs - timeUs;
688 if (msg->what() == kWhatFetchSubtitleData) {
689 const int64_t oneSecUs = 1000000ll;
690 delayUs -= oneSecUs;
691 }
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800692 sp<AMessage> msg2 = new AMessage(sendWhat, this);
Lajos Molnare26940f2014-07-31 10:31:26 -0700693 msg2->setInt32("generation", msgGeneration);
694 msg2->post(delayUs < 0 ? 0 : delayUs);
695}
696
697void NuPlayer::GenericSource::sendTextData(
698 uint32_t what,
699 media_track_type type,
700 int32_t curGen,
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -0700701 const sp<AnotherPacketSource>& packets,
702 const sp<AMessage>& msg) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700703 int32_t msgGeneration;
704 CHECK(msg->findInt32("generation", &msgGeneration));
705 if (msgGeneration != curGen) {
706 // stale
707 return;
708 }
709
710 int64_t subTimeUs;
711 if (packets->nextBufferTime(&subTimeUs) != OK) {
712 return;
713 }
714
715 int64_t nextSubTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -0800716 readBuffer(type, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &nextSubTimeUs);
Lajos Molnare26940f2014-07-31 10:31:26 -0700717
718 sp<ABuffer> buffer;
719 status_t dequeueStatus = packets->dequeueAccessUnit(&buffer);
720 if (dequeueStatus == OK) {
721 sp<AMessage> notify = dupNotify();
722 notify->setInt32("what", what);
723 notify->setBuffer("buffer", buffer);
724 notify->post();
725
726 const int64_t delayUs = nextSubTimeUs - subTimeUs;
727 msg->post(delayUs < 0 ? 0 : delayUs);
728 }
729}
730
Marco Nelissen55e2f4c2015-09-04 15:57:15 -0700731void NuPlayer::GenericSource::sendGlobalTextData(
732 uint32_t what,
733 int32_t curGen,
734 sp<AMessage> msg) {
735 int32_t msgGeneration;
736 CHECK(msg->findInt32("generation", &msgGeneration));
737 if (msgGeneration != curGen) {
738 // stale
739 return;
740 }
741
742 uint32_t textType;
743 const void *data;
744 size_t size = 0;
745 if (mTimedTextTrack.mSource->getFormat()->findData(
746 kKeyTextFormatData, &textType, &data, &size)) {
747 mGlobalTimedText = new ABuffer(size);
748 if (mGlobalTimedText->data()) {
749 memcpy(mGlobalTimedText->data(), data, size);
750 sp<AMessage> globalMeta = mGlobalTimedText->meta();
751 globalMeta->setInt64("timeUs", 0);
752 globalMeta->setString("mime", MEDIA_MIMETYPE_TEXT_3GPP);
753 globalMeta->setInt32("global", 1);
754 sp<AMessage> notify = dupNotify();
755 notify->setInt32("what", what);
756 notify->setBuffer("buffer", mGlobalTimedText);
757 notify->post();
758 }
759 }
760}
761
Andreas Huber84066782011-08-16 09:34:26 -0700762sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800763 sp<AMessage> msg = new AMessage(kWhatGetFormat, this);
Robert Shih17f6dd62014-08-20 17:00:21 -0700764 msg->setInt32("audio", audio);
765
766 sp<AMessage> response;
Marco Nelissen10a121b2015-11-04 14:46:44 -0800767 sp<RefBase> format;
Robert Shih17f6dd62014-08-20 17:00:21 -0700768 status_t err = msg->postAndAwaitResponse(&response);
769 if (err == OK && response != NULL) {
Marco Nelissen10a121b2015-11-04 14:46:44 -0800770 CHECK(response->findObject("format", &format));
771 return static_cast<MetaData*>(format.get());
Robert Shih17f6dd62014-08-20 17:00:21 -0700772 } else {
773 return NULL;
774 }
775}
776
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -0700777void NuPlayer::GenericSource::onGetFormatMeta(const sp<AMessage>& msg) const {
Robert Shih17f6dd62014-08-20 17:00:21 -0700778 int32_t audio;
779 CHECK(msg->findInt32("audio", &audio));
780
781 sp<AMessage> response = new AMessage;
782 sp<MetaData> format = doGetFormatMeta(audio);
Marco Nelissen10a121b2015-11-04 14:46:44 -0800783 response->setObject("format", format);
Robert Shih17f6dd62014-08-20 17:00:21 -0700784
Lajos Molnar3f274362015-03-05 14:35:41 -0800785 sp<AReplyToken> replyID;
Robert Shih17f6dd62014-08-20 17:00:21 -0700786 CHECK(msg->senderAwaitsResponse(&replyID));
787 response->postReply(replyID);
788}
789
790sp<MetaData> NuPlayer::GenericSource::doGetFormatMeta(bool audio) const {
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 Jiaff486642016-04-04 16:17:39 -0700802 if (audio && !mStarted) {
Wei Jia14532f22015-12-29 11:28:15 -0800803 return -EWOULDBLOCK;
804 }
805
Andreas Huberafed0e12011-09-20 15:39:58 -0700806 Track *track = audio ? &mAudioTrack : &mVideoTrack;
807
808 if (track->mSource == NULL) {
809 return -EWOULDBLOCK;
810 }
811
812 status_t finalResult;
813 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
Chong Zhang42e81532014-12-01 13:44:26 -0800814 if (finalResult == OK) {
815 postReadBuffer(
816 audio ? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
817 return -EWOULDBLOCK;
818 }
819 return finalResult;
Andreas Huberafed0e12011-09-20 15:39:58 -0700820 }
821
822 status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
823
Chong Zhangfcf044a2015-07-14 15:58:51 -0700824 // start pulling in more buffers if we only have one (or no) buffer left
825 // so that decoder has less chance of being starved
826 if (track->mPackets->getAvailableBufferCount(&finalResult) < 2) {
Robert Shih17f6dd62014-08-20 17:00:21 -0700827 postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
Lajos Molnare26940f2014-07-31 10:31:26 -0700828 }
829
Robert Shih3423bbd2014-07-16 15:47:09 -0700830 if (result != OK) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700831 if (mSubtitleTrack.mSource != NULL) {
832 mSubtitleTrack.mPackets->clear();
833 mFetchSubtitleDataGeneration++;
834 }
835 if (mTimedTextTrack.mSource != NULL) {
836 mTimedTextTrack.mPackets->clear();
837 mFetchTimedTextDataGeneration++;
838 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700839 return result;
840 }
841
842 int64_t timeUs;
843 status_t eosResult; // ignored
844 CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
Robert Shih5c67ddc2014-11-04 17:46:05 -0800845 if (audio) {
846 mAudioLastDequeueTimeUs = timeUs;
Wei Jia14532f22015-12-29 11:28:15 -0800847 mBufferingMonitor->updateDequeuedBufferTime(timeUs);
Robert Shih5c67ddc2014-11-04 17:46:05 -0800848 } else {
849 mVideoLastDequeueTimeUs = timeUs;
850 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700851
852 if (mSubtitleTrack.mSource != NULL
853 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800854 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
Robert Shih3423bbd2014-07-16 15:47:09 -0700855 msg->setInt64("timeUs", timeUs);
856 msg->setInt32("generation", mFetchSubtitleDataGeneration);
857 msg->post();
858 }
Robert Shiheb1735e2014-07-23 15:53:14 -0700859
Lajos Molnare26940f2014-07-31 10:31:26 -0700860 if (mTimedTextTrack.mSource != NULL
861 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800862 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
Lajos Molnare26940f2014-07-31 10:31:26 -0700863 msg->setInt64("timeUs", timeUs);
864 msg->setInt32("generation", mFetchTimedTextDataGeneration);
865 msg->post();
866 }
867
Andreas Huberafed0e12011-09-20 15:39:58 -0700868 return result;
869}
870
871status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
872 *durationUs = mDurationUs;
873 return OK;
874}
875
Robert Shihdd235722014-06-12 14:49:23 -0700876size_t NuPlayer::GenericSource::getTrackCount() const {
877 return mSources.size();
878}
879
880sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const {
qinzhichao9935bd42016-12-31 15:36:18 +0800881 sp<AMessage> msg = new AMessage(kWhatGetTrackInfo, this);
882 msg->setSize("trackIndex", trackIndex);
883
884 sp<AMessage> response;
885 sp<RefBase> format;
886 status_t err = msg->postAndAwaitResponse(&response);
887 if (err == OK && response != NULL) {
888 CHECK(response->findObject("format", &format));
889 return static_cast<AMessage*>(format.get());
890 } else {
891 return NULL;
892 }
893}
894
895void NuPlayer::GenericSource::onGetTrackInfo(const sp<AMessage>& msg) const {
896 size_t trackIndex;
897 CHECK(msg->findSize("trackIndex", &trackIndex));
898
899 sp<AMessage> response = new AMessage;
900 sp<AMessage> format = doGetTrackInfo(trackIndex);
901 response->setObject("format", format);
902
903 sp<AReplyToken> replyID;
904 CHECK(msg->senderAwaitsResponse(&replyID));
905 response->postReply(replyID);
906}
907
908sp<AMessage> NuPlayer::GenericSource::doGetTrackInfo(size_t trackIndex) const {
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 {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800958 sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, this);
Robert Shih17f6dd62014-08-20 17:00:21 -0700959 msg->setInt32("type", type);
960
961 sp<AMessage> response;
962 int32_t index;
963 status_t err = msg->postAndAwaitResponse(&response);
964 if (err == OK && response != NULL) {
965 CHECK(response->findInt32("index", &index));
966 return index;
967 } else {
968 return -1;
969 }
970}
971
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -0700972void NuPlayer::GenericSource::onGetSelectedTrack(const sp<AMessage>& msg) const {
Robert Shih17f6dd62014-08-20 17:00:21 -0700973 int32_t tmpType;
974 CHECK(msg->findInt32("type", &tmpType));
975 media_track_type type = (media_track_type)tmpType;
976
977 sp<AMessage> response = new AMessage;
978 ssize_t index = doGetSelectedTrack(type);
979 response->setInt32("index", index);
980
Lajos Molnar3f274362015-03-05 14:35:41 -0800981 sp<AReplyToken> replyID;
Robert Shih17f6dd62014-08-20 17:00:21 -0700982 CHECK(msg->senderAwaitsResponse(&replyID));
983 response->postReply(replyID);
984}
985
986ssize_t NuPlayer::GenericSource::doGetSelectedTrack(media_track_type type) const {
Lajos Molnare26940f2014-07-31 10:31:26 -0700987 const Track *track = NULL;
988 switch (type) {
989 case MEDIA_TRACK_TYPE_VIDEO:
990 track = &mVideoTrack;
991 break;
992 case MEDIA_TRACK_TYPE_AUDIO:
993 track = &mAudioTrack;
994 break;
995 case MEDIA_TRACK_TYPE_TIMEDTEXT:
996 track = &mTimedTextTrack;
997 break;
998 case MEDIA_TRACK_TYPE_SUBTITLE:
999 track = &mSubtitleTrack;
1000 break;
1001 default:
1002 break;
1003 }
1004
1005 if (track != NULL && track->mSource != NULL) {
1006 return track->mIndex;
1007 }
1008
1009 return -1;
1010}
1011
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001012status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
Lajos Molnare26940f2014-07-31 10:31:26 -07001013 ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001014 sp<AMessage> msg = new AMessage(kWhatSelectTrack, this);
Robert Shih17f6dd62014-08-20 17:00:21 -07001015 msg->setInt32("trackIndex", trackIndex);
Robert Shihda23ab92014-09-16 11:34:08 -07001016 msg->setInt32("select", select);
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001017 msg->setInt64("timeUs", timeUs);
Robert Shih17f6dd62014-08-20 17:00:21 -07001018
1019 sp<AMessage> response;
1020 status_t err = msg->postAndAwaitResponse(&response);
1021 if (err == OK && response != NULL) {
1022 CHECK(response->findInt32("err", &err));
1023 }
1024
1025 return err;
1026}
1027
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -07001028void NuPlayer::GenericSource::onSelectTrack(const sp<AMessage>& msg) {
Robert Shih17f6dd62014-08-20 17:00:21 -07001029 int32_t trackIndex, select;
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001030 int64_t timeUs;
Robert Shih17f6dd62014-08-20 17:00:21 -07001031 CHECK(msg->findInt32("trackIndex", &trackIndex));
1032 CHECK(msg->findInt32("select", &select));
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001033 CHECK(msg->findInt64("timeUs", &timeUs));
Robert Shih17f6dd62014-08-20 17:00:21 -07001034
1035 sp<AMessage> response = new AMessage;
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001036 status_t err = doSelectTrack(trackIndex, select, timeUs);
Robert Shih17f6dd62014-08-20 17:00:21 -07001037 response->setInt32("err", err);
1038
Lajos Molnar3f274362015-03-05 14:35:41 -08001039 sp<AReplyToken> replyID;
Robert Shih17f6dd62014-08-20 17:00:21 -07001040 CHECK(msg->senderAwaitsResponse(&replyID));
1041 response->postReply(replyID);
1042}
1043
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001044status_t NuPlayer::GenericSource::doSelectTrack(size_t trackIndex, bool select, int64_t timeUs) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001045 if (trackIndex >= mSources.size()) {
1046 return BAD_INDEX;
1047 }
1048
1049 if (!select) {
Lajos Molnare26940f2014-07-31 10:31:26 -07001050 Track* track = NULL;
1051 if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) {
1052 track = &mSubtitleTrack;
1053 mFetchSubtitleDataGeneration++;
1054 } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) {
1055 track = &mTimedTextTrack;
1056 mFetchTimedTextDataGeneration++;
1057 }
1058 if (track == NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001059 return INVALID_OPERATION;
1060 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001061 track->mSource->stop();
1062 track->mSource = NULL;
1063 track->mPackets->clear();
Robert Shih3423bbd2014-07-16 15:47:09 -07001064 return OK;
1065 }
1066
Marco Nelissenb2487f02015-09-01 13:23:23 -07001067 const sp<IMediaSource> source = mSources.itemAt(trackIndex);
Robert Shih3423bbd2014-07-16 15:47:09 -07001068 sp<MetaData> meta = source->getFormat();
1069 const char *mime;
1070 CHECK(meta->findCString(kKeyMIMEType, &mime));
1071 if (!strncasecmp(mime, "text/", 5)) {
Lajos Molnare26940f2014-07-31 10:31:26 -07001072 bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP);
1073 Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack;
1074 if (track->mSource != NULL && track->mIndex == trackIndex) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001075 return OK;
1076 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001077 track->mIndex = trackIndex;
1078 if (track->mSource != NULL) {
1079 track->mSource->stop();
Robert Shih3423bbd2014-07-16 15:47:09 -07001080 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001081 track->mSource = mSources.itemAt(trackIndex);
1082 track->mSource->start();
1083 if (track->mPackets == NULL) {
1084 track->mPackets = new AnotherPacketSource(track->mSource->getFormat());
Robert Shih3423bbd2014-07-16 15:47:09 -07001085 } else {
Lajos Molnare26940f2014-07-31 10:31:26 -07001086 track->mPackets->clear();
1087 track->mPackets->setFormat(track->mSource->getFormat());
Robert Shih3423bbd2014-07-16 15:47:09 -07001088
1089 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001090
1091 if (isSubtitle) {
1092 mFetchSubtitleDataGeneration++;
1093 } else {
1094 mFetchTimedTextDataGeneration++;
1095 }
1096
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001097 status_t eosResult; // ignored
1098 if (mSubtitleTrack.mSource != NULL
1099 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001100 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001101 msg->setInt64("timeUs", timeUs);
1102 msg->setInt32("generation", mFetchSubtitleDataGeneration);
1103 msg->post();
1104 }
1105
Marco Nelissen55e2f4c2015-09-04 15:57:15 -07001106 sp<AMessage> msg2 = new AMessage(kWhatSendGlobalTimedTextData, this);
1107 msg2->setInt32("generation", mFetchTimedTextDataGeneration);
1108 msg2->post();
1109
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001110 if (mTimedTextTrack.mSource != NULL
1111 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001112 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001113 msg->setInt64("timeUs", timeUs);
1114 msg->setInt32("generation", mFetchTimedTextDataGeneration);
1115 msg->post();
1116 }
1117
Robert Shih3423bbd2014-07-16 15:47:09 -07001118 return OK;
1119 } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
1120 bool audio = !strncasecmp(mime, "audio/", 6);
1121 Track *track = audio ? &mAudioTrack : &mVideoTrack;
1122 if (track->mSource != NULL && track->mIndex == trackIndex) {
1123 return OK;
1124 }
1125
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001126 sp<AMessage> msg = new AMessage(kWhatChangeAVSource, this);
Robert Shih3423bbd2014-07-16 15:47:09 -07001127 msg->setInt32("trackIndex", trackIndex);
1128 msg->post();
1129 return OK;
1130 }
1131
1132 return INVALID_OPERATION;
1133}
1134
Wei Jiac5de0912016-11-18 10:22:14 -08001135status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001136 sp<AMessage> msg = new AMessage(kWhatSeek, this);
Robert Shih17f6dd62014-08-20 17:00:21 -07001137 msg->setInt64("seekTimeUs", seekTimeUs);
Wei Jiac5de0912016-11-18 10:22:14 -08001138 msg->setInt32("mode", mode);
Robert Shih17f6dd62014-08-20 17:00:21 -07001139
1140 sp<AMessage> response;
1141 status_t err = msg->postAndAwaitResponse(&response);
1142 if (err == OK && response != NULL) {
1143 CHECK(response->findInt32("err", &err));
1144 }
1145
1146 return err;
1147}
1148
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -07001149void NuPlayer::GenericSource::onSeek(const sp<AMessage>& msg) {
Robert Shih17f6dd62014-08-20 17:00:21 -07001150 int64_t seekTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -08001151 int32_t mode;
Robert Shih17f6dd62014-08-20 17:00:21 -07001152 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
Wei Jiac5de0912016-11-18 10:22:14 -08001153 CHECK(msg->findInt32("mode", &mode));
Robert Shih17f6dd62014-08-20 17:00:21 -07001154
1155 sp<AMessage> response = new AMessage;
Wei Jiac5de0912016-11-18 10:22:14 -08001156 status_t err = doSeek(seekTimeUs, (MediaPlayerSeekMode)mode);
Robert Shih17f6dd62014-08-20 17:00:21 -07001157 response->setInt32("err", err);
1158
Lajos Molnar3f274362015-03-05 14:35:41 -08001159 sp<AReplyToken> replyID;
Robert Shih17f6dd62014-08-20 17:00:21 -07001160 CHECK(msg->senderAwaitsResponse(&replyID));
1161 response->postReply(replyID);
1162}
1163
Wei Jiac5de0912016-11-18 10:22:14 -08001164status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
Wei Jia14532f22015-12-29 11:28:15 -08001165 mBufferingMonitor->updateDequeuedBufferTime(-1ll);
1166
Andy Hung2abde2c2014-09-30 14:40:32 -07001167 // If the Widevine source is stopped, do not attempt to read any
1168 // more buffers.
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001169 //
1170 // TODO: revisit after widevine is removed. May be able to
1171 // combine mStopRead with mStarted.
Andy Hung2abde2c2014-09-30 14:40:32 -07001172 if (mStopRead) {
1173 return INVALID_OPERATION;
1174 }
Andreas Huberafed0e12011-09-20 15:39:58 -07001175 if (mVideoTrack.mSource != NULL) {
1176 int64_t actualTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -08001177 readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, mode, &actualTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -07001178
Wei Jiac5de0912016-11-18 10:22:14 -08001179 if (mode != MediaPlayerSeekMode::SEEK_CLOSEST) {
Wei Jia5ec347f2016-11-01 17:07:54 -07001180 seekTimeUs = actualTimeUs;
1181 }
1182 mVideoLastDequeueTimeUs = actualTimeUs;
Andreas Huberafed0e12011-09-20 15:39:58 -07001183 }
1184
1185 if (mAudioTrack.mSource != NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001186 readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs);
Robert Shih5c67ddc2014-11-04 17:46:05 -08001187 mAudioLastDequeueTimeUs = seekTimeUs;
Andreas Huberafed0e12011-09-20 15:39:58 -07001188 }
1189
Chong Zhangefbb6192015-01-30 17:13:27 -08001190 // If currently buffering, post kWhatBufferingEnd first, so that
1191 // NuPlayer resumes. Otherwise, if cache hits high watermark
1192 // before new polling happens, no one will resume the playback.
Wei Jia14532f22015-12-29 11:28:15 -08001193 mBufferingMonitor->stopBufferingIfNecessary();
1194 mBufferingMonitor->restartPollBuffering();
Chong Zhangefbb6192015-01-30 17:13:27 -08001195
Andreas Huberafed0e12011-09-20 15:39:58 -07001196 return OK;
1197}
1198
Robert Shih3423bbd2014-07-16 15:47:09 -07001199sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
1200 MediaBuffer* mb,
Wei Jia14486822016-11-02 17:51:30 -07001201 media_track_type trackType) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001202 bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
1203 size_t outLength = mb->range_length();
1204
1205 if (audio && mAudioIsVorbis) {
1206 outLength += sizeof(int32_t);
1207 }
1208
1209 sp<ABuffer> ab;
Hassan Shojaniacefac142017-02-06 21:02:02 -08001210
1211 if (mIsDrmProtected) {
1212 // Modular DRM
1213 // Enabled for both video/audio so 1) media buffer is reused without extra copying
1214 // 2) meta data can be retrieved in onInputBufferFetched for calling queueSecureInputBuffer.
1215
Robert Shih3423bbd2014-07-16 15:47:09 -07001216 // data is already provided in the buffer
1217 ab = new ABuffer(NULL, mb->range_length());
Robert Shih3423bbd2014-07-16 15:47:09 -07001218 mb->add_ref();
Wei Jia96e92b52014-09-18 17:36:20 -07001219 ab->setMediaBufferBase(mb);
Hassan Shojaniacefac142017-02-06 21:02:02 -08001220
1221 // Modular DRM: Required b/c of the above add_ref.
1222 // If ref>0, there must be an observer, or it'll crash at release().
1223 // TODO: MediaBuffer might need to be revised to ease such need.
1224 mb->setObserver(this);
1225 // setMediaBufferBase() interestingly doesn't increment the ref count on its own.
1226 // Extra increment (since we want to keep mb alive and attached to ab beyond this function
1227 // call. This is to counter the effect of mb->release() towards the end.
1228 mb->add_ref();
1229
Robert Shih3423bbd2014-07-16 15:47:09 -07001230 } else {
1231 ab = new ABuffer(outLength);
1232 memcpy(ab->data(),
1233 (const uint8_t *)mb->data() + mb->range_offset(),
1234 mb->range_length());
1235 }
1236
1237 if (audio && mAudioIsVorbis) {
1238 int32_t numPageSamples;
1239 if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
1240 numPageSamples = -1;
1241 }
1242
1243 uint8_t* abEnd = ab->data() + mb->range_length();
1244 memcpy(abEnd, &numPageSamples, sizeof(numPageSamples));
1245 }
1246
Lajos Molnare26940f2014-07-31 10:31:26 -07001247 sp<AMessage> meta = ab->meta();
1248
Robert Shih3423bbd2014-07-16 15:47:09 -07001249 int64_t timeUs;
1250 CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs));
Robert Shih3423bbd2014-07-16 15:47:09 -07001251 meta->setInt64("timeUs", timeUs);
1252
Praveen Chavanbbaa1442016-04-08 13:33:49 -07001253 if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
1254 int32_t layerId;
1255 if (mb->meta_data()->findInt32(kKeyTemporalLayerId, &layerId)) {
1256 meta->setInt32("temporal-layer-id", layerId);
1257 }
1258 }
1259
Lajos Molnare26940f2014-07-31 10:31:26 -07001260 if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
1261 const char *mime;
1262 CHECK(mTimedTextTrack.mSource != NULL
1263 && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime));
1264 meta->setString("mime", mime);
1265 }
1266
Robert Shih3423bbd2014-07-16 15:47:09 -07001267 int64_t durationUs;
1268 if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) {
1269 meta->setInt64("durationUs", durationUs);
1270 }
1271
1272 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
1273 meta->setInt32("trackIndex", mSubtitleTrack.mIndex);
1274 }
1275
Robert Shihf8bd8512015-04-23 16:39:18 -07001276 uint32_t dataType; // unused
1277 const void *seiData;
1278 size_t seiLength;
1279 if (mb->meta_data()->findData(kKeySEI, &dataType, &seiData, &seiLength)) {
1280 sp<ABuffer> sei = ABuffer::CreateAsCopy(seiData, seiLength);;
1281 meta->setBuffer("sei", sei);
1282 }
1283
Jaesung Chung3694d7c2015-10-21 11:41:38 +09001284 const void *mpegUserDataPointer;
1285 size_t mpegUserDataLength;
1286 if (mb->meta_data()->findData(
1287 kKeyMpegUserData, &dataType, &mpegUserDataPointer, &mpegUserDataLength)) {
1288 sp<ABuffer> mpegUserData = ABuffer::CreateAsCopy(mpegUserDataPointer, mpegUserDataLength);
1289 meta->setBuffer("mpegUserData", mpegUserData);
1290 }
1291
Robert Shih3423bbd2014-07-16 15:47:09 -07001292 mb->release();
1293 mb = NULL;
1294
1295 return ab;
1296}
1297
Robert Shih17f6dd62014-08-20 17:00:21 -07001298void NuPlayer::GenericSource::postReadBuffer(media_track_type trackType) {
Lajos Molnar84f52782014-09-11 10:01:55 -07001299 Mutex::Autolock _l(mReadBufferLock);
1300
1301 if ((mPendingReadBufferTypes & (1 << trackType)) == 0) {
1302 mPendingReadBufferTypes |= (1 << trackType);
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001303 sp<AMessage> msg = new AMessage(kWhatReadBuffer, this);
Lajos Molnar84f52782014-09-11 10:01:55 -07001304 msg->setInt32("trackType", trackType);
1305 msg->post();
1306 }
Robert Shih17f6dd62014-08-20 17:00:21 -07001307}
1308
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -07001309void NuPlayer::GenericSource::onReadBuffer(const sp<AMessage>& msg) {
Robert Shih17f6dd62014-08-20 17:00:21 -07001310 int32_t tmpType;
1311 CHECK(msg->findInt32("trackType", &tmpType));
1312 media_track_type trackType = (media_track_type)tmpType;
Chong Zhang42e81532014-12-01 13:44:26 -08001313 readBuffer(trackType);
Lajos Molnar84f52782014-09-11 10:01:55 -07001314 {
1315 // only protect the variable change, as readBuffer may
Chong Zhang42e81532014-12-01 13:44:26 -08001316 // take considerable time.
Lajos Molnar84f52782014-09-11 10:01:55 -07001317 Mutex::Autolock _l(mReadBufferLock);
1318 mPendingReadBufferTypes &= ~(1 << trackType);
1319 }
Robert Shih17f6dd62014-08-20 17:00:21 -07001320}
1321
Andreas Huberafed0e12011-09-20 15:39:58 -07001322void NuPlayer::GenericSource::readBuffer(
Wei Jiac5de0912016-11-18 10:22:14 -08001323 media_track_type trackType, int64_t seekTimeUs, MediaPlayerSeekMode mode,
Wei Jia5ec347f2016-11-01 17:07:54 -07001324 int64_t *actualTimeUs, bool formatChange) {
Andy Hung2abde2c2014-09-30 14:40:32 -07001325 // Do not read data if Widevine source is stopped
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001326 //
1327 // TODO: revisit after widevine is removed. May be able to
1328 // combine mStopRead with mStarted.
Andy Hung2abde2c2014-09-30 14:40:32 -07001329 if (mStopRead) {
1330 return;
1331 }
Robert Shih3423bbd2014-07-16 15:47:09 -07001332 Track *track;
Phil Burkc5cc2e22014-09-09 20:08:39 -07001333 size_t maxBuffers = 1;
Robert Shih3423bbd2014-07-16 15:47:09 -07001334 switch (trackType) {
1335 case MEDIA_TRACK_TYPE_VIDEO:
1336 track = &mVideoTrack;
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001337 maxBuffers = 8; // too large of a number may influence seeks
Robert Shih3423bbd2014-07-16 15:47:09 -07001338 break;
1339 case MEDIA_TRACK_TYPE_AUDIO:
1340 track = &mAudioTrack;
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001341 maxBuffers = 64;
Robert Shih3423bbd2014-07-16 15:47:09 -07001342 break;
1343 case MEDIA_TRACK_TYPE_SUBTITLE:
1344 track = &mSubtitleTrack;
1345 break;
Lajos Molnare26940f2014-07-31 10:31:26 -07001346 case MEDIA_TRACK_TYPE_TIMEDTEXT:
1347 track = &mTimedTextTrack;
1348 break;
Robert Shih3423bbd2014-07-16 15:47:09 -07001349 default:
1350 TRESPASS();
1351 }
1352
1353 if (track->mSource == NULL) {
1354 return;
1355 }
Andreas Huberafed0e12011-09-20 15:39:58 -07001356
1357 if (actualTimeUs) {
1358 *actualTimeUs = seekTimeUs;
1359 }
1360
1361 MediaSource::ReadOptions options;
1362
1363 bool seeking = false;
Andreas Huberafed0e12011-09-20 15:39:58 -07001364 if (seekTimeUs >= 0) {
Wei Jiac5de0912016-11-18 10:22:14 -08001365 options.setSeekTo(seekTimeUs, mode);
Andreas Huberafed0e12011-09-20 15:39:58 -07001366 seeking = true;
1367 }
1368
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001369 const bool couldReadMultiple = (track->mSource->supportReadMultiple());
Andy Hungcdeb6602016-06-28 17:21:44 -07001370
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001371 if (couldReadMultiple) {
Lajos Molnarcc227032014-07-17 15:33:06 -07001372 options.setNonBlocking();
1373 }
1374
Phil Burkc5cc2e22014-09-09 20:08:39 -07001375 for (size_t numBuffers = 0; numBuffers < maxBuffers; ) {
Wei Jia1f1fc452016-05-11 16:17:22 -07001376 Vector<MediaBuffer *> mediaBuffers;
1377 status_t err = NO_ERROR;
1378
Andy Hungcdeb6602016-06-28 17:21:44 -07001379 if (couldReadMultiple) {
1380 err = track->mSource->readMultiple(
1381 &mediaBuffers, maxBuffers - numBuffers, &options);
Wei Jia1f1fc452016-05-11 16:17:22 -07001382 } else {
1383 MediaBuffer *mbuf = NULL;
1384 err = track->mSource->read(&mbuf, &options);
1385 if (err == OK && mbuf != NULL) {
1386 mediaBuffers.push_back(mbuf);
1387 }
1388 }
Andreas Huberafed0e12011-09-20 15:39:58 -07001389
Andy Hungf59c0ba2016-06-15 17:59:30 -07001390 options.clearNonPersistent();
Andreas Huberafed0e12011-09-20 15:39:58 -07001391
Wei Jia1f1fc452016-05-11 16:17:22 -07001392 size_t id = 0;
1393 size_t count = mediaBuffers.size();
1394 for (; id < count; ++id) {
Ronghua Wu80276872014-08-28 15:50:29 -07001395 int64_t timeUs;
Wei Jia1f1fc452016-05-11 16:17:22 -07001396 MediaBuffer *mbuf = mediaBuffers[id];
Robert Shih3b9912b2016-04-07 16:56:54 -07001397 if (!mbuf->meta_data()->findInt64(kKeyTime, &timeUs)) {
1398 mbuf->meta_data()->dumpToLog();
1399 track->mPackets->signalEOS(ERROR_MALFORMED);
1400 break;
1401 }
Ronghua Wu80276872014-08-28 15:50:29 -07001402 if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
1403 mAudioTimeUs = timeUs;
Wei Jia14532f22015-12-29 11:28:15 -08001404 mBufferingMonitor->updateQueuedTime(true /* isAudio */, timeUs);
Ronghua Wu80276872014-08-28 15:50:29 -07001405 } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
1406 mVideoTimeUs = timeUs;
Wei Jia14532f22015-12-29 11:28:15 -08001407 mBufferingMonitor->updateQueuedTime(false /* isAudio */, timeUs);
Ronghua Wu80276872014-08-28 15:50:29 -07001408 }
1409
Ronghua Wu8f291bc2015-05-19 10:11:53 -07001410 queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
Andreas Huberafed0e12011-09-20 15:39:58 -07001411
Wei Jia14486822016-11-02 17:51:30 -07001412 sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType);
1413 if (numBuffers == 0 && actualTimeUs != nullptr) {
1414 *actualTimeUs = timeUs;
1415 }
1416 if (seeking && buffer != nullptr) {
1417 sp<AMessage> meta = buffer->meta();
Wei Jiac5de0912016-11-18 10:22:14 -08001418 if (meta != nullptr && mode == MediaPlayerSeekMode::SEEK_CLOSEST
1419 && seekTimeUs > timeUs) {
Wei Jia14486822016-11-02 17:51:30 -07001420 sp<AMessage> extra = new AMessage;
1421 extra->setInt64("resume-at-mediaTimeUs", seekTimeUs);
1422 meta->setMessage("extra", extra);
1423 }
1424 }
1425
Andreas Huberafed0e12011-09-20 15:39:58 -07001426 track->mPackets->queueAccessUnit(buffer);
Marco Nelissen317a49a2014-09-16 21:32:33 -07001427 formatChange = false;
1428 seeking = false;
Phil Burkc5cc2e22014-09-09 20:08:39 -07001429 ++numBuffers;
Wei Jia1f1fc452016-05-11 16:17:22 -07001430 }
1431 if (id < count) {
1432 // Error, some mediaBuffer doesn't have kKeyTime.
1433 for (; id < count; ++id) {
1434 mediaBuffers[id]->release();
1435 }
1436 break;
1437 }
1438
1439 if (err == WOULD_BLOCK) {
Lajos Molnarcc227032014-07-17 15:33:06 -07001440 break;
Andreas Huberafed0e12011-09-20 15:39:58 -07001441 } else if (err == INFO_FORMAT_CHANGED) {
1442#if 0
1443 track->mPackets->queueDiscontinuity(
Chong Zhang632740c2014-06-26 13:03:47 -07001444 ATSParser::DISCONTINUITY_FORMATCHANGE,
1445 NULL,
1446 false /* discard */);
Andreas Huberafed0e12011-09-20 15:39:58 -07001447#endif
Wei Jia1f1fc452016-05-11 16:17:22 -07001448 } else if (err != OK) {
Ronghua Wu8f291bc2015-05-19 10:11:53 -07001449 queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
Andreas Huberafed0e12011-09-20 15:39:58 -07001450 track->mPackets->signalEOS(err);
1451 break;
1452 }
1453 }
1454}
1455
Ronghua Wu8f291bc2015-05-19 10:11:53 -07001456void NuPlayer::GenericSource::queueDiscontinuityIfNeeded(
1457 bool seeking, bool formatChange, media_track_type trackType, Track *track) {
1458 // formatChange && seeking: track whose source is changed during selection
1459 // formatChange && !seeking: track whose source is not changed during selection
1460 // !formatChange: normal seek
1461 if ((seeking || formatChange)
1462 && (trackType == MEDIA_TRACK_TYPE_AUDIO
1463 || trackType == MEDIA_TRACK_TYPE_VIDEO)) {
1464 ATSParser::DiscontinuityType type = (formatChange && seeking)
1465 ? ATSParser::DISCONTINUITY_FORMATCHANGE
1466 : ATSParser::DISCONTINUITY_NONE;
1467 track->mPackets->queueDiscontinuity(type, NULL /* extra */, true /* discard */);
1468 }
1469}
1470
Wei Jia14532f22015-12-29 11:28:15 -08001471NuPlayer::GenericSource::BufferingMonitor::BufferingMonitor(const sp<AMessage> &notify)
1472 : mNotify(notify),
1473 mDurationUs(-1ll),
1474 mBitrate(-1ll),
1475 mIsStreaming(false),
1476 mAudioTimeUs(0),
1477 mVideoTimeUs(0),
1478 mPollBufferingGeneration(0),
1479 mPrepareBuffering(false),
1480 mBuffering(false),
1481 mPrevBufferPercentage(-1),
1482 mOffloadAudio(false),
1483 mFirstDequeuedBufferRealUs(-1ll),
1484 mFirstDequeuedBufferMediaUs(-1ll),
1485 mlastDequeuedBufferMediaUs(-1ll) {
Wei Jia48fa06d2016-12-20 15:30:49 -08001486 getDefaultBufferingSettings(&mSettings);
Wei Jia14532f22015-12-29 11:28:15 -08001487}
1488
1489NuPlayer::GenericSource::BufferingMonitor::~BufferingMonitor() {
1490}
1491
Wei Jia48fa06d2016-12-20 15:30:49 -08001492void NuPlayer::GenericSource::BufferingMonitor::getDefaultBufferingSettings(
1493 BufferingSettings *buffering /* nonnull */) {
1494 buffering->mInitialBufferingMode = BUFFERING_MODE_TIME_ONLY;
1495 buffering->mRebufferingMode = BUFFERING_MODE_TIME_THEN_SIZE;
1496 buffering->mInitialWatermarkMs = kHighWaterMarkMs;
1497 buffering->mRebufferingWatermarkLowMs = kLowWaterMarkMs;
1498 buffering->mRebufferingWatermarkHighMs = kHighWaterMarkRebufferMs;
1499 buffering->mRebufferingWatermarkLowKB = kLowWaterMarkKB;
1500 buffering->mRebufferingWatermarkHighKB = kHighWaterMarkKB;
Wei Jiadc6f3402017-01-09 15:04:18 -08001501
1502 ALOGV("BufferingMonitor::getDefaultBufferingSettings{%s}",
1503 buffering->toString().string());
Wei Jia48fa06d2016-12-20 15:30:49 -08001504}
1505
1506status_t NuPlayer::GenericSource::BufferingMonitor::setBufferingSettings(
1507 const BufferingSettings &buffering) {
Wei Jiadc6f3402017-01-09 15:04:18 -08001508 ALOGV("BufferingMonitor::setBufferingSettings{%s}",
1509 buffering.toString().string());
1510
Wei Jia48fa06d2016-12-20 15:30:49 -08001511 Mutex::Autolock _l(mLock);
1512 if (buffering.IsSizeBasedBufferingMode(buffering.mInitialBufferingMode)
1513 || (buffering.IsTimeBasedBufferingMode(buffering.mRebufferingMode)
1514 && buffering.mRebufferingWatermarkLowMs > buffering.mRebufferingWatermarkHighMs)
1515 || (buffering.IsSizeBasedBufferingMode(buffering.mRebufferingMode)
1516 && buffering.mRebufferingWatermarkLowKB > buffering.mRebufferingWatermarkHighKB)) {
1517 return BAD_VALUE;
1518 }
1519 mSettings = buffering;
1520 if (mSettings.mInitialBufferingMode == BUFFERING_MODE_NONE) {
1521 mSettings.mInitialWatermarkMs = BufferingSettings::kNoWatermark;
1522 }
1523 if (!mSettings.IsTimeBasedBufferingMode(mSettings.mRebufferingMode)) {
1524 mSettings.mRebufferingWatermarkLowMs = BufferingSettings::kNoWatermark;
1525 mSettings.mRebufferingWatermarkHighMs = INT32_MAX;
1526 }
1527 if (!mSettings.IsSizeBasedBufferingMode(mSettings.mRebufferingMode)) {
1528 mSettings.mRebufferingWatermarkLowKB = BufferingSettings::kNoWatermark;
1529 mSettings.mRebufferingWatermarkHighKB = INT32_MAX;
1530 }
1531 return OK;
1532}
1533
Wei Jia14532f22015-12-29 11:28:15 -08001534void NuPlayer::GenericSource::BufferingMonitor::prepare(
1535 const sp<NuCachedSource2> &cachedSource,
Wei Jia14532f22015-12-29 11:28:15 -08001536 int64_t durationUs,
1537 int64_t bitrate,
1538 bool isStreaming) {
1539 Mutex::Autolock _l(mLock);
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001540 prepare_l(cachedSource, durationUs, bitrate, isStreaming);
Wei Jia14532f22015-12-29 11:28:15 -08001541}
1542
1543void NuPlayer::GenericSource::BufferingMonitor::stop() {
1544 Mutex::Autolock _l(mLock);
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001545 prepare_l(NULL /* cachedSource */, -1 /* durationUs */,
Wei Jia14532f22015-12-29 11:28:15 -08001546 -1 /* bitrate */, false /* isStreaming */);
1547}
1548
1549void NuPlayer::GenericSource::BufferingMonitor::cancelPollBuffering() {
1550 Mutex::Autolock _l(mLock);
1551 cancelPollBuffering_l();
1552}
1553
1554void NuPlayer::GenericSource::BufferingMonitor::restartPollBuffering() {
1555 Mutex::Autolock _l(mLock);
1556 if (mIsStreaming) {
1557 cancelPollBuffering_l();
1558 onPollBuffering_l();
1559 }
1560}
1561
1562void NuPlayer::GenericSource::BufferingMonitor::stopBufferingIfNecessary() {
1563 Mutex::Autolock _l(mLock);
1564 stopBufferingIfNecessary_l();
1565}
1566
1567void NuPlayer::GenericSource::BufferingMonitor::ensureCacheIsFetching() {
1568 Mutex::Autolock _l(mLock);
1569 ensureCacheIsFetching_l();
1570}
1571
1572void NuPlayer::GenericSource::BufferingMonitor::updateQueuedTime(bool isAudio, int64_t timeUs) {
1573 Mutex::Autolock _l(mLock);
1574 if (isAudio) {
1575 mAudioTimeUs = timeUs;
1576 } else {
1577 mVideoTimeUs = timeUs;
1578 }
1579}
1580
1581void NuPlayer::GenericSource::BufferingMonitor::setOffloadAudio(bool offload) {
1582 Mutex::Autolock _l(mLock);
1583 mOffloadAudio = offload;
1584}
1585
1586void NuPlayer::GenericSource::BufferingMonitor::updateDequeuedBufferTime(int64_t mediaUs) {
1587 Mutex::Autolock _l(mLock);
1588 if (mediaUs < 0) {
1589 mFirstDequeuedBufferRealUs = -1ll;
1590 mFirstDequeuedBufferMediaUs = -1ll;
1591 } else if (mFirstDequeuedBufferRealUs < 0) {
1592 mFirstDequeuedBufferRealUs = ALooper::GetNowUs();
1593 mFirstDequeuedBufferMediaUs = mediaUs;
1594 }
1595 mlastDequeuedBufferMediaUs = mediaUs;
1596}
1597
1598void NuPlayer::GenericSource::BufferingMonitor::prepare_l(
1599 const sp<NuCachedSource2> &cachedSource,
Wei Jia14532f22015-12-29 11:28:15 -08001600 int64_t durationUs,
1601 int64_t bitrate,
1602 bool isStreaming) {
Wei Jia14532f22015-12-29 11:28:15 -08001603
1604 mCachedSource = cachedSource;
Wei Jia14532f22015-12-29 11:28:15 -08001605 mDurationUs = durationUs;
1606 mBitrate = bitrate;
1607 mIsStreaming = isStreaming;
1608 mAudioTimeUs = 0;
1609 mVideoTimeUs = 0;
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001610 mPrepareBuffering = (cachedSource != NULL);
Wei Jia14532f22015-12-29 11:28:15 -08001611 cancelPollBuffering_l();
1612 mOffloadAudio = false;
1613 mFirstDequeuedBufferRealUs = -1ll;
1614 mFirstDequeuedBufferMediaUs = -1ll;
1615 mlastDequeuedBufferMediaUs = -1ll;
1616}
1617
1618void NuPlayer::GenericSource::BufferingMonitor::cancelPollBuffering_l() {
1619 mBuffering = false;
1620 ++mPollBufferingGeneration;
1621 mPrevBufferPercentage = -1;
1622}
1623
1624void NuPlayer::GenericSource::BufferingMonitor::notifyBufferingUpdate_l(int32_t percentage) {
1625 // Buffering percent could go backward as it's estimated from remaining
1626 // data and last access time. This could cause the buffering position
1627 // drawn on media control to jitter slightly. Remember previously reported
1628 // percentage and don't allow it to go backward.
1629 if (percentage < mPrevBufferPercentage) {
1630 percentage = mPrevBufferPercentage;
1631 } else if (percentage > 100) {
1632 percentage = 100;
1633 }
1634
1635 mPrevBufferPercentage = percentage;
1636
1637 ALOGV("notifyBufferingUpdate_l: buffering %d%%", percentage);
1638
1639 sp<AMessage> msg = mNotify->dup();
1640 msg->setInt32("what", kWhatBufferingUpdate);
1641 msg->setInt32("percentage", percentage);
1642 msg->post();
1643}
1644
1645void NuPlayer::GenericSource::BufferingMonitor::startBufferingIfNecessary_l() {
Wei Jia14532f22015-12-29 11:28:15 -08001646 if (mPrepareBuffering) {
1647 return;
1648 }
1649
1650 if (!mBuffering) {
Wei Jia4d71c022016-04-26 17:18:18 -07001651 ALOGD("startBufferingIfNecessary_l");
1652
Wei Jia14532f22015-12-29 11:28:15 -08001653 mBuffering = true;
1654
1655 ensureCacheIsFetching_l();
1656 sendCacheStats_l();
1657
1658 sp<AMessage> notify = mNotify->dup();
1659 notify->setInt32("what", kWhatPauseOnBufferingStart);
1660 notify->post();
1661 }
1662}
1663
1664void NuPlayer::GenericSource::BufferingMonitor::stopBufferingIfNecessary_l() {
Wei Jia14532f22015-12-29 11:28:15 -08001665 if (mPrepareBuffering) {
Wei Jia4d71c022016-04-26 17:18:18 -07001666 ALOGD("stopBufferingIfNecessary_l, mBuffering=%d", mBuffering);
1667
Wei Jia14532f22015-12-29 11:28:15 -08001668 mPrepareBuffering = false;
1669
1670 sp<AMessage> notify = mNotify->dup();
1671 notify->setInt32("what", kWhatPrepared);
1672 notify->setInt32("err", OK);
1673 notify->post();
1674
1675 return;
1676 }
1677
1678 if (mBuffering) {
Wei Jia4d71c022016-04-26 17:18:18 -07001679 ALOGD("stopBufferingIfNecessary_l");
Wei Jia14532f22015-12-29 11:28:15 -08001680 mBuffering = false;
1681
1682 sendCacheStats_l();
1683
1684 sp<AMessage> notify = mNotify->dup();
1685 notify->setInt32("what", kWhatResumeOnBufferingEnd);
1686 notify->post();
1687 }
1688}
1689
1690void NuPlayer::GenericSource::BufferingMonitor::sendCacheStats_l() {
1691 int32_t kbps = 0;
1692 status_t err = UNKNOWN_ERROR;
1693
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001694 if (mCachedSource != NULL) {
Wei Jia14532f22015-12-29 11:28:15 -08001695 err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
1696 }
1697
1698 if (err == OK) {
1699 sp<AMessage> notify = mNotify->dup();
1700 notify->setInt32("what", kWhatCacheStats);
1701 notify->setInt32("bandwidth", kbps);
1702 notify->post();
1703 }
1704}
1705
1706void NuPlayer::GenericSource::BufferingMonitor::ensureCacheIsFetching_l() {
1707 if (mCachedSource != NULL) {
1708 mCachedSource->resumeFetchingIfNecessary();
1709 }
1710}
1711
1712void NuPlayer::GenericSource::BufferingMonitor::schedulePollBuffering_l() {
1713 sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
1714 msg->setInt32("generation", mPollBufferingGeneration);
1715 // Enquires buffering status every second.
1716 msg->post(1000000ll);
1717}
1718
1719int64_t NuPlayer::GenericSource::BufferingMonitor::getLastReadPosition_l() {
1720 if (mAudioTimeUs > 0) {
1721 return mAudioTimeUs;
1722 } else if (mVideoTimeUs > 0) {
1723 return mVideoTimeUs;
1724 } else {
1725 return 0;
1726 }
1727}
1728
1729void NuPlayer::GenericSource::BufferingMonitor::onPollBuffering_l() {
1730 status_t finalStatus = UNKNOWN_ERROR;
1731 int64_t cachedDurationUs = -1ll;
1732 ssize_t cachedDataRemaining = -1;
1733
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001734 if (mCachedSource != NULL) {
Wei Jia14532f22015-12-29 11:28:15 -08001735 cachedDataRemaining =
1736 mCachedSource->approxDataRemaining(&finalStatus);
1737
1738 if (finalStatus == OK) {
1739 off64_t size;
1740 int64_t bitrate = 0ll;
1741 if (mDurationUs > 0 && mCachedSource->getSize(&size) == OK) {
1742 // |bitrate| uses bits/second unit, while size is number of bytes.
1743 bitrate = size * 8000000ll / mDurationUs;
1744 } else if (mBitrate > 0) {
1745 bitrate = mBitrate;
1746 }
1747 if (bitrate > 0) {
1748 cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate;
1749 }
1750 }
1751 }
1752
1753 if (finalStatus != OK) {
1754 ALOGV("onPollBuffering_l: EOS (finalStatus = %d)", finalStatus);
1755
1756 if (finalStatus == ERROR_END_OF_STREAM) {
1757 notifyBufferingUpdate_l(100);
1758 }
1759
1760 stopBufferingIfNecessary_l();
1761 return;
Wei Jia48fa06d2016-12-20 15:30:49 -08001762 }
1763
1764 if (cachedDurationUs >= 0ll) {
Wei Jia14532f22015-12-29 11:28:15 -08001765 if (mDurationUs > 0ll) {
1766 int64_t cachedPosUs = getLastReadPosition_l() + cachedDurationUs;
1767 int percentage = 100.0 * cachedPosUs / mDurationUs;
1768 if (percentage > 100) {
1769 percentage = 100;
1770 }
1771
1772 notifyBufferingUpdate_l(percentage);
1773 }
1774
Wei Jia48fa06d2016-12-20 15:30:49 -08001775 ALOGV("onPollBuffering_l: cachedDurationUs %.1f sec", cachedDurationUs / 1000000.0f);
Wei Jia14532f22015-12-29 11:28:15 -08001776
Wei Jia48fa06d2016-12-20 15:30:49 -08001777 if (mPrepareBuffering) {
1778 if (cachedDurationUs > mSettings.mInitialWatermarkMs * 1000) {
1779 stopBufferingIfNecessary_l();
1780 }
1781 } else if (mSettings.IsTimeBasedBufferingMode(mSettings.mRebufferingMode)) {
1782 if (cachedDurationUs < mSettings.mRebufferingWatermarkLowMs * 1000) {
1783 // Take into account the data cached in downstream components to try to avoid
1784 // unnecessary pause.
1785 if (mOffloadAudio && mFirstDequeuedBufferRealUs >= 0) {
1786 int64_t downStreamCacheUs =
1787 mlastDequeuedBufferMediaUs - mFirstDequeuedBufferMediaUs
1788 - (ALooper::GetNowUs() - mFirstDequeuedBufferRealUs);
1789 if (downStreamCacheUs > 0) {
1790 cachedDurationUs += downStreamCacheUs;
1791 }
Wei Jia14532f22015-12-29 11:28:15 -08001792 }
Wei Jia14532f22015-12-29 11:28:15 -08001793
Wei Jia48fa06d2016-12-20 15:30:49 -08001794 if (cachedDurationUs < mSettings.mRebufferingWatermarkLowMs * 1000) {
1795 startBufferingIfNecessary_l();
1796 }
1797 } else if (cachedDurationUs > mSettings.mRebufferingWatermarkHighMs * 1000) {
Wei Jia14532f22015-12-29 11:28:15 -08001798 stopBufferingIfNecessary_l();
1799 }
1800 }
Wei Jia48fa06d2016-12-20 15:30:49 -08001801 } else if (cachedDataRemaining >= 0
1802 && mSettings.IsSizeBasedBufferingMode(mSettings.mRebufferingMode)) {
Wei Jia14532f22015-12-29 11:28:15 -08001803 ALOGV("onPollBuffering_l: cachedDataRemaining %zd bytes",
1804 cachedDataRemaining);
1805
Wei Jia48fa06d2016-12-20 15:30:49 -08001806 if (cachedDataRemaining < (mSettings.mRebufferingWatermarkLowKB << 10)) {
Wei Jia14532f22015-12-29 11:28:15 -08001807 startBufferingIfNecessary_l();
Wei Jia48fa06d2016-12-20 15:30:49 -08001808 } else if (cachedDataRemaining > (mSettings.mRebufferingWatermarkHighKB << 10)) {
Wei Jia14532f22015-12-29 11:28:15 -08001809 stopBufferingIfNecessary_l();
1810 }
1811 }
1812
1813 schedulePollBuffering_l();
1814}
1815
1816void NuPlayer::GenericSource::BufferingMonitor::onMessageReceived(const sp<AMessage> &msg) {
1817 switch (msg->what()) {
1818 case kWhatPollBuffering:
1819 {
1820 int32_t generation;
1821 CHECK(msg->findInt32("generation", &generation));
1822 Mutex::Autolock _l(mLock);
1823 if (generation == mPollBufferingGeneration) {
1824 onPollBuffering_l();
1825 }
1826 break;
1827 }
1828 default:
1829 TRESPASS();
1830 break;
1831 }
1832}
1833
Hassan Shojaniacefac142017-02-06 21:02:02 -08001834// Modular DRM
1835status_t NuPlayer::GenericSource::prepareDrm(
1836 const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId, sp<ICrypto> *crypto)
1837{
1838 ALOGV("prepareDrm");
1839
1840 sp<AMessage> msg = new AMessage(kWhatPrepareDrm, this);
1841 // synchronous call so just passing the address but with local copies of "const" args
1842 uint8_t UUID[16];
1843 memcpy(UUID, uuid, sizeof(UUID));
1844 Vector<uint8_t> sessionId = drmSessionId;
1845 msg->setPointer("uuid", (void*)UUID);
1846 msg->setPointer("drmSessionId", (void*)&sessionId);
1847 msg->setPointer("crypto", (void*)crypto);
1848
1849 sp<AMessage> response;
1850 status_t status = msg->postAndAwaitResponse(&response);
1851
1852 if (status == OK && response != NULL) {
1853 CHECK(response->findInt32("status", &status));
1854 ALOGV_IF(status == OK, "prepareDrm: mCrypto: %p (%d)", crypto->get(),
1855 (*crypto != NULL ? (*crypto)->getStrongCount() : 0));
1856 ALOGD("prepareDrm ret: %d ", status);
1857 } else {
1858 ALOGE("prepareDrm err: %d", status);
1859 }
1860
1861 return status;
1862}
1863
1864status_t NuPlayer::GenericSource::onPrepareDrm(const sp<AMessage> &msg)
1865{
1866 ALOGV("onPrepareDrm ");
1867
1868 mIsDrmProtected = false;
1869 mIsSecure = false;
1870
1871 uint8_t *uuid;
1872 Vector<uint8_t> *drmSessionId;
1873 sp<ICrypto> *outCrypto;
1874 CHECK(msg->findPointer("uuid", (void**)&uuid));
1875 CHECK(msg->findPointer("drmSessionId", (void**)&drmSessionId));
1876 CHECK(msg->findPointer("crypto", (void**)&outCrypto));
1877
1878 status_t status = OK;
1879 sp<ICrypto> crypto = NuPlayerDrm::createCryptoAndPlugin(uuid, *drmSessionId, status);
1880 if (crypto == NULL) {
1881 ALOGE("onPrepareDrm: createCrypto failed. status: %d", status);
1882 return status;
1883 }
1884 ALOGV("onPrepareDrm: createCryptoAndPlugin succeeded for uuid: %s",
1885 DrmUUID::toHexString(uuid).string());
1886
1887 *outCrypto = crypto;
1888 // as long a there is an active crypto
1889 mIsDrmProtected = true;
1890
1891 if (mMimes.size() == 0) {
1892 status = UNKNOWN_ERROR;
1893 ALOGE("onPrepareDrm: Unexpected. Must have at least one track. status: %d", status);
1894 return status;
1895 }
1896
1897 // first mime in this list is either the video track, or the first audio track
1898 const char *mime = mMimes[0].string();
1899 mIsSecure = crypto->requiresSecureDecoderComponent(mime);
1900 ALOGV("onPrepareDrm: requiresSecureDecoderComponent mime: %s isSecure: %d",
1901 mime, mIsSecure);
1902
1903 // Checking the member flags while in the looper to send out the notification.
1904 // The legacy mDecryptHandle!=NULL check (for FLAG_PROTECTED) is equivalent to mIsDrmProtected.
1905 notifyFlagsChanged(
1906 (mIsSecure ? FLAG_SECURE : 0) |
1907 (mIsDrmProtected ? FLAG_PROTECTED : 0) |
1908 FLAG_CAN_PAUSE |
1909 FLAG_CAN_SEEK_BACKWARD |
1910 FLAG_CAN_SEEK_FORWARD |
1911 FLAG_CAN_SEEK);
1912
1913 return status;
1914}
1915
1916status_t NuPlayer::GenericSource::checkDrmInfo()
1917{
1918 if (mFileMeta == NULL) {
Hassan Shojaniae7a1f6c2017-03-14 09:24:28 -07001919 ALOGI("checkDrmInfo: No metadata");
Hassan Shojaniacefac142017-02-06 21:02:02 -08001920 return OK; // letting the caller responds accordingly
1921 }
1922
1923 uint32_t type;
1924 const void *pssh;
1925 size_t psshsize;
1926
1927 if (!mFileMeta->findData(kKeyPssh, &type, &pssh, &psshsize)) {
1928 ALOGE("checkDrmInfo: No PSSH");
1929 return OK; // source without DRM info
1930 }
1931
1932 Parcel parcel;
1933 NuPlayerDrm::retrieveDrmInfo(pssh, psshsize, mMimes, &parcel);
1934 ALOGV("checkDrmInfo: MEDIA_DRM_INFO PSSH size: %d Parcel size: %d objects#: %d",
Hassan Shojania06a70812017-02-15 21:57:45 -08001935 (int)psshsize, (int)parcel.dataSize(), (int)parcel.objectsCount());
Hassan Shojaniacefac142017-02-06 21:02:02 -08001936
1937 if (parcel.dataSize() == 0) {
1938 ALOGE("checkDrmInfo: Unexpected parcel size: 0");
1939 return UNKNOWN_ERROR;
1940 }
1941
1942 // Can't pass parcel as a message to the player. Converting Parcel->ABuffer to pass it
1943 // to the Player's onSourceNotify then back to Parcel for calling driver's notifyListener.
1944 sp<ABuffer> drmInfoBuffer = ABuffer::CreateAsCopy(parcel.data(), parcel.dataSize());
1945 notifyDrmInfo(drmInfoBuffer);
1946
1947 return OK;
1948}
1949
1950void NuPlayer::GenericSource::signalBufferReturned(MediaBuffer *buffer)
1951{
1952 //ALOGV("signalBufferReturned %p refCount: %d", buffer, buffer->localRefcount());
1953
1954 buffer->setObserver(NULL);
1955 buffer->release(); // this leads to delete since that there is no observor
1956}
1957
Andreas Huberafed0e12011-09-20 15:39:58 -07001958} // namespace android