blob: 4c6a59c627300862e320b41840b3d5f52512dd0a [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 Shih05312bc2014-07-16 15:47:09 -070044 mFetchSubtitleDataGeneration(0),
Robert Shiheb1735e2014-07-23 15:53:14 -070045 mFetchTimedTextDataGeneration(0),
Andreas Huberb5f25f02013-02-05 10:14:26 -080046 mDurationUs(0ll),
Lajos Molnarcc227032014-07-17 15:33:06 -070047 mAudioIsVorbis(false),
48 mIsWidevine(isWidevine),
49 mUIDValid(uidValid),
50 mUID(uid) {
Andreas Huberafed0e12011-09-20 15:39:58 -070051 DataSource::RegisterDefaultSniffers();
52
53 sp<DataSource> dataSource =
Andreas Huber1b86fe02014-01-29 11:13:26 -080054 DataSource::CreateFromURI(httpService, url, headers);
Andreas Huberafed0e12011-09-20 15:39:58 -070055 CHECK(dataSource != NULL);
56
57 initFromDataSource(dataSource);
58}
59
60NuPlayer::GenericSource::GenericSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080061 const sp<AMessage> &notify,
Andreas Huberafed0e12011-09-20 15:39:58 -070062 int fd, int64_t offset, int64_t length)
Andreas Huberb5f25f02013-02-05 10:14:26 -080063 : Source(notify),
Robert Shih05312bc2014-07-16 15:47:09 -070064 mFetchSubtitleDataGeneration(0),
Robert Shiheb1735e2014-07-23 15:53:14 -070065 mFetchTimedTextDataGeneration(0),
Andreas Huberb5f25f02013-02-05 10:14:26 -080066 mDurationUs(0ll),
Andreas Huberafed0e12011-09-20 15:39:58 -070067 mAudioIsVorbis(false) {
68 DataSource::RegisterDefaultSniffers();
69
70 sp<DataSource> dataSource = new FileSource(dup(fd), offset, length);
71
72 initFromDataSource(dataSource);
73}
74
75void NuPlayer::GenericSource::initFromDataSource(
76 const sp<DataSource> &dataSource) {
Lajos Molnarcc227032014-07-17 15:33:06 -070077 sp<MediaExtractor> extractor;
78
79 if (mIsWidevine) {
80 String8 mimeType;
81 float confidence;
82 sp<AMessage> dummy;
83 bool success;
84
85 success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
86 if (!success
87 || strcasecmp(
88 mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
89 ALOGE("unsupported widevine mime: %s", mimeType.string());
90 return;
91 }
92
93 sp<WVMExtractor> wvmExtractor = new WVMExtractor(dataSource);
94 wvmExtractor->setAdaptiveStreamingMode(true);
95 if (mUIDValid) {
96 wvmExtractor->setUID(mUID);
97 }
98 extractor = wvmExtractor;
99 } else {
100 extractor = MediaExtractor::Create(dataSource);
101 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700102
103 CHECK(extractor != NULL);
104
Marco Nelissenc1f4b2b2014-06-17 14:48:32 -0700105 sp<MetaData> fileMeta = extractor->getMetaData();
106 if (fileMeta != NULL) {
107 int64_t duration;
108 if (fileMeta->findInt64(kKeyDuration, &duration)) {
109 mDurationUs = duration;
110 }
111 }
112
Andreas Huberafed0e12011-09-20 15:39:58 -0700113 for (size_t i = 0; i < extractor->countTracks(); ++i) {
114 sp<MetaData> meta = extractor->getTrackMetaData(i);
115
116 const char *mime;
117 CHECK(meta->findCString(kKeyMIMEType, &mime));
118
Robert Shihdd235722014-06-12 14:49:23 -0700119 sp<MediaSource> track = extractor->getTrack(i);
Andreas Huberafed0e12011-09-20 15:39:58 -0700120
121 if (!strncasecmp(mime, "audio/", 6)) {
122 if (mAudioTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700123 mAudioTrack.mIndex = i;
124 mAudioTrack.mSource = track;
Andreas Huberafed0e12011-09-20 15:39:58 -0700125
126 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
127 mAudioIsVorbis = true;
128 } else {
129 mAudioIsVorbis = false;
130 }
131 }
132 } else if (!strncasecmp(mime, "video/", 6)) {
133 if (mVideoTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700134 mVideoTrack.mIndex = i;
135 mVideoTrack.mSource = track;
Andreas Huberafed0e12011-09-20 15:39:58 -0700136 }
137 }
138
139 if (track != NULL) {
Robert Shih05312bc2014-07-16 15:47:09 -0700140 CHECK_EQ(track->start(), (status_t)OK);
Robert Shihdd235722014-06-12 14:49:23 -0700141 mSources.push(track);
Andreas Huberafed0e12011-09-20 15:39:58 -0700142 int64_t durationUs;
143 if (meta->findInt64(kKeyDuration, &durationUs)) {
144 if (durationUs > mDurationUs) {
145 mDurationUs = durationUs;
146 }
147 }
148 }
149 }
150}
151
Lajos Molnarcc227032014-07-17 15:33:06 -0700152status_t NuPlayer::GenericSource::setBuffers(bool audio, Vector<MediaBuffer *> &buffers) {
153 if (mIsWidevine && !audio) {
154 return mVideoTrack.mSource->setBuffers(buffers);
155 }
156 return INVALID_OPERATION;
157}
158
Andreas Huberafed0e12011-09-20 15:39:58 -0700159NuPlayer::GenericSource::~GenericSource() {
160}
161
Andreas Huber9575c962013-02-05 13:59:56 -0800162void NuPlayer::GenericSource::prepareAsync() {
163 if (mVideoTrack.mSource != NULL) {
164 sp<MetaData> meta = mVideoTrack.mSource->getFormat();
165
166 int32_t width, height;
167 CHECK(meta->findInt32(kKeyWidth, &width));
168 CHECK(meta->findInt32(kKeyHeight, &height));
169
170 notifyVideoSizeChanged(width, height);
171 }
172
173 notifyFlagsChanged(
Lajos Molnarcc227032014-07-17 15:33:06 -0700174 (mIsWidevine ? FLAG_SECURE : 0)
175 | FLAG_CAN_PAUSE
Andreas Huber9575c962013-02-05 13:59:56 -0800176 | FLAG_CAN_SEEK_BACKWARD
177 | FLAG_CAN_SEEK_FORWARD
178 | FLAG_CAN_SEEK);
179
180 notifyPrepared();
181}
182
Andreas Huberafed0e12011-09-20 15:39:58 -0700183void NuPlayer::GenericSource::start() {
184 ALOGI("start");
185
186 if (mAudioTrack.mSource != NULL) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700187 mAudioTrack.mPackets =
188 new AnotherPacketSource(mAudioTrack.mSource->getFormat());
189
Robert Shih05312bc2014-07-16 15:47:09 -0700190 readBuffer(MEDIA_TRACK_TYPE_AUDIO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700191 }
192
193 if (mVideoTrack.mSource != NULL) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700194 mVideoTrack.mPackets =
195 new AnotherPacketSource(mVideoTrack.mSource->getFormat());
196
Robert Shih05312bc2014-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 Shih05312bc2014-07-16 15:47:09 -0700205void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
206 switch (msg->what()) {
207 case kWhatFetchSubtitleData:
208 {
Robert Shiheb1735e2014-07-23 15:53:14 -0700209 fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
210 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
211 break;
212 }
Robert Shih05312bc2014-07-16 15:47:09 -0700213
Robert Shiheb1735e2014-07-23 15:53:14 -0700214 case kWhatFetchTimedTextData:
215 {
216 fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
217 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih05312bc2014-07-16 15:47:09 -0700218 break;
219 }
220
221 case kWhatSendSubtitleData:
222 {
Robert Shiheb1735e2014-07-23 15:53:14 -0700223 sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
224 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
225 break;
226 }
Robert Shih05312bc2014-07-16 15:47:09 -0700227
Robert Shiheb1735e2014-07-23 15:53:14 -0700228 case kWhatSendTimedTextData:
229 {
230 sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
231 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih05312bc2014-07-16 15:47:09 -0700232 break;
233 }
234
235 case kWhatChangeAVSource:
236 {
237 int32_t trackIndex;
238 CHECK(msg->findInt32("trackIndex", &trackIndex));
239 const sp<MediaSource> source = mSources.itemAt(trackIndex);
240
241 Track* track;
242 const char *mime;
243 media_track_type trackType, counterpartType;
244 sp<MetaData> meta = source->getFormat();
245 meta->findCString(kKeyMIMEType, &mime);
246 if (!strncasecmp(mime, "audio/", 6)) {
247 track = &mAudioTrack;
248 trackType = MEDIA_TRACK_TYPE_AUDIO;
249 counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
250 } else {
251 CHECK(!strncasecmp(mime, "video/", 6));
252 track = &mVideoTrack;
253 trackType = MEDIA_TRACK_TYPE_VIDEO;
254 counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
255 }
256
257
258 track->mSource = source;
259 track->mIndex = trackIndex;
260
261 status_t avail;
262 if (!track->mPackets->hasBufferAvailable(&avail)) {
263 // sync from other source
264 TRESPASS();
265 break;
266 }
267
268 int64_t timeUs, actualTimeUs;
269 const bool formatChange = true;
270 sp<AMessage> latestMeta = track->mPackets->getLatestMeta();
271 CHECK(latestMeta != NULL && latestMeta->findInt64("timeUs", &timeUs));
272 readBuffer(trackType, timeUs, &actualTimeUs, formatChange);
273 readBuffer(counterpartType, -1, NULL, formatChange);
274 ALOGV("timeUs %lld actualTimeUs %lld", timeUs, actualTimeUs);
275
276 break;
277 }
278
279 default:
280 Source::onMessageReceived(msg);
281 break;
282 }
283}
284
Robert Shiheb1735e2014-07-23 15:53:14 -0700285void NuPlayer::GenericSource::fetchTextData(
286 uint32_t sendWhat,
287 media_track_type type,
288 int32_t curGen,
289 sp<AnotherPacketSource> packets,
290 sp<AMessage> msg) {
291 int32_t msgGeneration;
292 CHECK(msg->findInt32("generation", &msgGeneration));
293 if (msgGeneration != curGen) {
294 // stale
295 return;
296 }
297
298 int32_t avail;
299 if (packets->hasBufferAvailable(&avail)) {
300 return;
301 }
302
303 int64_t timeUs;
304 CHECK(msg->findInt64("timeUs", &timeUs));
305
306 int64_t subTimeUs;
307 readBuffer(type, timeUs, &subTimeUs);
308
309 int64_t delayUs = subTimeUs - timeUs;
310 if (msg->what() == kWhatFetchSubtitleData) {
311 const int64_t oneSecUs = 1000000ll;
312 delayUs -= oneSecUs;
313 }
314 sp<AMessage> msg2 = new AMessage(sendWhat, id());
315 msg2->setInt32("generation", msgGeneration);
316 msg2->post(delayUs < 0 ? 0 : delayUs);
317}
318
319void NuPlayer::GenericSource::sendTextData(
320 uint32_t what,
321 media_track_type type,
322 int32_t curGen,
323 sp<AnotherPacketSource> packets,
324 sp<AMessage> msg) {
325 int32_t msgGeneration;
326 CHECK(msg->findInt32("generation", &msgGeneration));
327 if (msgGeneration != curGen) {
328 // stale
329 return;
330 }
331
332 int64_t subTimeUs;
333 if (packets->nextBufferTime(&subTimeUs) != OK) {
334 return;
335 }
336
337 int64_t nextSubTimeUs;
338 readBuffer(type, -1, &nextSubTimeUs);
339
340 sp<ABuffer> buffer;
341 status_t dequeueStatus = packets->dequeueAccessUnit(&buffer);
342 if (dequeueStatus == OK) {
343 sp<AMessage> notify = dupNotify();
344 notify->setInt32("what", what);
345 notify->setBuffer("buffer", buffer);
346 notify->post();
347
348 const int64_t delayUs = nextSubTimeUs - subTimeUs;
349 msg->post(delayUs < 0 ? 0 : delayUs);
350 }
351}
352
Andreas Huber84066782011-08-16 09:34:26 -0700353sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700354 sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
355
356 if (source == NULL) {
357 return NULL;
358 }
359
360 return source->getFormat();
361}
362
363status_t NuPlayer::GenericSource::dequeueAccessUnit(
364 bool audio, sp<ABuffer> *accessUnit) {
365 Track *track = audio ? &mAudioTrack : &mVideoTrack;
366
367 if (track->mSource == NULL) {
368 return -EWOULDBLOCK;
369 }
370
Lajos Molnarcc227032014-07-17 15:33:06 -0700371 if (mIsWidevine && !audio) {
372 // try to read a buffer as we may not have been able to the last time
Robert Shih05312bc2014-07-16 15:47:09 -0700373 readBuffer(MEDIA_TRACK_TYPE_AUDIO, -1ll);
Lajos Molnarcc227032014-07-17 15:33:06 -0700374 }
375
Andreas Huberafed0e12011-09-20 15:39:58 -0700376 status_t finalResult;
377 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
Lajos Molnarcc227032014-07-17 15:33:06 -0700378 return (finalResult == OK ? -EWOULDBLOCK : finalResult);
Andreas Huberafed0e12011-09-20 15:39:58 -0700379 }
380
381 status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
382
Robert Shih05312bc2014-07-16 15:47:09 -0700383 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
384 readBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO, -1ll);
385 }
386
Robert Shiheb1735e2014-07-23 15:53:14 -0700387 if (mSubtitleTrack.mSource == NULL && mTimedTextTrack.mSource == NULL) {
Robert Shih05312bc2014-07-16 15:47:09 -0700388 return result;
389 }
390
Robert Shiheb1735e2014-07-23 15:53:14 -0700391 if (mSubtitleTrack.mSource != NULL) {
392 CHECK(mSubtitleTrack.mPackets != NULL);
393 }
394 if (mTimedTextTrack.mSource != NULL) {
395 CHECK(mTimedTextTrack.mPackets != NULL);
396 }
397
Robert Shih05312bc2014-07-16 15:47:09 -0700398 if (result != OK) {
Robert Shiheb1735e2014-07-23 15:53:14 -0700399 if (mSubtitleTrack.mSource != NULL) {
400 mSubtitleTrack.mPackets->clear();
401 mFetchSubtitleDataGeneration++;
402 }
403 if (mTimedTextTrack.mSource != NULL) {
404 mTimedTextTrack.mPackets->clear();
405 mFetchTimedTextDataGeneration++;
406 }
Robert Shih05312bc2014-07-16 15:47:09 -0700407 return result;
408 }
409
410 int64_t timeUs;
411 status_t eosResult; // ignored
412 CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
Robert Shiheb1735e2014-07-23 15:53:14 -0700413
414 if (mSubtitleTrack.mSource != NULL
415 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
Robert Shih05312bc2014-07-16 15:47:09 -0700416 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, id());
417 msg->setInt64("timeUs", timeUs);
418 msg->setInt32("generation", mFetchSubtitleDataGeneration);
419 msg->post();
420 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700421
Robert Shiheb1735e2014-07-23 15:53:14 -0700422 if (mTimedTextTrack.mSource != NULL
423 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
424 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, id());
425 msg->setInt64("timeUs", timeUs);
426 msg->setInt32("generation", mFetchTimedTextDataGeneration);
427 msg->post();
428 }
429
Andreas Huberafed0e12011-09-20 15:39:58 -0700430 return result;
431}
432
433status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
434 *durationUs = mDurationUs;
435 return OK;
436}
437
Robert Shihdd235722014-06-12 14:49:23 -0700438size_t NuPlayer::GenericSource::getTrackCount() const {
439 return mSources.size();
440}
441
442sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const {
443 size_t trackCount = mSources.size();
444 if (trackIndex >= trackCount) {
445 return NULL;
446 }
447
448 sp<AMessage> format = new AMessage();
449 sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat();
450
451 const char *mime;
452 CHECK(meta->findCString(kKeyMIMEType, &mime));
453
454 int32_t trackType;
455 if (!strncasecmp(mime, "video/", 6)) {
456 trackType = MEDIA_TRACK_TYPE_VIDEO;
457 } else if (!strncasecmp(mime, "audio/", 6)) {
458 trackType = MEDIA_TRACK_TYPE_AUDIO;
459 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
460 trackType = MEDIA_TRACK_TYPE_TIMEDTEXT;
461 } else {
462 trackType = MEDIA_TRACK_TYPE_UNKNOWN;
463 }
464 format->setInt32("type", trackType);
465
466 const char *lang;
467 if (!meta->findCString(kKeyMediaLanguage, &lang)) {
468 lang = "und";
469 }
470 format->setString("language", lang);
471
472 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
473 format->setString("mime", mime);
474
475 int32_t isAutoselect = 1, isDefault = 0, isForced = 0;
476 meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect);
477 meta->findInt32(kKeyTrackIsDefault, &isDefault);
478 meta->findInt32(kKeyTrackIsForced, &isForced);
479
480 format->setInt32("auto", !!isAutoselect);
481 format->setInt32("default", !!isDefault);
482 format->setInt32("forced", !!isForced);
483 }
484
485 return format;
486}
487
Robert Shiheb1735e2014-07-23 15:53:14 -0700488ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const {
489 const Track *track = NULL;
490 switch (type) {
491 case MEDIA_TRACK_TYPE_VIDEO:
492 track = &mVideoTrack;
493 break;
494 case MEDIA_TRACK_TYPE_AUDIO:
495 track = &mAudioTrack;
496 break;
497 case MEDIA_TRACK_TYPE_TIMEDTEXT:
498 track = &mTimedTextTrack;
499 break;
500 case MEDIA_TRACK_TYPE_SUBTITLE:
501 track = &mSubtitleTrack;
502 break;
503 default:
504 break;
505 }
506
507 if (track != NULL && track->mSource != NULL) {
508 return track->mIndex;
509 }
510
511 return -1;
512}
513
Robert Shih05312bc2014-07-16 15:47:09 -0700514status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select) {
Robert Shiheb1735e2014-07-23 15:53:14 -0700515 ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
Robert Shih05312bc2014-07-16 15:47:09 -0700516 if (trackIndex >= mSources.size()) {
517 return BAD_INDEX;
518 }
519
520 if (!select) {
Robert Shiheb1735e2014-07-23 15:53:14 -0700521 Track* track = NULL;
522 if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) {
523 track = &mSubtitleTrack;
524 mFetchSubtitleDataGeneration++;
525 } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) {
526 track = &mTimedTextTrack;
527 mFetchTimedTextDataGeneration++;
528 }
529 if (track == NULL) {
Robert Shih05312bc2014-07-16 15:47:09 -0700530 return INVALID_OPERATION;
531 }
Robert Shiheb1735e2014-07-23 15:53:14 -0700532 track->mSource = NULL;
533 track->mPackets->clear();
Robert Shih05312bc2014-07-16 15:47:09 -0700534 return OK;
535 }
536
537 const sp<MediaSource> source = mSources.itemAt(trackIndex);
538 sp<MetaData> meta = source->getFormat();
539 const char *mime;
540 CHECK(meta->findCString(kKeyMIMEType, &mime));
541 if (!strncasecmp(mime, "text/", 5)) {
Robert Shiheb1735e2014-07-23 15:53:14 -0700542 bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP);
543 Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack;
544 if (track->mSource != NULL && track->mIndex == trackIndex) {
Robert Shih05312bc2014-07-16 15:47:09 -0700545 return OK;
546 }
Robert Shiheb1735e2014-07-23 15:53:14 -0700547 track->mIndex = trackIndex;
548 track->mSource = mSources.itemAt(trackIndex);
549 if (track->mPackets == NULL) {
550 track->mPackets = new AnotherPacketSource(track->mSource->getFormat());
Robert Shih05312bc2014-07-16 15:47:09 -0700551 } else {
Robert Shiheb1735e2014-07-23 15:53:14 -0700552 track->mPackets->clear();
553 track->mPackets->setFormat(track->mSource->getFormat());
Robert Shih05312bc2014-07-16 15:47:09 -0700554
555 }
Robert Shiheb1735e2014-07-23 15:53:14 -0700556
557 if (isSubtitle) {
558 mFetchSubtitleDataGeneration++;
559 } else {
560 mFetchTimedTextDataGeneration++;
561 }
562
Robert Shih05312bc2014-07-16 15:47:09 -0700563 return OK;
564 } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
565 bool audio = !strncasecmp(mime, "audio/", 6);
566 Track *track = audio ? &mAudioTrack : &mVideoTrack;
567 if (track->mSource != NULL && track->mIndex == trackIndex) {
568 return OK;
569 }
570
571 sp<AMessage> msg = new AMessage(kWhatChangeAVSource, id());
572 msg->setInt32("trackIndex", trackIndex);
573 msg->post();
574 return OK;
575 }
576
577 return INVALID_OPERATION;
578}
579
Andreas Huberafed0e12011-09-20 15:39:58 -0700580status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs) {
581 if (mVideoTrack.mSource != NULL) {
582 int64_t actualTimeUs;
Robert Shih05312bc2014-07-16 15:47:09 -0700583 readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, &actualTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -0700584
585 seekTimeUs = actualTimeUs;
586 }
587
588 if (mAudioTrack.mSource != NULL) {
Robert Shih05312bc2014-07-16 15:47:09 -0700589 readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -0700590 }
591
592 return OK;
593}
594
Robert Shih05312bc2014-07-16 15:47:09 -0700595sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
596 MediaBuffer* mb,
597 media_track_type trackType,
598 int64_t *actualTimeUs) {
599 bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
600 size_t outLength = mb->range_length();
601
602 if (audio && mAudioIsVorbis) {
603 outLength += sizeof(int32_t);
604 }
605
606 sp<ABuffer> ab;
607 if (mIsWidevine && !audio) {
608 // data is already provided in the buffer
609 ab = new ABuffer(NULL, mb->range_length());
610 ab->meta()->setPointer("mediaBuffer", mb);
611 mb->add_ref();
612 } else {
613 ab = new ABuffer(outLength);
614 memcpy(ab->data(),
615 (const uint8_t *)mb->data() + mb->range_offset(),
616 mb->range_length());
617 }
618
619 if (audio && mAudioIsVorbis) {
620 int32_t numPageSamples;
621 if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
622 numPageSamples = -1;
623 }
624
625 uint8_t* abEnd = ab->data() + mb->range_length();
626 memcpy(abEnd, &numPageSamples, sizeof(numPageSamples));
627 }
628
Robert Shiheb1735e2014-07-23 15:53:14 -0700629 sp<AMessage> meta = ab->meta();
630
Robert Shih05312bc2014-07-16 15:47:09 -0700631 int64_t timeUs;
632 CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs));
Robert Shih05312bc2014-07-16 15:47:09 -0700633 meta->setInt64("timeUs", timeUs);
634
Robert Shiheb1735e2014-07-23 15:53:14 -0700635 if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
636 const char *mime;
637 CHECK(mTimedTextTrack.mSource != NULL
638 && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime));
639 meta->setString("mime", mime);
640 }
641
Robert Shih05312bc2014-07-16 15:47:09 -0700642 int64_t durationUs;
643 if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) {
644 meta->setInt64("durationUs", durationUs);
645 }
646
647 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
648 meta->setInt32("trackIndex", mSubtitleTrack.mIndex);
649 }
650
651 if (actualTimeUs) {
652 *actualTimeUs = timeUs;
653 }
654
655 mb->release();
656 mb = NULL;
657
658 return ab;
659}
660
Andreas Huberafed0e12011-09-20 15:39:58 -0700661void NuPlayer::GenericSource::readBuffer(
Robert Shih05312bc2014-07-16 15:47:09 -0700662 media_track_type trackType, int64_t seekTimeUs, int64_t *actualTimeUs, bool formatChange) {
663 Track *track;
664 switch (trackType) {
665 case MEDIA_TRACK_TYPE_VIDEO:
666 track = &mVideoTrack;
667 break;
668 case MEDIA_TRACK_TYPE_AUDIO:
669 track = &mAudioTrack;
670 break;
671 case MEDIA_TRACK_TYPE_SUBTITLE:
672 track = &mSubtitleTrack;
673 break;
Robert Shiheb1735e2014-07-23 15:53:14 -0700674 case MEDIA_TRACK_TYPE_TIMEDTEXT:
675 track = &mTimedTextTrack;
676 break;
Robert Shih05312bc2014-07-16 15:47:09 -0700677 default:
678 TRESPASS();
679 }
680
681 if (track->mSource == NULL) {
682 return;
683 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700684
685 if (actualTimeUs) {
686 *actualTimeUs = seekTimeUs;
687 }
688
689 MediaSource::ReadOptions options;
690
691 bool seeking = false;
692
693 if (seekTimeUs >= 0) {
Robert Shih05312bc2014-07-16 15:47:09 -0700694 options.setSeekTo(seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
Andreas Huberafed0e12011-09-20 15:39:58 -0700695 seeking = true;
696 }
697
Robert Shih05312bc2014-07-16 15:47:09 -0700698 if (mIsWidevine && trackType != MEDIA_TRACK_TYPE_AUDIO) {
Lajos Molnarcc227032014-07-17 15:33:06 -0700699 options.setNonBlocking();
700 }
701
Andreas Huberafed0e12011-09-20 15:39:58 -0700702 for (;;) {
703 MediaBuffer *mbuf;
704 status_t err = track->mSource->read(&mbuf, &options);
705
706 options.clearSeekTo();
707
708 if (err == OK) {
Robert Shih05312bc2014-07-16 15:47:09 -0700709 // formatChange && seeking: track whose source is changed during selection
710 // formatChange && !seeking: track whose source is not changed during selection
711 // !formatChange: normal seek
Robert Shiheb1735e2014-07-23 15:53:14 -0700712 if ((seeking || formatChange)
713 && (trackType == MEDIA_TRACK_TYPE_AUDIO
714 || trackType == MEDIA_TRACK_TYPE_VIDEO)) {
Robert Shih05312bc2014-07-16 15:47:09 -0700715 ATSParser::DiscontinuityType type = formatChange
716 ? (seeking
717 ? ATSParser::DISCONTINUITY_FORMATCHANGE
718 : ATSParser::DISCONTINUITY_NONE)
719 : ATSParser::DISCONTINUITY_SEEK;
720 track->mPackets->queueDiscontinuity( type, NULL, true /* discard */);
Andreas Huberafed0e12011-09-20 15:39:58 -0700721 }
722
Robert Shih05312bc2014-07-16 15:47:09 -0700723 sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType, actualTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -0700724 track->mPackets->queueAccessUnit(buffer);
725 break;
Lajos Molnarcc227032014-07-17 15:33:06 -0700726 } else if (err == WOULD_BLOCK) {
727 break;
Andreas Huberafed0e12011-09-20 15:39:58 -0700728 } else if (err == INFO_FORMAT_CHANGED) {
729#if 0
730 track->mPackets->queueDiscontinuity(
Chong Zhang632740c2014-06-26 13:03:47 -0700731 ATSParser::DISCONTINUITY_FORMATCHANGE,
732 NULL,
733 false /* discard */);
Andreas Huberafed0e12011-09-20 15:39:58 -0700734#endif
735 } else {
736 track->mPackets->signalEOS(err);
737 break;
738 }
739 }
740}
741
Andreas Huberafed0e12011-09-20 15:39:58 -0700742} // namespace android