blob: ebc3d08daab3ed1195415fba8c6a42339d0d13c2 [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
17#include "GenericSource.h"
18
19#include "AnotherPacketSource.h"
20
21#include <media/stagefright/foundation/ABuffer.h>
22#include <media/stagefright/foundation/ADebug.h>
23#include <media/stagefright/foundation/AMessage.h>
24#include <media/stagefright/DataSource.h>
25#include <media/stagefright/FileSource.h>
26#include <media/stagefright/MediaBuffer.h>
27#include <media/stagefright/MediaDefs.h>
28#include <media/stagefright/MediaExtractor.h>
29#include <media/stagefright/MediaSource.h>
30#include <media/stagefright/MetaData.h>
Lajos Molnarcc227032014-07-17 15:33:06 -070031#include "../../libstagefright/include/WVMExtractor.h"
Andreas Huberafed0e12011-09-20 15:39:58 -070032
33namespace android {
34
35NuPlayer::GenericSource::GenericSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080036 const sp<AMessage> &notify,
Andreas Huber1b86fe02014-01-29 11:13:26 -080037 const sp<IMediaHTTPService> &httpService,
Andreas Huberafed0e12011-09-20 15:39:58 -070038 const char *url,
Lajos Molnarcc227032014-07-17 15:33:06 -070039 const KeyedVector<String8, String8> *headers,
40 bool isWidevine,
41 bool uidValid,
42 uid_t uid)
Andreas Huberb5f25f02013-02-05 10:14:26 -080043 : Source(notify),
Robert Shih3423bbd2014-07-16 15:47:09 -070044 mFetchSubtitleDataGeneration(0),
Andreas Huberb5f25f02013-02-05 10:14:26 -080045 mDurationUs(0ll),
Lajos Molnarcc227032014-07-17 15:33:06 -070046 mAudioIsVorbis(false),
47 mIsWidevine(isWidevine),
48 mUIDValid(uidValid),
49 mUID(uid) {
Andreas Huberafed0e12011-09-20 15:39:58 -070050 DataSource::RegisterDefaultSniffers();
51
52 sp<DataSource> dataSource =
Andreas Huber1b86fe02014-01-29 11:13:26 -080053 DataSource::CreateFromURI(httpService, url, headers);
Andreas Huberafed0e12011-09-20 15:39:58 -070054 CHECK(dataSource != NULL);
55
56 initFromDataSource(dataSource);
57}
58
59NuPlayer::GenericSource::GenericSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080060 const sp<AMessage> &notify,
Andreas Huberafed0e12011-09-20 15:39:58 -070061 int fd, int64_t offset, int64_t length)
Andreas Huberb5f25f02013-02-05 10:14:26 -080062 : Source(notify),
Robert Shih3423bbd2014-07-16 15:47:09 -070063 mFetchSubtitleDataGeneration(0),
Andreas Huberb5f25f02013-02-05 10:14:26 -080064 mDurationUs(0ll),
Lajos Molnar63c0ce72014-07-31 07:13:32 -070065 mAudioIsVorbis(false),
66 mIsWidevine(false) {
Andreas Huberafed0e12011-09-20 15:39:58 -070067 DataSource::RegisterDefaultSniffers();
68
69 sp<DataSource> dataSource = new FileSource(dup(fd), offset, length);
70
71 initFromDataSource(dataSource);
72}
73
74void NuPlayer::GenericSource::initFromDataSource(
75 const sp<DataSource> &dataSource) {
Lajos Molnarcc227032014-07-17 15:33:06 -070076 sp<MediaExtractor> extractor;
77
78 if (mIsWidevine) {
79 String8 mimeType;
80 float confidence;
81 sp<AMessage> dummy;
82 bool success;
83
84 success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
85 if (!success
86 || strcasecmp(
87 mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
88 ALOGE("unsupported widevine mime: %s", mimeType.string());
89 return;
90 }
91
92 sp<WVMExtractor> wvmExtractor = new WVMExtractor(dataSource);
93 wvmExtractor->setAdaptiveStreamingMode(true);
94 if (mUIDValid) {
95 wvmExtractor->setUID(mUID);
96 }
97 extractor = wvmExtractor;
98 } else {
99 extractor = MediaExtractor::Create(dataSource);
100 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700101
102 CHECK(extractor != NULL);
103
Marco Nelissenc1f4b2b2014-06-17 14:48:32 -0700104 sp<MetaData> fileMeta = extractor->getMetaData();
105 if (fileMeta != NULL) {
106 int64_t duration;
107 if (fileMeta->findInt64(kKeyDuration, &duration)) {
108 mDurationUs = duration;
109 }
110 }
111
Andreas Huberafed0e12011-09-20 15:39:58 -0700112 for (size_t i = 0; i < extractor->countTracks(); ++i) {
113 sp<MetaData> meta = extractor->getTrackMetaData(i);
114
115 const char *mime;
116 CHECK(meta->findCString(kKeyMIMEType, &mime));
117
Robert Shihdd235722014-06-12 14:49:23 -0700118 sp<MediaSource> track = extractor->getTrack(i);
Andreas Huberafed0e12011-09-20 15:39:58 -0700119
120 if (!strncasecmp(mime, "audio/", 6)) {
121 if (mAudioTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700122 mAudioTrack.mIndex = i;
123 mAudioTrack.mSource = track;
Andreas Huberafed0e12011-09-20 15:39:58 -0700124
125 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
126 mAudioIsVorbis = true;
127 } else {
128 mAudioIsVorbis = false;
129 }
130 }
131 } else if (!strncasecmp(mime, "video/", 6)) {
132 if (mVideoTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700133 mVideoTrack.mIndex = i;
134 mVideoTrack.mSource = track;
Andreas Huberafed0e12011-09-20 15:39:58 -0700135 }
136 }
137
138 if (track != NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700139 mSources.push(track);
Andreas Huberafed0e12011-09-20 15:39:58 -0700140 int64_t durationUs;
141 if (meta->findInt64(kKeyDuration, &durationUs)) {
142 if (durationUs > mDurationUs) {
143 mDurationUs = durationUs;
144 }
145 }
146 }
147 }
148}
149
Lajos Molnarcc227032014-07-17 15:33:06 -0700150status_t NuPlayer::GenericSource::setBuffers(bool audio, Vector<MediaBuffer *> &buffers) {
151 if (mIsWidevine && !audio) {
152 return mVideoTrack.mSource->setBuffers(buffers);
153 }
154 return INVALID_OPERATION;
155}
156
Andreas Huberafed0e12011-09-20 15:39:58 -0700157NuPlayer::GenericSource::~GenericSource() {
158}
159
Andreas Huber9575c962013-02-05 13:59:56 -0800160void NuPlayer::GenericSource::prepareAsync() {
161 if (mVideoTrack.mSource != NULL) {
162 sp<MetaData> meta = mVideoTrack.mSource->getFormat();
163
164 int32_t width, height;
165 CHECK(meta->findInt32(kKeyWidth, &width));
166 CHECK(meta->findInt32(kKeyHeight, &height));
167
168 notifyVideoSizeChanged(width, height);
169 }
170
171 notifyFlagsChanged(
Lajos Molnarcc227032014-07-17 15:33:06 -0700172 (mIsWidevine ? FLAG_SECURE : 0)
173 | FLAG_CAN_PAUSE
Andreas Huber9575c962013-02-05 13:59:56 -0800174 | FLAG_CAN_SEEK_BACKWARD
175 | FLAG_CAN_SEEK_FORWARD
176 | FLAG_CAN_SEEK);
177
178 notifyPrepared();
179}
180
Andreas Huberafed0e12011-09-20 15:39:58 -0700181void NuPlayer::GenericSource::start() {
182 ALOGI("start");
183
184 if (mAudioTrack.mSource != NULL) {
Robert Shihbace25b2014-07-25 14:14:34 -0700185 CHECK_EQ(mAudioTrack.mSource->start(), (status_t)OK);
Andreas Huberafed0e12011-09-20 15:39:58 -0700186 mAudioTrack.mPackets =
187 new AnotherPacketSource(mAudioTrack.mSource->getFormat());
188
Robert Shih3423bbd2014-07-16 15:47:09 -0700189 readBuffer(MEDIA_TRACK_TYPE_AUDIO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700190 }
191
192 if (mVideoTrack.mSource != NULL) {
Robert Shihbace25b2014-07-25 14:14:34 -0700193 CHECK_EQ(mVideoTrack.mSource->start(), (status_t)OK);
Andreas Huberafed0e12011-09-20 15:39:58 -0700194 mVideoTrack.mPackets =
195 new AnotherPacketSource(mVideoTrack.mSource->getFormat());
196
Robert Shih3423bbd2014-07-16 15:47:09 -0700197 readBuffer(MEDIA_TRACK_TYPE_VIDEO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700198 }
199}
200
201status_t NuPlayer::GenericSource::feedMoreTSData() {
202 return OK;
203}
204
Robert Shih3423bbd2014-07-16 15:47:09 -0700205void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
206 switch (msg->what()) {
207 case kWhatFetchSubtitleData:
208 {
209 int32_t generation;
210 CHECK(msg->findInt32("generation", &generation));
211 if (generation != mFetchSubtitleDataGeneration) {
212 // stale
213 break;
214 }
215
216 int32_t avail;
217 if (mSubtitleTrack.mPackets->hasBufferAvailable(&avail)) {
218 break;
219 }
220
221 int64_t timeUs;
222 CHECK(msg->findInt64("timeUs", &timeUs));
223
224 int64_t subTimeUs;
225 readBuffer(MEDIA_TRACK_TYPE_SUBTITLE, timeUs, &subTimeUs);
226
227 const int64_t oneSecUs = 1000000ll;
228 const int64_t delayUs = subTimeUs - timeUs - oneSecUs;
229 sp<AMessage> msg2 = new AMessage(kWhatSendSubtitleData, id());
230 msg2->setInt32("generation", generation);
231 msg2->post(delayUs < 0 ? 0 : delayUs);
232 ALOGV("kWhatFetchSubtitleData generation %d, delayUs %lld",
233 mFetchSubtitleDataGeneration, delayUs);
234
235 break;
236 }
237
238 case kWhatSendSubtitleData:
239 {
240 int32_t generation;
241 CHECK(msg->findInt32("generation", &generation));
242 if (generation != mFetchSubtitleDataGeneration) {
243 // stale
244 break;
245 }
246
247 int64_t subTimeUs;
248 if (mSubtitleTrack.mPackets->nextBufferTime(&subTimeUs) != OK) {
249 break;
250 }
251
252 int64_t nextSubTimeUs;
253 readBuffer(MEDIA_TRACK_TYPE_SUBTITLE, -1, &nextSubTimeUs);
254
255 sp<ABuffer> buffer;
256 status_t dequeueStatus = mSubtitleTrack.mPackets->dequeueAccessUnit(&buffer);
257 if (dequeueStatus != OK) {
258 ALOGE("kWhatSendSubtitleData dequeueAccessUnit: %d", dequeueStatus);
259 } else {
260 sp<AMessage> notify = dupNotify();
261 notify->setInt32("what", kWhatSubtitleData);
262 notify->setBuffer("buffer", buffer);
263 notify->post();
264
265 const int64_t delayUs = nextSubTimeUs - subTimeUs;
266 msg->post(delayUs < 0 ? 0 : delayUs);
267 }
268
269 break;
270 }
271
272 case kWhatChangeAVSource:
273 {
274 int32_t trackIndex;
275 CHECK(msg->findInt32("trackIndex", &trackIndex));
276 const sp<MediaSource> source = mSources.itemAt(trackIndex);
277
278 Track* track;
279 const char *mime;
280 media_track_type trackType, counterpartType;
281 sp<MetaData> meta = source->getFormat();
282 meta->findCString(kKeyMIMEType, &mime);
283 if (!strncasecmp(mime, "audio/", 6)) {
284 track = &mAudioTrack;
285 trackType = MEDIA_TRACK_TYPE_AUDIO;
286 counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
287 } else {
288 CHECK(!strncasecmp(mime, "video/", 6));
289 track = &mVideoTrack;
290 trackType = MEDIA_TRACK_TYPE_VIDEO;
291 counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
292 }
293
294
295 if (track->mSource != NULL) {
296 track->mSource->stop();
297 }
298 track->mSource = source;
299 track->mSource->start();
300 track->mIndex = trackIndex;
301
302 status_t avail;
303 if (!track->mPackets->hasBufferAvailable(&avail)) {
304 // sync from other source
305 TRESPASS();
306 break;
307 }
308
309 int64_t timeUs, actualTimeUs;
310 const bool formatChange = true;
Robert Shih309aa8b2014-07-29 18:34:36 -0700311 sp<AMessage> latestMeta = track->mPackets->getLatestEnqueuedMeta();
Robert Shih3423bbd2014-07-16 15:47:09 -0700312 CHECK(latestMeta != NULL && latestMeta->findInt64("timeUs", &timeUs));
313 readBuffer(trackType, timeUs, &actualTimeUs, formatChange);
314 readBuffer(counterpartType, -1, NULL, formatChange);
315 ALOGV("timeUs %lld actualTimeUs %lld", timeUs, actualTimeUs);
316
317 break;
318 }
319
320 default:
321 Source::onMessageReceived(msg);
322 break;
323 }
324}
325
Andreas Huber84066782011-08-16 09:34:26 -0700326sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700327 sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
328
329 if (source == NULL) {
330 return NULL;
331 }
332
333 return source->getFormat();
334}
335
336status_t NuPlayer::GenericSource::dequeueAccessUnit(
337 bool audio, sp<ABuffer> *accessUnit) {
338 Track *track = audio ? &mAudioTrack : &mVideoTrack;
339
340 if (track->mSource == NULL) {
341 return -EWOULDBLOCK;
342 }
343
Lajos Molnarcc227032014-07-17 15:33:06 -0700344 if (mIsWidevine && !audio) {
345 // try to read a buffer as we may not have been able to the last time
Robert Shih3423bbd2014-07-16 15:47:09 -0700346 readBuffer(MEDIA_TRACK_TYPE_VIDEO, -1ll);
Lajos Molnarcc227032014-07-17 15:33:06 -0700347 }
348
Andreas Huberafed0e12011-09-20 15:39:58 -0700349 status_t finalResult;
350 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
Lajos Molnarcc227032014-07-17 15:33:06 -0700351 return (finalResult == OK ? -EWOULDBLOCK : finalResult);
Andreas Huberafed0e12011-09-20 15:39:58 -0700352 }
353
354 status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
355
Robert Shih3423bbd2014-07-16 15:47:09 -0700356 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
357 readBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO, -1ll);
358 }
359
360 if (mSubtitleTrack.mSource == NULL) {
361 return result;
362 }
363
364 CHECK(mSubtitleTrack.mPackets != NULL);
365 if (result != OK) {
366 mSubtitleTrack.mPackets->clear();
367 mFetchSubtitleDataGeneration++;
368 return result;
369 }
370
371 int64_t timeUs;
372 status_t eosResult; // ignored
373 CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
374 if (!mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
375 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, id());
376 msg->setInt64("timeUs", timeUs);
377 msg->setInt32("generation", mFetchSubtitleDataGeneration);
378 msg->post();
379 }
Robert Shiheb1735e2014-07-23 15:53:14 -0700380
Andreas Huberafed0e12011-09-20 15:39:58 -0700381 return result;
382}
383
384status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
385 *durationUs = mDurationUs;
386 return OK;
387}
388
Robert Shihdd235722014-06-12 14:49:23 -0700389size_t NuPlayer::GenericSource::getTrackCount() const {
390 return mSources.size();
391}
392
393sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const {
394 size_t trackCount = mSources.size();
395 if (trackIndex >= trackCount) {
396 return NULL;
397 }
398
399 sp<AMessage> format = new AMessage();
400 sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat();
401
402 const char *mime;
403 CHECK(meta->findCString(kKeyMIMEType, &mime));
404
405 int32_t trackType;
406 if (!strncasecmp(mime, "video/", 6)) {
407 trackType = MEDIA_TRACK_TYPE_VIDEO;
408 } else if (!strncasecmp(mime, "audio/", 6)) {
409 trackType = MEDIA_TRACK_TYPE_AUDIO;
410 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
411 trackType = MEDIA_TRACK_TYPE_TIMEDTEXT;
412 } else {
413 trackType = MEDIA_TRACK_TYPE_UNKNOWN;
414 }
415 format->setInt32("type", trackType);
416
417 const char *lang;
418 if (!meta->findCString(kKeyMediaLanguage, &lang)) {
419 lang = "und";
420 }
421 format->setString("language", lang);
422
423 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
424 format->setString("mime", mime);
425
426 int32_t isAutoselect = 1, isDefault = 0, isForced = 0;
427 meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect);
428 meta->findInt32(kKeyTrackIsDefault, &isDefault);
429 meta->findInt32(kKeyTrackIsForced, &isForced);
430
431 format->setInt32("auto", !!isAutoselect);
432 format->setInt32("default", !!isDefault);
433 format->setInt32("forced", !!isForced);
434 }
435
436 return format;
437}
438
Robert Shih3423bbd2014-07-16 15:47:09 -0700439status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select) {
440 ALOGV("selectTrack: %zu", trackIndex);
441 if (trackIndex >= mSources.size()) {
442 return BAD_INDEX;
443 }
444
445 if (!select) {
446 if (mSubtitleTrack.mSource == NULL || trackIndex != mSubtitleTrack.mIndex) {
447 return INVALID_OPERATION;
448 }
449 mSubtitleTrack.mSource->stop();
450 mSubtitleTrack.mSource = NULL;
451 mSubtitleTrack.mPackets->clear();
452 mFetchSubtitleDataGeneration++;
453 return OK;
454 }
455
456 const sp<MediaSource> source = mSources.itemAt(trackIndex);
457 sp<MetaData> meta = source->getFormat();
458 const char *mime;
459 CHECK(meta->findCString(kKeyMIMEType, &mime));
460 if (!strncasecmp(mime, "text/", 5)) {
461 if (mSubtitleTrack.mSource != NULL && mSubtitleTrack.mIndex == trackIndex) {
462 return OK;
463 }
464 mSubtitleTrack.mIndex = trackIndex;
465 if (mSubtitleTrack.mSource != NULL) {
466 mSubtitleTrack.mSource->stop();
467 }
468 mSubtitleTrack.mSource = mSources.itemAt(trackIndex);
469 mSubtitleTrack.mSource->start();
470 if (mSubtitleTrack.mPackets == NULL) {
471 mSubtitleTrack.mPackets = new AnotherPacketSource(mSubtitleTrack.mSource->getFormat());
472 } else {
473 mSubtitleTrack.mPackets->clear();
474
475 }
476 mFetchSubtitleDataGeneration++;
477 return OK;
478 } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
479 bool audio = !strncasecmp(mime, "audio/", 6);
480 Track *track = audio ? &mAudioTrack : &mVideoTrack;
481 if (track->mSource != NULL && track->mIndex == trackIndex) {
482 return OK;
483 }
484
485 sp<AMessage> msg = new AMessage(kWhatChangeAVSource, id());
486 msg->setInt32("trackIndex", trackIndex);
487 msg->post();
488 return OK;
489 }
490
491 return INVALID_OPERATION;
492}
493
Andreas Huberafed0e12011-09-20 15:39:58 -0700494status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs) {
495 if (mVideoTrack.mSource != NULL) {
496 int64_t actualTimeUs;
Robert Shih3423bbd2014-07-16 15:47:09 -0700497 readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, &actualTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -0700498
499 seekTimeUs = actualTimeUs;
500 }
501
502 if (mAudioTrack.mSource != NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700503 readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -0700504 }
505
506 return OK;
507}
508
Robert Shih3423bbd2014-07-16 15:47:09 -0700509sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
510 MediaBuffer* mb,
511 media_track_type trackType,
512 int64_t *actualTimeUs) {
513 bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
514 size_t outLength = mb->range_length();
515
516 if (audio && mAudioIsVorbis) {
517 outLength += sizeof(int32_t);
518 }
519
520 sp<ABuffer> ab;
521 if (mIsWidevine && !audio) {
522 // data is already provided in the buffer
523 ab = new ABuffer(NULL, mb->range_length());
524 ab->meta()->setPointer("mediaBuffer", mb);
525 mb->add_ref();
526 } else {
527 ab = new ABuffer(outLength);
528 memcpy(ab->data(),
529 (const uint8_t *)mb->data() + mb->range_offset(),
530 mb->range_length());
531 }
532
533 if (audio && mAudioIsVorbis) {
534 int32_t numPageSamples;
535 if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
536 numPageSamples = -1;
537 }
538
539 uint8_t* abEnd = ab->data() + mb->range_length();
540 memcpy(abEnd, &numPageSamples, sizeof(numPageSamples));
541 }
542
543 int64_t timeUs;
544 CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs));
545
546 sp<AMessage> meta = ab->meta();
547 meta->setInt64("timeUs", timeUs);
548
549 int64_t durationUs;
550 if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) {
551 meta->setInt64("durationUs", durationUs);
552 }
553
554 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
555 meta->setInt32("trackIndex", mSubtitleTrack.mIndex);
556 }
557
558 if (actualTimeUs) {
559 *actualTimeUs = timeUs;
560 }
561
562 mb->release();
563 mb = NULL;
564
565 return ab;
566}
567
Andreas Huberafed0e12011-09-20 15:39:58 -0700568void NuPlayer::GenericSource::readBuffer(
Robert Shih3423bbd2014-07-16 15:47:09 -0700569 media_track_type trackType, int64_t seekTimeUs, int64_t *actualTimeUs, bool formatChange) {
570 Track *track;
571 switch (trackType) {
572 case MEDIA_TRACK_TYPE_VIDEO:
573 track = &mVideoTrack;
574 break;
575 case MEDIA_TRACK_TYPE_AUDIO:
576 track = &mAudioTrack;
577 break;
578 case MEDIA_TRACK_TYPE_SUBTITLE:
579 track = &mSubtitleTrack;
580 break;
581 default:
582 TRESPASS();
583 }
584
585 if (track->mSource == NULL) {
586 return;
587 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700588
589 if (actualTimeUs) {
590 *actualTimeUs = seekTimeUs;
591 }
592
593 MediaSource::ReadOptions options;
594
595 bool seeking = false;
596
597 if (seekTimeUs >= 0) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700598 options.setSeekTo(seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
Andreas Huberafed0e12011-09-20 15:39:58 -0700599 seeking = true;
600 }
601
Robert Shih3423bbd2014-07-16 15:47:09 -0700602 if (mIsWidevine && trackType != MEDIA_TRACK_TYPE_AUDIO) {
Lajos Molnarcc227032014-07-17 15:33:06 -0700603 options.setNonBlocking();
604 }
605
Andreas Huberafed0e12011-09-20 15:39:58 -0700606 for (;;) {
607 MediaBuffer *mbuf;
608 status_t err = track->mSource->read(&mbuf, &options);
609
610 options.clearSeekTo();
611
612 if (err == OK) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700613 // formatChange && seeking: track whose source is changed during selection
614 // formatChange && !seeking: track whose source is not changed during selection
615 // !formatChange: normal seek
616 if ((seeking || formatChange) && trackType != MEDIA_TRACK_TYPE_SUBTITLE) {
617 ATSParser::DiscontinuityType type = formatChange
618 ? (seeking
619 ? ATSParser::DISCONTINUITY_FORMATCHANGE
620 : ATSParser::DISCONTINUITY_NONE)
621 : ATSParser::DISCONTINUITY_SEEK;
622 track->mPackets->queueDiscontinuity( type, NULL, true /* discard */);
Andreas Huberafed0e12011-09-20 15:39:58 -0700623 }
624
Robert Shih3423bbd2014-07-16 15:47:09 -0700625 sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType, actualTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -0700626 track->mPackets->queueAccessUnit(buffer);
627 break;
Lajos Molnarcc227032014-07-17 15:33:06 -0700628 } else if (err == WOULD_BLOCK) {
629 break;
Andreas Huberafed0e12011-09-20 15:39:58 -0700630 } else if (err == INFO_FORMAT_CHANGED) {
631#if 0
632 track->mPackets->queueDiscontinuity(
Chong Zhang632740c2014-06-26 13:03:47 -0700633 ATSParser::DISCONTINUITY_FORMATCHANGE,
634 NULL,
635 false /* discard */);
Andreas Huberafed0e12011-09-20 15:39:58 -0700636#endif
637 } else {
638 track->mPackets->signalEOS(err);
639 break;
640 }
641 }
642}
643
Andreas Huberafed0e12011-09-20 15:39:58 -0700644} // namespace android