blob: 32842bb4d4253e0820fed13a86ab5e3793064951 [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
24#include <media/stagefright/foundation/ABuffer.h>
25#include <media/stagefright/foundation/ADebug.h>
26#include <media/stagefright/foundation/AMessage.h>
27#include <media/stagefright/DataSource.h>
28#include <media/stagefright/FileSource.h>
29#include <media/stagefright/MediaBuffer.h>
30#include <media/stagefright/MediaDefs.h>
31#include <media/stagefright/MediaExtractor.h>
32#include <media/stagefright/MediaSource.h>
33#include <media/stagefright/MetaData.h>
Lajos Molnarcc227032014-07-17 15:33:06 -070034#include "../../libstagefright/include/WVMExtractor.h"
Andreas Huberafed0e12011-09-20 15:39:58 -070035
36namespace android {
37
38NuPlayer::GenericSource::GenericSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080039 const sp<AMessage> &notify,
Andreas Huber1b86fe02014-01-29 11:13:26 -080040 const sp<IMediaHTTPService> &httpService,
Andreas Huberafed0e12011-09-20 15:39:58 -070041 const char *url,
Lajos Molnarcc227032014-07-17 15:33:06 -070042 const KeyedVector<String8, String8> *headers,
43 bool isWidevine,
44 bool uidValid,
45 uid_t uid)
Andreas Huberb5f25f02013-02-05 10:14:26 -080046 : Source(notify),
Robert Shih3423bbd2014-07-16 15:47:09 -070047 mFetchSubtitleDataGeneration(0),
Lajos Molnare26940f2014-07-31 10:31:26 -070048 mFetchTimedTextDataGeneration(0),
Andreas Huberb5f25f02013-02-05 10:14:26 -080049 mDurationUs(0ll),
Lajos Molnarcc227032014-07-17 15:33:06 -070050 mAudioIsVorbis(false),
51 mIsWidevine(isWidevine),
52 mUIDValid(uidValid),
53 mUID(uid) {
Andreas Huberafed0e12011-09-20 15:39:58 -070054 DataSource::RegisterDefaultSniffers();
55
56 sp<DataSource> dataSource =
Andreas Huber1b86fe02014-01-29 11:13:26 -080057 DataSource::CreateFromURI(httpService, url, headers);
Andreas Huberafed0e12011-09-20 15:39:58 -070058 CHECK(dataSource != NULL);
59
60 initFromDataSource(dataSource);
61}
62
63NuPlayer::GenericSource::GenericSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080064 const sp<AMessage> &notify,
Andreas Huberafed0e12011-09-20 15:39:58 -070065 int fd, int64_t offset, int64_t length)
Andreas Huberb5f25f02013-02-05 10:14:26 -080066 : Source(notify),
Robert Shih3423bbd2014-07-16 15:47:09 -070067 mFetchSubtitleDataGeneration(0),
Lajos Molnare26940f2014-07-31 10:31:26 -070068 mFetchTimedTextDataGeneration(0),
Andreas Huberb5f25f02013-02-05 10:14:26 -080069 mDurationUs(0ll),
Lajos Molnar63c0ce72014-07-31 07:13:32 -070070 mAudioIsVorbis(false),
Chong Zhang7e892182014-08-05 11:58:21 -070071 mIsWidevine(false),
72 mUIDValid(false),
73 mUID(0) {
Andreas Huberafed0e12011-09-20 15:39:58 -070074 DataSource::RegisterDefaultSniffers();
75
76 sp<DataSource> dataSource = new FileSource(dup(fd), offset, length);
77
78 initFromDataSource(dataSource);
79}
80
81void NuPlayer::GenericSource::initFromDataSource(
82 const sp<DataSource> &dataSource) {
Lajos Molnarcc227032014-07-17 15:33:06 -070083 sp<MediaExtractor> extractor;
84
85 if (mIsWidevine) {
86 String8 mimeType;
87 float confidence;
88 sp<AMessage> dummy;
89 bool success;
90
91 success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
92 if (!success
93 || strcasecmp(
94 mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
95 ALOGE("unsupported widevine mime: %s", mimeType.string());
96 return;
97 }
98
99 sp<WVMExtractor> wvmExtractor = new WVMExtractor(dataSource);
100 wvmExtractor->setAdaptiveStreamingMode(true);
101 if (mUIDValid) {
102 wvmExtractor->setUID(mUID);
103 }
104 extractor = wvmExtractor;
105 } else {
106 extractor = MediaExtractor::Create(dataSource);
107 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700108
109 CHECK(extractor != NULL);
110
Marco Nelissenc1f4b2b2014-06-17 14:48:32 -0700111 sp<MetaData> fileMeta = extractor->getMetaData();
112 if (fileMeta != NULL) {
113 int64_t duration;
114 if (fileMeta->findInt64(kKeyDuration, &duration)) {
115 mDurationUs = duration;
116 }
117 }
118
Andreas Huberafed0e12011-09-20 15:39:58 -0700119 for (size_t i = 0; i < extractor->countTracks(); ++i) {
120 sp<MetaData> meta = extractor->getTrackMetaData(i);
121
122 const char *mime;
123 CHECK(meta->findCString(kKeyMIMEType, &mime));
124
Robert Shihdd235722014-06-12 14:49:23 -0700125 sp<MediaSource> track = extractor->getTrack(i);
Andreas Huberafed0e12011-09-20 15:39:58 -0700126
127 if (!strncasecmp(mime, "audio/", 6)) {
128 if (mAudioTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700129 mAudioTrack.mIndex = i;
130 mAudioTrack.mSource = track;
Andreas Huberafed0e12011-09-20 15:39:58 -0700131
132 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
133 mAudioIsVorbis = true;
134 } else {
135 mAudioIsVorbis = false;
136 }
137 }
138 } else if (!strncasecmp(mime, "video/", 6)) {
139 if (mVideoTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700140 mVideoTrack.mIndex = i;
141 mVideoTrack.mSource = track;
Chong Zhang7e892182014-08-05 11:58:21 -0700142
143 // check if the source requires secure buffers
144 int32_t secure;
145 if (meta->findInt32(kKeyRequiresSecureBuffers, &secure) && secure) {
146 mIsWidevine = true;
147 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700148 }
149 }
150
151 if (track != NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700152 mSources.push(track);
Andreas Huberafed0e12011-09-20 15:39:58 -0700153 int64_t durationUs;
154 if (meta->findInt64(kKeyDuration, &durationUs)) {
155 if (durationUs > mDurationUs) {
156 mDurationUs = durationUs;
157 }
158 }
159 }
160 }
161}
162
Lajos Molnarcc227032014-07-17 15:33:06 -0700163status_t NuPlayer::GenericSource::setBuffers(bool audio, Vector<MediaBuffer *> &buffers) {
164 if (mIsWidevine && !audio) {
165 return mVideoTrack.mSource->setBuffers(buffers);
166 }
167 return INVALID_OPERATION;
168}
169
Andreas Huberafed0e12011-09-20 15:39:58 -0700170NuPlayer::GenericSource::~GenericSource() {
171}
172
Andreas Huber9575c962013-02-05 13:59:56 -0800173void NuPlayer::GenericSource::prepareAsync() {
174 if (mVideoTrack.mSource != NULL) {
175 sp<MetaData> meta = mVideoTrack.mSource->getFormat();
176
177 int32_t width, height;
178 CHECK(meta->findInt32(kKeyWidth, &width));
179 CHECK(meta->findInt32(kKeyHeight, &height));
180
181 notifyVideoSizeChanged(width, height);
182 }
183
184 notifyFlagsChanged(
Lajos Molnarcc227032014-07-17 15:33:06 -0700185 (mIsWidevine ? FLAG_SECURE : 0)
186 | FLAG_CAN_PAUSE
Andreas Huber9575c962013-02-05 13:59:56 -0800187 | FLAG_CAN_SEEK_BACKWARD
188 | FLAG_CAN_SEEK_FORWARD
189 | FLAG_CAN_SEEK);
190
191 notifyPrepared();
192}
193
Andreas Huberafed0e12011-09-20 15:39:58 -0700194void NuPlayer::GenericSource::start() {
195 ALOGI("start");
196
197 if (mAudioTrack.mSource != NULL) {
Robert Shihbace25b2014-07-25 14:14:34 -0700198 CHECK_EQ(mAudioTrack.mSource->start(), (status_t)OK);
Andreas Huberafed0e12011-09-20 15:39:58 -0700199 mAudioTrack.mPackets =
200 new AnotherPacketSource(mAudioTrack.mSource->getFormat());
201
Robert Shih3423bbd2014-07-16 15:47:09 -0700202 readBuffer(MEDIA_TRACK_TYPE_AUDIO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700203 }
204
205 if (mVideoTrack.mSource != NULL) {
Robert Shihbace25b2014-07-25 14:14:34 -0700206 CHECK_EQ(mVideoTrack.mSource->start(), (status_t)OK);
Andreas Huberafed0e12011-09-20 15:39:58 -0700207 mVideoTrack.mPackets =
208 new AnotherPacketSource(mVideoTrack.mSource->getFormat());
209
Robert Shih3423bbd2014-07-16 15:47:09 -0700210 readBuffer(MEDIA_TRACK_TYPE_VIDEO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700211 }
212}
213
214status_t NuPlayer::GenericSource::feedMoreTSData() {
215 return OK;
216}
217
Robert Shih3423bbd2014-07-16 15:47:09 -0700218void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
219 switch (msg->what()) {
220 case kWhatFetchSubtitleData:
221 {
Lajos Molnare26940f2014-07-31 10:31:26 -0700222 fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
223 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
224 break;
225 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700226
Lajos Molnare26940f2014-07-31 10:31:26 -0700227 case kWhatFetchTimedTextData:
228 {
229 fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
230 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih3423bbd2014-07-16 15:47:09 -0700231 break;
232 }
233
234 case kWhatSendSubtitleData:
235 {
Lajos Molnare26940f2014-07-31 10:31:26 -0700236 sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
237 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
238 break;
239 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700240
Lajos Molnare26940f2014-07-31 10:31:26 -0700241 case kWhatSendTimedTextData:
242 {
243 sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
244 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih3423bbd2014-07-16 15:47:09 -0700245 break;
246 }
247
248 case kWhatChangeAVSource:
249 {
250 int32_t trackIndex;
251 CHECK(msg->findInt32("trackIndex", &trackIndex));
252 const sp<MediaSource> source = mSources.itemAt(trackIndex);
253
254 Track* track;
255 const char *mime;
256 media_track_type trackType, counterpartType;
257 sp<MetaData> meta = source->getFormat();
258 meta->findCString(kKeyMIMEType, &mime);
259 if (!strncasecmp(mime, "audio/", 6)) {
260 track = &mAudioTrack;
261 trackType = MEDIA_TRACK_TYPE_AUDIO;
262 counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
263 } else {
264 CHECK(!strncasecmp(mime, "video/", 6));
265 track = &mVideoTrack;
266 trackType = MEDIA_TRACK_TYPE_VIDEO;
267 counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
268 }
269
270
271 if (track->mSource != NULL) {
272 track->mSource->stop();
273 }
274 track->mSource = source;
275 track->mSource->start();
276 track->mIndex = trackIndex;
277
278 status_t avail;
279 if (!track->mPackets->hasBufferAvailable(&avail)) {
280 // sync from other source
281 TRESPASS();
282 break;
283 }
284
285 int64_t timeUs, actualTimeUs;
286 const bool formatChange = true;
287 sp<AMessage> latestMeta = track->mPackets->getLatestMeta();
288 CHECK(latestMeta != NULL && latestMeta->findInt64("timeUs", &timeUs));
289 readBuffer(trackType, timeUs, &actualTimeUs, formatChange);
290 readBuffer(counterpartType, -1, NULL, formatChange);
291 ALOGV("timeUs %lld actualTimeUs %lld", timeUs, actualTimeUs);
292
293 break;
294 }
295
296 default:
297 Source::onMessageReceived(msg);
298 break;
299 }
300}
301
Lajos Molnare26940f2014-07-31 10:31:26 -0700302void NuPlayer::GenericSource::fetchTextData(
303 uint32_t sendWhat,
304 media_track_type type,
305 int32_t curGen,
306 sp<AnotherPacketSource> packets,
307 sp<AMessage> msg) {
308 int32_t msgGeneration;
309 CHECK(msg->findInt32("generation", &msgGeneration));
310 if (msgGeneration != curGen) {
311 // stale
312 return;
313 }
314
315 int32_t avail;
316 if (packets->hasBufferAvailable(&avail)) {
317 return;
318 }
319
320 int64_t timeUs;
321 CHECK(msg->findInt64("timeUs", &timeUs));
322
323 int64_t subTimeUs;
324 readBuffer(type, timeUs, &subTimeUs);
325
326 int64_t delayUs = subTimeUs - timeUs;
327 if (msg->what() == kWhatFetchSubtitleData) {
328 const int64_t oneSecUs = 1000000ll;
329 delayUs -= oneSecUs;
330 }
331 sp<AMessage> msg2 = new AMessage(sendWhat, id());
332 msg2->setInt32("generation", msgGeneration);
333 msg2->post(delayUs < 0 ? 0 : delayUs);
334}
335
336void NuPlayer::GenericSource::sendTextData(
337 uint32_t what,
338 media_track_type type,
339 int32_t curGen,
340 sp<AnotherPacketSource> packets,
341 sp<AMessage> msg) {
342 int32_t msgGeneration;
343 CHECK(msg->findInt32("generation", &msgGeneration));
344 if (msgGeneration != curGen) {
345 // stale
346 return;
347 }
348
349 int64_t subTimeUs;
350 if (packets->nextBufferTime(&subTimeUs) != OK) {
351 return;
352 }
353
354 int64_t nextSubTimeUs;
355 readBuffer(type, -1, &nextSubTimeUs);
356
357 sp<ABuffer> buffer;
358 status_t dequeueStatus = packets->dequeueAccessUnit(&buffer);
359 if (dequeueStatus == OK) {
360 sp<AMessage> notify = dupNotify();
361 notify->setInt32("what", what);
362 notify->setBuffer("buffer", buffer);
363 notify->post();
364
365 const int64_t delayUs = nextSubTimeUs - subTimeUs;
366 msg->post(delayUs < 0 ? 0 : delayUs);
367 }
368}
369
Andreas Huber84066782011-08-16 09:34:26 -0700370sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700371 sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
372
373 if (source == NULL) {
374 return NULL;
375 }
376
377 return source->getFormat();
378}
379
380status_t NuPlayer::GenericSource::dequeueAccessUnit(
381 bool audio, sp<ABuffer> *accessUnit) {
382 Track *track = audio ? &mAudioTrack : &mVideoTrack;
383
384 if (track->mSource == NULL) {
385 return -EWOULDBLOCK;
386 }
387
Lajos Molnarcc227032014-07-17 15:33:06 -0700388 if (mIsWidevine && !audio) {
389 // try to read a buffer as we may not have been able to the last time
Robert Shih3423bbd2014-07-16 15:47:09 -0700390 readBuffer(MEDIA_TRACK_TYPE_VIDEO, -1ll);
Lajos Molnarcc227032014-07-17 15:33:06 -0700391 }
392
Andreas Huberafed0e12011-09-20 15:39:58 -0700393 status_t finalResult;
394 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
Lajos Molnarcc227032014-07-17 15:33:06 -0700395 return (finalResult == OK ? -EWOULDBLOCK : finalResult);
Andreas Huberafed0e12011-09-20 15:39:58 -0700396 }
397
398 status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
399
Robert Shih3423bbd2014-07-16 15:47:09 -0700400 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
401 readBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO, -1ll);
402 }
403
Lajos Molnare26940f2014-07-31 10:31:26 -0700404 if (mSubtitleTrack.mSource == NULL && mTimedTextTrack.mSource == NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700405 return result;
406 }
407
Lajos Molnare26940f2014-07-31 10:31:26 -0700408 if (mSubtitleTrack.mSource != NULL) {
409 CHECK(mSubtitleTrack.mPackets != NULL);
410 }
411 if (mTimedTextTrack.mSource != NULL) {
412 CHECK(mTimedTextTrack.mPackets != NULL);
413 }
414
Robert Shih3423bbd2014-07-16 15:47:09 -0700415 if (result != OK) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700416 if (mSubtitleTrack.mSource != NULL) {
417 mSubtitleTrack.mPackets->clear();
418 mFetchSubtitleDataGeneration++;
419 }
420 if (mTimedTextTrack.mSource != NULL) {
421 mTimedTextTrack.mPackets->clear();
422 mFetchTimedTextDataGeneration++;
423 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700424 return result;
425 }
426
427 int64_t timeUs;
428 status_t eosResult; // ignored
429 CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
Lajos Molnare26940f2014-07-31 10:31:26 -0700430
431 if (mSubtitleTrack.mSource != NULL
432 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700433 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, id());
434 msg->setInt64("timeUs", timeUs);
435 msg->setInt32("generation", mFetchSubtitleDataGeneration);
436 msg->post();
437 }
Robert Shiheb1735e2014-07-23 15:53:14 -0700438
Lajos Molnare26940f2014-07-31 10:31:26 -0700439 if (mTimedTextTrack.mSource != NULL
440 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
441 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, id());
442 msg->setInt64("timeUs", timeUs);
443 msg->setInt32("generation", mFetchTimedTextDataGeneration);
444 msg->post();
445 }
446
Andreas Huberafed0e12011-09-20 15:39:58 -0700447 return result;
448}
449
450status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
451 *durationUs = mDurationUs;
452 return OK;
453}
454
Robert Shihdd235722014-06-12 14:49:23 -0700455size_t NuPlayer::GenericSource::getTrackCount() const {
456 return mSources.size();
457}
458
459sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const {
460 size_t trackCount = mSources.size();
461 if (trackIndex >= trackCount) {
462 return NULL;
463 }
464
465 sp<AMessage> format = new AMessage();
466 sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat();
467
468 const char *mime;
469 CHECK(meta->findCString(kKeyMIMEType, &mime));
470
471 int32_t trackType;
472 if (!strncasecmp(mime, "video/", 6)) {
473 trackType = MEDIA_TRACK_TYPE_VIDEO;
474 } else if (!strncasecmp(mime, "audio/", 6)) {
475 trackType = MEDIA_TRACK_TYPE_AUDIO;
476 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
477 trackType = MEDIA_TRACK_TYPE_TIMEDTEXT;
478 } else {
479 trackType = MEDIA_TRACK_TYPE_UNKNOWN;
480 }
481 format->setInt32("type", trackType);
482
483 const char *lang;
484 if (!meta->findCString(kKeyMediaLanguage, &lang)) {
485 lang = "und";
486 }
487 format->setString("language", lang);
488
489 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
490 format->setString("mime", mime);
491
492 int32_t isAutoselect = 1, isDefault = 0, isForced = 0;
493 meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect);
494 meta->findInt32(kKeyTrackIsDefault, &isDefault);
495 meta->findInt32(kKeyTrackIsForced, &isForced);
496
497 format->setInt32("auto", !!isAutoselect);
498 format->setInt32("default", !!isDefault);
499 format->setInt32("forced", !!isForced);
500 }
501
502 return format;
503}
504
Lajos Molnare26940f2014-07-31 10:31:26 -0700505ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const {
506 const Track *track = NULL;
507 switch (type) {
508 case MEDIA_TRACK_TYPE_VIDEO:
509 track = &mVideoTrack;
510 break;
511 case MEDIA_TRACK_TYPE_AUDIO:
512 track = &mAudioTrack;
513 break;
514 case MEDIA_TRACK_TYPE_TIMEDTEXT:
515 track = &mTimedTextTrack;
516 break;
517 case MEDIA_TRACK_TYPE_SUBTITLE:
518 track = &mSubtitleTrack;
519 break;
520 default:
521 break;
522 }
523
524 if (track != NULL && track->mSource != NULL) {
525 return track->mIndex;
526 }
527
528 return -1;
529}
530
Robert Shih3423bbd2014-07-16 15:47:09 -0700531status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700532 ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
Robert Shih3423bbd2014-07-16 15:47:09 -0700533 if (trackIndex >= mSources.size()) {
534 return BAD_INDEX;
535 }
536
537 if (!select) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700538 Track* track = NULL;
539 if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) {
540 track = &mSubtitleTrack;
541 mFetchSubtitleDataGeneration++;
542 } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) {
543 track = &mTimedTextTrack;
544 mFetchTimedTextDataGeneration++;
545 }
546 if (track == NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700547 return INVALID_OPERATION;
548 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700549 track->mSource->stop();
550 track->mSource = NULL;
551 track->mPackets->clear();
Robert Shih3423bbd2014-07-16 15:47:09 -0700552 return OK;
553 }
554
555 const sp<MediaSource> source = mSources.itemAt(trackIndex);
556 sp<MetaData> meta = source->getFormat();
557 const char *mime;
558 CHECK(meta->findCString(kKeyMIMEType, &mime));
559 if (!strncasecmp(mime, "text/", 5)) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700560 bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP);
561 Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack;
562 if (track->mSource != NULL && track->mIndex == trackIndex) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700563 return OK;
564 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700565 track->mIndex = trackIndex;
566 if (track->mSource != NULL) {
567 track->mSource->stop();
Robert Shih3423bbd2014-07-16 15:47:09 -0700568 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700569 track->mSource = mSources.itemAt(trackIndex);
570 track->mSource->start();
571 if (track->mPackets == NULL) {
572 track->mPackets = new AnotherPacketSource(track->mSource->getFormat());
Robert Shih3423bbd2014-07-16 15:47:09 -0700573 } else {
Lajos Molnare26940f2014-07-31 10:31:26 -0700574 track->mPackets->clear();
575 track->mPackets->setFormat(track->mSource->getFormat());
Robert Shih3423bbd2014-07-16 15:47:09 -0700576
577 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700578
579 if (isSubtitle) {
580 mFetchSubtitleDataGeneration++;
581 } else {
582 mFetchTimedTextDataGeneration++;
583 }
584
Robert Shih3423bbd2014-07-16 15:47:09 -0700585 return OK;
586 } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
587 bool audio = !strncasecmp(mime, "audio/", 6);
588 Track *track = audio ? &mAudioTrack : &mVideoTrack;
589 if (track->mSource != NULL && track->mIndex == trackIndex) {
590 return OK;
591 }
592
593 sp<AMessage> msg = new AMessage(kWhatChangeAVSource, id());
594 msg->setInt32("trackIndex", trackIndex);
595 msg->post();
596 return OK;
597 }
598
599 return INVALID_OPERATION;
600}
601
Andreas Huberafed0e12011-09-20 15:39:58 -0700602status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs) {
603 if (mVideoTrack.mSource != NULL) {
604 int64_t actualTimeUs;
Robert Shih3423bbd2014-07-16 15:47:09 -0700605 readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, &actualTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -0700606
607 seekTimeUs = actualTimeUs;
608 }
609
610 if (mAudioTrack.mSource != NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700611 readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -0700612 }
613
614 return OK;
615}
616
Robert Shih3423bbd2014-07-16 15:47:09 -0700617sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
618 MediaBuffer* mb,
619 media_track_type trackType,
620 int64_t *actualTimeUs) {
621 bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
622 size_t outLength = mb->range_length();
623
624 if (audio && mAudioIsVorbis) {
625 outLength += sizeof(int32_t);
626 }
627
628 sp<ABuffer> ab;
629 if (mIsWidevine && !audio) {
630 // data is already provided in the buffer
631 ab = new ABuffer(NULL, mb->range_length());
632 ab->meta()->setPointer("mediaBuffer", mb);
633 mb->add_ref();
634 } else {
635 ab = new ABuffer(outLength);
636 memcpy(ab->data(),
637 (const uint8_t *)mb->data() + mb->range_offset(),
638 mb->range_length());
639 }
640
641 if (audio && mAudioIsVorbis) {
642 int32_t numPageSamples;
643 if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
644 numPageSamples = -1;
645 }
646
647 uint8_t* abEnd = ab->data() + mb->range_length();
648 memcpy(abEnd, &numPageSamples, sizeof(numPageSamples));
649 }
650
Lajos Molnare26940f2014-07-31 10:31:26 -0700651 sp<AMessage> meta = ab->meta();
652
Robert Shih3423bbd2014-07-16 15:47:09 -0700653 int64_t timeUs;
654 CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs));
Robert Shih3423bbd2014-07-16 15:47:09 -0700655 meta->setInt64("timeUs", timeUs);
656
Lajos Molnare26940f2014-07-31 10:31:26 -0700657 if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
658 const char *mime;
659 CHECK(mTimedTextTrack.mSource != NULL
660 && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime));
661 meta->setString("mime", mime);
662 }
663
Robert Shih3423bbd2014-07-16 15:47:09 -0700664 int64_t durationUs;
665 if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) {
666 meta->setInt64("durationUs", durationUs);
667 }
668
669 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
670 meta->setInt32("trackIndex", mSubtitleTrack.mIndex);
671 }
672
673 if (actualTimeUs) {
674 *actualTimeUs = timeUs;
675 }
676
677 mb->release();
678 mb = NULL;
679
680 return ab;
681}
682
Andreas Huberafed0e12011-09-20 15:39:58 -0700683void NuPlayer::GenericSource::readBuffer(
Robert Shih3423bbd2014-07-16 15:47:09 -0700684 media_track_type trackType, int64_t seekTimeUs, int64_t *actualTimeUs, bool formatChange) {
685 Track *track;
686 switch (trackType) {
687 case MEDIA_TRACK_TYPE_VIDEO:
688 track = &mVideoTrack;
689 break;
690 case MEDIA_TRACK_TYPE_AUDIO:
691 track = &mAudioTrack;
692 break;
693 case MEDIA_TRACK_TYPE_SUBTITLE:
694 track = &mSubtitleTrack;
695 break;
Lajos Molnare26940f2014-07-31 10:31:26 -0700696 case MEDIA_TRACK_TYPE_TIMEDTEXT:
697 track = &mTimedTextTrack;
698 break;
Robert Shih3423bbd2014-07-16 15:47:09 -0700699 default:
700 TRESPASS();
701 }
702
703 if (track->mSource == NULL) {
704 return;
705 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700706
707 if (actualTimeUs) {
708 *actualTimeUs = seekTimeUs;
709 }
710
711 MediaSource::ReadOptions options;
712
713 bool seeking = false;
714
715 if (seekTimeUs >= 0) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700716 options.setSeekTo(seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
Andreas Huberafed0e12011-09-20 15:39:58 -0700717 seeking = true;
718 }
719
Robert Shih3423bbd2014-07-16 15:47:09 -0700720 if (mIsWidevine && trackType != MEDIA_TRACK_TYPE_AUDIO) {
Lajos Molnarcc227032014-07-17 15:33:06 -0700721 options.setNonBlocking();
722 }
723
Andreas Huberafed0e12011-09-20 15:39:58 -0700724 for (;;) {
725 MediaBuffer *mbuf;
726 status_t err = track->mSource->read(&mbuf, &options);
727
728 options.clearSeekTo();
729
730 if (err == OK) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700731 // formatChange && seeking: track whose source is changed during selection
732 // formatChange && !seeking: track whose source is not changed during selection
733 // !formatChange: normal seek
Lajos Molnare26940f2014-07-31 10:31:26 -0700734 if ((seeking || formatChange)
735 && (trackType == MEDIA_TRACK_TYPE_AUDIO
736 || trackType == MEDIA_TRACK_TYPE_VIDEO)) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700737 ATSParser::DiscontinuityType type = formatChange
738 ? (seeking
739 ? ATSParser::DISCONTINUITY_FORMATCHANGE
740 : ATSParser::DISCONTINUITY_NONE)
741 : ATSParser::DISCONTINUITY_SEEK;
742 track->mPackets->queueDiscontinuity( type, NULL, true /* discard */);
Andreas Huberafed0e12011-09-20 15:39:58 -0700743 }
744
Robert Shih3423bbd2014-07-16 15:47:09 -0700745 sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType, actualTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -0700746 track->mPackets->queueAccessUnit(buffer);
747 break;
Lajos Molnarcc227032014-07-17 15:33:06 -0700748 } else if (err == WOULD_BLOCK) {
749 break;
Andreas Huberafed0e12011-09-20 15:39:58 -0700750 } else if (err == INFO_FORMAT_CHANGED) {
751#if 0
752 track->mPackets->queueDiscontinuity(
Chong Zhang632740c2014-06-26 13:03:47 -0700753 ATSParser::DISCONTINUITY_FORMATCHANGE,
754 NULL,
755 false /* discard */);
Andreas Huberafed0e12011-09-20 15:39:58 -0700756#endif
757 } else {
758 track->mPackets->signalEOS(err);
759 break;
760 }
761 }
762}
763
Andreas Huberafed0e12011-09-20 15:39:58 -0700764} // namespace android