blob: 3691c853dadd7df6f4bd55d9efb7a81b518b3ee8 [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>
Ronghua Wu80276872014-08-28 15:50:29 -070035#include "../../libstagefright/include/DRMExtractor.h"
Chong Zhangd354d8d2014-08-20 13:09:58 -070036#include "../../libstagefright/include/NuCachedSource2.h"
Lajos Molnarcc227032014-07-17 15:33:06 -070037#include "../../libstagefright/include/WVMExtractor.h"
Andreas Huberafed0e12011-09-20 15:39:58 -070038
39namespace android {
40
41NuPlayer::GenericSource::GenericSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080042 const sp<AMessage> &notify,
Lajos Molnarcc227032014-07-17 15:33:06 -070043 bool uidValid,
44 uid_t uid)
Andreas Huberb5f25f02013-02-05 10:14:26 -080045 : Source(notify),
Robert Shih3423bbd2014-07-16 15:47:09 -070046 mFetchSubtitleDataGeneration(0),
Lajos Molnare26940f2014-07-31 10:31:26 -070047 mFetchTimedTextDataGeneration(0),
Andreas Huberb5f25f02013-02-05 10:14:26 -080048 mDurationUs(0ll),
Lajos Molnarcc227032014-07-17 15:33:06 -070049 mAudioIsVorbis(false),
Chong Zhang3de157d2014-08-05 20:54:44 -070050 mIsWidevine(false),
Lajos Molnarcc227032014-07-17 15:33:06 -070051 mUIDValid(uidValid),
Chong Zhangd354d8d2014-08-20 13:09:58 -070052 mUID(uid),
Ronghua Wu80276872014-08-28 15:50:29 -070053 mDrmManagerClient(NULL),
Chong Zhang2a3cc9a2014-08-21 17:48:26 -070054 mMetaDataSize(-1ll),
55 mBitrate(-1ll),
56 mPollBufferingGeneration(0) {
Chong Zhanga19f33e2014-08-07 15:35:07 -070057 resetDataSource();
Andreas Huberafed0e12011-09-20 15:39:58 -070058 DataSource::RegisterDefaultSniffers();
Chong Zhang3de157d2014-08-05 20:54:44 -070059}
60
Chong Zhanga19f33e2014-08-07 15:35:07 -070061void NuPlayer::GenericSource::resetDataSource() {
Ronghua Wu80276872014-08-28 15:50:29 -070062 mAudioTimeUs = 0;
63 mVideoTimeUs = 0;
Chong Zhanga19f33e2014-08-07 15:35:07 -070064 mHTTPService.clear();
65 mUri.clear();
66 mUriHeaders.clear();
67 mFd = -1;
68 mOffset = 0;
69 mLength = 0;
Ronghua Wu80276872014-08-28 15:50:29 -070070 setDrmPlaybackStatusIfNeeded(Playback::STOP, 0);
71 mDecryptHandle = NULL;
72 mDrmManagerClient = NULL;
73 mStarted = false;
Chong Zhanga19f33e2014-08-07 15:35:07 -070074}
75
76status_t NuPlayer::GenericSource::setDataSource(
Chong Zhang3de157d2014-08-05 20:54:44 -070077 const sp<IMediaHTTPService> &httpService,
78 const char *url,
79 const KeyedVector<String8, String8> *headers) {
Chong Zhanga19f33e2014-08-07 15:35:07 -070080 resetDataSource();
Chong Zhang3de157d2014-08-05 20:54:44 -070081
Chong Zhanga19f33e2014-08-07 15:35:07 -070082 mHTTPService = httpService;
83 mUri = url;
Andreas Huberafed0e12011-09-20 15:39:58 -070084
Chong Zhanga19f33e2014-08-07 15:35:07 -070085 if (headers) {
86 mUriHeaders = *headers;
Chong Zhang3de157d2014-08-05 20:54:44 -070087 }
88
Chong Zhanga19f33e2014-08-07 15:35:07 -070089 // delay data source creation to prepareAsync() to avoid blocking
90 // the calling thread in setDataSource for any significant time.
91 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -070092}
93
Chong Zhanga19f33e2014-08-07 15:35:07 -070094status_t NuPlayer::GenericSource::setDataSource(
Chong Zhang3de157d2014-08-05 20:54:44 -070095 int fd, int64_t offset, int64_t length) {
Chong Zhanga19f33e2014-08-07 15:35:07 -070096 resetDataSource();
Andreas Huberafed0e12011-09-20 15:39:58 -070097
Chong Zhanga19f33e2014-08-07 15:35:07 -070098 mFd = dup(fd);
99 mOffset = offset;
100 mLength = length;
101
102 // delay data source creation to prepareAsync() to avoid blocking
103 // the calling thread in setDataSource for any significant time.
104 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700105}
106
Chong Zhangd354d8d2014-08-20 13:09:58 -0700107status_t NuPlayer::GenericSource::initFromDataSource() {
Lajos Molnarcc227032014-07-17 15:33:06 -0700108 sp<MediaExtractor> extractor;
109
Chong Zhangd354d8d2014-08-20 13:09:58 -0700110 CHECK(mDataSource != NULL);
111
Lajos Molnarcc227032014-07-17 15:33:06 -0700112 if (mIsWidevine) {
113 String8 mimeType;
114 float confidence;
115 sp<AMessage> dummy;
116 bool success;
117
Chong Zhangd354d8d2014-08-20 13:09:58 -0700118 success = SniffWVM(mDataSource, &mimeType, &confidence, &dummy);
Lajos Molnarcc227032014-07-17 15:33:06 -0700119 if (!success
120 || strcasecmp(
121 mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
122 ALOGE("unsupported widevine mime: %s", mimeType.string());
Chong Zhang3de157d2014-08-05 20:54:44 -0700123 return UNKNOWN_ERROR;
Lajos Molnarcc227032014-07-17 15:33:06 -0700124 }
125
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700126 mWVMExtractor = new WVMExtractor(mDataSource);
127 mWVMExtractor->setAdaptiveStreamingMode(true);
Lajos Molnarcc227032014-07-17 15:33:06 -0700128 if (mUIDValid) {
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700129 mWVMExtractor->setUID(mUID);
Lajos Molnarcc227032014-07-17 15:33:06 -0700130 }
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700131 extractor = mWVMExtractor;
Lajos Molnarcc227032014-07-17 15:33:06 -0700132 } else {
Chong Zhangd354d8d2014-08-20 13:09:58 -0700133 extractor = MediaExtractor::Create(mDataSource,
134 mSniffedMIME.empty() ? NULL: mSniffedMIME.c_str());
Lajos Molnarcc227032014-07-17 15:33:06 -0700135 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700136
Chong Zhang3de157d2014-08-05 20:54:44 -0700137 if (extractor == NULL) {
138 return UNKNOWN_ERROR;
139 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700140
Ronghua Wu80276872014-08-28 15:50:29 -0700141 if (extractor->getDrmFlag()) {
142 checkDrmStatus(mDataSource);
143 }
144
Marco Nelissenc1f4b2b2014-06-17 14:48:32 -0700145 sp<MetaData> fileMeta = extractor->getMetaData();
146 if (fileMeta != NULL) {
147 int64_t duration;
148 if (fileMeta->findInt64(kKeyDuration, &duration)) {
149 mDurationUs = duration;
150 }
151 }
152
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700153 int32_t totalBitrate = 0;
154
Andreas Huberafed0e12011-09-20 15:39:58 -0700155 for (size_t i = 0; i < extractor->countTracks(); ++i) {
156 sp<MetaData> meta = extractor->getTrackMetaData(i);
157
158 const char *mime;
159 CHECK(meta->findCString(kKeyMIMEType, &mime));
160
Robert Shihdd235722014-06-12 14:49:23 -0700161 sp<MediaSource> track = extractor->getTrack(i);
Andreas Huberafed0e12011-09-20 15:39:58 -0700162
163 if (!strncasecmp(mime, "audio/", 6)) {
164 if (mAudioTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700165 mAudioTrack.mIndex = i;
166 mAudioTrack.mSource = track;
Andreas Huberafed0e12011-09-20 15:39:58 -0700167
168 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
169 mAudioIsVorbis = true;
170 } else {
171 mAudioIsVorbis = false;
172 }
173 }
174 } else if (!strncasecmp(mime, "video/", 6)) {
175 if (mVideoTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700176 mVideoTrack.mIndex = i;
177 mVideoTrack.mSource = track;
Chong Zhang7e892182014-08-05 11:58:21 -0700178
179 // check if the source requires secure buffers
180 int32_t secure;
Chong Zhanga19f33e2014-08-07 15:35:07 -0700181 if (meta->findInt32(kKeyRequiresSecureBuffers, &secure)
182 && secure) {
Chong Zhang7e892182014-08-05 11:58:21 -0700183 mIsWidevine = true;
Chong Zhang3de157d2014-08-05 20:54:44 -0700184 if (mUIDValid) {
185 extractor->setUID(mUID);
186 }
Chong Zhang7e892182014-08-05 11:58:21 -0700187 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700188 }
189 }
190
191 if (track != NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700192 mSources.push(track);
Andreas Huberafed0e12011-09-20 15:39:58 -0700193 int64_t durationUs;
194 if (meta->findInt64(kKeyDuration, &durationUs)) {
195 if (durationUs > mDurationUs) {
196 mDurationUs = durationUs;
197 }
198 }
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700199
200 int32_t bitrate;
201 if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) {
202 totalBitrate += bitrate;
203 } else {
204 totalBitrate = -1;
205 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700206 }
207 }
Chong Zhang3de157d2014-08-05 20:54:44 -0700208
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700209 mBitrate = totalBitrate;
210
Chong Zhang3de157d2014-08-05 20:54:44 -0700211 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700212}
213
Ronghua Wu80276872014-08-28 15:50:29 -0700214void NuPlayer::GenericSource::checkDrmStatus(const sp<DataSource>& dataSource) {
215 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
216 if (mDecryptHandle != NULL) {
217 CHECK(mDrmManagerClient);
218 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
219 sp<AMessage> msg = dupNotify();
220 msg->setInt32("what", kWhatDrmNoLicense);
221 msg->post();
222 }
223 }
224}
225
226int64_t NuPlayer::GenericSource::getLastReadPosition() {
227 if (mAudioTrack.mSource != NULL) {
228 return mAudioTimeUs;
229 } else if (mVideoTrack.mSource != NULL) {
230 return mVideoTimeUs;
231 } else {
232 return 0;
233 }
234}
235
Chong Zhanga19f33e2014-08-07 15:35:07 -0700236status_t NuPlayer::GenericSource::setBuffers(
237 bool audio, Vector<MediaBuffer *> &buffers) {
Lajos Molnarcc227032014-07-17 15:33:06 -0700238 if (mIsWidevine && !audio) {
239 return mVideoTrack.mSource->setBuffers(buffers);
240 }
241 return INVALID_OPERATION;
242}
243
Andreas Huberafed0e12011-09-20 15:39:58 -0700244NuPlayer::GenericSource::~GenericSource() {
Chong Zhang1228d6b2014-08-12 21:25:48 -0700245 if (mLooper != NULL) {
246 mLooper->unregisterHandler(id());
247 mLooper->stop();
248 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700249}
250
Andreas Huber9575c962013-02-05 13:59:56 -0800251void NuPlayer::GenericSource::prepareAsync() {
Chong Zhang1228d6b2014-08-12 21:25:48 -0700252 if (mLooper == NULL) {
253 mLooper = new ALooper;
254 mLooper->setName("generic");
255 mLooper->start();
256
257 mLooper->registerHandler(this);
258 }
259
260 sp<AMessage> msg = new AMessage(kWhatPrepareAsync, id());
261 msg->post();
262}
263
264void NuPlayer::GenericSource::onPrepareAsync() {
Chong Zhanga19f33e2014-08-07 15:35:07 -0700265 // delayed data source creation
Chong Zhangd354d8d2014-08-20 13:09:58 -0700266 if (mDataSource == NULL) {
267 if (!mUri.empty()) {
268 mIsWidevine = !strncasecmp(mUri.c_str(), "widevine://", 11);
Chong Zhanga19f33e2014-08-07 15:35:07 -0700269
Chong Zhangd354d8d2014-08-20 13:09:58 -0700270 mDataSource = DataSource::CreateFromURI(
271 mHTTPService, mUri.c_str(), &mUriHeaders, &mContentType);
272 } else {
273 // set to false first, if the extractor
274 // comes back as secure, set it to true then.
275 mIsWidevine = false;
Chong Zhanga19f33e2014-08-07 15:35:07 -0700276
Chong Zhangd354d8d2014-08-20 13:09:58 -0700277 mDataSource = new FileSource(mFd, mOffset, mLength);
278 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700279
Chong Zhangd354d8d2014-08-20 13:09:58 -0700280 if (mDataSource == NULL) {
281 ALOGE("Failed to create data source!");
282 notifyPreparedAndCleanup(UNKNOWN_ERROR);
283 return;
284 }
285
286 if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
287 mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
288 }
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700289
290 if (mIsWidevine || mCachedSource != NULL) {
291 schedulePollBuffering();
292 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700293 }
294
Chong Zhangd354d8d2014-08-20 13:09:58 -0700295 // check initial caching status
296 status_t err = prefillCacheIfNecessary();
297 if (err != OK) {
298 if (err == -EAGAIN) {
299 (new AMessage(kWhatPrepareAsync, id()))->post(200000);
300 } else {
301 ALOGE("Failed to prefill data cache!");
302 notifyPreparedAndCleanup(UNKNOWN_ERROR);
303 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700304 return;
305 }
306
Chong Zhangd354d8d2014-08-20 13:09:58 -0700307 // init extrator from data source
308 err = initFromDataSource();
Chong Zhanga19f33e2014-08-07 15:35:07 -0700309
310 if (err != OK) {
311 ALOGE("Failed to init from data source!");
Chong Zhangd354d8d2014-08-20 13:09:58 -0700312 notifyPreparedAndCleanup(err);
Chong Zhanga19f33e2014-08-07 15:35:07 -0700313 return;
314 }
315
Andreas Huber9575c962013-02-05 13:59:56 -0800316 if (mVideoTrack.mSource != NULL) {
Chong Zhangced1c2f2014-08-08 15:22:35 -0700317 notifyVideoSizeChanged(getFormat(false /* audio */));
Andreas Huber9575c962013-02-05 13:59:56 -0800318 }
319
320 notifyFlagsChanged(
Lajos Molnarcc227032014-07-17 15:33:06 -0700321 (mIsWidevine ? FLAG_SECURE : 0)
322 | FLAG_CAN_PAUSE
Andreas Huber9575c962013-02-05 13:59:56 -0800323 | FLAG_CAN_SEEK_BACKWARD
324 | FLAG_CAN_SEEK_FORWARD
325 | FLAG_CAN_SEEK);
326
327 notifyPrepared();
328}
329
Chong Zhangd354d8d2014-08-20 13:09:58 -0700330void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
331 if (err != OK) {
332 mMetaDataSize = -1ll;
333 mContentType = "";
334 mSniffedMIME = "";
335 mDataSource.clear();
336 mCachedSource.clear();
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700337
338 cancelPollBuffering();
Chong Zhangd354d8d2014-08-20 13:09:58 -0700339 }
340 notifyPrepared(err);
341}
342
343status_t NuPlayer::GenericSource::prefillCacheIfNecessary() {
344 CHECK(mDataSource != NULL);
345
346 if (mCachedSource == NULL) {
347 // no prefill if the data source is not cached
348 return OK;
349 }
350
351 // We're not doing this for streams that appear to be audio-only
352 // streams to ensure that even low bandwidth streams start
353 // playing back fairly instantly.
354 if (!strncasecmp(mContentType.string(), "audio/", 6)) {
355 return OK;
356 }
357
358 // We're going to prefill the cache before trying to instantiate
359 // the extractor below, as the latter is an operation that otherwise
360 // could block on the datasource for a significant amount of time.
361 // During that time we'd be unable to abort the preparation phase
362 // without this prefill.
363
364 // Initially make sure we have at least 192 KB for the sniff
365 // to complete without blocking.
366 static const size_t kMinBytesForSniffing = 192 * 1024;
367 static const size_t kDefaultMetaSize = 200000;
368
369 status_t finalStatus;
370
371 size_t cachedDataRemaining =
372 mCachedSource->approxDataRemaining(&finalStatus);
373
374 if (finalStatus != OK || (mMetaDataSize >= 0
375 && (off64_t)cachedDataRemaining >= mMetaDataSize)) {
376 ALOGV("stop caching, status %d, "
377 "metaDataSize %lld, cachedDataRemaining %zu",
378 finalStatus, mMetaDataSize, cachedDataRemaining);
379 return OK;
380 }
381
382 ALOGV("now cached %zu bytes of data", cachedDataRemaining);
383
384 if (mMetaDataSize < 0
385 && cachedDataRemaining >= kMinBytesForSniffing) {
386 String8 tmp;
387 float confidence;
388 sp<AMessage> meta;
389 if (!mCachedSource->sniff(&tmp, &confidence, &meta)) {
390 return UNKNOWN_ERROR;
391 }
392
393 // We successfully identified the file's extractor to
394 // be, remember this mime type so we don't have to
395 // sniff it again when we call MediaExtractor::Create()
396 mSniffedMIME = tmp.string();
397
398 if (meta == NULL
399 || !meta->findInt64("meta-data-size",
400 reinterpret_cast<int64_t*>(&mMetaDataSize))) {
401 mMetaDataSize = kDefaultMetaSize;
402 }
403
404 if (mMetaDataSize < 0ll) {
405 ALOGE("invalid metaDataSize = %lld bytes", mMetaDataSize);
406 return UNKNOWN_ERROR;
407 }
408 }
409
410 return -EAGAIN;
411}
412
Andreas Huberafed0e12011-09-20 15:39:58 -0700413void NuPlayer::GenericSource::start() {
414 ALOGI("start");
415
416 if (mAudioTrack.mSource != NULL) {
Robert Shihbace25b2014-07-25 14:14:34 -0700417 CHECK_EQ(mAudioTrack.mSource->start(), (status_t)OK);
Andreas Huberafed0e12011-09-20 15:39:58 -0700418 mAudioTrack.mPackets =
419 new AnotherPacketSource(mAudioTrack.mSource->getFormat());
420
Robert Shih3423bbd2014-07-16 15:47:09 -0700421 readBuffer(MEDIA_TRACK_TYPE_AUDIO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700422 }
423
424 if (mVideoTrack.mSource != NULL) {
Robert Shihbace25b2014-07-25 14:14:34 -0700425 CHECK_EQ(mVideoTrack.mSource->start(), (status_t)OK);
Andreas Huberafed0e12011-09-20 15:39:58 -0700426 mVideoTrack.mPackets =
427 new AnotherPacketSource(mVideoTrack.mSource->getFormat());
428
Robert Shih3423bbd2014-07-16 15:47:09 -0700429 readBuffer(MEDIA_TRACK_TYPE_VIDEO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700430 }
Ronghua Wu80276872014-08-28 15:50:29 -0700431
432 setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000);
433 mStarted = true;
434}
435
436void NuPlayer::GenericSource::stop() {
437 // nothing to do, just account for DRM playback status
438 setDrmPlaybackStatusIfNeeded(Playback::STOP, 0);
439 mStarted = false;
440}
441
442void NuPlayer::GenericSource::pause() {
443 // nothing to do, just account for DRM playback status
444 setDrmPlaybackStatusIfNeeded(Playback::PAUSE, 0);
445 mStarted = false;
446}
447
448void NuPlayer::GenericSource::resume() {
449 // nothing to do, just account for DRM playback status
450 setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000);
451 mStarted = true;
452}
453
454void NuPlayer::GenericSource::setDrmPlaybackStatusIfNeeded(int playbackStatus, int64_t position) {
455 if (mDecryptHandle != NULL) {
456 mDrmManagerClient->setPlaybackStatus(mDecryptHandle, playbackStatus, position);
457 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700458}
459
460status_t NuPlayer::GenericSource::feedMoreTSData() {
461 return OK;
462}
463
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700464void NuPlayer::GenericSource::schedulePollBuffering() {
465 sp<AMessage> msg = new AMessage(kWhatPollBuffering, id());
466 msg->setInt32("generation", mPollBufferingGeneration);
467 msg->post(1000000ll);
468}
469
470void NuPlayer::GenericSource::cancelPollBuffering() {
471 ++mPollBufferingGeneration;
472}
473
474void NuPlayer::GenericSource::notifyBufferingUpdate(int percentage) {
475 sp<AMessage> msg = dupNotify();
476 msg->setInt32("what", kWhatBufferingUpdate);
477 msg->setInt32("percentage", percentage);
478 msg->post();
479}
480
481void NuPlayer::GenericSource::onPollBuffering() {
482 status_t finalStatus = UNKNOWN_ERROR;
483 int64_t cachedDurationUs = 0ll;
484
485 if (mCachedSource != NULL) {
486 size_t cachedDataRemaining =
487 mCachedSource->approxDataRemaining(&finalStatus);
488
489 if (finalStatus == OK) {
490 off64_t size;
491 int64_t bitrate = 0ll;
492 if (mDurationUs > 0 && mCachedSource->getSize(&size) == OK) {
493 bitrate = size * 8000000ll / mDurationUs;
494 } else if (mBitrate > 0) {
495 bitrate = mBitrate;
496 }
497 if (bitrate > 0) {
498 cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate;
499 }
500 }
501 } else if (mWVMExtractor != NULL) {
502 cachedDurationUs
503 = mWVMExtractor->getCachedDurationUs(&finalStatus);
504 }
505
506 if (finalStatus == ERROR_END_OF_STREAM) {
507 notifyBufferingUpdate(100);
508 cancelPollBuffering();
509 return;
510 } else if (cachedDurationUs > 0ll && mDurationUs > 0ll) {
511 int percentage = 100.0 * cachedDurationUs / mDurationUs;
512 if (percentage > 100) {
513 percentage = 100;
514 }
515
516 notifyBufferingUpdate(percentage);
517 }
518
519 schedulePollBuffering();
520}
521
522
Robert Shih3423bbd2014-07-16 15:47:09 -0700523void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
524 switch (msg->what()) {
Chong Zhang1228d6b2014-08-12 21:25:48 -0700525 case kWhatPrepareAsync:
526 {
527 onPrepareAsync();
528 break;
529 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700530 case kWhatFetchSubtitleData:
531 {
Lajos Molnare26940f2014-07-31 10:31:26 -0700532 fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
533 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
534 break;
535 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700536
Lajos Molnare26940f2014-07-31 10:31:26 -0700537 case kWhatFetchTimedTextData:
538 {
539 fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
540 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih3423bbd2014-07-16 15:47:09 -0700541 break;
542 }
543
544 case kWhatSendSubtitleData:
545 {
Lajos Molnare26940f2014-07-31 10:31:26 -0700546 sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
547 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
548 break;
549 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700550
Lajos Molnare26940f2014-07-31 10:31:26 -0700551 case kWhatSendTimedTextData:
552 {
553 sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
554 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih3423bbd2014-07-16 15:47:09 -0700555 break;
556 }
557
558 case kWhatChangeAVSource:
559 {
560 int32_t trackIndex;
561 CHECK(msg->findInt32("trackIndex", &trackIndex));
562 const sp<MediaSource> source = mSources.itemAt(trackIndex);
563
564 Track* track;
565 const char *mime;
566 media_track_type trackType, counterpartType;
567 sp<MetaData> meta = source->getFormat();
568 meta->findCString(kKeyMIMEType, &mime);
569 if (!strncasecmp(mime, "audio/", 6)) {
570 track = &mAudioTrack;
571 trackType = MEDIA_TRACK_TYPE_AUDIO;
572 counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
573 } else {
574 CHECK(!strncasecmp(mime, "video/", 6));
575 track = &mVideoTrack;
576 trackType = MEDIA_TRACK_TYPE_VIDEO;
577 counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
578 }
579
580
581 if (track->mSource != NULL) {
582 track->mSource->stop();
583 }
584 track->mSource = source;
585 track->mSource->start();
586 track->mIndex = trackIndex;
587
588 status_t avail;
589 if (!track->mPackets->hasBufferAvailable(&avail)) {
590 // sync from other source
591 TRESPASS();
592 break;
593 }
594
595 int64_t timeUs, actualTimeUs;
596 const bool formatChange = true;
Robert Shih309aa8b2014-07-29 18:34:36 -0700597 sp<AMessage> latestMeta = track->mPackets->getLatestEnqueuedMeta();
Robert Shih3423bbd2014-07-16 15:47:09 -0700598 CHECK(latestMeta != NULL && latestMeta->findInt64("timeUs", &timeUs));
599 readBuffer(trackType, timeUs, &actualTimeUs, formatChange);
600 readBuffer(counterpartType, -1, NULL, formatChange);
601 ALOGV("timeUs %lld actualTimeUs %lld", timeUs, actualTimeUs);
602
603 break;
604 }
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700605 case kWhatPollBuffering:
606 {
607 int32_t generation;
608 CHECK(msg->findInt32("generation", &generation));
609 if (generation == mPollBufferingGeneration) {
610 onPollBuffering();
611 }
612 break;
613 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700614 default:
615 Source::onMessageReceived(msg);
616 break;
617 }
618}
619
Lajos Molnare26940f2014-07-31 10:31:26 -0700620void NuPlayer::GenericSource::fetchTextData(
621 uint32_t sendWhat,
622 media_track_type type,
623 int32_t curGen,
624 sp<AnotherPacketSource> packets,
625 sp<AMessage> msg) {
626 int32_t msgGeneration;
627 CHECK(msg->findInt32("generation", &msgGeneration));
628 if (msgGeneration != curGen) {
629 // stale
630 return;
631 }
632
633 int32_t avail;
634 if (packets->hasBufferAvailable(&avail)) {
635 return;
636 }
637
638 int64_t timeUs;
639 CHECK(msg->findInt64("timeUs", &timeUs));
640
641 int64_t subTimeUs;
642 readBuffer(type, timeUs, &subTimeUs);
643
644 int64_t delayUs = subTimeUs - timeUs;
645 if (msg->what() == kWhatFetchSubtitleData) {
646 const int64_t oneSecUs = 1000000ll;
647 delayUs -= oneSecUs;
648 }
649 sp<AMessage> msg2 = new AMessage(sendWhat, id());
650 msg2->setInt32("generation", msgGeneration);
651 msg2->post(delayUs < 0 ? 0 : delayUs);
652}
653
654void NuPlayer::GenericSource::sendTextData(
655 uint32_t what,
656 media_track_type type,
657 int32_t curGen,
658 sp<AnotherPacketSource> packets,
659 sp<AMessage> msg) {
660 int32_t msgGeneration;
661 CHECK(msg->findInt32("generation", &msgGeneration));
662 if (msgGeneration != curGen) {
663 // stale
664 return;
665 }
666
667 int64_t subTimeUs;
668 if (packets->nextBufferTime(&subTimeUs) != OK) {
669 return;
670 }
671
672 int64_t nextSubTimeUs;
673 readBuffer(type, -1, &nextSubTimeUs);
674
675 sp<ABuffer> buffer;
676 status_t dequeueStatus = packets->dequeueAccessUnit(&buffer);
677 if (dequeueStatus == OK) {
678 sp<AMessage> notify = dupNotify();
679 notify->setInt32("what", what);
680 notify->setBuffer("buffer", buffer);
681 notify->post();
682
683 const int64_t delayUs = nextSubTimeUs - subTimeUs;
684 msg->post(delayUs < 0 ? 0 : delayUs);
685 }
686}
687
Andreas Huber84066782011-08-16 09:34:26 -0700688sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700689 sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
690
691 if (source == NULL) {
692 return NULL;
693 }
694
695 return source->getFormat();
696}
697
698status_t NuPlayer::GenericSource::dequeueAccessUnit(
699 bool audio, sp<ABuffer> *accessUnit) {
700 Track *track = audio ? &mAudioTrack : &mVideoTrack;
701
702 if (track->mSource == NULL) {
703 return -EWOULDBLOCK;
704 }
705
Lajos Molnarcc227032014-07-17 15:33:06 -0700706 if (mIsWidevine && !audio) {
707 // try to read a buffer as we may not have been able to the last time
Robert Shih3423bbd2014-07-16 15:47:09 -0700708 readBuffer(MEDIA_TRACK_TYPE_VIDEO, -1ll);
Lajos Molnarcc227032014-07-17 15:33:06 -0700709 }
710
Andreas Huberafed0e12011-09-20 15:39:58 -0700711 status_t finalResult;
712 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
Lajos Molnarcc227032014-07-17 15:33:06 -0700713 return (finalResult == OK ? -EWOULDBLOCK : finalResult);
Andreas Huberafed0e12011-09-20 15:39:58 -0700714 }
715
716 status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
717
Robert Shih3423bbd2014-07-16 15:47:09 -0700718 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
719 readBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO, -1ll);
720 }
721
Lajos Molnare26940f2014-07-31 10:31:26 -0700722 if (mSubtitleTrack.mSource == NULL && mTimedTextTrack.mSource == NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700723 return result;
724 }
725
Lajos Molnare26940f2014-07-31 10:31:26 -0700726 if (mSubtitleTrack.mSource != NULL) {
727 CHECK(mSubtitleTrack.mPackets != NULL);
728 }
729 if (mTimedTextTrack.mSource != NULL) {
730 CHECK(mTimedTextTrack.mPackets != NULL);
731 }
732
Robert Shih3423bbd2014-07-16 15:47:09 -0700733 if (result != OK) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700734 if (mSubtitleTrack.mSource != NULL) {
735 mSubtitleTrack.mPackets->clear();
736 mFetchSubtitleDataGeneration++;
737 }
738 if (mTimedTextTrack.mSource != NULL) {
739 mTimedTextTrack.mPackets->clear();
740 mFetchTimedTextDataGeneration++;
741 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700742 return result;
743 }
744
745 int64_t timeUs;
746 status_t eosResult; // ignored
747 CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
Lajos Molnare26940f2014-07-31 10:31:26 -0700748
749 if (mSubtitleTrack.mSource != NULL
750 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700751 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, id());
752 msg->setInt64("timeUs", timeUs);
753 msg->setInt32("generation", mFetchSubtitleDataGeneration);
754 msg->post();
755 }
Robert Shiheb1735e2014-07-23 15:53:14 -0700756
Lajos Molnare26940f2014-07-31 10:31:26 -0700757 if (mTimedTextTrack.mSource != NULL
758 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
759 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, id());
760 msg->setInt64("timeUs", timeUs);
761 msg->setInt32("generation", mFetchTimedTextDataGeneration);
762 msg->post();
763 }
764
Andreas Huberafed0e12011-09-20 15:39:58 -0700765 return result;
766}
767
768status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
769 *durationUs = mDurationUs;
770 return OK;
771}
772
Robert Shihdd235722014-06-12 14:49:23 -0700773size_t NuPlayer::GenericSource::getTrackCount() const {
774 return mSources.size();
775}
776
777sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const {
778 size_t trackCount = mSources.size();
779 if (trackIndex >= trackCount) {
780 return NULL;
781 }
782
783 sp<AMessage> format = new AMessage();
784 sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat();
785
786 const char *mime;
787 CHECK(meta->findCString(kKeyMIMEType, &mime));
788
789 int32_t trackType;
790 if (!strncasecmp(mime, "video/", 6)) {
791 trackType = MEDIA_TRACK_TYPE_VIDEO;
792 } else if (!strncasecmp(mime, "audio/", 6)) {
793 trackType = MEDIA_TRACK_TYPE_AUDIO;
794 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
795 trackType = MEDIA_TRACK_TYPE_TIMEDTEXT;
796 } else {
797 trackType = MEDIA_TRACK_TYPE_UNKNOWN;
798 }
799 format->setInt32("type", trackType);
800
801 const char *lang;
802 if (!meta->findCString(kKeyMediaLanguage, &lang)) {
803 lang = "und";
804 }
805 format->setString("language", lang);
806
807 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
808 format->setString("mime", mime);
809
810 int32_t isAutoselect = 1, isDefault = 0, isForced = 0;
811 meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect);
812 meta->findInt32(kKeyTrackIsDefault, &isDefault);
813 meta->findInt32(kKeyTrackIsForced, &isForced);
814
815 format->setInt32("auto", !!isAutoselect);
816 format->setInt32("default", !!isDefault);
817 format->setInt32("forced", !!isForced);
818 }
819
820 return format;
821}
822
Lajos Molnare26940f2014-07-31 10:31:26 -0700823ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const {
824 const Track *track = NULL;
825 switch (type) {
826 case MEDIA_TRACK_TYPE_VIDEO:
827 track = &mVideoTrack;
828 break;
829 case MEDIA_TRACK_TYPE_AUDIO:
830 track = &mAudioTrack;
831 break;
832 case MEDIA_TRACK_TYPE_TIMEDTEXT:
833 track = &mTimedTextTrack;
834 break;
835 case MEDIA_TRACK_TYPE_SUBTITLE:
836 track = &mSubtitleTrack;
837 break;
838 default:
839 break;
840 }
841
842 if (track != NULL && track->mSource != NULL) {
843 return track->mIndex;
844 }
845
846 return -1;
847}
848
Robert Shih3423bbd2014-07-16 15:47:09 -0700849status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700850 ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
Robert Shih3423bbd2014-07-16 15:47:09 -0700851 if (trackIndex >= mSources.size()) {
852 return BAD_INDEX;
853 }
854
855 if (!select) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700856 Track* track = NULL;
857 if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) {
858 track = &mSubtitleTrack;
859 mFetchSubtitleDataGeneration++;
860 } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) {
861 track = &mTimedTextTrack;
862 mFetchTimedTextDataGeneration++;
863 }
864 if (track == NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700865 return INVALID_OPERATION;
866 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700867 track->mSource->stop();
868 track->mSource = NULL;
869 track->mPackets->clear();
Robert Shih3423bbd2014-07-16 15:47:09 -0700870 return OK;
871 }
872
873 const sp<MediaSource> source = mSources.itemAt(trackIndex);
874 sp<MetaData> meta = source->getFormat();
875 const char *mime;
876 CHECK(meta->findCString(kKeyMIMEType, &mime));
877 if (!strncasecmp(mime, "text/", 5)) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700878 bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP);
879 Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack;
880 if (track->mSource != NULL && track->mIndex == trackIndex) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700881 return OK;
882 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700883 track->mIndex = trackIndex;
884 if (track->mSource != NULL) {
885 track->mSource->stop();
Robert Shih3423bbd2014-07-16 15:47:09 -0700886 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700887 track->mSource = mSources.itemAt(trackIndex);
888 track->mSource->start();
889 if (track->mPackets == NULL) {
890 track->mPackets = new AnotherPacketSource(track->mSource->getFormat());
Robert Shih3423bbd2014-07-16 15:47:09 -0700891 } else {
Lajos Molnare26940f2014-07-31 10:31:26 -0700892 track->mPackets->clear();
893 track->mPackets->setFormat(track->mSource->getFormat());
Robert Shih3423bbd2014-07-16 15:47:09 -0700894
895 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700896
897 if (isSubtitle) {
898 mFetchSubtitleDataGeneration++;
899 } else {
900 mFetchTimedTextDataGeneration++;
901 }
902
Robert Shih3423bbd2014-07-16 15:47:09 -0700903 return OK;
904 } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
905 bool audio = !strncasecmp(mime, "audio/", 6);
906 Track *track = audio ? &mAudioTrack : &mVideoTrack;
907 if (track->mSource != NULL && track->mIndex == trackIndex) {
908 return OK;
909 }
910
911 sp<AMessage> msg = new AMessage(kWhatChangeAVSource, id());
912 msg->setInt32("trackIndex", trackIndex);
913 msg->post();
914 return OK;
915 }
916
917 return INVALID_OPERATION;
918}
919
Andreas Huberafed0e12011-09-20 15:39:58 -0700920status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs) {
921 if (mVideoTrack.mSource != NULL) {
922 int64_t actualTimeUs;
Robert Shih3423bbd2014-07-16 15:47:09 -0700923 readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, &actualTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -0700924
925 seekTimeUs = actualTimeUs;
926 }
927
928 if (mAudioTrack.mSource != NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700929 readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -0700930 }
931
Ronghua Wu80276872014-08-28 15:50:29 -0700932 setDrmPlaybackStatusIfNeeded(Playback::START, seekTimeUs / 1000);
933 if (!mStarted) {
934 setDrmPlaybackStatusIfNeeded(Playback::PAUSE, 0);
935 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700936 return OK;
937}
938
Robert Shih3423bbd2014-07-16 15:47:09 -0700939sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
940 MediaBuffer* mb,
941 media_track_type trackType,
942 int64_t *actualTimeUs) {
943 bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
944 size_t outLength = mb->range_length();
945
946 if (audio && mAudioIsVorbis) {
947 outLength += sizeof(int32_t);
948 }
949
950 sp<ABuffer> ab;
951 if (mIsWidevine && !audio) {
952 // data is already provided in the buffer
953 ab = new ABuffer(NULL, mb->range_length());
954 ab->meta()->setPointer("mediaBuffer", mb);
955 mb->add_ref();
956 } else {
957 ab = new ABuffer(outLength);
958 memcpy(ab->data(),
959 (const uint8_t *)mb->data() + mb->range_offset(),
960 mb->range_length());
961 }
962
963 if (audio && mAudioIsVorbis) {
964 int32_t numPageSamples;
965 if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
966 numPageSamples = -1;
967 }
968
969 uint8_t* abEnd = ab->data() + mb->range_length();
970 memcpy(abEnd, &numPageSamples, sizeof(numPageSamples));
971 }
972
Lajos Molnare26940f2014-07-31 10:31:26 -0700973 sp<AMessage> meta = ab->meta();
974
Robert Shih3423bbd2014-07-16 15:47:09 -0700975 int64_t timeUs;
976 CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs));
Robert Shih3423bbd2014-07-16 15:47:09 -0700977 meta->setInt64("timeUs", timeUs);
978
Lajos Molnare26940f2014-07-31 10:31:26 -0700979 if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
980 const char *mime;
981 CHECK(mTimedTextTrack.mSource != NULL
982 && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime));
983 meta->setString("mime", mime);
984 }
985
Robert Shih3423bbd2014-07-16 15:47:09 -0700986 int64_t durationUs;
987 if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) {
988 meta->setInt64("durationUs", durationUs);
989 }
990
991 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
992 meta->setInt32("trackIndex", mSubtitleTrack.mIndex);
993 }
994
995 if (actualTimeUs) {
996 *actualTimeUs = timeUs;
997 }
998
999 mb->release();
1000 mb = NULL;
1001
1002 return ab;
1003}
1004
Andreas Huberafed0e12011-09-20 15:39:58 -07001005void NuPlayer::GenericSource::readBuffer(
Robert Shih3423bbd2014-07-16 15:47:09 -07001006 media_track_type trackType, int64_t seekTimeUs, int64_t *actualTimeUs, bool formatChange) {
1007 Track *track;
1008 switch (trackType) {
1009 case MEDIA_TRACK_TYPE_VIDEO:
1010 track = &mVideoTrack;
1011 break;
1012 case MEDIA_TRACK_TYPE_AUDIO:
1013 track = &mAudioTrack;
1014 break;
1015 case MEDIA_TRACK_TYPE_SUBTITLE:
1016 track = &mSubtitleTrack;
1017 break;
Lajos Molnare26940f2014-07-31 10:31:26 -07001018 case MEDIA_TRACK_TYPE_TIMEDTEXT:
1019 track = &mTimedTextTrack;
1020 break;
Robert Shih3423bbd2014-07-16 15:47:09 -07001021 default:
1022 TRESPASS();
1023 }
1024
1025 if (track->mSource == NULL) {
1026 return;
1027 }
Andreas Huberafed0e12011-09-20 15:39:58 -07001028
1029 if (actualTimeUs) {
1030 *actualTimeUs = seekTimeUs;
1031 }
1032
1033 MediaSource::ReadOptions options;
1034
1035 bool seeking = false;
1036
1037 if (seekTimeUs >= 0) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001038 options.setSeekTo(seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
Andreas Huberafed0e12011-09-20 15:39:58 -07001039 seeking = true;
1040 }
1041
Robert Shih3423bbd2014-07-16 15:47:09 -07001042 if (mIsWidevine && trackType != MEDIA_TRACK_TYPE_AUDIO) {
Lajos Molnarcc227032014-07-17 15:33:06 -07001043 options.setNonBlocking();
1044 }
1045
Andreas Huberafed0e12011-09-20 15:39:58 -07001046 for (;;) {
1047 MediaBuffer *mbuf;
1048 status_t err = track->mSource->read(&mbuf, &options);
1049
1050 options.clearSeekTo();
1051
1052 if (err == OK) {
Ronghua Wu80276872014-08-28 15:50:29 -07001053 int64_t timeUs;
1054 CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
1055 if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
1056 mAudioTimeUs = timeUs;
1057 } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
1058 mVideoTimeUs = timeUs;
1059 }
1060
Robert Shih3423bbd2014-07-16 15:47:09 -07001061 // formatChange && seeking: track whose source is changed during selection
1062 // formatChange && !seeking: track whose source is not changed during selection
1063 // !formatChange: normal seek
Lajos Molnare26940f2014-07-31 10:31:26 -07001064 if ((seeking || formatChange)
1065 && (trackType == MEDIA_TRACK_TYPE_AUDIO
1066 || trackType == MEDIA_TRACK_TYPE_VIDEO)) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001067 ATSParser::DiscontinuityType type = formatChange
1068 ? (seeking
1069 ? ATSParser::DISCONTINUITY_FORMATCHANGE
1070 : ATSParser::DISCONTINUITY_NONE)
1071 : ATSParser::DISCONTINUITY_SEEK;
1072 track->mPackets->queueDiscontinuity( type, NULL, true /* discard */);
Andreas Huberafed0e12011-09-20 15:39:58 -07001073 }
1074
Robert Shih3423bbd2014-07-16 15:47:09 -07001075 sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType, actualTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -07001076 track->mPackets->queueAccessUnit(buffer);
1077 break;
Lajos Molnarcc227032014-07-17 15:33:06 -07001078 } else if (err == WOULD_BLOCK) {
1079 break;
Andreas Huberafed0e12011-09-20 15:39:58 -07001080 } else if (err == INFO_FORMAT_CHANGED) {
1081#if 0
1082 track->mPackets->queueDiscontinuity(
Chong Zhang632740c2014-06-26 13:03:47 -07001083 ATSParser::DISCONTINUITY_FORMATCHANGE,
1084 NULL,
1085 false /* discard */);
Andreas Huberafed0e12011-09-20 15:39:58 -07001086#endif
1087 } else {
1088 track->mPackets->signalEOS(err);
1089 break;
1090 }
1091 }
1092}
1093
Andreas Huberafed0e12011-09-20 15:39:58 -07001094} // namespace android