blob: 3051df8d6d798b117d16ecdf90a942ff690b2c6a [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"
21
22#include "AnotherPacketSource.h"
23
Chong Zhanga19f33e2014-08-07 15:35:07 -070024#include <media/IMediaHTTPService.h>
Andreas Huberafed0e12011-09-20 15:39:58 -070025#include <media/stagefright/foundation/ABuffer.h>
26#include <media/stagefright/foundation/ADebug.h>
27#include <media/stagefright/foundation/AMessage.h>
28#include <media/stagefright/DataSource.h>
29#include <media/stagefright/FileSource.h>
30#include <media/stagefright/MediaBuffer.h>
31#include <media/stagefright/MediaDefs.h>
32#include <media/stagefright/MediaExtractor.h>
33#include <media/stagefright/MediaSource.h>
34#include <media/stagefright/MetaData.h>
Robert Shih17f6dd62014-08-20 17:00:21 -070035#include <media/stagefright/Utils.h>
Chong Zhangd354d8d2014-08-20 13:09:58 -070036#include "../../libstagefright/include/NuCachedSource2.h"
Robert Shih360d6d02014-09-29 14:42:35 -070037#include "../../libstagefright/include/HTTPBase.h"
Andreas Huberafed0e12011-09-20 15:39:58 -070038
39namespace android {
40
Wei Jia48fa06d2016-12-20 15:30:49 -080041static const int kLowWaterMarkMs = 2000; // 2secs
42static const int kHighWaterMarkMs = 5000; // 5secs
43static const int kHighWaterMarkRebufferMs = 15000; // 15secs
44
45static const int kLowWaterMarkKB = 40;
46static const int kHighWaterMarkKB = 200;
Chong Zhangefbb6192015-01-30 17:13:27 -080047
Andreas Huberafed0e12011-09-20 15:39:58 -070048NuPlayer::GenericSource::GenericSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080049 const sp<AMessage> &notify,
Lajos Molnarcc227032014-07-17 15:33:06 -070050 bool uidValid,
51 uid_t uid)
Andreas Huberb5f25f02013-02-05 10:14:26 -080052 : Source(notify),
Robert Shih5c67ddc2014-11-04 17:46:05 -080053 mAudioTimeUs(0),
54 mAudioLastDequeueTimeUs(0),
55 mVideoTimeUs(0),
56 mVideoLastDequeueTimeUs(0),
Robert Shih3423bbd2014-07-16 15:47:09 -070057 mFetchSubtitleDataGeneration(0),
Lajos Molnare26940f2014-07-31 10:31:26 -070058 mFetchTimedTextDataGeneration(0),
Marco Nelissen02fc5e32015-05-27 11:20:41 -070059 mDurationUs(-1ll),
Lajos Molnarcc227032014-07-17 15:33:06 -070060 mAudioIsVorbis(false),
Chong Zhang42e81532014-12-01 13:44:26 -080061 mIsSecure(false),
Chong Zhangefbb6192015-01-30 17:13:27 -080062 mIsStreaming(false),
Lajos Molnarcc227032014-07-17 15:33:06 -070063 mUIDValid(uidValid),
Chong Zhangd354d8d2014-08-20 13:09:58 -070064 mUID(uid),
Chong Zhanga6bf21f2014-11-19 20:26:34 -080065 mFd(-1),
Ronghua Wu80276872014-08-28 15:50:29 -070066 mDrmManagerClient(NULL),
Chong Zhang2a3cc9a2014-08-21 17:48:26 -070067 mBitrate(-1ll),
Wei Jia14532f22015-12-29 11:28:15 -080068 mPendingReadBufferTypes(0) {
69 mBufferingMonitor = new BufferingMonitor(notify);
Chong Zhanga19f33e2014-08-07 15:35:07 -070070 resetDataSource();
Chong Zhang3de157d2014-08-05 20:54:44 -070071}
72
Chong Zhanga19f33e2014-08-07 15:35:07 -070073void NuPlayer::GenericSource::resetDataSource() {
74 mHTTPService.clear();
Robert Shih360d6d02014-09-29 14:42:35 -070075 mHttpSource.clear();
Chong Zhanga19f33e2014-08-07 15:35:07 -070076 mUri.clear();
77 mUriHeaders.clear();
Chong Zhanga6bf21f2014-11-19 20:26:34 -080078 if (mFd >= 0) {
79 close(mFd);
80 mFd = -1;
81 }
Chong Zhanga19f33e2014-08-07 15:35:07 -070082 mOffset = 0;
83 mLength = 0;
Ronghua Wu80276872014-08-28 15:50:29 -070084 setDrmPlaybackStatusIfNeeded(Playback::STOP, 0);
85 mDecryptHandle = NULL;
86 mDrmManagerClient = NULL;
87 mStarted = false;
Andy Hung2abde2c2014-09-30 14:40:32 -070088 mStopRead = true;
Wei Jia14532f22015-12-29 11:28:15 -080089
90 if (mBufferingMonitorLooper != NULL) {
91 mBufferingMonitorLooper->unregisterHandler(mBufferingMonitor->id());
92 mBufferingMonitorLooper->stop();
93 mBufferingMonitorLooper = NULL;
94 }
95 mBufferingMonitor->stop();
Chong Zhanga19f33e2014-08-07 15:35:07 -070096}
97
98status_t NuPlayer::GenericSource::setDataSource(
Chong Zhang3de157d2014-08-05 20:54:44 -070099 const sp<IMediaHTTPService> &httpService,
100 const char *url,
101 const KeyedVector<String8, String8> *headers) {
Chong Zhanga19f33e2014-08-07 15:35:07 -0700102 resetDataSource();
Chong Zhang3de157d2014-08-05 20:54:44 -0700103
Chong Zhanga19f33e2014-08-07 15:35:07 -0700104 mHTTPService = httpService;
105 mUri = url;
Andreas Huberafed0e12011-09-20 15:39:58 -0700106
Chong Zhanga19f33e2014-08-07 15:35:07 -0700107 if (headers) {
108 mUriHeaders = *headers;
Chong Zhang3de157d2014-08-05 20:54:44 -0700109 }
110
Chong Zhanga19f33e2014-08-07 15:35:07 -0700111 // delay data source creation to prepareAsync() to avoid blocking
112 // the calling thread in setDataSource for any significant time.
113 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700114}
115
Chong Zhanga19f33e2014-08-07 15:35:07 -0700116status_t NuPlayer::GenericSource::setDataSource(
Chong Zhang3de157d2014-08-05 20:54:44 -0700117 int fd, int64_t offset, int64_t length) {
Chong Zhanga19f33e2014-08-07 15:35:07 -0700118 resetDataSource();
Andreas Huberafed0e12011-09-20 15:39:58 -0700119
Chong Zhanga19f33e2014-08-07 15:35:07 -0700120 mFd = dup(fd);
121 mOffset = offset;
122 mLength = length;
123
124 // delay data source creation to prepareAsync() to avoid blocking
125 // the calling thread in setDataSource for any significant time.
126 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700127}
128
Chris Watkins99f31602015-03-20 13:06:33 -0700129status_t NuPlayer::GenericSource::setDataSource(const sp<DataSource>& source) {
130 resetDataSource();
131 mDataSource = source;
132 return OK;
133}
134
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700135sp<MetaData> NuPlayer::GenericSource::getFileFormatMeta() const {
136 return mFileMeta;
137}
138
Chong Zhangd354d8d2014-08-20 13:09:58 -0700139status_t NuPlayer::GenericSource::initFromDataSource() {
Marco Nelissenb2487f02015-09-01 13:23:23 -0700140 sp<IMediaExtractor> extractor;
Chong Zhangd354d8d2014-08-20 13:09:58 -0700141 CHECK(mDataSource != NULL);
142
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700143 extractor = MediaExtractor::Create(mDataSource, NULL);
Andreas Huberafed0e12011-09-20 15:39:58 -0700144
Chong Zhang3de157d2014-08-05 20:54:44 -0700145 if (extractor == NULL) {
146 return UNKNOWN_ERROR;
147 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700148
Ronghua Wu80276872014-08-28 15:50:29 -0700149 if (extractor->getDrmFlag()) {
150 checkDrmStatus(mDataSource);
151 }
152
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700153 mFileMeta = extractor->getMetaData();
154 if (mFileMeta != NULL) {
Marco Nelissenc1f4b2b2014-06-17 14:48:32 -0700155 int64_t duration;
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700156 if (mFileMeta->findInt64(kKeyDuration, &duration)) {
Marco Nelissenc1f4b2b2014-06-17 14:48:32 -0700157 mDurationUs = duration;
158 }
159 }
160
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700161 int32_t totalBitrate = 0;
162
Marco Nelissen705d3292014-09-19 15:14:37 -0700163 size_t numtracks = extractor->countTracks();
164 if (numtracks == 0) {
165 return UNKNOWN_ERROR;
166 }
167
168 for (size_t i = 0; i < numtracks; ++i) {
Marco Nelissenb2487f02015-09-01 13:23:23 -0700169 sp<IMediaSource> track = extractor->getTrack(i);
Wei Jia0386c912015-08-28 10:35:35 -0700170 if (track == NULL) {
171 continue;
172 }
Chong Zhangafc0a872014-08-26 09:56:52 -0700173
Andreas Huberafed0e12011-09-20 15:39:58 -0700174 sp<MetaData> meta = extractor->getTrackMetaData(i);
Marco Nelissenc367ca12015-09-15 09:51:59 -0700175 if (meta == NULL) {
176 ALOGE("no metadata for track %zu", i);
177 return UNKNOWN_ERROR;
178 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700179
180 const char *mime;
181 CHECK(meta->findCString(kKeyMIMEType, &mime));
182
Chong Zhangafc0a872014-08-26 09:56:52 -0700183 // Do the string compare immediately with "mime",
184 // we can't assume "mime" would stay valid after another
185 // extractor operation, some extractors might modify meta
186 // during getTrack() and make it invalid.
Andreas Huberafed0e12011-09-20 15:39:58 -0700187 if (!strncasecmp(mime, "audio/", 6)) {
188 if (mAudioTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700189 mAudioTrack.mIndex = i;
190 mAudioTrack.mSource = track;
Robert Shihaf52c1a2014-09-11 15:38:54 -0700191 mAudioTrack.mPackets =
192 new AnotherPacketSource(mAudioTrack.mSource->getFormat());
Andreas Huberafed0e12011-09-20 15:39:58 -0700193
194 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
195 mAudioIsVorbis = true;
196 } else {
197 mAudioIsVorbis = false;
198 }
199 }
200 } else if (!strncasecmp(mime, "video/", 6)) {
201 if (mVideoTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700202 mVideoTrack.mIndex = i;
203 mVideoTrack.mSource = track;
Robert Shihaf52c1a2014-09-11 15:38:54 -0700204 mVideoTrack.mPackets =
205 new AnotherPacketSource(mVideoTrack.mSource->getFormat());
Chong Zhang7e892182014-08-05 11:58:21 -0700206
207 // check if the source requires secure buffers
208 int32_t secure;
Chong Zhanga19f33e2014-08-07 15:35:07 -0700209 if (meta->findInt32(kKeyRequiresSecureBuffers, &secure)
210 && secure) {
Chong Zhang42e81532014-12-01 13:44:26 -0800211 mIsSecure = true;
Chong Zhang3de157d2014-08-05 20:54:44 -0700212 if (mUIDValid) {
213 extractor->setUID(mUID);
214 }
Chong Zhang7e892182014-08-05 11:58:21 -0700215 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700216 }
217 }
218
Wei Jia0386c912015-08-28 10:35:35 -0700219 mSources.push(track);
220 int64_t durationUs;
221 if (meta->findInt64(kKeyDuration, &durationUs)) {
222 if (durationUs > mDurationUs) {
223 mDurationUs = durationUs;
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700224 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700225 }
Wei Jia0386c912015-08-28 10:35:35 -0700226
227 int32_t bitrate;
228 if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) {
229 totalBitrate += bitrate;
230 } else {
231 totalBitrate = -1;
232 }
233 }
234
235 if (mSources.size() == 0) {
236 ALOGE("b/23705695");
237 return UNKNOWN_ERROR;
Andreas Huberafed0e12011-09-20 15:39:58 -0700238 }
Chong Zhang3de157d2014-08-05 20:54:44 -0700239
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700240 mBitrate = totalBitrate;
241
242 return OK;
243}
244
Wei Jia48fa06d2016-12-20 15:30:49 -0800245status_t NuPlayer::GenericSource::getDefaultBufferingSettings(
246 BufferingSettings* buffering /* nonnull */) {
247 mBufferingMonitor->getDefaultBufferingSettings(buffering);
248 return OK;
249}
250
251status_t NuPlayer::GenericSource::setBufferingSettings(const BufferingSettings& buffering) {
252 return mBufferingMonitor->setBufferingSettings(buffering);
253}
254
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700255status_t NuPlayer::GenericSource::startSources() {
Chong Zhangefbb6192015-01-30 17:13:27 -0800256 // Start the selected A/V tracks now before we start buffering.
257 // Widevine sources might re-initialize crypto when starting, if we delay
258 // this to start(), all data buffered during prepare would be wasted.
259 // (We don't actually start reading until start().)
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700260 //
261 // TODO: this logic may no longer be relevant after the removal of widevine
262 // support
Chong Zhangefbb6192015-01-30 17:13:27 -0800263 if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) {
264 ALOGE("failed to start audio track!");
265 return UNKNOWN_ERROR;
266 }
267
268 if (mVideoTrack.mSource != NULL && mVideoTrack.mSource->start() != OK) {
269 ALOGE("failed to start video track!");
270 return UNKNOWN_ERROR;
271 }
272
Chong Zhang3de157d2014-08-05 20:54:44 -0700273 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700274}
275
Ronghua Wu80276872014-08-28 15:50:29 -0700276void NuPlayer::GenericSource::checkDrmStatus(const sp<DataSource>& dataSource) {
277 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
278 if (mDecryptHandle != NULL) {
279 CHECK(mDrmManagerClient);
280 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
281 sp<AMessage> msg = dupNotify();
282 msg->setInt32("what", kWhatDrmNoLicense);
283 msg->post();
284 }
285 }
286}
287
288int64_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() {
Chong Zhang1228d6b2014-08-12 21:25:48 -0700315 if (mLooper != NULL) {
316 mLooper->unregisterHandler(id());
317 mLooper->stop();
318 }
Chong Zhanga6bf21f2014-11-19 20:26:34 -0800319 resetDataSource();
Andreas Huberafed0e12011-09-20 15:39:58 -0700320}
321
Andreas Huber9575c962013-02-05 13:59:56 -0800322void NuPlayer::GenericSource::prepareAsync() {
Chong Zhang1228d6b2014-08-12 21:25:48 -0700323 if (mLooper == NULL) {
324 mLooper = new ALooper;
325 mLooper->setName("generic");
326 mLooper->start();
327
328 mLooper->registerHandler(this);
329 }
330
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800331 sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this);
Chong Zhang1228d6b2014-08-12 21:25:48 -0700332 msg->post();
333}
334
335void NuPlayer::GenericSource::onPrepareAsync() {
Chong Zhanga19f33e2014-08-07 15:35:07 -0700336 // delayed data source creation
Chong Zhangd354d8d2014-08-20 13:09:58 -0700337 if (mDataSource == NULL) {
Chong Zhang42e81532014-12-01 13:44:26 -0800338 // set to false first, if the extractor
339 // comes back as secure, set it to true then.
340 mIsSecure = false;
341
Chong Zhangd354d8d2014-08-20 13:09:58 -0700342 if (!mUri.empty()) {
Robert Shih360d6d02014-09-29 14:42:35 -0700343 const char* uri = mUri.c_str();
Chong Zhangc287cad2015-02-19 18:30:30 -0800344 String8 contentType;
Robert Shih360d6d02014-09-29 14:42:35 -0700345
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700346 if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
Robert Shih360d6d02014-09-29 14:42:35 -0700347 mHttpSource = DataSource::CreateMediaHTTP(mHTTPService);
348 if (mHttpSource == NULL) {
349 ALOGE("Failed to create http source!");
350 notifyPreparedAndCleanup(UNKNOWN_ERROR);
351 return;
352 }
353 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700354
Chong Zhangd354d8d2014-08-20 13:09:58 -0700355 mDataSource = DataSource::CreateFromURI(
Chong Zhangc287cad2015-02-19 18:30:30 -0800356 mHTTPService, uri, &mUriHeaders, &contentType,
Robert Shih360d6d02014-09-29 14:42:35 -0700357 static_cast<HTTPBase *>(mHttpSource.get()));
Chong Zhangd354d8d2014-08-20 13:09:58 -0700358 } else {
Chong Zhangd354d8d2014-08-20 13:09:58 -0700359 mDataSource = new FileSource(mFd, mOffset, mLength);
Chong Zhanga6bf21f2014-11-19 20:26:34 -0800360 mFd = -1;
Chong Zhangd354d8d2014-08-20 13:09:58 -0700361 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700362
Chong Zhangd354d8d2014-08-20 13:09:58 -0700363 if (mDataSource == NULL) {
364 ALOGE("Failed to create data source!");
365 notifyPreparedAndCleanup(UNKNOWN_ERROR);
366 return;
367 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700368 }
369
Chris Watkins99f31602015-03-20 13:06:33 -0700370 if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
371 mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
372 }
373
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700374 // For cached streaming cases, we need to wait for enough
375 // buffering before reporting prepared.
376 mIsStreaming = (mCachedSource != NULL);
Chris Watkins99f31602015-03-20 13:06:33 -0700377
Chong Zhangc287cad2015-02-19 18:30:30 -0800378 // init extractor from data source
379 status_t err = initFromDataSource();
Chong Zhanga19f33e2014-08-07 15:35:07 -0700380
381 if (err != OK) {
382 ALOGE("Failed to init from data source!");
Chong Zhangd354d8d2014-08-20 13:09:58 -0700383 notifyPreparedAndCleanup(err);
Chong Zhanga19f33e2014-08-07 15:35:07 -0700384 return;
385 }
386
Andreas Huber9575c962013-02-05 13:59:56 -0800387 if (mVideoTrack.mSource != NULL) {
Robert Shih17f6dd62014-08-20 17:00:21 -0700388 sp<MetaData> meta = doGetFormatMeta(false /* audio */);
389 sp<AMessage> msg = new AMessage;
390 err = convertMetaDataToMessage(meta, &msg);
391 if(err != OK) {
392 notifyPreparedAndCleanup(err);
393 return;
394 }
395 notifyVideoSizeChanged(msg);
Andreas Huber9575c962013-02-05 13:59:56 -0800396 }
397
398 notifyFlagsChanged(
Chong Zhang42e81532014-12-01 13:44:26 -0800399 (mIsSecure ? FLAG_SECURE : 0)
Chong Zhang17134602015-01-07 16:14:34 -0800400 | (mDecryptHandle != NULL ? FLAG_PROTECTED : 0)
Lajos Molnarcc227032014-07-17 15:33:06 -0700401 | FLAG_CAN_PAUSE
Andreas Huber9575c962013-02-05 13:59:56 -0800402 | FLAG_CAN_SEEK_BACKWARD
403 | FLAG_CAN_SEEK_FORWARD
404 | FLAG_CAN_SEEK);
405
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700406 if (mIsSecure) {
407 // secure decoders must be instantiated before starting widevine source
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700408 //
409 // TODO: mIsSecure and FLAG_SECURE may be obsolete, revisit after
410 // removing widevine
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700411 sp<AMessage> reply = new AMessage(kWhatSecureDecodersInstantiated, this);
412 notifyInstantiateSecureDecoders(reply);
413 } else {
414 finishPrepareAsync();
415 }
416}
417
418void NuPlayer::GenericSource::onSecureDecodersInstantiated(status_t err) {
419 if (err != OK) {
420 ALOGE("Failed to instantiate secure decoders!");
421 notifyPreparedAndCleanup(err);
422 return;
423 }
424 finishPrepareAsync();
425}
426
427void NuPlayer::GenericSource::finishPrepareAsync() {
428 status_t err = startSources();
429 if (err != OK) {
430 ALOGE("Failed to init start data source!");
431 notifyPreparedAndCleanup(err);
432 return;
433 }
434
Chong Zhangefbb6192015-01-30 17:13:27 -0800435 if (mIsStreaming) {
Wei Jia14532f22015-12-29 11:28:15 -0800436 if (mBufferingMonitorLooper == NULL) {
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700437 mBufferingMonitor->prepare(mCachedSource, mDurationUs, mBitrate,
Wei Jia14532f22015-12-29 11:28:15 -0800438 mIsStreaming);
Chong Zhangefbb6192015-01-30 17:13:27 -0800439
Wei Jia14532f22015-12-29 11:28:15 -0800440 mBufferingMonitorLooper = new ALooper;
441 mBufferingMonitorLooper->setName("GSBMonitor");
442 mBufferingMonitorLooper->start();
443 mBufferingMonitorLooper->registerHandler(mBufferingMonitor);
444 }
445
446 mBufferingMonitor->ensureCacheIsFetching();
447 mBufferingMonitor->restartPollBuffering();
Chong Zhangefbb6192015-01-30 17:13:27 -0800448 } else {
449 notifyPrepared();
450 }
Andreas Huber9575c962013-02-05 13:59:56 -0800451}
452
Chong Zhangd354d8d2014-08-20 13:09:58 -0700453void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
454 if (err != OK) {
Robert Shihebc27122015-09-02 14:02:47 -0700455 {
456 sp<DataSource> dataSource = mDataSource;
457 sp<NuCachedSource2> cachedSource = mCachedSource;
458 sp<DataSource> httpSource = mHttpSource;
459 {
460 Mutex::Autolock _l(mDisconnectLock);
461 mDataSource.clear();
Wei Jiacdc9cf62015-10-22 11:35:04 -0700462 mDecryptHandle = NULL;
Wei Jiab41fd0d2015-10-19 16:14:14 -0700463 mDrmManagerClient = NULL;
Robert Shihebc27122015-09-02 14:02:47 -0700464 mCachedSource.clear();
465 mHttpSource.clear();
466 }
467 }
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700468 mBitrate = -1;
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700469
Wei Jia14532f22015-12-29 11:28:15 -0800470 mBufferingMonitor->cancelPollBuffering();
Chong Zhangd354d8d2014-08-20 13:09:58 -0700471 }
472 notifyPrepared(err);
473}
474
Andreas Huberafed0e12011-09-20 15:39:58 -0700475void NuPlayer::GenericSource::start() {
476 ALOGI("start");
477
Andy Hung2abde2c2014-09-30 14:40:32 -0700478 mStopRead = false;
Andreas Huberafed0e12011-09-20 15:39:58 -0700479 if (mAudioTrack.mSource != NULL) {
Robert Shih17f6dd62014-08-20 17:00:21 -0700480 postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700481 }
482
483 if (mVideoTrack.mSource != NULL) {
Robert Shih17f6dd62014-08-20 17:00:21 -0700484 postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700485 }
Ronghua Wu80276872014-08-28 15:50:29 -0700486
487 setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000);
488 mStarted = true;
Chong Zhangefbb6192015-01-30 17:13:27 -0800489
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800490 (new AMessage(kWhatStart, this))->post();
Ronghua Wu80276872014-08-28 15:50:29 -0700491}
492
493void NuPlayer::GenericSource::stop() {
494 // nothing to do, just account for DRM playback status
495 setDrmPlaybackStatusIfNeeded(Playback::STOP, 0);
496 mStarted = false;
497}
498
499void NuPlayer::GenericSource::pause() {
500 // nothing to do, just account for DRM playback status
501 setDrmPlaybackStatusIfNeeded(Playback::PAUSE, 0);
502 mStarted = false;
503}
504
505void NuPlayer::GenericSource::resume() {
506 // nothing to do, just account for DRM playback status
507 setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000);
508 mStarted = true;
Chong Zhangefbb6192015-01-30 17:13:27 -0800509
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800510 (new AMessage(kWhatResume, this))->post();
Ronghua Wu80276872014-08-28 15:50:29 -0700511}
512
Chong Zhang48296b72014-09-14 14:28:45 -0700513void NuPlayer::GenericSource::disconnect() {
Robert Shihebc27122015-09-02 14:02:47 -0700514 sp<DataSource> dataSource, httpSource;
515 {
516 Mutex::Autolock _l(mDisconnectLock);
517 dataSource = mDataSource;
518 httpSource = mHttpSource;
519 }
520
521 if (dataSource != NULL) {
Chong Zhang48296b72014-09-14 14:28:45 -0700522 // disconnect data source
Robert Shihebc27122015-09-02 14:02:47 -0700523 if (dataSource->flags() & DataSource::kIsCachingDataSource) {
524 static_cast<NuCachedSource2 *>(dataSource.get())->disconnect();
Chong Zhang48296b72014-09-14 14:28:45 -0700525 }
Robert Shihebc27122015-09-02 14:02:47 -0700526 } else if (httpSource != NULL) {
527 static_cast<HTTPBase *>(httpSource.get())->disconnect();
Chong Zhang48296b72014-09-14 14:28:45 -0700528 }
529}
530
Ronghua Wu80276872014-08-28 15:50:29 -0700531void NuPlayer::GenericSource::setDrmPlaybackStatusIfNeeded(int playbackStatus, int64_t position) {
532 if (mDecryptHandle != NULL) {
533 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, playbackStatus, position);
534 }
Robert Shih17f6dd62014-08-20 17:00:21 -0700535 mSubtitleTrack.mPackets = new AnotherPacketSource(NULL);
536 mTimedTextTrack.mPackets = new AnotherPacketSource(NULL);
Andreas Huberafed0e12011-09-20 15:39:58 -0700537}
538
539status_t NuPlayer::GenericSource::feedMoreTSData() {
540 return OK;
541}
542
Robert Shih3423bbd2014-07-16 15:47:09 -0700543void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
544 switch (msg->what()) {
Chong Zhang1228d6b2014-08-12 21:25:48 -0700545 case kWhatPrepareAsync:
546 {
547 onPrepareAsync();
548 break;
549 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700550 case kWhatFetchSubtitleData:
551 {
Lajos Molnare26940f2014-07-31 10:31:26 -0700552 fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
553 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
554 break;
555 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700556
Lajos Molnare26940f2014-07-31 10:31:26 -0700557 case kWhatFetchTimedTextData:
558 {
559 fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
560 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih3423bbd2014-07-16 15:47:09 -0700561 break;
562 }
563
564 case kWhatSendSubtitleData:
565 {
Lajos Molnare26940f2014-07-31 10:31:26 -0700566 sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
567 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
568 break;
569 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700570
Marco Nelissen55e2f4c2015-09-04 15:57:15 -0700571 case kWhatSendGlobalTimedTextData:
572 {
573 sendGlobalTextData(kWhatTimedTextData, mFetchTimedTextDataGeneration, msg);
574 break;
575 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700576 case kWhatSendTimedTextData:
577 {
578 sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
579 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih3423bbd2014-07-16 15:47:09 -0700580 break;
581 }
582
583 case kWhatChangeAVSource:
584 {
585 int32_t trackIndex;
586 CHECK(msg->findInt32("trackIndex", &trackIndex));
Marco Nelissenb2487f02015-09-01 13:23:23 -0700587 const sp<IMediaSource> source = mSources.itemAt(trackIndex);
Robert Shih3423bbd2014-07-16 15:47:09 -0700588
589 Track* track;
590 const char *mime;
591 media_track_type trackType, counterpartType;
592 sp<MetaData> meta = source->getFormat();
593 meta->findCString(kKeyMIMEType, &mime);
594 if (!strncasecmp(mime, "audio/", 6)) {
595 track = &mAudioTrack;
596 trackType = MEDIA_TRACK_TYPE_AUDIO;
597 counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
598 } else {
599 CHECK(!strncasecmp(mime, "video/", 6));
600 track = &mVideoTrack;
601 trackType = MEDIA_TRACK_TYPE_VIDEO;
602 counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
603 }
604
605
606 if (track->mSource != NULL) {
607 track->mSource->stop();
608 }
609 track->mSource = source;
610 track->mSource->start();
611 track->mIndex = trackIndex;
612
Robert Shih3423bbd2014-07-16 15:47:09 -0700613 int64_t timeUs, actualTimeUs;
614 const bool formatChange = true;
Robert Shih5c67ddc2014-11-04 17:46:05 -0800615 if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
616 timeUs = mAudioLastDequeueTimeUs;
617 } else {
618 timeUs = mVideoLastDequeueTimeUs;
619 }
Wei Jiac5de0912016-11-18 10:22:14 -0800620 readBuffer(trackType, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
621 &actualTimeUs, formatChange);
622 readBuffer(counterpartType, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
623 NULL, !formatChange);
Lajos Molnar6d339f12015-04-17 16:15:53 -0700624 ALOGV("timeUs %lld actualTimeUs %lld", (long long)timeUs, (long long)actualTimeUs);
Robert Shih3423bbd2014-07-16 15:47:09 -0700625
626 break;
627 }
Chong Zhangefbb6192015-01-30 17:13:27 -0800628
629 case kWhatStart:
630 case kWhatResume:
631 {
Wei Jia14532f22015-12-29 11:28:15 -0800632 mBufferingMonitor->restartPollBuffering();
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700633 break;
634 }
Robert Shih17f6dd62014-08-20 17:00:21 -0700635
636 case kWhatGetFormat:
637 {
638 onGetFormatMeta(msg);
639 break;
640 }
641
642 case kWhatGetSelectedTrack:
643 {
644 onGetSelectedTrack(msg);
645 break;
646 }
647
648 case kWhatSelectTrack:
649 {
650 onSelectTrack(msg);
651 break;
652 }
653
654 case kWhatSeek:
655 {
656 onSeek(msg);
657 break;
658 }
659
660 case kWhatReadBuffer:
661 {
662 onReadBuffer(msg);
663 break;
664 }
665
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700666 case kWhatSecureDecodersInstantiated:
667 {
668 int32_t err;
669 CHECK(msg->findInt32("err", &err));
670 onSecureDecodersInstantiated(err);
671 break;
672 }
673
Robert Shih3423bbd2014-07-16 15:47:09 -0700674 default:
675 Source::onMessageReceived(msg);
676 break;
677 }
678}
679
Lajos Molnare26940f2014-07-31 10:31:26 -0700680void NuPlayer::GenericSource::fetchTextData(
681 uint32_t sendWhat,
682 media_track_type type,
683 int32_t curGen,
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -0700684 const sp<AnotherPacketSource>& packets,
685 const sp<AMessage>& msg) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700686 int32_t msgGeneration;
687 CHECK(msg->findInt32("generation", &msgGeneration));
688 if (msgGeneration != curGen) {
689 // stale
690 return;
691 }
692
693 int32_t avail;
694 if (packets->hasBufferAvailable(&avail)) {
695 return;
696 }
697
698 int64_t timeUs;
699 CHECK(msg->findInt64("timeUs", &timeUs));
700
701 int64_t subTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -0800702 readBuffer(type, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &subTimeUs);
Lajos Molnare26940f2014-07-31 10:31:26 -0700703
704 int64_t delayUs = subTimeUs - timeUs;
705 if (msg->what() == kWhatFetchSubtitleData) {
706 const int64_t oneSecUs = 1000000ll;
707 delayUs -= oneSecUs;
708 }
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800709 sp<AMessage> msg2 = new AMessage(sendWhat, this);
Lajos Molnare26940f2014-07-31 10:31:26 -0700710 msg2->setInt32("generation", msgGeneration);
711 msg2->post(delayUs < 0 ? 0 : delayUs);
712}
713
714void NuPlayer::GenericSource::sendTextData(
715 uint32_t what,
716 media_track_type type,
717 int32_t curGen,
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -0700718 const sp<AnotherPacketSource>& packets,
719 const sp<AMessage>& msg) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700720 int32_t msgGeneration;
721 CHECK(msg->findInt32("generation", &msgGeneration));
722 if (msgGeneration != curGen) {
723 // stale
724 return;
725 }
726
727 int64_t subTimeUs;
728 if (packets->nextBufferTime(&subTimeUs) != OK) {
729 return;
730 }
731
732 int64_t nextSubTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -0800733 readBuffer(type, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &nextSubTimeUs);
Lajos Molnare26940f2014-07-31 10:31:26 -0700734
735 sp<ABuffer> buffer;
736 status_t dequeueStatus = packets->dequeueAccessUnit(&buffer);
737 if (dequeueStatus == OK) {
738 sp<AMessage> notify = dupNotify();
739 notify->setInt32("what", what);
740 notify->setBuffer("buffer", buffer);
741 notify->post();
742
743 const int64_t delayUs = nextSubTimeUs - subTimeUs;
744 msg->post(delayUs < 0 ? 0 : delayUs);
745 }
746}
747
Marco Nelissen55e2f4c2015-09-04 15:57:15 -0700748void NuPlayer::GenericSource::sendGlobalTextData(
749 uint32_t what,
750 int32_t curGen,
751 sp<AMessage> msg) {
752 int32_t msgGeneration;
753 CHECK(msg->findInt32("generation", &msgGeneration));
754 if (msgGeneration != curGen) {
755 // stale
756 return;
757 }
758
759 uint32_t textType;
760 const void *data;
761 size_t size = 0;
762 if (mTimedTextTrack.mSource->getFormat()->findData(
763 kKeyTextFormatData, &textType, &data, &size)) {
764 mGlobalTimedText = new ABuffer(size);
765 if (mGlobalTimedText->data()) {
766 memcpy(mGlobalTimedText->data(), data, size);
767 sp<AMessage> globalMeta = mGlobalTimedText->meta();
768 globalMeta->setInt64("timeUs", 0);
769 globalMeta->setString("mime", MEDIA_MIMETYPE_TEXT_3GPP);
770 globalMeta->setInt32("global", 1);
771 sp<AMessage> notify = dupNotify();
772 notify->setInt32("what", what);
773 notify->setBuffer("buffer", mGlobalTimedText);
774 notify->post();
775 }
776 }
777}
778
Andreas Huber84066782011-08-16 09:34:26 -0700779sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800780 sp<AMessage> msg = new AMessage(kWhatGetFormat, this);
Robert Shih17f6dd62014-08-20 17:00:21 -0700781 msg->setInt32("audio", audio);
782
783 sp<AMessage> response;
Marco Nelissen10a121b2015-11-04 14:46:44 -0800784 sp<RefBase> format;
Robert Shih17f6dd62014-08-20 17:00:21 -0700785 status_t err = msg->postAndAwaitResponse(&response);
786 if (err == OK && response != NULL) {
Marco Nelissen10a121b2015-11-04 14:46:44 -0800787 CHECK(response->findObject("format", &format));
788 return static_cast<MetaData*>(format.get());
Robert Shih17f6dd62014-08-20 17:00:21 -0700789 } else {
790 return NULL;
791 }
792}
793
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -0700794void NuPlayer::GenericSource::onGetFormatMeta(const sp<AMessage>& msg) const {
Robert Shih17f6dd62014-08-20 17:00:21 -0700795 int32_t audio;
796 CHECK(msg->findInt32("audio", &audio));
797
798 sp<AMessage> response = new AMessage;
799 sp<MetaData> format = doGetFormatMeta(audio);
Marco Nelissen10a121b2015-11-04 14:46:44 -0800800 response->setObject("format", format);
Robert Shih17f6dd62014-08-20 17:00:21 -0700801
Lajos Molnar3f274362015-03-05 14:35:41 -0800802 sp<AReplyToken> replyID;
Robert Shih17f6dd62014-08-20 17:00:21 -0700803 CHECK(msg->senderAwaitsResponse(&replyID));
804 response->postReply(replyID);
805}
806
807sp<MetaData> NuPlayer::GenericSource::doGetFormatMeta(bool audio) const {
Marco Nelissenb2487f02015-09-01 13:23:23 -0700808 sp<IMediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
Andreas Huberafed0e12011-09-20 15:39:58 -0700809
810 if (source == NULL) {
811 return NULL;
812 }
813
814 return source->getFormat();
815}
816
817status_t NuPlayer::GenericSource::dequeueAccessUnit(
818 bool audio, sp<ABuffer> *accessUnit) {
Wei Jiaff486642016-04-04 16:17:39 -0700819 if (audio && !mStarted) {
Wei Jia14532f22015-12-29 11:28:15 -0800820 return -EWOULDBLOCK;
821 }
822
Andreas Huberafed0e12011-09-20 15:39:58 -0700823 Track *track = audio ? &mAudioTrack : &mVideoTrack;
824
825 if (track->mSource == NULL) {
826 return -EWOULDBLOCK;
827 }
828
829 status_t finalResult;
830 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
Chong Zhang42e81532014-12-01 13:44:26 -0800831 if (finalResult == OK) {
832 postReadBuffer(
833 audio ? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
834 return -EWOULDBLOCK;
835 }
836 return finalResult;
Andreas Huberafed0e12011-09-20 15:39:58 -0700837 }
838
839 status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
840
Chong Zhangfcf044a2015-07-14 15:58:51 -0700841 // start pulling in more buffers if we only have one (or no) buffer left
842 // so that decoder has less chance of being starved
843 if (track->mPackets->getAvailableBufferCount(&finalResult) < 2) {
Robert Shih17f6dd62014-08-20 17:00:21 -0700844 postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
Lajos Molnare26940f2014-07-31 10:31:26 -0700845 }
846
Robert Shih3423bbd2014-07-16 15:47:09 -0700847 if (result != OK) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700848 if (mSubtitleTrack.mSource != NULL) {
849 mSubtitleTrack.mPackets->clear();
850 mFetchSubtitleDataGeneration++;
851 }
852 if (mTimedTextTrack.mSource != NULL) {
853 mTimedTextTrack.mPackets->clear();
854 mFetchTimedTextDataGeneration++;
855 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700856 return result;
857 }
858
859 int64_t timeUs;
860 status_t eosResult; // ignored
861 CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
Robert Shih5c67ddc2014-11-04 17:46:05 -0800862 if (audio) {
863 mAudioLastDequeueTimeUs = timeUs;
Wei Jia14532f22015-12-29 11:28:15 -0800864 mBufferingMonitor->updateDequeuedBufferTime(timeUs);
Robert Shih5c67ddc2014-11-04 17:46:05 -0800865 } else {
866 mVideoLastDequeueTimeUs = timeUs;
867 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700868
869 if (mSubtitleTrack.mSource != NULL
870 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800871 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
Robert Shih3423bbd2014-07-16 15:47:09 -0700872 msg->setInt64("timeUs", timeUs);
873 msg->setInt32("generation", mFetchSubtitleDataGeneration);
874 msg->post();
875 }
Robert Shiheb1735e2014-07-23 15:53:14 -0700876
Lajos Molnare26940f2014-07-31 10:31:26 -0700877 if (mTimedTextTrack.mSource != NULL
878 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800879 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
Lajos Molnare26940f2014-07-31 10:31:26 -0700880 msg->setInt64("timeUs", timeUs);
881 msg->setInt32("generation", mFetchTimedTextDataGeneration);
882 msg->post();
883 }
884
Andreas Huberafed0e12011-09-20 15:39:58 -0700885 return result;
886}
887
888status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
889 *durationUs = mDurationUs;
890 return OK;
891}
892
Robert Shihdd235722014-06-12 14:49:23 -0700893size_t NuPlayer::GenericSource::getTrackCount() const {
894 return mSources.size();
895}
896
897sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const {
898 size_t trackCount = mSources.size();
899 if (trackIndex >= trackCount) {
900 return NULL;
901 }
902
903 sp<AMessage> format = new AMessage();
904 sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat();
Marco Nelissenc367ca12015-09-15 09:51:59 -0700905 if (meta == NULL) {
906 ALOGE("no metadata for track %zu", trackIndex);
907 return NULL;
908 }
Robert Shihdd235722014-06-12 14:49:23 -0700909
910 const char *mime;
911 CHECK(meta->findCString(kKeyMIMEType, &mime));
Robert Shih755106e2015-04-30 14:36:45 -0700912 format->setString("mime", mime);
Robert Shihdd235722014-06-12 14:49:23 -0700913
914 int32_t trackType;
915 if (!strncasecmp(mime, "video/", 6)) {
916 trackType = MEDIA_TRACK_TYPE_VIDEO;
917 } else if (!strncasecmp(mime, "audio/", 6)) {
918 trackType = MEDIA_TRACK_TYPE_AUDIO;
919 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
920 trackType = MEDIA_TRACK_TYPE_TIMEDTEXT;
921 } else {
922 trackType = MEDIA_TRACK_TYPE_UNKNOWN;
923 }
924 format->setInt32("type", trackType);
925
926 const char *lang;
927 if (!meta->findCString(kKeyMediaLanguage, &lang)) {
928 lang = "und";
929 }
930 format->setString("language", lang);
931
932 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
Robert Shihdd235722014-06-12 14:49:23 -0700933 int32_t isAutoselect = 1, isDefault = 0, isForced = 0;
934 meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect);
935 meta->findInt32(kKeyTrackIsDefault, &isDefault);
936 meta->findInt32(kKeyTrackIsForced, &isForced);
937
938 format->setInt32("auto", !!isAutoselect);
939 format->setInt32("default", !!isDefault);
940 format->setInt32("forced", !!isForced);
941 }
942
943 return format;
944}
945
Lajos Molnare26940f2014-07-31 10:31:26 -0700946ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800947 sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, this);
Robert Shih17f6dd62014-08-20 17:00:21 -0700948 msg->setInt32("type", type);
949
950 sp<AMessage> response;
951 int32_t index;
952 status_t err = msg->postAndAwaitResponse(&response);
953 if (err == OK && response != NULL) {
954 CHECK(response->findInt32("index", &index));
955 return index;
956 } else {
957 return -1;
958 }
959}
960
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -0700961void NuPlayer::GenericSource::onGetSelectedTrack(const sp<AMessage>& msg) const {
Robert Shih17f6dd62014-08-20 17:00:21 -0700962 int32_t tmpType;
963 CHECK(msg->findInt32("type", &tmpType));
964 media_track_type type = (media_track_type)tmpType;
965
966 sp<AMessage> response = new AMessage;
967 ssize_t index = doGetSelectedTrack(type);
968 response->setInt32("index", index);
969
Lajos Molnar3f274362015-03-05 14:35:41 -0800970 sp<AReplyToken> replyID;
Robert Shih17f6dd62014-08-20 17:00:21 -0700971 CHECK(msg->senderAwaitsResponse(&replyID));
972 response->postReply(replyID);
973}
974
975ssize_t NuPlayer::GenericSource::doGetSelectedTrack(media_track_type type) const {
Lajos Molnare26940f2014-07-31 10:31:26 -0700976 const Track *track = NULL;
977 switch (type) {
978 case MEDIA_TRACK_TYPE_VIDEO:
979 track = &mVideoTrack;
980 break;
981 case MEDIA_TRACK_TYPE_AUDIO:
982 track = &mAudioTrack;
983 break;
984 case MEDIA_TRACK_TYPE_TIMEDTEXT:
985 track = &mTimedTextTrack;
986 break;
987 case MEDIA_TRACK_TYPE_SUBTITLE:
988 track = &mSubtitleTrack;
989 break;
990 default:
991 break;
992 }
993
994 if (track != NULL && track->mSource != NULL) {
995 return track->mIndex;
996 }
997
998 return -1;
999}
1000
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001001status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
Lajos Molnare26940f2014-07-31 10:31:26 -07001002 ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001003 sp<AMessage> msg = new AMessage(kWhatSelectTrack, this);
Robert Shih17f6dd62014-08-20 17:00:21 -07001004 msg->setInt32("trackIndex", trackIndex);
Robert Shihda23ab92014-09-16 11:34:08 -07001005 msg->setInt32("select", select);
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001006 msg->setInt64("timeUs", timeUs);
Robert Shih17f6dd62014-08-20 17:00:21 -07001007
1008 sp<AMessage> response;
1009 status_t err = msg->postAndAwaitResponse(&response);
1010 if (err == OK && response != NULL) {
1011 CHECK(response->findInt32("err", &err));
1012 }
1013
1014 return err;
1015}
1016
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -07001017void NuPlayer::GenericSource::onSelectTrack(const sp<AMessage>& msg) {
Robert Shih17f6dd62014-08-20 17:00:21 -07001018 int32_t trackIndex, select;
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001019 int64_t timeUs;
Robert Shih17f6dd62014-08-20 17:00:21 -07001020 CHECK(msg->findInt32("trackIndex", &trackIndex));
1021 CHECK(msg->findInt32("select", &select));
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001022 CHECK(msg->findInt64("timeUs", &timeUs));
Robert Shih17f6dd62014-08-20 17:00:21 -07001023
1024 sp<AMessage> response = new AMessage;
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001025 status_t err = doSelectTrack(trackIndex, select, timeUs);
Robert Shih17f6dd62014-08-20 17:00:21 -07001026 response->setInt32("err", err);
1027
Lajos Molnar3f274362015-03-05 14:35:41 -08001028 sp<AReplyToken> replyID;
Robert Shih17f6dd62014-08-20 17:00:21 -07001029 CHECK(msg->senderAwaitsResponse(&replyID));
1030 response->postReply(replyID);
1031}
1032
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001033status_t NuPlayer::GenericSource::doSelectTrack(size_t trackIndex, bool select, int64_t timeUs) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001034 if (trackIndex >= mSources.size()) {
1035 return BAD_INDEX;
1036 }
1037
1038 if (!select) {
Lajos Molnare26940f2014-07-31 10:31:26 -07001039 Track* track = NULL;
1040 if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) {
1041 track = &mSubtitleTrack;
1042 mFetchSubtitleDataGeneration++;
1043 } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) {
1044 track = &mTimedTextTrack;
1045 mFetchTimedTextDataGeneration++;
1046 }
1047 if (track == NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001048 return INVALID_OPERATION;
1049 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001050 track->mSource->stop();
1051 track->mSource = NULL;
1052 track->mPackets->clear();
Robert Shih3423bbd2014-07-16 15:47:09 -07001053 return OK;
1054 }
1055
Marco Nelissenb2487f02015-09-01 13:23:23 -07001056 const sp<IMediaSource> source = mSources.itemAt(trackIndex);
Robert Shih3423bbd2014-07-16 15:47:09 -07001057 sp<MetaData> meta = source->getFormat();
1058 const char *mime;
1059 CHECK(meta->findCString(kKeyMIMEType, &mime));
1060 if (!strncasecmp(mime, "text/", 5)) {
Lajos Molnare26940f2014-07-31 10:31:26 -07001061 bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP);
1062 Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack;
1063 if (track->mSource != NULL && track->mIndex == trackIndex) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001064 return OK;
1065 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001066 track->mIndex = trackIndex;
1067 if (track->mSource != NULL) {
1068 track->mSource->stop();
Robert Shih3423bbd2014-07-16 15:47:09 -07001069 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001070 track->mSource = mSources.itemAt(trackIndex);
1071 track->mSource->start();
1072 if (track->mPackets == NULL) {
1073 track->mPackets = new AnotherPacketSource(track->mSource->getFormat());
Robert Shih3423bbd2014-07-16 15:47:09 -07001074 } else {
Lajos Molnare26940f2014-07-31 10:31:26 -07001075 track->mPackets->clear();
1076 track->mPackets->setFormat(track->mSource->getFormat());
Robert Shih3423bbd2014-07-16 15:47:09 -07001077
1078 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001079
1080 if (isSubtitle) {
1081 mFetchSubtitleDataGeneration++;
1082 } else {
1083 mFetchTimedTextDataGeneration++;
1084 }
1085
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001086 status_t eosResult; // ignored
1087 if (mSubtitleTrack.mSource != NULL
1088 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001089 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001090 msg->setInt64("timeUs", timeUs);
1091 msg->setInt32("generation", mFetchSubtitleDataGeneration);
1092 msg->post();
1093 }
1094
Marco Nelissen55e2f4c2015-09-04 15:57:15 -07001095 sp<AMessage> msg2 = new AMessage(kWhatSendGlobalTimedTextData, this);
1096 msg2->setInt32("generation", mFetchTimedTextDataGeneration);
1097 msg2->post();
1098
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001099 if (mTimedTextTrack.mSource != NULL
1100 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001101 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001102 msg->setInt64("timeUs", timeUs);
1103 msg->setInt32("generation", mFetchTimedTextDataGeneration);
1104 msg->post();
1105 }
1106
Robert Shih3423bbd2014-07-16 15:47:09 -07001107 return OK;
1108 } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
1109 bool audio = !strncasecmp(mime, "audio/", 6);
1110 Track *track = audio ? &mAudioTrack : &mVideoTrack;
1111 if (track->mSource != NULL && track->mIndex == trackIndex) {
1112 return OK;
1113 }
1114
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001115 sp<AMessage> msg = new AMessage(kWhatChangeAVSource, this);
Robert Shih3423bbd2014-07-16 15:47:09 -07001116 msg->setInt32("trackIndex", trackIndex);
1117 msg->post();
1118 return OK;
1119 }
1120
1121 return INVALID_OPERATION;
1122}
1123
Wei Jiac5de0912016-11-18 10:22:14 -08001124status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001125 sp<AMessage> msg = new AMessage(kWhatSeek, this);
Robert Shih17f6dd62014-08-20 17:00:21 -07001126 msg->setInt64("seekTimeUs", seekTimeUs);
Wei Jiac5de0912016-11-18 10:22:14 -08001127 msg->setInt32("mode", mode);
Robert Shih17f6dd62014-08-20 17:00:21 -07001128
1129 sp<AMessage> response;
1130 status_t err = msg->postAndAwaitResponse(&response);
1131 if (err == OK && response != NULL) {
1132 CHECK(response->findInt32("err", &err));
1133 }
1134
1135 return err;
1136}
1137
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -07001138void NuPlayer::GenericSource::onSeek(const sp<AMessage>& msg) {
Robert Shih17f6dd62014-08-20 17:00:21 -07001139 int64_t seekTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -08001140 int32_t mode;
Robert Shih17f6dd62014-08-20 17:00:21 -07001141 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
Wei Jiac5de0912016-11-18 10:22:14 -08001142 CHECK(msg->findInt32("mode", &mode));
Robert Shih17f6dd62014-08-20 17:00:21 -07001143
1144 sp<AMessage> response = new AMessage;
Wei Jiac5de0912016-11-18 10:22:14 -08001145 status_t err = doSeek(seekTimeUs, (MediaPlayerSeekMode)mode);
Robert Shih17f6dd62014-08-20 17:00:21 -07001146 response->setInt32("err", err);
1147
Lajos Molnar3f274362015-03-05 14:35:41 -08001148 sp<AReplyToken> replyID;
Robert Shih17f6dd62014-08-20 17:00:21 -07001149 CHECK(msg->senderAwaitsResponse(&replyID));
1150 response->postReply(replyID);
1151}
1152
Wei Jiac5de0912016-11-18 10:22:14 -08001153status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
Wei Jia14532f22015-12-29 11:28:15 -08001154 mBufferingMonitor->updateDequeuedBufferTime(-1ll);
1155
Andy Hung2abde2c2014-09-30 14:40:32 -07001156 // If the Widevine source is stopped, do not attempt to read any
1157 // more buffers.
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001158 //
1159 // TODO: revisit after widevine is removed. May be able to
1160 // combine mStopRead with mStarted.
Andy Hung2abde2c2014-09-30 14:40:32 -07001161 if (mStopRead) {
1162 return INVALID_OPERATION;
1163 }
Andreas Huberafed0e12011-09-20 15:39:58 -07001164 if (mVideoTrack.mSource != NULL) {
1165 int64_t actualTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -08001166 readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, mode, &actualTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -07001167
Wei Jiac5de0912016-11-18 10:22:14 -08001168 if (mode != MediaPlayerSeekMode::SEEK_CLOSEST) {
Wei Jia5ec347f2016-11-01 17:07:54 -07001169 seekTimeUs = actualTimeUs;
1170 }
1171 mVideoLastDequeueTimeUs = actualTimeUs;
Andreas Huberafed0e12011-09-20 15:39:58 -07001172 }
1173
1174 if (mAudioTrack.mSource != NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001175 readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs);
Robert Shih5c67ddc2014-11-04 17:46:05 -08001176 mAudioLastDequeueTimeUs = seekTimeUs;
Andreas Huberafed0e12011-09-20 15:39:58 -07001177 }
1178
Ronghua Wu80276872014-08-28 15:50:29 -07001179 setDrmPlaybackStatusIfNeeded(Playback::START, seekTimeUs / 1000);
1180 if (!mStarted) {
1181 setDrmPlaybackStatusIfNeeded(Playback::PAUSE, 0);
1182 }
Chong Zhangefbb6192015-01-30 17:13:27 -08001183
1184 // If currently buffering, post kWhatBufferingEnd first, so that
1185 // NuPlayer resumes. Otherwise, if cache hits high watermark
1186 // before new polling happens, no one will resume the playback.
Wei Jia14532f22015-12-29 11:28:15 -08001187 mBufferingMonitor->stopBufferingIfNecessary();
1188 mBufferingMonitor->restartPollBuffering();
Chong Zhangefbb6192015-01-30 17:13:27 -08001189
Andreas Huberafed0e12011-09-20 15:39:58 -07001190 return OK;
1191}
1192
Robert Shih3423bbd2014-07-16 15:47:09 -07001193sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
1194 MediaBuffer* mb,
Wei Jia14486822016-11-02 17:51:30 -07001195 media_track_type trackType) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001196 bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
1197 size_t outLength = mb->range_length();
1198
1199 if (audio && mAudioIsVorbis) {
1200 outLength += sizeof(int32_t);
1201 }
1202
1203 sp<ABuffer> ab;
Chong Zhang42e81532014-12-01 13:44:26 -08001204 if (mIsSecure && !audio) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001205 // data is already provided in the buffer
1206 ab = new ABuffer(NULL, mb->range_length());
Robert Shih3423bbd2014-07-16 15:47:09 -07001207 mb->add_ref();
Wei Jia96e92b52014-09-18 17:36:20 -07001208 ab->setMediaBufferBase(mb);
Robert Shih3423bbd2014-07-16 15:47:09 -07001209 } else {
1210 ab = new ABuffer(outLength);
1211 memcpy(ab->data(),
1212 (const uint8_t *)mb->data() + mb->range_offset(),
1213 mb->range_length());
1214 }
1215
1216 if (audio && mAudioIsVorbis) {
1217 int32_t numPageSamples;
1218 if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
1219 numPageSamples = -1;
1220 }
1221
1222 uint8_t* abEnd = ab->data() + mb->range_length();
1223 memcpy(abEnd, &numPageSamples, sizeof(numPageSamples));
1224 }
1225
Lajos Molnare26940f2014-07-31 10:31:26 -07001226 sp<AMessage> meta = ab->meta();
1227
Robert Shih3423bbd2014-07-16 15:47:09 -07001228 int64_t timeUs;
1229 CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs));
Robert Shih3423bbd2014-07-16 15:47:09 -07001230 meta->setInt64("timeUs", timeUs);
1231
Praveen Chavanbbaa1442016-04-08 13:33:49 -07001232 if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
1233 int32_t layerId;
1234 if (mb->meta_data()->findInt32(kKeyTemporalLayerId, &layerId)) {
1235 meta->setInt32("temporal-layer-id", layerId);
1236 }
1237 }
1238
Lajos Molnare26940f2014-07-31 10:31:26 -07001239 if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
1240 const char *mime;
1241 CHECK(mTimedTextTrack.mSource != NULL
1242 && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime));
1243 meta->setString("mime", mime);
1244 }
1245
Robert Shih3423bbd2014-07-16 15:47:09 -07001246 int64_t durationUs;
1247 if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) {
1248 meta->setInt64("durationUs", durationUs);
1249 }
1250
1251 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
1252 meta->setInt32("trackIndex", mSubtitleTrack.mIndex);
1253 }
1254
Robert Shihf8bd8512015-04-23 16:39:18 -07001255 uint32_t dataType; // unused
1256 const void *seiData;
1257 size_t seiLength;
1258 if (mb->meta_data()->findData(kKeySEI, &dataType, &seiData, &seiLength)) {
1259 sp<ABuffer> sei = ABuffer::CreateAsCopy(seiData, seiLength);;
1260 meta->setBuffer("sei", sei);
1261 }
1262
Jaesung Chung3694d7c2015-10-21 11:41:38 +09001263 const void *mpegUserDataPointer;
1264 size_t mpegUserDataLength;
1265 if (mb->meta_data()->findData(
1266 kKeyMpegUserData, &dataType, &mpegUserDataPointer, &mpegUserDataLength)) {
1267 sp<ABuffer> mpegUserData = ABuffer::CreateAsCopy(mpegUserDataPointer, mpegUserDataLength);
1268 meta->setBuffer("mpegUserData", mpegUserData);
1269 }
1270
Robert Shih3423bbd2014-07-16 15:47:09 -07001271 mb->release();
1272 mb = NULL;
1273
1274 return ab;
1275}
1276
Robert Shih17f6dd62014-08-20 17:00:21 -07001277void NuPlayer::GenericSource::postReadBuffer(media_track_type trackType) {
Lajos Molnar84f52782014-09-11 10:01:55 -07001278 Mutex::Autolock _l(mReadBufferLock);
1279
1280 if ((mPendingReadBufferTypes & (1 << trackType)) == 0) {
1281 mPendingReadBufferTypes |= (1 << trackType);
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001282 sp<AMessage> msg = new AMessage(kWhatReadBuffer, this);
Lajos Molnar84f52782014-09-11 10:01:55 -07001283 msg->setInt32("trackType", trackType);
1284 msg->post();
1285 }
Robert Shih17f6dd62014-08-20 17:00:21 -07001286}
1287
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -07001288void NuPlayer::GenericSource::onReadBuffer(const sp<AMessage>& msg) {
Robert Shih17f6dd62014-08-20 17:00:21 -07001289 int32_t tmpType;
1290 CHECK(msg->findInt32("trackType", &tmpType));
1291 media_track_type trackType = (media_track_type)tmpType;
Chong Zhang42e81532014-12-01 13:44:26 -08001292 readBuffer(trackType);
Lajos Molnar84f52782014-09-11 10:01:55 -07001293 {
1294 // only protect the variable change, as readBuffer may
Chong Zhang42e81532014-12-01 13:44:26 -08001295 // take considerable time.
Lajos Molnar84f52782014-09-11 10:01:55 -07001296 Mutex::Autolock _l(mReadBufferLock);
1297 mPendingReadBufferTypes &= ~(1 << trackType);
1298 }
Robert Shih17f6dd62014-08-20 17:00:21 -07001299}
1300
Andreas Huberafed0e12011-09-20 15:39:58 -07001301void NuPlayer::GenericSource::readBuffer(
Wei Jiac5de0912016-11-18 10:22:14 -08001302 media_track_type trackType, int64_t seekTimeUs, MediaPlayerSeekMode mode,
Wei Jia5ec347f2016-11-01 17:07:54 -07001303 int64_t *actualTimeUs, bool formatChange) {
Andy Hung2abde2c2014-09-30 14:40:32 -07001304 // Do not read data if Widevine source is stopped
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001305 //
1306 // TODO: revisit after widevine is removed. May be able to
1307 // combine mStopRead with mStarted.
Andy Hung2abde2c2014-09-30 14:40:32 -07001308 if (mStopRead) {
1309 return;
1310 }
Robert Shih3423bbd2014-07-16 15:47:09 -07001311 Track *track;
Phil Burkc5cc2e22014-09-09 20:08:39 -07001312 size_t maxBuffers = 1;
Robert Shih3423bbd2014-07-16 15:47:09 -07001313 switch (trackType) {
1314 case MEDIA_TRACK_TYPE_VIDEO:
1315 track = &mVideoTrack;
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001316 maxBuffers = 8; // too large of a number may influence seeks
Robert Shih3423bbd2014-07-16 15:47:09 -07001317 break;
1318 case MEDIA_TRACK_TYPE_AUDIO:
1319 track = &mAudioTrack;
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001320 maxBuffers = 64;
Robert Shih3423bbd2014-07-16 15:47:09 -07001321 break;
1322 case MEDIA_TRACK_TYPE_SUBTITLE:
1323 track = &mSubtitleTrack;
1324 break;
Lajos Molnare26940f2014-07-31 10:31:26 -07001325 case MEDIA_TRACK_TYPE_TIMEDTEXT:
1326 track = &mTimedTextTrack;
1327 break;
Robert Shih3423bbd2014-07-16 15:47:09 -07001328 default:
1329 TRESPASS();
1330 }
1331
1332 if (track->mSource == NULL) {
1333 return;
1334 }
Andreas Huberafed0e12011-09-20 15:39:58 -07001335
1336 if (actualTimeUs) {
1337 *actualTimeUs = seekTimeUs;
1338 }
1339
1340 MediaSource::ReadOptions options;
1341
1342 bool seeking = false;
Andreas Huberafed0e12011-09-20 15:39:58 -07001343 if (seekTimeUs >= 0) {
Wei Jiac5de0912016-11-18 10:22:14 -08001344 options.setSeekTo(seekTimeUs, mode);
Andreas Huberafed0e12011-09-20 15:39:58 -07001345 seeking = true;
1346 }
1347
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001348 const bool couldReadMultiple = (track->mSource->supportReadMultiple());
Andy Hungcdeb6602016-06-28 17:21:44 -07001349
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001350 if (couldReadMultiple) {
Lajos Molnarcc227032014-07-17 15:33:06 -07001351 options.setNonBlocking();
1352 }
1353
Phil Burkc5cc2e22014-09-09 20:08:39 -07001354 for (size_t numBuffers = 0; numBuffers < maxBuffers; ) {
Wei Jia1f1fc452016-05-11 16:17:22 -07001355 Vector<MediaBuffer *> mediaBuffers;
1356 status_t err = NO_ERROR;
1357
Andy Hungcdeb6602016-06-28 17:21:44 -07001358 if (couldReadMultiple) {
1359 err = track->mSource->readMultiple(
1360 &mediaBuffers, maxBuffers - numBuffers, &options);
Wei Jia1f1fc452016-05-11 16:17:22 -07001361 } else {
1362 MediaBuffer *mbuf = NULL;
1363 err = track->mSource->read(&mbuf, &options);
1364 if (err == OK && mbuf != NULL) {
1365 mediaBuffers.push_back(mbuf);
1366 }
1367 }
Andreas Huberafed0e12011-09-20 15:39:58 -07001368
Andy Hungf59c0ba2016-06-15 17:59:30 -07001369 options.clearNonPersistent();
Andreas Huberafed0e12011-09-20 15:39:58 -07001370
Wei Jia1f1fc452016-05-11 16:17:22 -07001371 size_t id = 0;
1372 size_t count = mediaBuffers.size();
1373 for (; id < count; ++id) {
Ronghua Wu80276872014-08-28 15:50:29 -07001374 int64_t timeUs;
Wei Jia1f1fc452016-05-11 16:17:22 -07001375 MediaBuffer *mbuf = mediaBuffers[id];
Robert Shih3b9912b2016-04-07 16:56:54 -07001376 if (!mbuf->meta_data()->findInt64(kKeyTime, &timeUs)) {
1377 mbuf->meta_data()->dumpToLog();
1378 track->mPackets->signalEOS(ERROR_MALFORMED);
1379 break;
1380 }
Ronghua Wu80276872014-08-28 15:50:29 -07001381 if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
1382 mAudioTimeUs = timeUs;
Wei Jia14532f22015-12-29 11:28:15 -08001383 mBufferingMonitor->updateQueuedTime(true /* isAudio */, timeUs);
Ronghua Wu80276872014-08-28 15:50:29 -07001384 } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
1385 mVideoTimeUs = timeUs;
Wei Jia14532f22015-12-29 11:28:15 -08001386 mBufferingMonitor->updateQueuedTime(false /* isAudio */, timeUs);
Ronghua Wu80276872014-08-28 15:50:29 -07001387 }
1388
Ronghua Wu8f291bc2015-05-19 10:11:53 -07001389 queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
Andreas Huberafed0e12011-09-20 15:39:58 -07001390
Wei Jia14486822016-11-02 17:51:30 -07001391 sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType);
1392 if (numBuffers == 0 && actualTimeUs != nullptr) {
1393 *actualTimeUs = timeUs;
1394 }
1395 if (seeking && buffer != nullptr) {
1396 sp<AMessage> meta = buffer->meta();
Wei Jiac5de0912016-11-18 10:22:14 -08001397 if (meta != nullptr && mode == MediaPlayerSeekMode::SEEK_CLOSEST
1398 && seekTimeUs > timeUs) {
Wei Jia14486822016-11-02 17:51:30 -07001399 sp<AMessage> extra = new AMessage;
1400 extra->setInt64("resume-at-mediaTimeUs", seekTimeUs);
1401 meta->setMessage("extra", extra);
1402 }
1403 }
1404
Andreas Huberafed0e12011-09-20 15:39:58 -07001405 track->mPackets->queueAccessUnit(buffer);
Marco Nelissen317a49a2014-09-16 21:32:33 -07001406 formatChange = false;
1407 seeking = false;
Phil Burkc5cc2e22014-09-09 20:08:39 -07001408 ++numBuffers;
Wei Jia1f1fc452016-05-11 16:17:22 -07001409 }
1410 if (id < count) {
1411 // Error, some mediaBuffer doesn't have kKeyTime.
1412 for (; id < count; ++id) {
1413 mediaBuffers[id]->release();
1414 }
1415 break;
1416 }
1417
1418 if (err == WOULD_BLOCK) {
Lajos Molnarcc227032014-07-17 15:33:06 -07001419 break;
Andreas Huberafed0e12011-09-20 15:39:58 -07001420 } else if (err == INFO_FORMAT_CHANGED) {
1421#if 0
1422 track->mPackets->queueDiscontinuity(
Chong Zhang632740c2014-06-26 13:03:47 -07001423 ATSParser::DISCONTINUITY_FORMATCHANGE,
1424 NULL,
1425 false /* discard */);
Andreas Huberafed0e12011-09-20 15:39:58 -07001426#endif
Wei Jia1f1fc452016-05-11 16:17:22 -07001427 } else if (err != OK) {
Ronghua Wu8f291bc2015-05-19 10:11:53 -07001428 queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
Andreas Huberafed0e12011-09-20 15:39:58 -07001429 track->mPackets->signalEOS(err);
1430 break;
1431 }
1432 }
1433}
1434
Ronghua Wu8f291bc2015-05-19 10:11:53 -07001435void NuPlayer::GenericSource::queueDiscontinuityIfNeeded(
1436 bool seeking, bool formatChange, media_track_type trackType, Track *track) {
1437 // formatChange && seeking: track whose source is changed during selection
1438 // formatChange && !seeking: track whose source is not changed during selection
1439 // !formatChange: normal seek
1440 if ((seeking || formatChange)
1441 && (trackType == MEDIA_TRACK_TYPE_AUDIO
1442 || trackType == MEDIA_TRACK_TYPE_VIDEO)) {
1443 ATSParser::DiscontinuityType type = (formatChange && seeking)
1444 ? ATSParser::DISCONTINUITY_FORMATCHANGE
1445 : ATSParser::DISCONTINUITY_NONE;
1446 track->mPackets->queueDiscontinuity(type, NULL /* extra */, true /* discard */);
1447 }
1448}
1449
Wei Jia14532f22015-12-29 11:28:15 -08001450NuPlayer::GenericSource::BufferingMonitor::BufferingMonitor(const sp<AMessage> &notify)
1451 : mNotify(notify),
1452 mDurationUs(-1ll),
1453 mBitrate(-1ll),
1454 mIsStreaming(false),
1455 mAudioTimeUs(0),
1456 mVideoTimeUs(0),
1457 mPollBufferingGeneration(0),
1458 mPrepareBuffering(false),
1459 mBuffering(false),
1460 mPrevBufferPercentage(-1),
1461 mOffloadAudio(false),
1462 mFirstDequeuedBufferRealUs(-1ll),
1463 mFirstDequeuedBufferMediaUs(-1ll),
1464 mlastDequeuedBufferMediaUs(-1ll) {
Wei Jia48fa06d2016-12-20 15:30:49 -08001465 getDefaultBufferingSettings(&mSettings);
Wei Jia14532f22015-12-29 11:28:15 -08001466}
1467
1468NuPlayer::GenericSource::BufferingMonitor::~BufferingMonitor() {
1469}
1470
Wei Jia48fa06d2016-12-20 15:30:49 -08001471void NuPlayer::GenericSource::BufferingMonitor::getDefaultBufferingSettings(
1472 BufferingSettings *buffering /* nonnull */) {
1473 buffering->mInitialBufferingMode = BUFFERING_MODE_TIME_ONLY;
1474 buffering->mRebufferingMode = BUFFERING_MODE_TIME_THEN_SIZE;
1475 buffering->mInitialWatermarkMs = kHighWaterMarkMs;
1476 buffering->mRebufferingWatermarkLowMs = kLowWaterMarkMs;
1477 buffering->mRebufferingWatermarkHighMs = kHighWaterMarkRebufferMs;
1478 buffering->mRebufferingWatermarkLowKB = kLowWaterMarkKB;
1479 buffering->mRebufferingWatermarkHighKB = kHighWaterMarkKB;
1480}
1481
1482status_t NuPlayer::GenericSource::BufferingMonitor::setBufferingSettings(
1483 const BufferingSettings &buffering) {
1484 Mutex::Autolock _l(mLock);
1485 if (buffering.IsSizeBasedBufferingMode(buffering.mInitialBufferingMode)
1486 || (buffering.IsTimeBasedBufferingMode(buffering.mRebufferingMode)
1487 && buffering.mRebufferingWatermarkLowMs > buffering.mRebufferingWatermarkHighMs)
1488 || (buffering.IsSizeBasedBufferingMode(buffering.mRebufferingMode)
1489 && buffering.mRebufferingWatermarkLowKB > buffering.mRebufferingWatermarkHighKB)) {
1490 return BAD_VALUE;
1491 }
1492 mSettings = buffering;
1493 if (mSettings.mInitialBufferingMode == BUFFERING_MODE_NONE) {
1494 mSettings.mInitialWatermarkMs = BufferingSettings::kNoWatermark;
1495 }
1496 if (!mSettings.IsTimeBasedBufferingMode(mSettings.mRebufferingMode)) {
1497 mSettings.mRebufferingWatermarkLowMs = BufferingSettings::kNoWatermark;
1498 mSettings.mRebufferingWatermarkHighMs = INT32_MAX;
1499 }
1500 if (!mSettings.IsSizeBasedBufferingMode(mSettings.mRebufferingMode)) {
1501 mSettings.mRebufferingWatermarkLowKB = BufferingSettings::kNoWatermark;
1502 mSettings.mRebufferingWatermarkHighKB = INT32_MAX;
1503 }
1504 return OK;
1505}
1506
Wei Jia14532f22015-12-29 11:28:15 -08001507void NuPlayer::GenericSource::BufferingMonitor::prepare(
1508 const sp<NuCachedSource2> &cachedSource,
Wei Jia14532f22015-12-29 11:28:15 -08001509 int64_t durationUs,
1510 int64_t bitrate,
1511 bool isStreaming) {
1512 Mutex::Autolock _l(mLock);
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001513 prepare_l(cachedSource, durationUs, bitrate, isStreaming);
Wei Jia14532f22015-12-29 11:28:15 -08001514}
1515
1516void NuPlayer::GenericSource::BufferingMonitor::stop() {
1517 Mutex::Autolock _l(mLock);
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001518 prepare_l(NULL /* cachedSource */, -1 /* durationUs */,
Wei Jia14532f22015-12-29 11:28:15 -08001519 -1 /* bitrate */, false /* isStreaming */);
1520}
1521
1522void NuPlayer::GenericSource::BufferingMonitor::cancelPollBuffering() {
1523 Mutex::Autolock _l(mLock);
1524 cancelPollBuffering_l();
1525}
1526
1527void NuPlayer::GenericSource::BufferingMonitor::restartPollBuffering() {
1528 Mutex::Autolock _l(mLock);
1529 if (mIsStreaming) {
1530 cancelPollBuffering_l();
1531 onPollBuffering_l();
1532 }
1533}
1534
1535void NuPlayer::GenericSource::BufferingMonitor::stopBufferingIfNecessary() {
1536 Mutex::Autolock _l(mLock);
1537 stopBufferingIfNecessary_l();
1538}
1539
1540void NuPlayer::GenericSource::BufferingMonitor::ensureCacheIsFetching() {
1541 Mutex::Autolock _l(mLock);
1542 ensureCacheIsFetching_l();
1543}
1544
1545void NuPlayer::GenericSource::BufferingMonitor::updateQueuedTime(bool isAudio, int64_t timeUs) {
1546 Mutex::Autolock _l(mLock);
1547 if (isAudio) {
1548 mAudioTimeUs = timeUs;
1549 } else {
1550 mVideoTimeUs = timeUs;
1551 }
1552}
1553
1554void NuPlayer::GenericSource::BufferingMonitor::setOffloadAudio(bool offload) {
1555 Mutex::Autolock _l(mLock);
1556 mOffloadAudio = offload;
1557}
1558
1559void NuPlayer::GenericSource::BufferingMonitor::updateDequeuedBufferTime(int64_t mediaUs) {
1560 Mutex::Autolock _l(mLock);
1561 if (mediaUs < 0) {
1562 mFirstDequeuedBufferRealUs = -1ll;
1563 mFirstDequeuedBufferMediaUs = -1ll;
1564 } else if (mFirstDequeuedBufferRealUs < 0) {
1565 mFirstDequeuedBufferRealUs = ALooper::GetNowUs();
1566 mFirstDequeuedBufferMediaUs = mediaUs;
1567 }
1568 mlastDequeuedBufferMediaUs = mediaUs;
1569}
1570
1571void NuPlayer::GenericSource::BufferingMonitor::prepare_l(
1572 const sp<NuCachedSource2> &cachedSource,
Wei Jia14532f22015-12-29 11:28:15 -08001573 int64_t durationUs,
1574 int64_t bitrate,
1575 bool isStreaming) {
Wei Jia14532f22015-12-29 11:28:15 -08001576
1577 mCachedSource = cachedSource;
Wei Jia14532f22015-12-29 11:28:15 -08001578 mDurationUs = durationUs;
1579 mBitrate = bitrate;
1580 mIsStreaming = isStreaming;
1581 mAudioTimeUs = 0;
1582 mVideoTimeUs = 0;
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001583 mPrepareBuffering = (cachedSource != NULL);
Wei Jia14532f22015-12-29 11:28:15 -08001584 cancelPollBuffering_l();
1585 mOffloadAudio = false;
1586 mFirstDequeuedBufferRealUs = -1ll;
1587 mFirstDequeuedBufferMediaUs = -1ll;
1588 mlastDequeuedBufferMediaUs = -1ll;
1589}
1590
1591void NuPlayer::GenericSource::BufferingMonitor::cancelPollBuffering_l() {
1592 mBuffering = false;
1593 ++mPollBufferingGeneration;
1594 mPrevBufferPercentage = -1;
1595}
1596
1597void NuPlayer::GenericSource::BufferingMonitor::notifyBufferingUpdate_l(int32_t percentage) {
1598 // Buffering percent could go backward as it's estimated from remaining
1599 // data and last access time. This could cause the buffering position
1600 // drawn on media control to jitter slightly. Remember previously reported
1601 // percentage and don't allow it to go backward.
1602 if (percentage < mPrevBufferPercentage) {
1603 percentage = mPrevBufferPercentage;
1604 } else if (percentage > 100) {
1605 percentage = 100;
1606 }
1607
1608 mPrevBufferPercentage = percentage;
1609
1610 ALOGV("notifyBufferingUpdate_l: buffering %d%%", percentage);
1611
1612 sp<AMessage> msg = mNotify->dup();
1613 msg->setInt32("what", kWhatBufferingUpdate);
1614 msg->setInt32("percentage", percentage);
1615 msg->post();
1616}
1617
1618void NuPlayer::GenericSource::BufferingMonitor::startBufferingIfNecessary_l() {
Wei Jia14532f22015-12-29 11:28:15 -08001619 if (mPrepareBuffering) {
1620 return;
1621 }
1622
1623 if (!mBuffering) {
Wei Jia4d71c022016-04-26 17:18:18 -07001624 ALOGD("startBufferingIfNecessary_l");
1625
Wei Jia14532f22015-12-29 11:28:15 -08001626 mBuffering = true;
1627
1628 ensureCacheIsFetching_l();
1629 sendCacheStats_l();
1630
1631 sp<AMessage> notify = mNotify->dup();
1632 notify->setInt32("what", kWhatPauseOnBufferingStart);
1633 notify->post();
1634 }
1635}
1636
1637void NuPlayer::GenericSource::BufferingMonitor::stopBufferingIfNecessary_l() {
Wei Jia14532f22015-12-29 11:28:15 -08001638 if (mPrepareBuffering) {
Wei Jia4d71c022016-04-26 17:18:18 -07001639 ALOGD("stopBufferingIfNecessary_l, mBuffering=%d", mBuffering);
1640
Wei Jia14532f22015-12-29 11:28:15 -08001641 mPrepareBuffering = false;
1642
1643 sp<AMessage> notify = mNotify->dup();
1644 notify->setInt32("what", kWhatPrepared);
1645 notify->setInt32("err", OK);
1646 notify->post();
1647
1648 return;
1649 }
1650
1651 if (mBuffering) {
Wei Jia4d71c022016-04-26 17:18:18 -07001652 ALOGD("stopBufferingIfNecessary_l");
Wei Jia14532f22015-12-29 11:28:15 -08001653 mBuffering = false;
1654
1655 sendCacheStats_l();
1656
1657 sp<AMessage> notify = mNotify->dup();
1658 notify->setInt32("what", kWhatResumeOnBufferingEnd);
1659 notify->post();
1660 }
1661}
1662
1663void NuPlayer::GenericSource::BufferingMonitor::sendCacheStats_l() {
1664 int32_t kbps = 0;
1665 status_t err = UNKNOWN_ERROR;
1666
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001667 if (mCachedSource != NULL) {
Wei Jia14532f22015-12-29 11:28:15 -08001668 err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
1669 }
1670
1671 if (err == OK) {
1672 sp<AMessage> notify = mNotify->dup();
1673 notify->setInt32("what", kWhatCacheStats);
1674 notify->setInt32("bandwidth", kbps);
1675 notify->post();
1676 }
1677}
1678
1679void NuPlayer::GenericSource::BufferingMonitor::ensureCacheIsFetching_l() {
1680 if (mCachedSource != NULL) {
1681 mCachedSource->resumeFetchingIfNecessary();
1682 }
1683}
1684
1685void NuPlayer::GenericSource::BufferingMonitor::schedulePollBuffering_l() {
1686 sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
1687 msg->setInt32("generation", mPollBufferingGeneration);
1688 // Enquires buffering status every second.
1689 msg->post(1000000ll);
1690}
1691
1692int64_t NuPlayer::GenericSource::BufferingMonitor::getLastReadPosition_l() {
1693 if (mAudioTimeUs > 0) {
1694 return mAudioTimeUs;
1695 } else if (mVideoTimeUs > 0) {
1696 return mVideoTimeUs;
1697 } else {
1698 return 0;
1699 }
1700}
1701
1702void NuPlayer::GenericSource::BufferingMonitor::onPollBuffering_l() {
1703 status_t finalStatus = UNKNOWN_ERROR;
1704 int64_t cachedDurationUs = -1ll;
1705 ssize_t cachedDataRemaining = -1;
1706
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001707 if (mCachedSource != NULL) {
Wei Jia14532f22015-12-29 11:28:15 -08001708 cachedDataRemaining =
1709 mCachedSource->approxDataRemaining(&finalStatus);
1710
1711 if (finalStatus == OK) {
1712 off64_t size;
1713 int64_t bitrate = 0ll;
1714 if (mDurationUs > 0 && mCachedSource->getSize(&size) == OK) {
1715 // |bitrate| uses bits/second unit, while size is number of bytes.
1716 bitrate = size * 8000000ll / mDurationUs;
1717 } else if (mBitrate > 0) {
1718 bitrate = mBitrate;
1719 }
1720 if (bitrate > 0) {
1721 cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate;
1722 }
1723 }
1724 }
1725
1726 if (finalStatus != OK) {
1727 ALOGV("onPollBuffering_l: EOS (finalStatus = %d)", finalStatus);
1728
1729 if (finalStatus == ERROR_END_OF_STREAM) {
1730 notifyBufferingUpdate_l(100);
1731 }
1732
1733 stopBufferingIfNecessary_l();
1734 return;
Wei Jia48fa06d2016-12-20 15:30:49 -08001735 }
1736
1737 if (cachedDurationUs >= 0ll) {
Wei Jia14532f22015-12-29 11:28:15 -08001738 if (mDurationUs > 0ll) {
1739 int64_t cachedPosUs = getLastReadPosition_l() + cachedDurationUs;
1740 int percentage = 100.0 * cachedPosUs / mDurationUs;
1741 if (percentage > 100) {
1742 percentage = 100;
1743 }
1744
1745 notifyBufferingUpdate_l(percentage);
1746 }
1747
Wei Jia48fa06d2016-12-20 15:30:49 -08001748 ALOGV("onPollBuffering_l: cachedDurationUs %.1f sec", cachedDurationUs / 1000000.0f);
Wei Jia14532f22015-12-29 11:28:15 -08001749
Wei Jia48fa06d2016-12-20 15:30:49 -08001750 if (mPrepareBuffering) {
1751 if (cachedDurationUs > mSettings.mInitialWatermarkMs * 1000) {
1752 stopBufferingIfNecessary_l();
1753 }
1754 } else if (mSettings.IsTimeBasedBufferingMode(mSettings.mRebufferingMode)) {
1755 if (cachedDurationUs < mSettings.mRebufferingWatermarkLowMs * 1000) {
1756 // Take into account the data cached in downstream components to try to avoid
1757 // unnecessary pause.
1758 if (mOffloadAudio && mFirstDequeuedBufferRealUs >= 0) {
1759 int64_t downStreamCacheUs =
1760 mlastDequeuedBufferMediaUs - mFirstDequeuedBufferMediaUs
1761 - (ALooper::GetNowUs() - mFirstDequeuedBufferRealUs);
1762 if (downStreamCacheUs > 0) {
1763 cachedDurationUs += downStreamCacheUs;
1764 }
Wei Jia14532f22015-12-29 11:28:15 -08001765 }
Wei Jia14532f22015-12-29 11:28:15 -08001766
Wei Jia48fa06d2016-12-20 15:30:49 -08001767 if (cachedDurationUs < mSettings.mRebufferingWatermarkLowMs * 1000) {
1768 startBufferingIfNecessary_l();
1769 }
1770 } else if (cachedDurationUs > mSettings.mRebufferingWatermarkHighMs * 1000) {
Wei Jia14532f22015-12-29 11:28:15 -08001771 stopBufferingIfNecessary_l();
1772 }
1773 }
Wei Jia48fa06d2016-12-20 15:30:49 -08001774 } else if (cachedDataRemaining >= 0
1775 && mSettings.IsSizeBasedBufferingMode(mSettings.mRebufferingMode)) {
Wei Jia14532f22015-12-29 11:28:15 -08001776 ALOGV("onPollBuffering_l: cachedDataRemaining %zd bytes",
1777 cachedDataRemaining);
1778
Wei Jia48fa06d2016-12-20 15:30:49 -08001779 if (cachedDataRemaining < (mSettings.mRebufferingWatermarkLowKB << 10)) {
Wei Jia14532f22015-12-29 11:28:15 -08001780 startBufferingIfNecessary_l();
Wei Jia48fa06d2016-12-20 15:30:49 -08001781 } else if (cachedDataRemaining > (mSettings.mRebufferingWatermarkHighKB << 10)) {
Wei Jia14532f22015-12-29 11:28:15 -08001782 stopBufferingIfNecessary_l();
1783 }
1784 }
1785
1786 schedulePollBuffering_l();
1787}
1788
1789void NuPlayer::GenericSource::BufferingMonitor::onMessageReceived(const sp<AMessage> &msg) {
1790 switch (msg->what()) {
1791 case kWhatPollBuffering:
1792 {
1793 int32_t generation;
1794 CHECK(msg->findInt32("generation", &generation));
1795 Mutex::Autolock _l(mLock);
1796 if (generation == mPollBufferingGeneration) {
1797 onPollBuffering_l();
1798 }
1799 break;
1800 }
1801 default:
1802 TRESPASS();
1803 break;
1804 }
1805}
1806
Andreas Huberafed0e12011-09-20 15:39:58 -07001807} // namespace android