blob: 22b09d4aa4c8ddf23fe88b6390cf483696aaaaec [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>
26#include <media/IMediaExtractorService.h>
Chong Zhanga19f33e2014-08-07 15:35:07 -070027#include <media/IMediaHTTPService.h>
Andreas Huberafed0e12011-09-20 15:39:58 -070028#include <media/stagefright/foundation/ABuffer.h>
29#include <media/stagefright/foundation/ADebug.h>
30#include <media/stagefright/foundation/AMessage.h>
31#include <media/stagefright/DataSource.h>
32#include <media/stagefright/FileSource.h>
33#include <media/stagefright/MediaBuffer.h>
34#include <media/stagefright/MediaDefs.h>
35#include <media/stagefright/MediaExtractor.h>
36#include <media/stagefright/MediaSource.h>
37#include <media/stagefright/MetaData.h>
Robert Shih17f6dd62014-08-20 17:00:21 -070038#include <media/stagefright/Utils.h>
Chong Zhangd354d8d2014-08-20 13:09:58 -070039#include "../../libstagefright/include/NuCachedSource2.h"
Robert Shih360d6d02014-09-29 14:42:35 -070040#include "../../libstagefright/include/HTTPBase.h"
Andreas Huberafed0e12011-09-20 15:39:58 -070041
42namespace android {
43
Wei Jia48fa06d2016-12-20 15:30:49 -080044static const int kLowWaterMarkMs = 2000; // 2secs
45static const int kHighWaterMarkMs = 5000; // 5secs
46static const int kHighWaterMarkRebufferMs = 15000; // 15secs
47
48static const int kLowWaterMarkKB = 40;
49static const int kHighWaterMarkKB = 200;
Chong Zhangefbb6192015-01-30 17:13:27 -080050
Andreas Huberafed0e12011-09-20 15:39:58 -070051NuPlayer::GenericSource::GenericSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080052 const sp<AMessage> &notify,
Lajos Molnarcc227032014-07-17 15:33:06 -070053 bool uidValid,
54 uid_t uid)
Andreas Huberb5f25f02013-02-05 10:14:26 -080055 : Source(notify),
Robert Shih5c67ddc2014-11-04 17:46:05 -080056 mAudioTimeUs(0),
57 mAudioLastDequeueTimeUs(0),
58 mVideoTimeUs(0),
59 mVideoLastDequeueTimeUs(0),
Robert Shih3423bbd2014-07-16 15:47:09 -070060 mFetchSubtitleDataGeneration(0),
Lajos Molnare26940f2014-07-31 10:31:26 -070061 mFetchTimedTextDataGeneration(0),
Marco Nelissen02fc5e32015-05-27 11:20:41 -070062 mDurationUs(-1ll),
Lajos Molnarcc227032014-07-17 15:33:06 -070063 mAudioIsVorbis(false),
Chong Zhang42e81532014-12-01 13:44:26 -080064 mIsSecure(false),
Chong Zhangefbb6192015-01-30 17:13:27 -080065 mIsStreaming(false),
Lajos Molnarcc227032014-07-17 15:33:06 -070066 mUIDValid(uidValid),
Chong Zhangd354d8d2014-08-20 13:09:58 -070067 mUID(uid),
Chong Zhanga6bf21f2014-11-19 20:26:34 -080068 mFd(-1),
Chong Zhang2a3cc9a2014-08-21 17:48:26 -070069 mBitrate(-1ll),
Wei Jia14532f22015-12-29 11:28:15 -080070 mPendingReadBufferTypes(0) {
Hassan Shojaniacefac142017-02-06 21:02:02 -080071 ALOGV("GenericSource");
72
Wei Jia14532f22015-12-29 11:28:15 -080073 mBufferingMonitor = new BufferingMonitor(notify);
Chong Zhanga19f33e2014-08-07 15:35:07 -070074 resetDataSource();
Chong Zhang3de157d2014-08-05 20:54:44 -070075}
76
Chong Zhanga19f33e2014-08-07 15:35:07 -070077void NuPlayer::GenericSource::resetDataSource() {
Hassan Shojaniacefac142017-02-06 21:02:02 -080078 ALOGV("resetDataSource");
79
Chong Zhanga19f33e2014-08-07 15:35:07 -070080 mHTTPService.clear();
Robert Shih360d6d02014-09-29 14:42:35 -070081 mHttpSource.clear();
Chong Zhanga19f33e2014-08-07 15:35:07 -070082 mUri.clear();
83 mUriHeaders.clear();
Chong Zhanga6bf21f2014-11-19 20:26:34 -080084 if (mFd >= 0) {
85 close(mFd);
86 mFd = -1;
87 }
Chong Zhanga19f33e2014-08-07 15:35:07 -070088 mOffset = 0;
89 mLength = 0;
Ronghua Wu80276872014-08-28 15:50:29 -070090 mStarted = false;
Andy Hung2abde2c2014-09-30 14:40:32 -070091 mStopRead = true;
Wei Jia14532f22015-12-29 11:28:15 -080092
93 if (mBufferingMonitorLooper != NULL) {
94 mBufferingMonitorLooper->unregisterHandler(mBufferingMonitor->id());
95 mBufferingMonitorLooper->stop();
96 mBufferingMonitorLooper = NULL;
97 }
98 mBufferingMonitor->stop();
Hassan Shojaniacefac142017-02-06 21:02:02 -080099
100 mIsDrmProtected = false;
101 mIsSecure = false;
102 mMimes.clear();
Chong Zhanga19f33e2014-08-07 15:35:07 -0700103}
104
105status_t NuPlayer::GenericSource::setDataSource(
Chong Zhang3de157d2014-08-05 20:54:44 -0700106 const sp<IMediaHTTPService> &httpService,
107 const char *url,
108 const KeyedVector<String8, String8> *headers) {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800109 ALOGV("setDataSource url: %s", url);
110
Chong Zhanga19f33e2014-08-07 15:35:07 -0700111 resetDataSource();
Chong Zhang3de157d2014-08-05 20:54:44 -0700112
Chong Zhanga19f33e2014-08-07 15:35:07 -0700113 mHTTPService = httpService;
114 mUri = url;
Andreas Huberafed0e12011-09-20 15:39:58 -0700115
Chong Zhanga19f33e2014-08-07 15:35:07 -0700116 if (headers) {
117 mUriHeaders = *headers;
Chong Zhang3de157d2014-08-05 20:54:44 -0700118 }
119
Chong Zhanga19f33e2014-08-07 15:35:07 -0700120 // delay data source creation to prepareAsync() to avoid blocking
121 // the calling thread in setDataSource for any significant time.
122 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700123}
124
Chong Zhanga19f33e2014-08-07 15:35:07 -0700125status_t NuPlayer::GenericSource::setDataSource(
Chong Zhang3de157d2014-08-05 20:54:44 -0700126 int fd, int64_t offset, int64_t length) {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800127 ALOGV("setDataSource %d/%lld/%lld", fd, (long long)offset, (long long)length);
128
Chong Zhanga19f33e2014-08-07 15:35:07 -0700129 resetDataSource();
Andreas Huberafed0e12011-09-20 15:39:58 -0700130
Chong Zhanga19f33e2014-08-07 15:35:07 -0700131 mFd = dup(fd);
132 mOffset = offset;
133 mLength = length;
134
135 // delay data source creation to prepareAsync() to avoid blocking
136 // the calling thread in setDataSource for any significant time.
137 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700138}
139
Chris Watkins99f31602015-03-20 13:06:33 -0700140status_t NuPlayer::GenericSource::setDataSource(const sp<DataSource>& source) {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800141 ALOGV("setDataSource (source: %p)", source.get());
142
Chris Watkins99f31602015-03-20 13:06:33 -0700143 resetDataSource();
144 mDataSource = source;
145 return OK;
146}
147
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700148sp<MetaData> NuPlayer::GenericSource::getFileFormatMeta() const {
149 return mFileMeta;
150}
151
Chong Zhangd354d8d2014-08-20 13:09:58 -0700152status_t NuPlayer::GenericSource::initFromDataSource() {
Marco Nelissenb2487f02015-09-01 13:23:23 -0700153 sp<IMediaExtractor> extractor;
Chong Zhangd354d8d2014-08-20 13:09:58 -0700154 CHECK(mDataSource != NULL);
155
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700156 extractor = MediaExtractor::Create(mDataSource, NULL);
Andreas Huberafed0e12011-09-20 15:39:58 -0700157
Chong Zhang3de157d2014-08-05 20:54:44 -0700158 if (extractor == NULL) {
Wei Jia161dc692017-04-20 16:40:06 -0700159 ALOGE("initFromDataSource, cannot create extractor!");
Chong Zhang3de157d2014-08-05 20:54:44 -0700160 return UNKNOWN_ERROR;
161 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700162
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700163 mFileMeta = extractor->getMetaData();
164 if (mFileMeta != NULL) {
Marco Nelissenc1f4b2b2014-06-17 14:48:32 -0700165 int64_t duration;
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700166 if (mFileMeta->findInt64(kKeyDuration, &duration)) {
Marco Nelissenc1f4b2b2014-06-17 14:48:32 -0700167 mDurationUs = duration;
168 }
169 }
170
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700171 int32_t totalBitrate = 0;
172
Marco Nelissen705d3292014-09-19 15:14:37 -0700173 size_t numtracks = extractor->countTracks();
174 if (numtracks == 0) {
Wei Jia161dc692017-04-20 16:40:06 -0700175 ALOGE("initFromDataSource, source has no track!");
Marco Nelissen705d3292014-09-19 15:14:37 -0700176 return UNKNOWN_ERROR;
177 }
178
Hassan Shojaniacefac142017-02-06 21:02:02 -0800179 mMimes.clear();
180
Marco Nelissen705d3292014-09-19 15:14:37 -0700181 for (size_t i = 0; i < numtracks; ++i) {
Marco Nelissenb2487f02015-09-01 13:23:23 -0700182 sp<IMediaSource> track = extractor->getTrack(i);
Wei Jia0386c912015-08-28 10:35:35 -0700183 if (track == NULL) {
184 continue;
185 }
Chong Zhangafc0a872014-08-26 09:56:52 -0700186
Andreas Huberafed0e12011-09-20 15:39:58 -0700187 sp<MetaData> meta = extractor->getTrackMetaData(i);
Marco Nelissenc367ca12015-09-15 09:51:59 -0700188 if (meta == NULL) {
189 ALOGE("no metadata for track %zu", i);
190 return UNKNOWN_ERROR;
191 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700192
193 const char *mime;
194 CHECK(meta->findCString(kKeyMIMEType, &mime));
195
Hassan Shojania06a70812017-02-15 21:57:45 -0800196 ALOGV("initFromDataSource track[%zu]: %s", i, mime);
Hassan Shojaniacefac142017-02-06 21:02:02 -0800197
Chong Zhangafc0a872014-08-26 09:56:52 -0700198 // Do the string compare immediately with "mime",
199 // we can't assume "mime" would stay valid after another
200 // extractor operation, some extractors might modify meta
201 // during getTrack() and make it invalid.
Andreas Huberafed0e12011-09-20 15:39:58 -0700202 if (!strncasecmp(mime, "audio/", 6)) {
203 if (mAudioTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700204 mAudioTrack.mIndex = i;
205 mAudioTrack.mSource = track;
Robert Shihaf52c1a2014-09-11 15:38:54 -0700206 mAudioTrack.mPackets =
207 new AnotherPacketSource(mAudioTrack.mSource->getFormat());
Andreas Huberafed0e12011-09-20 15:39:58 -0700208
209 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
210 mAudioIsVorbis = true;
211 } else {
212 mAudioIsVorbis = false;
213 }
Hassan Shojaniacefac142017-02-06 21:02:02 -0800214
215 mMimes.add(String8(mime));
Andreas Huberafed0e12011-09-20 15:39:58 -0700216 }
217 } else if (!strncasecmp(mime, "video/", 6)) {
218 if (mVideoTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700219 mVideoTrack.mIndex = i;
220 mVideoTrack.mSource = track;
Robert Shihaf52c1a2014-09-11 15:38:54 -0700221 mVideoTrack.mPackets =
222 new AnotherPacketSource(mVideoTrack.mSource->getFormat());
Chong Zhang7e892182014-08-05 11:58:21 -0700223
Hassan Shojaniacefac142017-02-06 21:02:02 -0800224 // video always at the beginning
225 mMimes.insertAt(String8(mime), 0);
Andreas Huberafed0e12011-09-20 15:39:58 -0700226 }
227 }
228
Wei Jia0386c912015-08-28 10:35:35 -0700229 mSources.push(track);
230 int64_t durationUs;
231 if (meta->findInt64(kKeyDuration, &durationUs)) {
232 if (durationUs > mDurationUs) {
233 mDurationUs = durationUs;
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700234 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700235 }
Wei Jia0386c912015-08-28 10:35:35 -0700236
237 int32_t bitrate;
238 if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) {
239 totalBitrate += bitrate;
240 } else {
241 totalBitrate = -1;
242 }
243 }
244
Hassan Shojaniacefac142017-02-06 21:02:02 -0800245 ALOGV("initFromDataSource mSources.size(): %zu mIsSecure: %d mime[0]: %s", mSources.size(),
246 mIsSecure, (mMimes.isEmpty() ? "NONE" : mMimes[0].string()));
247
Wei Jia0386c912015-08-28 10:35:35 -0700248 if (mSources.size() == 0) {
249 ALOGE("b/23705695");
250 return UNKNOWN_ERROR;
Andreas Huberafed0e12011-09-20 15:39:58 -0700251 }
Chong Zhang3de157d2014-08-05 20:54:44 -0700252
Hassan Shojaniacefac142017-02-06 21:02:02 -0800253 // Modular DRM: The return value doesn't affect source initialization.
254 (void)checkDrmInfo();
255
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700256 mBitrate = totalBitrate;
257
258 return OK;
259}
260
Wei Jia48fa06d2016-12-20 15:30:49 -0800261status_t NuPlayer::GenericSource::getDefaultBufferingSettings(
262 BufferingSettings* buffering /* nonnull */) {
263 mBufferingMonitor->getDefaultBufferingSettings(buffering);
264 return OK;
265}
266
267status_t NuPlayer::GenericSource::setBufferingSettings(const BufferingSettings& buffering) {
268 return mBufferingMonitor->setBufferingSettings(buffering);
269}
270
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700271status_t NuPlayer::GenericSource::startSources() {
Chong Zhangefbb6192015-01-30 17:13:27 -0800272 // Start the selected A/V tracks now before we start buffering.
273 // Widevine sources might re-initialize crypto when starting, if we delay
274 // this to start(), all data buffered during prepare would be wasted.
275 // (We don't actually start reading until start().)
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700276 //
277 // TODO: this logic may no longer be relevant after the removal of widevine
278 // support
Chong Zhangefbb6192015-01-30 17:13:27 -0800279 if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) {
280 ALOGE("failed to start audio track!");
281 return UNKNOWN_ERROR;
282 }
283
284 if (mVideoTrack.mSource != NULL && mVideoTrack.mSource->start() != OK) {
285 ALOGE("failed to start video track!");
286 return UNKNOWN_ERROR;
287 }
288
Chong Zhang3de157d2014-08-05 20:54:44 -0700289 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700290}
291
Ronghua Wu80276872014-08-28 15:50:29 -0700292int64_t NuPlayer::GenericSource::getLastReadPosition() {
293 if (mAudioTrack.mSource != NULL) {
294 return mAudioTimeUs;
295 } else if (mVideoTrack.mSource != NULL) {
296 return mVideoTimeUs;
297 } else {
298 return 0;
299 }
300}
301
Chong Zhanga19f33e2014-08-07 15:35:07 -0700302status_t NuPlayer::GenericSource::setBuffers(
303 bool audio, Vector<MediaBuffer *> &buffers) {
Wei Jia0386c912015-08-28 10:35:35 -0700304 if (mIsSecure && !audio && mVideoTrack.mSource != NULL) {
Lajos Molnarcc227032014-07-17 15:33:06 -0700305 return mVideoTrack.mSource->setBuffers(buffers);
306 }
307 return INVALID_OPERATION;
308}
309
Ronghua Wu02cb98d2015-05-27 11:02:54 -0700310bool NuPlayer::GenericSource::isStreaming() const {
311 return mIsStreaming;
312}
313
Wei Jia14532f22015-12-29 11:28:15 -0800314void NuPlayer::GenericSource::setOffloadAudio(bool offload) {
315 mBufferingMonitor->setOffloadAudio(offload);
316}
317
Andreas Huberafed0e12011-09-20 15:39:58 -0700318NuPlayer::GenericSource::~GenericSource() {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800319 ALOGV("~GenericSource");
Chong Zhang1228d6b2014-08-12 21:25:48 -0700320 if (mLooper != NULL) {
321 mLooper->unregisterHandler(id());
322 mLooper->stop();
323 }
Chong Zhanga6bf21f2014-11-19 20:26:34 -0800324 resetDataSource();
Andreas Huberafed0e12011-09-20 15:39:58 -0700325}
326
Andreas Huber9575c962013-02-05 13:59:56 -0800327void NuPlayer::GenericSource::prepareAsync() {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800328 ALOGV("prepareAsync: (looper: %d)", (mLooper != NULL));
329
Chong Zhang1228d6b2014-08-12 21:25:48 -0700330 if (mLooper == NULL) {
331 mLooper = new ALooper;
332 mLooper->setName("generic");
333 mLooper->start();
334
335 mLooper->registerHandler(this);
336 }
337
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800338 sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this);
Chong Zhang1228d6b2014-08-12 21:25:48 -0700339 msg->post();
340}
341
342void NuPlayer::GenericSource::onPrepareAsync() {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800343 ALOGV("onPrepareAsync: mDataSource: %d", (mDataSource != NULL));
344
Chong Zhanga19f33e2014-08-07 15:35:07 -0700345 // delayed data source creation
Chong Zhangd354d8d2014-08-20 13:09:58 -0700346 if (mDataSource == NULL) {
Chong Zhang42e81532014-12-01 13:44:26 -0800347 // set to false first, if the extractor
348 // comes back as secure, set it to true then.
349 mIsSecure = false;
350
Chong Zhangd354d8d2014-08-20 13:09:58 -0700351 if (!mUri.empty()) {
Robert Shih360d6d02014-09-29 14:42:35 -0700352 const char* uri = mUri.c_str();
Chong Zhangc287cad2015-02-19 18:30:30 -0800353 String8 contentType;
Robert Shih360d6d02014-09-29 14:42:35 -0700354
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700355 if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
Robert Shih360d6d02014-09-29 14:42:35 -0700356 mHttpSource = DataSource::CreateMediaHTTP(mHTTPService);
357 if (mHttpSource == NULL) {
358 ALOGE("Failed to create http source!");
359 notifyPreparedAndCleanup(UNKNOWN_ERROR);
360 return;
361 }
362 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700363
Chong Zhangd354d8d2014-08-20 13:09:58 -0700364 mDataSource = DataSource::CreateFromURI(
Chong Zhangc287cad2015-02-19 18:30:30 -0800365 mHTTPService, uri, &mUriHeaders, &contentType,
Robert Shih360d6d02014-09-29 14:42:35 -0700366 static_cast<HTTPBase *>(mHttpSource.get()));
Chong Zhangd354d8d2014-08-20 13:09:58 -0700367 } else {
Andy Hungd49dbd62016-07-07 14:20:35 -0700368 if (property_get_bool("media.stagefright.extractremote", true) &&
369 !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
370 sp<IBinder> binder =
371 defaultServiceManager()->getService(String16("media.extractor"));
372 if (binder != nullptr) {
373 ALOGD("FileSource remote");
374 sp<IMediaExtractorService> mediaExService(
375 interface_cast<IMediaExtractorService>(binder));
376 sp<IDataSource> source =
377 mediaExService->makeIDataSource(mFd, mOffset, mLength);
378 ALOGV("IDataSource(FileSource): %p %d %lld %lld",
379 source.get(), mFd, (long long)mOffset, (long long)mLength);
380 if (source.get() != nullptr) {
381 mDataSource = DataSource::CreateFromIDataSource(source);
Andy Hung116687f2017-05-01 09:51:40 -0700382 if (mDataSource != nullptr) {
383 // Close the local file descriptor as it is not needed anymore.
384 close(mFd);
385 mFd = -1;
386 }
Andy Hungd49dbd62016-07-07 14:20:35 -0700387 } else {
388 ALOGW("extractor service cannot make data source");
389 }
390 } else {
391 ALOGW("extractor service not running");
392 }
393 }
394 if (mDataSource == nullptr) {
395 ALOGD("FileSource local");
396 mDataSource = new FileSource(mFd, mOffset, mLength);
397 }
Andy Hung116687f2017-05-01 09:51:40 -0700398 // TODO: close should always be done on mFd, see the lines following
399 // DataSource::CreateFromIDataSource above,
400 // and the FileSource constructor should dup the mFd argument as needed.
Chong Zhanga6bf21f2014-11-19 20:26:34 -0800401 mFd = -1;
Chong Zhangd354d8d2014-08-20 13:09:58 -0700402 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700403
Chong Zhangd354d8d2014-08-20 13:09:58 -0700404 if (mDataSource == NULL) {
405 ALOGE("Failed to create data source!");
406 notifyPreparedAndCleanup(UNKNOWN_ERROR);
407 return;
408 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700409 }
410
Chris Watkins99f31602015-03-20 13:06:33 -0700411 if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
412 mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
413 }
414
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700415 // For cached streaming cases, we need to wait for enough
416 // buffering before reporting prepared.
417 mIsStreaming = (mCachedSource != NULL);
Chris Watkins99f31602015-03-20 13:06:33 -0700418
Chong Zhangc287cad2015-02-19 18:30:30 -0800419 // init extractor from data source
420 status_t err = initFromDataSource();
Chong Zhanga19f33e2014-08-07 15:35:07 -0700421
422 if (err != OK) {
423 ALOGE("Failed to init from data source!");
Chong Zhangd354d8d2014-08-20 13:09:58 -0700424 notifyPreparedAndCleanup(err);
Chong Zhanga19f33e2014-08-07 15:35:07 -0700425 return;
426 }
427
Andreas Huber9575c962013-02-05 13:59:56 -0800428 if (mVideoTrack.mSource != NULL) {
Robert Shih17f6dd62014-08-20 17:00:21 -0700429 sp<MetaData> meta = doGetFormatMeta(false /* audio */);
430 sp<AMessage> msg = new AMessage;
431 err = convertMetaDataToMessage(meta, &msg);
432 if(err != OK) {
433 notifyPreparedAndCleanup(err);
434 return;
435 }
436 notifyVideoSizeChanged(msg);
Andreas Huber9575c962013-02-05 13:59:56 -0800437 }
438
439 notifyFlagsChanged(
Hassan Shojaniacefac142017-02-06 21:02:02 -0800440 // FLAG_SECURE will be known if/when prepareDrm is called by the app
441 // FLAG_PROTECTED will be known if/when prepareDrm is called by the app
442 FLAG_CAN_PAUSE |
443 FLAG_CAN_SEEK_BACKWARD |
444 FLAG_CAN_SEEK_FORWARD |
445 FLAG_CAN_SEEK);
Andreas Huber9575c962013-02-05 13:59:56 -0800446
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700447 finishPrepareAsync();
Hassan Shojaniacefac142017-02-06 21:02:02 -0800448
449 ALOGV("onPrepareAsync: Done");
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700450}
451
452void NuPlayer::GenericSource::finishPrepareAsync() {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800453 ALOGV("finishPrepareAsync");
454
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700455 status_t err = startSources();
456 if (err != OK) {
457 ALOGE("Failed to init start data source!");
458 notifyPreparedAndCleanup(err);
459 return;
460 }
461
Chong Zhangefbb6192015-01-30 17:13:27 -0800462 if (mIsStreaming) {
Wei Jia14532f22015-12-29 11:28:15 -0800463 if (mBufferingMonitorLooper == NULL) {
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700464 mBufferingMonitor->prepare(mCachedSource, mDurationUs, mBitrate,
Wei Jia14532f22015-12-29 11:28:15 -0800465 mIsStreaming);
Chong Zhangefbb6192015-01-30 17:13:27 -0800466
Wei Jia14532f22015-12-29 11:28:15 -0800467 mBufferingMonitorLooper = new ALooper;
468 mBufferingMonitorLooper->setName("GSBMonitor");
469 mBufferingMonitorLooper->start();
470 mBufferingMonitorLooper->registerHandler(mBufferingMonitor);
471 }
472
473 mBufferingMonitor->ensureCacheIsFetching();
474 mBufferingMonitor->restartPollBuffering();
Chong Zhangefbb6192015-01-30 17:13:27 -0800475 } else {
476 notifyPrepared();
477 }
Andreas Huber9575c962013-02-05 13:59:56 -0800478}
479
Chong Zhangd354d8d2014-08-20 13:09:58 -0700480void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
481 if (err != OK) {
Robert Shihebc27122015-09-02 14:02:47 -0700482 {
483 sp<DataSource> dataSource = mDataSource;
484 sp<NuCachedSource2> cachedSource = mCachedSource;
485 sp<DataSource> httpSource = mHttpSource;
486 {
487 Mutex::Autolock _l(mDisconnectLock);
488 mDataSource.clear();
489 mCachedSource.clear();
490 mHttpSource.clear();
491 }
492 }
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700493 mBitrate = -1;
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700494
Wei Jia14532f22015-12-29 11:28:15 -0800495 mBufferingMonitor->cancelPollBuffering();
Chong Zhangd354d8d2014-08-20 13:09:58 -0700496 }
497 notifyPrepared(err);
498}
499
Andreas Huberafed0e12011-09-20 15:39:58 -0700500void NuPlayer::GenericSource::start() {
501 ALOGI("start");
502
Andy Hung2abde2c2014-09-30 14:40:32 -0700503 mStopRead = false;
Andreas Huberafed0e12011-09-20 15:39:58 -0700504 if (mAudioTrack.mSource != NULL) {
Robert Shih17f6dd62014-08-20 17:00:21 -0700505 postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700506 }
507
508 if (mVideoTrack.mSource != NULL) {
Robert Shih17f6dd62014-08-20 17:00:21 -0700509 postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700510 }
Ronghua Wu80276872014-08-28 15:50:29 -0700511
Ronghua Wu80276872014-08-28 15:50:29 -0700512 mStarted = true;
Chong Zhangefbb6192015-01-30 17:13:27 -0800513
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800514 (new AMessage(kWhatStart, this))->post();
Ronghua Wu80276872014-08-28 15:50:29 -0700515}
516
517void NuPlayer::GenericSource::stop() {
Ronghua Wu80276872014-08-28 15:50:29 -0700518 mStarted = false;
519}
520
521void NuPlayer::GenericSource::pause() {
Ronghua Wu80276872014-08-28 15:50:29 -0700522 mStarted = false;
523}
524
525void NuPlayer::GenericSource::resume() {
Ronghua Wu80276872014-08-28 15:50:29 -0700526 mStarted = true;
Chong Zhangefbb6192015-01-30 17:13:27 -0800527
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800528 (new AMessage(kWhatResume, this))->post();
Ronghua Wu80276872014-08-28 15:50:29 -0700529}
530
Chong Zhang48296b72014-09-14 14:28:45 -0700531void NuPlayer::GenericSource::disconnect() {
Robert Shihebc27122015-09-02 14:02:47 -0700532 sp<DataSource> dataSource, httpSource;
533 {
534 Mutex::Autolock _l(mDisconnectLock);
535 dataSource = mDataSource;
536 httpSource = mHttpSource;
537 }
538
539 if (dataSource != NULL) {
Chong Zhang48296b72014-09-14 14:28:45 -0700540 // disconnect data source
Robert Shihebc27122015-09-02 14:02:47 -0700541 if (dataSource->flags() & DataSource::kIsCachingDataSource) {
542 static_cast<NuCachedSource2 *>(dataSource.get())->disconnect();
Chong Zhang48296b72014-09-14 14:28:45 -0700543 }
Robert Shihebc27122015-09-02 14:02:47 -0700544 } else if (httpSource != NULL) {
545 static_cast<HTTPBase *>(httpSource.get())->disconnect();
Chong Zhang48296b72014-09-14 14:28:45 -0700546 }
547}
548
Andreas Huberafed0e12011-09-20 15:39:58 -0700549status_t NuPlayer::GenericSource::feedMoreTSData() {
550 return OK;
551}
552
Robert Shih3423bbd2014-07-16 15:47:09 -0700553void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
554 switch (msg->what()) {
Chong Zhang1228d6b2014-08-12 21:25:48 -0700555 case kWhatPrepareAsync:
556 {
557 onPrepareAsync();
558 break;
559 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700560 case kWhatFetchSubtitleData:
561 {
Lajos Molnare26940f2014-07-31 10:31:26 -0700562 fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
563 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
564 break;
565 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700566
Lajos Molnare26940f2014-07-31 10:31:26 -0700567 case kWhatFetchTimedTextData:
568 {
569 fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
570 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih3423bbd2014-07-16 15:47:09 -0700571 break;
572 }
573
574 case kWhatSendSubtitleData:
575 {
Lajos Molnare26940f2014-07-31 10:31:26 -0700576 sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
577 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
578 break;
579 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700580
Marco Nelissen55e2f4c2015-09-04 15:57:15 -0700581 case kWhatSendGlobalTimedTextData:
582 {
583 sendGlobalTextData(kWhatTimedTextData, mFetchTimedTextDataGeneration, msg);
584 break;
585 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700586 case kWhatSendTimedTextData:
587 {
588 sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
589 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih3423bbd2014-07-16 15:47:09 -0700590 break;
591 }
592
593 case kWhatChangeAVSource:
594 {
595 int32_t trackIndex;
596 CHECK(msg->findInt32("trackIndex", &trackIndex));
Marco Nelissenb2487f02015-09-01 13:23:23 -0700597 const sp<IMediaSource> source = mSources.itemAt(trackIndex);
Robert Shih3423bbd2014-07-16 15:47:09 -0700598
599 Track* track;
600 const char *mime;
601 media_track_type trackType, counterpartType;
602 sp<MetaData> meta = source->getFormat();
603 meta->findCString(kKeyMIMEType, &mime);
604 if (!strncasecmp(mime, "audio/", 6)) {
605 track = &mAudioTrack;
606 trackType = MEDIA_TRACK_TYPE_AUDIO;
607 counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
608 } else {
609 CHECK(!strncasecmp(mime, "video/", 6));
610 track = &mVideoTrack;
611 trackType = MEDIA_TRACK_TYPE_VIDEO;
612 counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
613 }
614
615
616 if (track->mSource != NULL) {
617 track->mSource->stop();
618 }
619 track->mSource = source;
620 track->mSource->start();
621 track->mIndex = trackIndex;
622
Robert Shih3423bbd2014-07-16 15:47:09 -0700623 int64_t timeUs, actualTimeUs;
624 const bool formatChange = true;
Robert Shih5c67ddc2014-11-04 17:46:05 -0800625 if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
626 timeUs = mAudioLastDequeueTimeUs;
627 } else {
628 timeUs = mVideoLastDequeueTimeUs;
629 }
Wei Jiac5de0912016-11-18 10:22:14 -0800630 readBuffer(trackType, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
631 &actualTimeUs, formatChange);
632 readBuffer(counterpartType, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
633 NULL, !formatChange);
Lajos Molnar6d339f12015-04-17 16:15:53 -0700634 ALOGV("timeUs %lld actualTimeUs %lld", (long long)timeUs, (long long)actualTimeUs);
Robert Shih3423bbd2014-07-16 15:47:09 -0700635
636 break;
637 }
Chong Zhangefbb6192015-01-30 17:13:27 -0800638
639 case kWhatStart:
640 case kWhatResume:
641 {
Wei Jia14532f22015-12-29 11:28:15 -0800642 mBufferingMonitor->restartPollBuffering();
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700643 break;
644 }
Robert Shih17f6dd62014-08-20 17:00:21 -0700645
646 case kWhatGetFormat:
647 {
648 onGetFormatMeta(msg);
649 break;
650 }
651
652 case kWhatGetSelectedTrack:
653 {
654 onGetSelectedTrack(msg);
655 break;
656 }
657
qinzhichao9935bd42016-12-31 15:36:18 +0800658 case kWhatGetTrackInfo:
659 {
660 onGetTrackInfo(msg);
661 break;
662 }
663
Robert Shih17f6dd62014-08-20 17:00:21 -0700664 case kWhatSelectTrack:
665 {
666 onSelectTrack(msg);
667 break;
668 }
669
670 case kWhatSeek:
671 {
672 onSeek(msg);
673 break;
674 }
675
676 case kWhatReadBuffer:
677 {
678 onReadBuffer(msg);
679 break;
680 }
681
Hassan Shojaniacefac142017-02-06 21:02:02 -0800682 case kWhatPrepareDrm:
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700683 {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800684 status_t status = onPrepareDrm(msg);
685 sp<AMessage> response = new AMessage;
686 response->setInt32("status", status);
687 sp<AReplyToken> replyID;
688 CHECK(msg->senderAwaitsResponse(&replyID));
689 response->postReply(replyID);
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700690 break;
691 }
692
Robert Shih3423bbd2014-07-16 15:47:09 -0700693 default:
694 Source::onMessageReceived(msg);
695 break;
696 }
697}
698
Lajos Molnare26940f2014-07-31 10:31:26 -0700699void NuPlayer::GenericSource::fetchTextData(
700 uint32_t sendWhat,
701 media_track_type type,
702 int32_t curGen,
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -0700703 const sp<AnotherPacketSource>& packets,
704 const sp<AMessage>& msg) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700705 int32_t msgGeneration;
706 CHECK(msg->findInt32("generation", &msgGeneration));
707 if (msgGeneration != curGen) {
708 // stale
709 return;
710 }
711
712 int32_t avail;
713 if (packets->hasBufferAvailable(&avail)) {
714 return;
715 }
716
717 int64_t timeUs;
718 CHECK(msg->findInt64("timeUs", &timeUs));
719
720 int64_t subTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -0800721 readBuffer(type, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &subTimeUs);
Lajos Molnare26940f2014-07-31 10:31:26 -0700722
723 int64_t delayUs = subTimeUs - timeUs;
724 if (msg->what() == kWhatFetchSubtitleData) {
725 const int64_t oneSecUs = 1000000ll;
726 delayUs -= oneSecUs;
727 }
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800728 sp<AMessage> msg2 = new AMessage(sendWhat, this);
Lajos Molnare26940f2014-07-31 10:31:26 -0700729 msg2->setInt32("generation", msgGeneration);
730 msg2->post(delayUs < 0 ? 0 : delayUs);
731}
732
733void NuPlayer::GenericSource::sendTextData(
734 uint32_t what,
735 media_track_type type,
736 int32_t curGen,
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -0700737 const sp<AnotherPacketSource>& packets,
738 const sp<AMessage>& msg) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700739 int32_t msgGeneration;
740 CHECK(msg->findInt32("generation", &msgGeneration));
741 if (msgGeneration != curGen) {
742 // stale
743 return;
744 }
745
746 int64_t subTimeUs;
747 if (packets->nextBufferTime(&subTimeUs) != OK) {
748 return;
749 }
750
751 int64_t nextSubTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -0800752 readBuffer(type, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &nextSubTimeUs);
Lajos Molnare26940f2014-07-31 10:31:26 -0700753
754 sp<ABuffer> buffer;
755 status_t dequeueStatus = packets->dequeueAccessUnit(&buffer);
756 if (dequeueStatus == OK) {
757 sp<AMessage> notify = dupNotify();
758 notify->setInt32("what", what);
759 notify->setBuffer("buffer", buffer);
760 notify->post();
761
762 const int64_t delayUs = nextSubTimeUs - subTimeUs;
763 msg->post(delayUs < 0 ? 0 : delayUs);
764 }
765}
766
Marco Nelissen55e2f4c2015-09-04 15:57:15 -0700767void NuPlayer::GenericSource::sendGlobalTextData(
768 uint32_t what,
769 int32_t curGen,
770 sp<AMessage> msg) {
771 int32_t msgGeneration;
772 CHECK(msg->findInt32("generation", &msgGeneration));
773 if (msgGeneration != curGen) {
774 // stale
775 return;
776 }
777
778 uint32_t textType;
779 const void *data;
780 size_t size = 0;
781 if (mTimedTextTrack.mSource->getFormat()->findData(
782 kKeyTextFormatData, &textType, &data, &size)) {
783 mGlobalTimedText = new ABuffer(size);
784 if (mGlobalTimedText->data()) {
785 memcpy(mGlobalTimedText->data(), data, size);
786 sp<AMessage> globalMeta = mGlobalTimedText->meta();
787 globalMeta->setInt64("timeUs", 0);
788 globalMeta->setString("mime", MEDIA_MIMETYPE_TEXT_3GPP);
789 globalMeta->setInt32("global", 1);
790 sp<AMessage> notify = dupNotify();
791 notify->setInt32("what", what);
792 notify->setBuffer("buffer", mGlobalTimedText);
793 notify->post();
794 }
795 }
796}
797
Andreas Huber84066782011-08-16 09:34:26 -0700798sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800799 sp<AMessage> msg = new AMessage(kWhatGetFormat, this);
Robert Shih17f6dd62014-08-20 17:00:21 -0700800 msg->setInt32("audio", audio);
801
802 sp<AMessage> response;
Marco Nelissen10a121b2015-11-04 14:46:44 -0800803 sp<RefBase> format;
Robert Shih17f6dd62014-08-20 17:00:21 -0700804 status_t err = msg->postAndAwaitResponse(&response);
805 if (err == OK && response != NULL) {
Marco Nelissen10a121b2015-11-04 14:46:44 -0800806 CHECK(response->findObject("format", &format));
807 return static_cast<MetaData*>(format.get());
Robert Shih17f6dd62014-08-20 17:00:21 -0700808 } else {
809 return NULL;
810 }
811}
812
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -0700813void NuPlayer::GenericSource::onGetFormatMeta(const sp<AMessage>& msg) const {
Robert Shih17f6dd62014-08-20 17:00:21 -0700814 int32_t audio;
815 CHECK(msg->findInt32("audio", &audio));
816
817 sp<AMessage> response = new AMessage;
818 sp<MetaData> format = doGetFormatMeta(audio);
Marco Nelissen10a121b2015-11-04 14:46:44 -0800819 response->setObject("format", format);
Robert Shih17f6dd62014-08-20 17:00:21 -0700820
Lajos Molnar3f274362015-03-05 14:35:41 -0800821 sp<AReplyToken> replyID;
Robert Shih17f6dd62014-08-20 17:00:21 -0700822 CHECK(msg->senderAwaitsResponse(&replyID));
823 response->postReply(replyID);
824}
825
826sp<MetaData> NuPlayer::GenericSource::doGetFormatMeta(bool audio) const {
Marco Nelissenb2487f02015-09-01 13:23:23 -0700827 sp<IMediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
Andreas Huberafed0e12011-09-20 15:39:58 -0700828
829 if (source == NULL) {
830 return NULL;
831 }
832
833 return source->getFormat();
834}
835
836status_t NuPlayer::GenericSource::dequeueAccessUnit(
837 bool audio, sp<ABuffer> *accessUnit) {
Wei Jiaff486642016-04-04 16:17:39 -0700838 if (audio && !mStarted) {
Wei Jia14532f22015-12-29 11:28:15 -0800839 return -EWOULDBLOCK;
840 }
841
Andreas Huberafed0e12011-09-20 15:39:58 -0700842 Track *track = audio ? &mAudioTrack : &mVideoTrack;
843
844 if (track->mSource == NULL) {
845 return -EWOULDBLOCK;
846 }
847
848 status_t finalResult;
849 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
Chong Zhang42e81532014-12-01 13:44:26 -0800850 if (finalResult == OK) {
851 postReadBuffer(
852 audio ? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
853 return -EWOULDBLOCK;
854 }
855 return finalResult;
Andreas Huberafed0e12011-09-20 15:39:58 -0700856 }
857
858 status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
859
Chong Zhangfcf044a2015-07-14 15:58:51 -0700860 // start pulling in more buffers if we only have one (or no) buffer left
861 // so that decoder has less chance of being starved
862 if (track->mPackets->getAvailableBufferCount(&finalResult) < 2) {
Robert Shih17f6dd62014-08-20 17:00:21 -0700863 postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
Lajos Molnare26940f2014-07-31 10:31:26 -0700864 }
865
Robert Shih3423bbd2014-07-16 15:47:09 -0700866 if (result != OK) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700867 if (mSubtitleTrack.mSource != NULL) {
868 mSubtitleTrack.mPackets->clear();
869 mFetchSubtitleDataGeneration++;
870 }
871 if (mTimedTextTrack.mSource != NULL) {
872 mTimedTextTrack.mPackets->clear();
873 mFetchTimedTextDataGeneration++;
874 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700875 return result;
876 }
877
878 int64_t timeUs;
879 status_t eosResult; // ignored
880 CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
Robert Shih5c67ddc2014-11-04 17:46:05 -0800881 if (audio) {
882 mAudioLastDequeueTimeUs = timeUs;
Wei Jia14532f22015-12-29 11:28:15 -0800883 mBufferingMonitor->updateDequeuedBufferTime(timeUs);
Robert Shih5c67ddc2014-11-04 17:46:05 -0800884 } else {
885 mVideoLastDequeueTimeUs = timeUs;
886 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700887
888 if (mSubtitleTrack.mSource != NULL
889 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800890 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
Robert Shih3423bbd2014-07-16 15:47:09 -0700891 msg->setInt64("timeUs", timeUs);
892 msg->setInt32("generation", mFetchSubtitleDataGeneration);
893 msg->post();
894 }
Robert Shiheb1735e2014-07-23 15:53:14 -0700895
Lajos Molnare26940f2014-07-31 10:31:26 -0700896 if (mTimedTextTrack.mSource != NULL
897 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800898 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
Lajos Molnare26940f2014-07-31 10:31:26 -0700899 msg->setInt64("timeUs", timeUs);
900 msg->setInt32("generation", mFetchTimedTextDataGeneration);
901 msg->post();
902 }
903
Andreas Huberafed0e12011-09-20 15:39:58 -0700904 return result;
905}
906
907status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
908 *durationUs = mDurationUs;
909 return OK;
910}
911
Robert Shihdd235722014-06-12 14:49:23 -0700912size_t NuPlayer::GenericSource::getTrackCount() const {
913 return mSources.size();
914}
915
916sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const {
qinzhichao9935bd42016-12-31 15:36:18 +0800917 sp<AMessage> msg = new AMessage(kWhatGetTrackInfo, this);
918 msg->setSize("trackIndex", trackIndex);
919
920 sp<AMessage> response;
921 sp<RefBase> format;
922 status_t err = msg->postAndAwaitResponse(&response);
923 if (err == OK && response != NULL) {
924 CHECK(response->findObject("format", &format));
925 return static_cast<AMessage*>(format.get());
926 } else {
927 return NULL;
928 }
929}
930
931void NuPlayer::GenericSource::onGetTrackInfo(const sp<AMessage>& msg) const {
932 size_t trackIndex;
933 CHECK(msg->findSize("trackIndex", &trackIndex));
934
935 sp<AMessage> response = new AMessage;
936 sp<AMessage> format = doGetTrackInfo(trackIndex);
937 response->setObject("format", format);
938
939 sp<AReplyToken> replyID;
940 CHECK(msg->senderAwaitsResponse(&replyID));
941 response->postReply(replyID);
942}
943
944sp<AMessage> NuPlayer::GenericSource::doGetTrackInfo(size_t trackIndex) const {
Robert Shihdd235722014-06-12 14:49:23 -0700945 size_t trackCount = mSources.size();
946 if (trackIndex >= trackCount) {
947 return NULL;
948 }
949
950 sp<AMessage> format = new AMessage();
951 sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat();
Marco Nelissenc367ca12015-09-15 09:51:59 -0700952 if (meta == NULL) {
953 ALOGE("no metadata for track %zu", trackIndex);
954 return NULL;
955 }
Robert Shihdd235722014-06-12 14:49:23 -0700956
957 const char *mime;
958 CHECK(meta->findCString(kKeyMIMEType, &mime));
Robert Shih755106e2015-04-30 14:36:45 -0700959 format->setString("mime", mime);
Robert Shihdd235722014-06-12 14:49:23 -0700960
961 int32_t trackType;
962 if (!strncasecmp(mime, "video/", 6)) {
963 trackType = MEDIA_TRACK_TYPE_VIDEO;
964 } else if (!strncasecmp(mime, "audio/", 6)) {
965 trackType = MEDIA_TRACK_TYPE_AUDIO;
966 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
967 trackType = MEDIA_TRACK_TYPE_TIMEDTEXT;
968 } else {
969 trackType = MEDIA_TRACK_TYPE_UNKNOWN;
970 }
971 format->setInt32("type", trackType);
972
973 const char *lang;
974 if (!meta->findCString(kKeyMediaLanguage, &lang)) {
975 lang = "und";
976 }
977 format->setString("language", lang);
978
979 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
Robert Shihdd235722014-06-12 14:49:23 -0700980 int32_t isAutoselect = 1, isDefault = 0, isForced = 0;
981 meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect);
982 meta->findInt32(kKeyTrackIsDefault, &isDefault);
983 meta->findInt32(kKeyTrackIsForced, &isForced);
984
985 format->setInt32("auto", !!isAutoselect);
986 format->setInt32("default", !!isDefault);
987 format->setInt32("forced", !!isForced);
988 }
989
990 return format;
991}
992
Lajos Molnare26940f2014-07-31 10:31:26 -0700993ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800994 sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, this);
Robert Shih17f6dd62014-08-20 17:00:21 -0700995 msg->setInt32("type", type);
996
997 sp<AMessage> response;
998 int32_t index;
999 status_t err = msg->postAndAwaitResponse(&response);
1000 if (err == OK && response != NULL) {
1001 CHECK(response->findInt32("index", &index));
1002 return index;
1003 } else {
1004 return -1;
1005 }
1006}
1007
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -07001008void NuPlayer::GenericSource::onGetSelectedTrack(const sp<AMessage>& msg) const {
Robert Shih17f6dd62014-08-20 17:00:21 -07001009 int32_t tmpType;
1010 CHECK(msg->findInt32("type", &tmpType));
1011 media_track_type type = (media_track_type)tmpType;
1012
1013 sp<AMessage> response = new AMessage;
1014 ssize_t index = doGetSelectedTrack(type);
1015 response->setInt32("index", index);
1016
Lajos Molnar3f274362015-03-05 14:35:41 -08001017 sp<AReplyToken> replyID;
Robert Shih17f6dd62014-08-20 17:00:21 -07001018 CHECK(msg->senderAwaitsResponse(&replyID));
1019 response->postReply(replyID);
1020}
1021
1022ssize_t NuPlayer::GenericSource::doGetSelectedTrack(media_track_type type) const {
Lajos Molnare26940f2014-07-31 10:31:26 -07001023 const Track *track = NULL;
1024 switch (type) {
1025 case MEDIA_TRACK_TYPE_VIDEO:
1026 track = &mVideoTrack;
1027 break;
1028 case MEDIA_TRACK_TYPE_AUDIO:
1029 track = &mAudioTrack;
1030 break;
1031 case MEDIA_TRACK_TYPE_TIMEDTEXT:
1032 track = &mTimedTextTrack;
1033 break;
1034 case MEDIA_TRACK_TYPE_SUBTITLE:
1035 track = &mSubtitleTrack;
1036 break;
1037 default:
1038 break;
1039 }
1040
1041 if (track != NULL && track->mSource != NULL) {
1042 return track->mIndex;
1043 }
1044
1045 return -1;
1046}
1047
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001048status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
Lajos Molnare26940f2014-07-31 10:31:26 -07001049 ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001050 sp<AMessage> msg = new AMessage(kWhatSelectTrack, this);
Robert Shih17f6dd62014-08-20 17:00:21 -07001051 msg->setInt32("trackIndex", trackIndex);
Robert Shihda23ab92014-09-16 11:34:08 -07001052 msg->setInt32("select", select);
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001053 msg->setInt64("timeUs", timeUs);
Robert Shih17f6dd62014-08-20 17:00:21 -07001054
1055 sp<AMessage> response;
1056 status_t err = msg->postAndAwaitResponse(&response);
1057 if (err == OK && response != NULL) {
1058 CHECK(response->findInt32("err", &err));
1059 }
1060
1061 return err;
1062}
1063
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -07001064void NuPlayer::GenericSource::onSelectTrack(const sp<AMessage>& msg) {
Robert Shih17f6dd62014-08-20 17:00:21 -07001065 int32_t trackIndex, select;
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001066 int64_t timeUs;
Robert Shih17f6dd62014-08-20 17:00:21 -07001067 CHECK(msg->findInt32("trackIndex", &trackIndex));
1068 CHECK(msg->findInt32("select", &select));
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001069 CHECK(msg->findInt64("timeUs", &timeUs));
Robert Shih17f6dd62014-08-20 17:00:21 -07001070
1071 sp<AMessage> response = new AMessage;
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001072 status_t err = doSelectTrack(trackIndex, select, timeUs);
Robert Shih17f6dd62014-08-20 17:00:21 -07001073 response->setInt32("err", err);
1074
Lajos Molnar3f274362015-03-05 14:35:41 -08001075 sp<AReplyToken> replyID;
Robert Shih17f6dd62014-08-20 17:00:21 -07001076 CHECK(msg->senderAwaitsResponse(&replyID));
1077 response->postReply(replyID);
1078}
1079
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001080status_t NuPlayer::GenericSource::doSelectTrack(size_t trackIndex, bool select, int64_t timeUs) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001081 if (trackIndex >= mSources.size()) {
1082 return BAD_INDEX;
1083 }
1084
1085 if (!select) {
Lajos Molnare26940f2014-07-31 10:31:26 -07001086 Track* track = NULL;
1087 if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) {
1088 track = &mSubtitleTrack;
1089 mFetchSubtitleDataGeneration++;
1090 } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) {
1091 track = &mTimedTextTrack;
1092 mFetchTimedTextDataGeneration++;
1093 }
1094 if (track == NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001095 return INVALID_OPERATION;
1096 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001097 track->mSource->stop();
1098 track->mSource = NULL;
1099 track->mPackets->clear();
Robert Shih3423bbd2014-07-16 15:47:09 -07001100 return OK;
1101 }
1102
Marco Nelissenb2487f02015-09-01 13:23:23 -07001103 const sp<IMediaSource> source = mSources.itemAt(trackIndex);
Robert Shih3423bbd2014-07-16 15:47:09 -07001104 sp<MetaData> meta = source->getFormat();
1105 const char *mime;
1106 CHECK(meta->findCString(kKeyMIMEType, &mime));
1107 if (!strncasecmp(mime, "text/", 5)) {
Lajos Molnare26940f2014-07-31 10:31:26 -07001108 bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP);
1109 Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack;
1110 if (track->mSource != NULL && track->mIndex == trackIndex) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001111 return OK;
1112 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001113 track->mIndex = trackIndex;
1114 if (track->mSource != NULL) {
1115 track->mSource->stop();
Robert Shih3423bbd2014-07-16 15:47:09 -07001116 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001117 track->mSource = mSources.itemAt(trackIndex);
1118 track->mSource->start();
1119 if (track->mPackets == NULL) {
1120 track->mPackets = new AnotherPacketSource(track->mSource->getFormat());
Robert Shih3423bbd2014-07-16 15:47:09 -07001121 } else {
Lajos Molnare26940f2014-07-31 10:31:26 -07001122 track->mPackets->clear();
1123 track->mPackets->setFormat(track->mSource->getFormat());
Robert Shih3423bbd2014-07-16 15:47:09 -07001124
1125 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001126
1127 if (isSubtitle) {
1128 mFetchSubtitleDataGeneration++;
1129 } else {
1130 mFetchTimedTextDataGeneration++;
1131 }
1132
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001133 status_t eosResult; // ignored
1134 if (mSubtitleTrack.mSource != NULL
1135 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001136 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001137 msg->setInt64("timeUs", timeUs);
1138 msg->setInt32("generation", mFetchSubtitleDataGeneration);
1139 msg->post();
1140 }
1141
Marco Nelissen55e2f4c2015-09-04 15:57:15 -07001142 sp<AMessage> msg2 = new AMessage(kWhatSendGlobalTimedTextData, this);
1143 msg2->setInt32("generation", mFetchTimedTextDataGeneration);
1144 msg2->post();
1145
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001146 if (mTimedTextTrack.mSource != NULL
1147 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001148 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001149 msg->setInt64("timeUs", timeUs);
1150 msg->setInt32("generation", mFetchTimedTextDataGeneration);
1151 msg->post();
1152 }
1153
Robert Shih3423bbd2014-07-16 15:47:09 -07001154 return OK;
1155 } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
1156 bool audio = !strncasecmp(mime, "audio/", 6);
1157 Track *track = audio ? &mAudioTrack : &mVideoTrack;
1158 if (track->mSource != NULL && track->mIndex == trackIndex) {
1159 return OK;
1160 }
1161
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001162 sp<AMessage> msg = new AMessage(kWhatChangeAVSource, this);
Robert Shih3423bbd2014-07-16 15:47:09 -07001163 msg->setInt32("trackIndex", trackIndex);
1164 msg->post();
1165 return OK;
1166 }
1167
1168 return INVALID_OPERATION;
1169}
1170
Wei Jiac5de0912016-11-18 10:22:14 -08001171status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001172 sp<AMessage> msg = new AMessage(kWhatSeek, this);
Robert Shih17f6dd62014-08-20 17:00:21 -07001173 msg->setInt64("seekTimeUs", seekTimeUs);
Wei Jiac5de0912016-11-18 10:22:14 -08001174 msg->setInt32("mode", mode);
Robert Shih17f6dd62014-08-20 17:00:21 -07001175
1176 sp<AMessage> response;
1177 status_t err = msg->postAndAwaitResponse(&response);
1178 if (err == OK && response != NULL) {
1179 CHECK(response->findInt32("err", &err));
1180 }
1181
1182 return err;
1183}
1184
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -07001185void NuPlayer::GenericSource::onSeek(const sp<AMessage>& msg) {
Robert Shih17f6dd62014-08-20 17:00:21 -07001186 int64_t seekTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -08001187 int32_t mode;
Robert Shih17f6dd62014-08-20 17:00:21 -07001188 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
Wei Jiac5de0912016-11-18 10:22:14 -08001189 CHECK(msg->findInt32("mode", &mode));
Robert Shih17f6dd62014-08-20 17:00:21 -07001190
1191 sp<AMessage> response = new AMessage;
Wei Jiac5de0912016-11-18 10:22:14 -08001192 status_t err = doSeek(seekTimeUs, (MediaPlayerSeekMode)mode);
Robert Shih17f6dd62014-08-20 17:00:21 -07001193 response->setInt32("err", err);
1194
Lajos Molnar3f274362015-03-05 14:35:41 -08001195 sp<AReplyToken> replyID;
Robert Shih17f6dd62014-08-20 17:00:21 -07001196 CHECK(msg->senderAwaitsResponse(&replyID));
1197 response->postReply(replyID);
1198}
1199
Wei Jiac5de0912016-11-18 10:22:14 -08001200status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
Wei Jia14532f22015-12-29 11:28:15 -08001201 mBufferingMonitor->updateDequeuedBufferTime(-1ll);
1202
Andy Hung2abde2c2014-09-30 14:40:32 -07001203 // If the Widevine source is stopped, do not attempt to read any
1204 // more buffers.
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001205 //
1206 // TODO: revisit after widevine is removed. May be able to
1207 // combine mStopRead with mStarted.
Andy Hung2abde2c2014-09-30 14:40:32 -07001208 if (mStopRead) {
1209 return INVALID_OPERATION;
1210 }
Andreas Huberafed0e12011-09-20 15:39:58 -07001211 if (mVideoTrack.mSource != NULL) {
1212 int64_t actualTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -08001213 readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, mode, &actualTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -07001214
Wei Jiac5de0912016-11-18 10:22:14 -08001215 if (mode != MediaPlayerSeekMode::SEEK_CLOSEST) {
Wei Jia5ec347f2016-11-01 17:07:54 -07001216 seekTimeUs = actualTimeUs;
1217 }
1218 mVideoLastDequeueTimeUs = actualTimeUs;
Andreas Huberafed0e12011-09-20 15:39:58 -07001219 }
1220
1221 if (mAudioTrack.mSource != NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001222 readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs);
Robert Shih5c67ddc2014-11-04 17:46:05 -08001223 mAudioLastDequeueTimeUs = seekTimeUs;
Andreas Huberafed0e12011-09-20 15:39:58 -07001224 }
1225
Chong Zhangefbb6192015-01-30 17:13:27 -08001226 // If currently buffering, post kWhatBufferingEnd first, so that
1227 // NuPlayer resumes. Otherwise, if cache hits high watermark
1228 // before new polling happens, no one will resume the playback.
Wei Jia14532f22015-12-29 11:28:15 -08001229 mBufferingMonitor->stopBufferingIfNecessary();
1230 mBufferingMonitor->restartPollBuffering();
Chong Zhangefbb6192015-01-30 17:13:27 -08001231
Andreas Huberafed0e12011-09-20 15:39:58 -07001232 return OK;
1233}
1234
Robert Shih3423bbd2014-07-16 15:47:09 -07001235sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
1236 MediaBuffer* mb,
Wei Jia14486822016-11-02 17:51:30 -07001237 media_track_type trackType) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001238 bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
1239 size_t outLength = mb->range_length();
1240
1241 if (audio && mAudioIsVorbis) {
1242 outLength += sizeof(int32_t);
1243 }
1244
1245 sp<ABuffer> ab;
Hassan Shojaniacefac142017-02-06 21:02:02 -08001246
1247 if (mIsDrmProtected) {
1248 // Modular DRM
1249 // Enabled for both video/audio so 1) media buffer is reused without extra copying
1250 // 2) meta data can be retrieved in onInputBufferFetched for calling queueSecureInputBuffer.
1251
Robert Shih3423bbd2014-07-16 15:47:09 -07001252 // data is already provided in the buffer
1253 ab = new ABuffer(NULL, mb->range_length());
Robert Shih3423bbd2014-07-16 15:47:09 -07001254 mb->add_ref();
Wei Jia96e92b52014-09-18 17:36:20 -07001255 ab->setMediaBufferBase(mb);
Hassan Shojaniacefac142017-02-06 21:02:02 -08001256
1257 // Modular DRM: Required b/c of the above add_ref.
1258 // If ref>0, there must be an observer, or it'll crash at release().
1259 // TODO: MediaBuffer might need to be revised to ease such need.
1260 mb->setObserver(this);
1261 // setMediaBufferBase() interestingly doesn't increment the ref count on its own.
1262 // Extra increment (since we want to keep mb alive and attached to ab beyond this function
1263 // call. This is to counter the effect of mb->release() towards the end.
1264 mb->add_ref();
1265
Robert Shih3423bbd2014-07-16 15:47:09 -07001266 } else {
1267 ab = new ABuffer(outLength);
1268 memcpy(ab->data(),
1269 (const uint8_t *)mb->data() + mb->range_offset(),
1270 mb->range_length());
1271 }
1272
1273 if (audio && mAudioIsVorbis) {
1274 int32_t numPageSamples;
1275 if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
1276 numPageSamples = -1;
1277 }
1278
1279 uint8_t* abEnd = ab->data() + mb->range_length();
1280 memcpy(abEnd, &numPageSamples, sizeof(numPageSamples));
1281 }
1282
Lajos Molnare26940f2014-07-31 10:31:26 -07001283 sp<AMessage> meta = ab->meta();
1284
Robert Shih3423bbd2014-07-16 15:47:09 -07001285 int64_t timeUs;
1286 CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs));
Robert Shih3423bbd2014-07-16 15:47:09 -07001287 meta->setInt64("timeUs", timeUs);
1288
Praveen Chavanbbaa1442016-04-08 13:33:49 -07001289 if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
1290 int32_t layerId;
1291 if (mb->meta_data()->findInt32(kKeyTemporalLayerId, &layerId)) {
1292 meta->setInt32("temporal-layer-id", layerId);
1293 }
1294 }
1295
Lajos Molnare26940f2014-07-31 10:31:26 -07001296 if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
1297 const char *mime;
1298 CHECK(mTimedTextTrack.mSource != NULL
1299 && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime));
1300 meta->setString("mime", mime);
1301 }
1302
Robert Shih3423bbd2014-07-16 15:47:09 -07001303 int64_t durationUs;
1304 if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) {
1305 meta->setInt64("durationUs", durationUs);
1306 }
1307
1308 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
1309 meta->setInt32("trackIndex", mSubtitleTrack.mIndex);
1310 }
1311
Robert Shihf8bd8512015-04-23 16:39:18 -07001312 uint32_t dataType; // unused
1313 const void *seiData;
1314 size_t seiLength;
1315 if (mb->meta_data()->findData(kKeySEI, &dataType, &seiData, &seiLength)) {
1316 sp<ABuffer> sei = ABuffer::CreateAsCopy(seiData, seiLength);;
1317 meta->setBuffer("sei", sei);
1318 }
1319
Jaesung Chung3694d7c2015-10-21 11:41:38 +09001320 const void *mpegUserDataPointer;
1321 size_t mpegUserDataLength;
1322 if (mb->meta_data()->findData(
1323 kKeyMpegUserData, &dataType, &mpegUserDataPointer, &mpegUserDataLength)) {
1324 sp<ABuffer> mpegUserData = ABuffer::CreateAsCopy(mpegUserDataPointer, mpegUserDataLength);
1325 meta->setBuffer("mpegUserData", mpegUserData);
1326 }
1327
Robert Shih3423bbd2014-07-16 15:47:09 -07001328 mb->release();
1329 mb = NULL;
1330
1331 return ab;
1332}
1333
Robert Shih17f6dd62014-08-20 17:00:21 -07001334void NuPlayer::GenericSource::postReadBuffer(media_track_type trackType) {
Lajos Molnar84f52782014-09-11 10:01:55 -07001335 Mutex::Autolock _l(mReadBufferLock);
1336
1337 if ((mPendingReadBufferTypes & (1 << trackType)) == 0) {
1338 mPendingReadBufferTypes |= (1 << trackType);
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001339 sp<AMessage> msg = new AMessage(kWhatReadBuffer, this);
Lajos Molnar84f52782014-09-11 10:01:55 -07001340 msg->setInt32("trackType", trackType);
1341 msg->post();
1342 }
Robert Shih17f6dd62014-08-20 17:00:21 -07001343}
1344
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -07001345void NuPlayer::GenericSource::onReadBuffer(const sp<AMessage>& msg) {
Robert Shih17f6dd62014-08-20 17:00:21 -07001346 int32_t tmpType;
1347 CHECK(msg->findInt32("trackType", &tmpType));
1348 media_track_type trackType = (media_track_type)tmpType;
Chong Zhang42e81532014-12-01 13:44:26 -08001349 readBuffer(trackType);
Lajos Molnar84f52782014-09-11 10:01:55 -07001350 {
1351 // only protect the variable change, as readBuffer may
Chong Zhang42e81532014-12-01 13:44:26 -08001352 // take considerable time.
Lajos Molnar84f52782014-09-11 10:01:55 -07001353 Mutex::Autolock _l(mReadBufferLock);
1354 mPendingReadBufferTypes &= ~(1 << trackType);
1355 }
Robert Shih17f6dd62014-08-20 17:00:21 -07001356}
1357
Andreas Huberafed0e12011-09-20 15:39:58 -07001358void NuPlayer::GenericSource::readBuffer(
Wei Jiac5de0912016-11-18 10:22:14 -08001359 media_track_type trackType, int64_t seekTimeUs, MediaPlayerSeekMode mode,
Wei Jia5ec347f2016-11-01 17:07:54 -07001360 int64_t *actualTimeUs, bool formatChange) {
Andy Hung2abde2c2014-09-30 14:40:32 -07001361 // Do not read data if Widevine source is stopped
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001362 //
1363 // TODO: revisit after widevine is removed. May be able to
1364 // combine mStopRead with mStarted.
Andy Hung2abde2c2014-09-30 14:40:32 -07001365 if (mStopRead) {
1366 return;
1367 }
Robert Shih3423bbd2014-07-16 15:47:09 -07001368 Track *track;
Phil Burkc5cc2e22014-09-09 20:08:39 -07001369 size_t maxBuffers = 1;
Robert Shih3423bbd2014-07-16 15:47:09 -07001370 switch (trackType) {
1371 case MEDIA_TRACK_TYPE_VIDEO:
1372 track = &mVideoTrack;
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001373 maxBuffers = 8; // too large of a number may influence seeks
Robert Shih3423bbd2014-07-16 15:47:09 -07001374 break;
1375 case MEDIA_TRACK_TYPE_AUDIO:
1376 track = &mAudioTrack;
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001377 maxBuffers = 64;
Robert Shih3423bbd2014-07-16 15:47:09 -07001378 break;
1379 case MEDIA_TRACK_TYPE_SUBTITLE:
1380 track = &mSubtitleTrack;
1381 break;
Lajos Molnare26940f2014-07-31 10:31:26 -07001382 case MEDIA_TRACK_TYPE_TIMEDTEXT:
1383 track = &mTimedTextTrack;
1384 break;
Robert Shih3423bbd2014-07-16 15:47:09 -07001385 default:
1386 TRESPASS();
1387 }
1388
1389 if (track->mSource == NULL) {
1390 return;
1391 }
Andreas Huberafed0e12011-09-20 15:39:58 -07001392
1393 if (actualTimeUs) {
1394 *actualTimeUs = seekTimeUs;
1395 }
1396
1397 MediaSource::ReadOptions options;
1398
1399 bool seeking = false;
Andreas Huberafed0e12011-09-20 15:39:58 -07001400 if (seekTimeUs >= 0) {
Wei Jiac5de0912016-11-18 10:22:14 -08001401 options.setSeekTo(seekTimeUs, mode);
Andreas Huberafed0e12011-09-20 15:39:58 -07001402 seeking = true;
1403 }
1404
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001405 const bool couldReadMultiple = (track->mSource->supportReadMultiple());
Andy Hungcdeb6602016-06-28 17:21:44 -07001406
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001407 if (couldReadMultiple) {
Lajos Molnarcc227032014-07-17 15:33:06 -07001408 options.setNonBlocking();
1409 }
1410
Phil Burkc5cc2e22014-09-09 20:08:39 -07001411 for (size_t numBuffers = 0; numBuffers < maxBuffers; ) {
Wei Jia1f1fc452016-05-11 16:17:22 -07001412 Vector<MediaBuffer *> mediaBuffers;
1413 status_t err = NO_ERROR;
1414
Andy Hungcdeb6602016-06-28 17:21:44 -07001415 if (couldReadMultiple) {
1416 err = track->mSource->readMultiple(
1417 &mediaBuffers, maxBuffers - numBuffers, &options);
Wei Jia1f1fc452016-05-11 16:17:22 -07001418 } else {
1419 MediaBuffer *mbuf = NULL;
1420 err = track->mSource->read(&mbuf, &options);
1421 if (err == OK && mbuf != NULL) {
1422 mediaBuffers.push_back(mbuf);
1423 }
1424 }
Andreas Huberafed0e12011-09-20 15:39:58 -07001425
Andy Hungf59c0ba2016-06-15 17:59:30 -07001426 options.clearNonPersistent();
Andreas Huberafed0e12011-09-20 15:39:58 -07001427
Wei Jia1f1fc452016-05-11 16:17:22 -07001428 size_t id = 0;
1429 size_t count = mediaBuffers.size();
1430 for (; id < count; ++id) {
Ronghua Wu80276872014-08-28 15:50:29 -07001431 int64_t timeUs;
Wei Jia1f1fc452016-05-11 16:17:22 -07001432 MediaBuffer *mbuf = mediaBuffers[id];
Robert Shih3b9912b2016-04-07 16:56:54 -07001433 if (!mbuf->meta_data()->findInt64(kKeyTime, &timeUs)) {
1434 mbuf->meta_data()->dumpToLog();
1435 track->mPackets->signalEOS(ERROR_MALFORMED);
1436 break;
1437 }
Ronghua Wu80276872014-08-28 15:50:29 -07001438 if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
1439 mAudioTimeUs = timeUs;
Wei Jia14532f22015-12-29 11:28:15 -08001440 mBufferingMonitor->updateQueuedTime(true /* isAudio */, timeUs);
Ronghua Wu80276872014-08-28 15:50:29 -07001441 } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
1442 mVideoTimeUs = timeUs;
Wei Jia14532f22015-12-29 11:28:15 -08001443 mBufferingMonitor->updateQueuedTime(false /* isAudio */, timeUs);
Ronghua Wu80276872014-08-28 15:50:29 -07001444 }
1445
Ronghua Wu8f291bc2015-05-19 10:11:53 -07001446 queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
Andreas Huberafed0e12011-09-20 15:39:58 -07001447
Wei Jia14486822016-11-02 17:51:30 -07001448 sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType);
1449 if (numBuffers == 0 && actualTimeUs != nullptr) {
1450 *actualTimeUs = timeUs;
1451 }
1452 if (seeking && buffer != nullptr) {
1453 sp<AMessage> meta = buffer->meta();
Wei Jiac5de0912016-11-18 10:22:14 -08001454 if (meta != nullptr && mode == MediaPlayerSeekMode::SEEK_CLOSEST
1455 && seekTimeUs > timeUs) {
Wei Jia14486822016-11-02 17:51:30 -07001456 sp<AMessage> extra = new AMessage;
1457 extra->setInt64("resume-at-mediaTimeUs", seekTimeUs);
1458 meta->setMessage("extra", extra);
1459 }
1460 }
1461
Andreas Huberafed0e12011-09-20 15:39:58 -07001462 track->mPackets->queueAccessUnit(buffer);
Marco Nelissen317a49a2014-09-16 21:32:33 -07001463 formatChange = false;
1464 seeking = false;
Phil Burkc5cc2e22014-09-09 20:08:39 -07001465 ++numBuffers;
Wei Jia1f1fc452016-05-11 16:17:22 -07001466 }
1467 if (id < count) {
1468 // Error, some mediaBuffer doesn't have kKeyTime.
1469 for (; id < count; ++id) {
1470 mediaBuffers[id]->release();
1471 }
1472 break;
1473 }
1474
1475 if (err == WOULD_BLOCK) {
Lajos Molnarcc227032014-07-17 15:33:06 -07001476 break;
Andreas Huberafed0e12011-09-20 15:39:58 -07001477 } else if (err == INFO_FORMAT_CHANGED) {
1478#if 0
1479 track->mPackets->queueDiscontinuity(
Chong Zhang632740c2014-06-26 13:03:47 -07001480 ATSParser::DISCONTINUITY_FORMATCHANGE,
1481 NULL,
1482 false /* discard */);
Andreas Huberafed0e12011-09-20 15:39:58 -07001483#endif
Wei Jia1f1fc452016-05-11 16:17:22 -07001484 } else if (err != OK) {
Ronghua Wu8f291bc2015-05-19 10:11:53 -07001485 queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
Andreas Huberafed0e12011-09-20 15:39:58 -07001486 track->mPackets->signalEOS(err);
1487 break;
1488 }
1489 }
1490}
1491
Ronghua Wu8f291bc2015-05-19 10:11:53 -07001492void NuPlayer::GenericSource::queueDiscontinuityIfNeeded(
1493 bool seeking, bool formatChange, media_track_type trackType, Track *track) {
1494 // formatChange && seeking: track whose source is changed during selection
1495 // formatChange && !seeking: track whose source is not changed during selection
1496 // !formatChange: normal seek
1497 if ((seeking || formatChange)
1498 && (trackType == MEDIA_TRACK_TYPE_AUDIO
1499 || trackType == MEDIA_TRACK_TYPE_VIDEO)) {
1500 ATSParser::DiscontinuityType type = (formatChange && seeking)
1501 ? ATSParser::DISCONTINUITY_FORMATCHANGE
1502 : ATSParser::DISCONTINUITY_NONE;
1503 track->mPackets->queueDiscontinuity(type, NULL /* extra */, true /* discard */);
1504 }
1505}
1506
Wei Jia14532f22015-12-29 11:28:15 -08001507NuPlayer::GenericSource::BufferingMonitor::BufferingMonitor(const sp<AMessage> &notify)
1508 : mNotify(notify),
1509 mDurationUs(-1ll),
1510 mBitrate(-1ll),
1511 mIsStreaming(false),
1512 mAudioTimeUs(0),
1513 mVideoTimeUs(0),
1514 mPollBufferingGeneration(0),
1515 mPrepareBuffering(false),
1516 mBuffering(false),
1517 mPrevBufferPercentage(-1),
1518 mOffloadAudio(false),
1519 mFirstDequeuedBufferRealUs(-1ll),
1520 mFirstDequeuedBufferMediaUs(-1ll),
1521 mlastDequeuedBufferMediaUs(-1ll) {
Wei Jia48fa06d2016-12-20 15:30:49 -08001522 getDefaultBufferingSettings(&mSettings);
Wei Jia14532f22015-12-29 11:28:15 -08001523}
1524
1525NuPlayer::GenericSource::BufferingMonitor::~BufferingMonitor() {
1526}
1527
Wei Jia48fa06d2016-12-20 15:30:49 -08001528void NuPlayer::GenericSource::BufferingMonitor::getDefaultBufferingSettings(
1529 BufferingSettings *buffering /* nonnull */) {
1530 buffering->mInitialBufferingMode = BUFFERING_MODE_TIME_ONLY;
1531 buffering->mRebufferingMode = BUFFERING_MODE_TIME_THEN_SIZE;
1532 buffering->mInitialWatermarkMs = kHighWaterMarkMs;
1533 buffering->mRebufferingWatermarkLowMs = kLowWaterMarkMs;
1534 buffering->mRebufferingWatermarkHighMs = kHighWaterMarkRebufferMs;
1535 buffering->mRebufferingWatermarkLowKB = kLowWaterMarkKB;
1536 buffering->mRebufferingWatermarkHighKB = kHighWaterMarkKB;
Wei Jiadc6f3402017-01-09 15:04:18 -08001537
1538 ALOGV("BufferingMonitor::getDefaultBufferingSettings{%s}",
1539 buffering->toString().string());
Wei Jia48fa06d2016-12-20 15:30:49 -08001540}
1541
1542status_t NuPlayer::GenericSource::BufferingMonitor::setBufferingSettings(
1543 const BufferingSettings &buffering) {
Wei Jiadc6f3402017-01-09 15:04:18 -08001544 ALOGV("BufferingMonitor::setBufferingSettings{%s}",
1545 buffering.toString().string());
1546
Wei Jia48fa06d2016-12-20 15:30:49 -08001547 Mutex::Autolock _l(mLock);
1548 if (buffering.IsSizeBasedBufferingMode(buffering.mInitialBufferingMode)
1549 || (buffering.IsTimeBasedBufferingMode(buffering.mRebufferingMode)
1550 && buffering.mRebufferingWatermarkLowMs > buffering.mRebufferingWatermarkHighMs)
1551 || (buffering.IsSizeBasedBufferingMode(buffering.mRebufferingMode)
1552 && buffering.mRebufferingWatermarkLowKB > buffering.mRebufferingWatermarkHighKB)) {
1553 return BAD_VALUE;
1554 }
1555 mSettings = buffering;
1556 if (mSettings.mInitialBufferingMode == BUFFERING_MODE_NONE) {
1557 mSettings.mInitialWatermarkMs = BufferingSettings::kNoWatermark;
1558 }
1559 if (!mSettings.IsTimeBasedBufferingMode(mSettings.mRebufferingMode)) {
1560 mSettings.mRebufferingWatermarkLowMs = BufferingSettings::kNoWatermark;
1561 mSettings.mRebufferingWatermarkHighMs = INT32_MAX;
1562 }
1563 if (!mSettings.IsSizeBasedBufferingMode(mSettings.mRebufferingMode)) {
1564 mSettings.mRebufferingWatermarkLowKB = BufferingSettings::kNoWatermark;
1565 mSettings.mRebufferingWatermarkHighKB = INT32_MAX;
1566 }
1567 return OK;
1568}
1569
Wei Jia14532f22015-12-29 11:28:15 -08001570void NuPlayer::GenericSource::BufferingMonitor::prepare(
1571 const sp<NuCachedSource2> &cachedSource,
Wei Jia14532f22015-12-29 11:28:15 -08001572 int64_t durationUs,
1573 int64_t bitrate,
1574 bool isStreaming) {
1575 Mutex::Autolock _l(mLock);
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001576 prepare_l(cachedSource, durationUs, bitrate, isStreaming);
Wei Jia14532f22015-12-29 11:28:15 -08001577}
1578
1579void NuPlayer::GenericSource::BufferingMonitor::stop() {
1580 Mutex::Autolock _l(mLock);
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001581 prepare_l(NULL /* cachedSource */, -1 /* durationUs */,
Wei Jia14532f22015-12-29 11:28:15 -08001582 -1 /* bitrate */, false /* isStreaming */);
1583}
1584
1585void NuPlayer::GenericSource::BufferingMonitor::cancelPollBuffering() {
1586 Mutex::Autolock _l(mLock);
1587 cancelPollBuffering_l();
1588}
1589
1590void NuPlayer::GenericSource::BufferingMonitor::restartPollBuffering() {
1591 Mutex::Autolock _l(mLock);
1592 if (mIsStreaming) {
1593 cancelPollBuffering_l();
1594 onPollBuffering_l();
1595 }
1596}
1597
1598void NuPlayer::GenericSource::BufferingMonitor::stopBufferingIfNecessary() {
1599 Mutex::Autolock _l(mLock);
1600 stopBufferingIfNecessary_l();
1601}
1602
1603void NuPlayer::GenericSource::BufferingMonitor::ensureCacheIsFetching() {
1604 Mutex::Autolock _l(mLock);
1605 ensureCacheIsFetching_l();
1606}
1607
1608void NuPlayer::GenericSource::BufferingMonitor::updateQueuedTime(bool isAudio, int64_t timeUs) {
1609 Mutex::Autolock _l(mLock);
1610 if (isAudio) {
1611 mAudioTimeUs = timeUs;
1612 } else {
1613 mVideoTimeUs = timeUs;
1614 }
1615}
1616
1617void NuPlayer::GenericSource::BufferingMonitor::setOffloadAudio(bool offload) {
1618 Mutex::Autolock _l(mLock);
1619 mOffloadAudio = offload;
1620}
1621
1622void NuPlayer::GenericSource::BufferingMonitor::updateDequeuedBufferTime(int64_t mediaUs) {
1623 Mutex::Autolock _l(mLock);
1624 if (mediaUs < 0) {
1625 mFirstDequeuedBufferRealUs = -1ll;
1626 mFirstDequeuedBufferMediaUs = -1ll;
1627 } else if (mFirstDequeuedBufferRealUs < 0) {
1628 mFirstDequeuedBufferRealUs = ALooper::GetNowUs();
1629 mFirstDequeuedBufferMediaUs = mediaUs;
1630 }
1631 mlastDequeuedBufferMediaUs = mediaUs;
1632}
1633
1634void NuPlayer::GenericSource::BufferingMonitor::prepare_l(
1635 const sp<NuCachedSource2> &cachedSource,
Wei Jia14532f22015-12-29 11:28:15 -08001636 int64_t durationUs,
1637 int64_t bitrate,
1638 bool isStreaming) {
Wei Jia14532f22015-12-29 11:28:15 -08001639
1640 mCachedSource = cachedSource;
Wei Jia14532f22015-12-29 11:28:15 -08001641 mDurationUs = durationUs;
1642 mBitrate = bitrate;
1643 mIsStreaming = isStreaming;
1644 mAudioTimeUs = 0;
1645 mVideoTimeUs = 0;
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001646 mPrepareBuffering = (cachedSource != NULL);
Wei Jia14532f22015-12-29 11:28:15 -08001647 cancelPollBuffering_l();
1648 mOffloadAudio = false;
1649 mFirstDequeuedBufferRealUs = -1ll;
1650 mFirstDequeuedBufferMediaUs = -1ll;
1651 mlastDequeuedBufferMediaUs = -1ll;
1652}
1653
1654void NuPlayer::GenericSource::BufferingMonitor::cancelPollBuffering_l() {
1655 mBuffering = false;
1656 ++mPollBufferingGeneration;
1657 mPrevBufferPercentage = -1;
1658}
1659
1660void NuPlayer::GenericSource::BufferingMonitor::notifyBufferingUpdate_l(int32_t percentage) {
1661 // Buffering percent could go backward as it's estimated from remaining
1662 // data and last access time. This could cause the buffering position
1663 // drawn on media control to jitter slightly. Remember previously reported
1664 // percentage and don't allow it to go backward.
1665 if (percentage < mPrevBufferPercentage) {
1666 percentage = mPrevBufferPercentage;
1667 } else if (percentage > 100) {
1668 percentage = 100;
1669 }
1670
1671 mPrevBufferPercentage = percentage;
1672
1673 ALOGV("notifyBufferingUpdate_l: buffering %d%%", percentage);
1674
1675 sp<AMessage> msg = mNotify->dup();
1676 msg->setInt32("what", kWhatBufferingUpdate);
1677 msg->setInt32("percentage", percentage);
1678 msg->post();
1679}
1680
1681void NuPlayer::GenericSource::BufferingMonitor::startBufferingIfNecessary_l() {
Wei Jia14532f22015-12-29 11:28:15 -08001682 if (mPrepareBuffering) {
1683 return;
1684 }
1685
1686 if (!mBuffering) {
Wei Jia4d71c022016-04-26 17:18:18 -07001687 ALOGD("startBufferingIfNecessary_l");
1688
Wei Jia14532f22015-12-29 11:28:15 -08001689 mBuffering = true;
1690
1691 ensureCacheIsFetching_l();
1692 sendCacheStats_l();
1693
1694 sp<AMessage> notify = mNotify->dup();
1695 notify->setInt32("what", kWhatPauseOnBufferingStart);
1696 notify->post();
1697 }
1698}
1699
1700void NuPlayer::GenericSource::BufferingMonitor::stopBufferingIfNecessary_l() {
Wei Jia14532f22015-12-29 11:28:15 -08001701 if (mPrepareBuffering) {
Wei Jia4d71c022016-04-26 17:18:18 -07001702 ALOGD("stopBufferingIfNecessary_l, mBuffering=%d", mBuffering);
1703
Wei Jia14532f22015-12-29 11:28:15 -08001704 mPrepareBuffering = false;
1705
1706 sp<AMessage> notify = mNotify->dup();
1707 notify->setInt32("what", kWhatPrepared);
1708 notify->setInt32("err", OK);
1709 notify->post();
1710
1711 return;
1712 }
1713
1714 if (mBuffering) {
Wei Jia4d71c022016-04-26 17:18:18 -07001715 ALOGD("stopBufferingIfNecessary_l");
Wei Jia14532f22015-12-29 11:28:15 -08001716 mBuffering = false;
1717
1718 sendCacheStats_l();
1719
1720 sp<AMessage> notify = mNotify->dup();
1721 notify->setInt32("what", kWhatResumeOnBufferingEnd);
1722 notify->post();
1723 }
1724}
1725
1726void NuPlayer::GenericSource::BufferingMonitor::sendCacheStats_l() {
1727 int32_t kbps = 0;
1728 status_t err = UNKNOWN_ERROR;
1729
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001730 if (mCachedSource != NULL) {
Wei Jia14532f22015-12-29 11:28:15 -08001731 err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
1732 }
1733
1734 if (err == OK) {
1735 sp<AMessage> notify = mNotify->dup();
1736 notify->setInt32("what", kWhatCacheStats);
1737 notify->setInt32("bandwidth", kbps);
1738 notify->post();
1739 }
1740}
1741
1742void NuPlayer::GenericSource::BufferingMonitor::ensureCacheIsFetching_l() {
1743 if (mCachedSource != NULL) {
1744 mCachedSource->resumeFetchingIfNecessary();
1745 }
1746}
1747
1748void NuPlayer::GenericSource::BufferingMonitor::schedulePollBuffering_l() {
1749 sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
1750 msg->setInt32("generation", mPollBufferingGeneration);
1751 // Enquires buffering status every second.
1752 msg->post(1000000ll);
1753}
1754
1755int64_t NuPlayer::GenericSource::BufferingMonitor::getLastReadPosition_l() {
1756 if (mAudioTimeUs > 0) {
1757 return mAudioTimeUs;
1758 } else if (mVideoTimeUs > 0) {
1759 return mVideoTimeUs;
1760 } else {
1761 return 0;
1762 }
1763}
1764
1765void NuPlayer::GenericSource::BufferingMonitor::onPollBuffering_l() {
1766 status_t finalStatus = UNKNOWN_ERROR;
1767 int64_t cachedDurationUs = -1ll;
1768 ssize_t cachedDataRemaining = -1;
1769
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001770 if (mCachedSource != NULL) {
Wei Jia14532f22015-12-29 11:28:15 -08001771 cachedDataRemaining =
1772 mCachedSource->approxDataRemaining(&finalStatus);
1773
1774 if (finalStatus == OK) {
1775 off64_t size;
1776 int64_t bitrate = 0ll;
1777 if (mDurationUs > 0 && mCachedSource->getSize(&size) == OK) {
1778 // |bitrate| uses bits/second unit, while size is number of bytes.
1779 bitrate = size * 8000000ll / mDurationUs;
1780 } else if (mBitrate > 0) {
1781 bitrate = mBitrate;
1782 }
1783 if (bitrate > 0) {
1784 cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate;
1785 }
1786 }
1787 }
1788
1789 if (finalStatus != OK) {
1790 ALOGV("onPollBuffering_l: EOS (finalStatus = %d)", finalStatus);
1791
1792 if (finalStatus == ERROR_END_OF_STREAM) {
1793 notifyBufferingUpdate_l(100);
1794 }
1795
1796 stopBufferingIfNecessary_l();
1797 return;
Wei Jia48fa06d2016-12-20 15:30:49 -08001798 }
1799
1800 if (cachedDurationUs >= 0ll) {
Wei Jia14532f22015-12-29 11:28:15 -08001801 if (mDurationUs > 0ll) {
1802 int64_t cachedPosUs = getLastReadPosition_l() + cachedDurationUs;
1803 int percentage = 100.0 * cachedPosUs / mDurationUs;
1804 if (percentage > 100) {
1805 percentage = 100;
1806 }
1807
1808 notifyBufferingUpdate_l(percentage);
1809 }
1810
Wei Jia48fa06d2016-12-20 15:30:49 -08001811 ALOGV("onPollBuffering_l: cachedDurationUs %.1f sec", cachedDurationUs / 1000000.0f);
Wei Jia14532f22015-12-29 11:28:15 -08001812
Wei Jia48fa06d2016-12-20 15:30:49 -08001813 if (mPrepareBuffering) {
1814 if (cachedDurationUs > mSettings.mInitialWatermarkMs * 1000) {
1815 stopBufferingIfNecessary_l();
1816 }
1817 } else if (mSettings.IsTimeBasedBufferingMode(mSettings.mRebufferingMode)) {
1818 if (cachedDurationUs < mSettings.mRebufferingWatermarkLowMs * 1000) {
1819 // Take into account the data cached in downstream components to try to avoid
1820 // unnecessary pause.
1821 if (mOffloadAudio && mFirstDequeuedBufferRealUs >= 0) {
1822 int64_t downStreamCacheUs =
1823 mlastDequeuedBufferMediaUs - mFirstDequeuedBufferMediaUs
1824 - (ALooper::GetNowUs() - mFirstDequeuedBufferRealUs);
1825 if (downStreamCacheUs > 0) {
1826 cachedDurationUs += downStreamCacheUs;
1827 }
Wei Jia14532f22015-12-29 11:28:15 -08001828 }
Wei Jia14532f22015-12-29 11:28:15 -08001829
Wei Jia48fa06d2016-12-20 15:30:49 -08001830 if (cachedDurationUs < mSettings.mRebufferingWatermarkLowMs * 1000) {
1831 startBufferingIfNecessary_l();
1832 }
1833 } else if (cachedDurationUs > mSettings.mRebufferingWatermarkHighMs * 1000) {
Wei Jia14532f22015-12-29 11:28:15 -08001834 stopBufferingIfNecessary_l();
1835 }
1836 }
Wei Jia48fa06d2016-12-20 15:30:49 -08001837 } else if (cachedDataRemaining >= 0
1838 && mSettings.IsSizeBasedBufferingMode(mSettings.mRebufferingMode)) {
Wei Jia14532f22015-12-29 11:28:15 -08001839 ALOGV("onPollBuffering_l: cachedDataRemaining %zd bytes",
1840 cachedDataRemaining);
1841
Wei Jia48fa06d2016-12-20 15:30:49 -08001842 if (cachedDataRemaining < (mSettings.mRebufferingWatermarkLowKB << 10)) {
Wei Jia14532f22015-12-29 11:28:15 -08001843 startBufferingIfNecessary_l();
Wei Jia48fa06d2016-12-20 15:30:49 -08001844 } else if (cachedDataRemaining > (mSettings.mRebufferingWatermarkHighKB << 10)) {
Wei Jia14532f22015-12-29 11:28:15 -08001845 stopBufferingIfNecessary_l();
1846 }
1847 }
1848
1849 schedulePollBuffering_l();
1850}
1851
1852void NuPlayer::GenericSource::BufferingMonitor::onMessageReceived(const sp<AMessage> &msg) {
1853 switch (msg->what()) {
1854 case kWhatPollBuffering:
1855 {
1856 int32_t generation;
1857 CHECK(msg->findInt32("generation", &generation));
1858 Mutex::Autolock _l(mLock);
1859 if (generation == mPollBufferingGeneration) {
1860 onPollBuffering_l();
1861 }
1862 break;
1863 }
1864 default:
1865 TRESPASS();
1866 break;
1867 }
1868}
1869
Hassan Shojaniacefac142017-02-06 21:02:02 -08001870// Modular DRM
1871status_t NuPlayer::GenericSource::prepareDrm(
1872 const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId, sp<ICrypto> *crypto)
1873{
1874 ALOGV("prepareDrm");
1875
1876 sp<AMessage> msg = new AMessage(kWhatPrepareDrm, this);
1877 // synchronous call so just passing the address but with local copies of "const" args
1878 uint8_t UUID[16];
1879 memcpy(UUID, uuid, sizeof(UUID));
1880 Vector<uint8_t> sessionId = drmSessionId;
1881 msg->setPointer("uuid", (void*)UUID);
1882 msg->setPointer("drmSessionId", (void*)&sessionId);
1883 msg->setPointer("crypto", (void*)crypto);
1884
1885 sp<AMessage> response;
1886 status_t status = msg->postAndAwaitResponse(&response);
1887
1888 if (status == OK && response != NULL) {
1889 CHECK(response->findInt32("status", &status));
1890 ALOGV_IF(status == OK, "prepareDrm: mCrypto: %p (%d)", crypto->get(),
1891 (*crypto != NULL ? (*crypto)->getStrongCount() : 0));
1892 ALOGD("prepareDrm ret: %d ", status);
1893 } else {
1894 ALOGE("prepareDrm err: %d", status);
1895 }
1896
1897 return status;
1898}
1899
1900status_t NuPlayer::GenericSource::onPrepareDrm(const sp<AMessage> &msg)
1901{
1902 ALOGV("onPrepareDrm ");
1903
1904 mIsDrmProtected = false;
1905 mIsSecure = false;
1906
1907 uint8_t *uuid;
1908 Vector<uint8_t> *drmSessionId;
1909 sp<ICrypto> *outCrypto;
1910 CHECK(msg->findPointer("uuid", (void**)&uuid));
1911 CHECK(msg->findPointer("drmSessionId", (void**)&drmSessionId));
1912 CHECK(msg->findPointer("crypto", (void**)&outCrypto));
1913
1914 status_t status = OK;
1915 sp<ICrypto> crypto = NuPlayerDrm::createCryptoAndPlugin(uuid, *drmSessionId, status);
1916 if (crypto == NULL) {
1917 ALOGE("onPrepareDrm: createCrypto failed. status: %d", status);
1918 return status;
1919 }
1920 ALOGV("onPrepareDrm: createCryptoAndPlugin succeeded for uuid: %s",
1921 DrmUUID::toHexString(uuid).string());
1922
1923 *outCrypto = crypto;
1924 // as long a there is an active crypto
1925 mIsDrmProtected = true;
1926
1927 if (mMimes.size() == 0) {
1928 status = UNKNOWN_ERROR;
1929 ALOGE("onPrepareDrm: Unexpected. Must have at least one track. status: %d", status);
1930 return status;
1931 }
1932
1933 // first mime in this list is either the video track, or the first audio track
1934 const char *mime = mMimes[0].string();
1935 mIsSecure = crypto->requiresSecureDecoderComponent(mime);
1936 ALOGV("onPrepareDrm: requiresSecureDecoderComponent mime: %s isSecure: %d",
1937 mime, mIsSecure);
1938
1939 // Checking the member flags while in the looper to send out the notification.
1940 // The legacy mDecryptHandle!=NULL check (for FLAG_PROTECTED) is equivalent to mIsDrmProtected.
1941 notifyFlagsChanged(
1942 (mIsSecure ? FLAG_SECURE : 0) |
1943 (mIsDrmProtected ? FLAG_PROTECTED : 0) |
1944 FLAG_CAN_PAUSE |
1945 FLAG_CAN_SEEK_BACKWARD |
1946 FLAG_CAN_SEEK_FORWARD |
1947 FLAG_CAN_SEEK);
1948
1949 return status;
1950}
1951
1952status_t NuPlayer::GenericSource::checkDrmInfo()
1953{
1954 if (mFileMeta == NULL) {
Hassan Shojaniae7a1f6c2017-03-14 09:24:28 -07001955 ALOGI("checkDrmInfo: No metadata");
Hassan Shojaniacefac142017-02-06 21:02:02 -08001956 return OK; // letting the caller responds accordingly
1957 }
1958
1959 uint32_t type;
1960 const void *pssh;
1961 size_t psshsize;
1962
1963 if (!mFileMeta->findData(kKeyPssh, &type, &pssh, &psshsize)) {
Hassan Shojaniadd4ce182017-04-20 15:25:39 -07001964 ALOGV("checkDrmInfo: No PSSH");
Hassan Shojaniacefac142017-02-06 21:02:02 -08001965 return OK; // source without DRM info
1966 }
1967
1968 Parcel parcel;
Hassan Shojaniadd4ce182017-04-20 15:25:39 -07001969 NuPlayerDrm::retrieveDrmInfo(pssh, psshsize, &parcel);
Hassan Shojaniacefac142017-02-06 21:02:02 -08001970 ALOGV("checkDrmInfo: MEDIA_DRM_INFO PSSH size: %d Parcel size: %d objects#: %d",
Hassan Shojania06a70812017-02-15 21:57:45 -08001971 (int)psshsize, (int)parcel.dataSize(), (int)parcel.objectsCount());
Hassan Shojaniacefac142017-02-06 21:02:02 -08001972
1973 if (parcel.dataSize() == 0) {
1974 ALOGE("checkDrmInfo: Unexpected parcel size: 0");
1975 return UNKNOWN_ERROR;
1976 }
1977
1978 // Can't pass parcel as a message to the player. Converting Parcel->ABuffer to pass it
1979 // to the Player's onSourceNotify then back to Parcel for calling driver's notifyListener.
1980 sp<ABuffer> drmInfoBuffer = ABuffer::CreateAsCopy(parcel.data(), parcel.dataSize());
1981 notifyDrmInfo(drmInfoBuffer);
1982
1983 return OK;
1984}
1985
1986void NuPlayer::GenericSource::signalBufferReturned(MediaBuffer *buffer)
1987{
1988 //ALOGV("signalBufferReturned %p refCount: %d", buffer, buffer->localRefcount());
1989
1990 buffer->setObserver(NULL);
1991 buffer->release(); // this leads to delete since that there is no observor
1992}
1993
Andreas Huberafed0e12011-09-20 15:39:58 -07001994} // namespace android