blob: a3e84df2d4e2b22ccf955c9ce8182505447590c1 [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),
Lajos Molnare26940f2014-07-31 10:31:26 -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 Shih3423bbd2014-07-16 15:47:09 -070064 mFetchSubtitleDataGeneration(0),
Lajos Molnare26940f2014-07-31 10:31:26 -070065 mFetchTimedTextDataGeneration(0),
Andreas Huberb5f25f02013-02-05 10:14:26 -080066 mDurationUs(0ll),
Lajos Molnar63c0ce72014-07-31 07:13:32 -070067 mAudioIsVorbis(false),
68 mIsWidevine(false) {
Andreas Huberafed0e12011-09-20 15:39:58 -070069 DataSource::RegisterDefaultSniffers();
70
71 sp<DataSource> dataSource = new FileSource(dup(fd), offset, length);
72
73 initFromDataSource(dataSource);
74}
75
76void NuPlayer::GenericSource::initFromDataSource(
77 const sp<DataSource> &dataSource) {
Lajos Molnarcc227032014-07-17 15:33:06 -070078 sp<MediaExtractor> extractor;
79
80 if (mIsWidevine) {
81 String8 mimeType;
82 float confidence;
83 sp<AMessage> dummy;
84 bool success;
85
86 success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
87 if (!success
88 || strcasecmp(
89 mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
90 ALOGE("unsupported widevine mime: %s", mimeType.string());
91 return;
92 }
93
94 sp<WVMExtractor> wvmExtractor = new WVMExtractor(dataSource);
95 wvmExtractor->setAdaptiveStreamingMode(true);
96 if (mUIDValid) {
97 wvmExtractor->setUID(mUID);
98 }
99 extractor = wvmExtractor;
100 } else {
101 extractor = MediaExtractor::Create(dataSource);
102 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700103
104 CHECK(extractor != NULL);
105
Marco Nelissenc1f4b2b2014-06-17 14:48:32 -0700106 sp<MetaData> fileMeta = extractor->getMetaData();
107 if (fileMeta != NULL) {
108 int64_t duration;
109 if (fileMeta->findInt64(kKeyDuration, &duration)) {
110 mDurationUs = duration;
111 }
112 }
113
Andreas Huberafed0e12011-09-20 15:39:58 -0700114 for (size_t i = 0; i < extractor->countTracks(); ++i) {
115 sp<MetaData> meta = extractor->getTrackMetaData(i);
116
117 const char *mime;
118 CHECK(meta->findCString(kKeyMIMEType, &mime));
119
Robert Shihdd235722014-06-12 14:49:23 -0700120 sp<MediaSource> track = extractor->getTrack(i);
Andreas Huberafed0e12011-09-20 15:39:58 -0700121
122 if (!strncasecmp(mime, "audio/", 6)) {
123 if (mAudioTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700124 mAudioTrack.mIndex = i;
125 mAudioTrack.mSource = track;
Andreas Huberafed0e12011-09-20 15:39:58 -0700126
127 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
128 mAudioIsVorbis = true;
129 } else {
130 mAudioIsVorbis = false;
131 }
132 }
133 } else if (!strncasecmp(mime, "video/", 6)) {
134 if (mVideoTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700135 mVideoTrack.mIndex = i;
136 mVideoTrack.mSource = track;
Andreas Huberafed0e12011-09-20 15:39:58 -0700137 }
138 }
139
140 if (track != NULL) {
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) {
Robert Shihbace25b2014-07-25 14:14:34 -0700187 CHECK_EQ(mAudioTrack.mSource->start(), (status_t)OK);
Andreas Huberafed0e12011-09-20 15:39:58 -0700188 mAudioTrack.mPackets =
189 new AnotherPacketSource(mAudioTrack.mSource->getFormat());
190
Robert Shih3423bbd2014-07-16 15:47:09 -0700191 readBuffer(MEDIA_TRACK_TYPE_AUDIO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700192 }
193
194 if (mVideoTrack.mSource != NULL) {
Robert Shihbace25b2014-07-25 14:14:34 -0700195 CHECK_EQ(mVideoTrack.mSource->start(), (status_t)OK);
Andreas Huberafed0e12011-09-20 15:39:58 -0700196 mVideoTrack.mPackets =
197 new AnotherPacketSource(mVideoTrack.mSource->getFormat());
198
Robert Shih3423bbd2014-07-16 15:47:09 -0700199 readBuffer(MEDIA_TRACK_TYPE_VIDEO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700200 }
201}
202
203status_t NuPlayer::GenericSource::feedMoreTSData() {
204 return OK;
205}
206
Robert Shih3423bbd2014-07-16 15:47:09 -0700207void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
208 switch (msg->what()) {
209 case kWhatFetchSubtitleData:
210 {
Lajos Molnare26940f2014-07-31 10:31:26 -0700211 fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
212 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
213 break;
214 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700215
Lajos Molnare26940f2014-07-31 10:31:26 -0700216 case kWhatFetchTimedTextData:
217 {
218 fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
219 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih3423bbd2014-07-16 15:47:09 -0700220 break;
221 }
222
223 case kWhatSendSubtitleData:
224 {
Lajos Molnare26940f2014-07-31 10:31:26 -0700225 sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
226 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
227 break;
228 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700229
Lajos Molnare26940f2014-07-31 10:31:26 -0700230 case kWhatSendTimedTextData:
231 {
232 sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
233 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih3423bbd2014-07-16 15:47:09 -0700234 break;
235 }
236
237 case kWhatChangeAVSource:
238 {
239 int32_t trackIndex;
240 CHECK(msg->findInt32("trackIndex", &trackIndex));
241 const sp<MediaSource> source = mSources.itemAt(trackIndex);
242
243 Track* track;
244 const char *mime;
245 media_track_type trackType, counterpartType;
246 sp<MetaData> meta = source->getFormat();
247 meta->findCString(kKeyMIMEType, &mime);
248 if (!strncasecmp(mime, "audio/", 6)) {
249 track = &mAudioTrack;
250 trackType = MEDIA_TRACK_TYPE_AUDIO;
251 counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
252 } else {
253 CHECK(!strncasecmp(mime, "video/", 6));
254 track = &mVideoTrack;
255 trackType = MEDIA_TRACK_TYPE_VIDEO;
256 counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
257 }
258
259
260 if (track->mSource != NULL) {
261 track->mSource->stop();
262 }
263 track->mSource = source;
264 track->mSource->start();
265 track->mIndex = trackIndex;
266
267 status_t avail;
268 if (!track->mPackets->hasBufferAvailable(&avail)) {
269 // sync from other source
270 TRESPASS();
271 break;
272 }
273
274 int64_t timeUs, actualTimeUs;
275 const bool formatChange = true;
276 sp<AMessage> latestMeta = track->mPackets->getLatestMeta();
277 CHECK(latestMeta != NULL && latestMeta->findInt64("timeUs", &timeUs));
278 readBuffer(trackType, timeUs, &actualTimeUs, formatChange);
279 readBuffer(counterpartType, -1, NULL, formatChange);
280 ALOGV("timeUs %lld actualTimeUs %lld", timeUs, actualTimeUs);
281
282 break;
283 }
284
285 default:
286 Source::onMessageReceived(msg);
287 break;
288 }
289}
290
Lajos Molnare26940f2014-07-31 10:31:26 -0700291void NuPlayer::GenericSource::fetchTextData(
292 uint32_t sendWhat,
293 media_track_type type,
294 int32_t curGen,
295 sp<AnotherPacketSource> packets,
296 sp<AMessage> msg) {
297 int32_t msgGeneration;
298 CHECK(msg->findInt32("generation", &msgGeneration));
299 if (msgGeneration != curGen) {
300 // stale
301 return;
302 }
303
304 int32_t avail;
305 if (packets->hasBufferAvailable(&avail)) {
306 return;
307 }
308
309 int64_t timeUs;
310 CHECK(msg->findInt64("timeUs", &timeUs));
311
312 int64_t subTimeUs;
313 readBuffer(type, timeUs, &subTimeUs);
314
315 int64_t delayUs = subTimeUs - timeUs;
316 if (msg->what() == kWhatFetchSubtitleData) {
317 const int64_t oneSecUs = 1000000ll;
318 delayUs -= oneSecUs;
319 }
320 sp<AMessage> msg2 = new AMessage(sendWhat, id());
321 msg2->setInt32("generation", msgGeneration);
322 msg2->post(delayUs < 0 ? 0 : delayUs);
323}
324
325void NuPlayer::GenericSource::sendTextData(
326 uint32_t what,
327 media_track_type type,
328 int32_t curGen,
329 sp<AnotherPacketSource> packets,
330 sp<AMessage> msg) {
331 int32_t msgGeneration;
332 CHECK(msg->findInt32("generation", &msgGeneration));
333 if (msgGeneration != curGen) {
334 // stale
335 return;
336 }
337
338 int64_t subTimeUs;
339 if (packets->nextBufferTime(&subTimeUs) != OK) {
340 return;
341 }
342
343 int64_t nextSubTimeUs;
344 readBuffer(type, -1, &nextSubTimeUs);
345
346 sp<ABuffer> buffer;
347 status_t dequeueStatus = packets->dequeueAccessUnit(&buffer);
348 if (dequeueStatus == OK) {
349 sp<AMessage> notify = dupNotify();
350 notify->setInt32("what", what);
351 notify->setBuffer("buffer", buffer);
352 notify->post();
353
354 const int64_t delayUs = nextSubTimeUs - subTimeUs;
355 msg->post(delayUs < 0 ? 0 : delayUs);
356 }
357}
358
Andreas Huber84066782011-08-16 09:34:26 -0700359sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700360 sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
361
362 if (source == NULL) {
363 return NULL;
364 }
365
366 return source->getFormat();
367}
368
369status_t NuPlayer::GenericSource::dequeueAccessUnit(
370 bool audio, sp<ABuffer> *accessUnit) {
371 Track *track = audio ? &mAudioTrack : &mVideoTrack;
372
373 if (track->mSource == NULL) {
374 return -EWOULDBLOCK;
375 }
376
Lajos Molnarcc227032014-07-17 15:33:06 -0700377 if (mIsWidevine && !audio) {
378 // try to read a buffer as we may not have been able to the last time
Robert Shih3423bbd2014-07-16 15:47:09 -0700379 readBuffer(MEDIA_TRACK_TYPE_VIDEO, -1ll);
Lajos Molnarcc227032014-07-17 15:33:06 -0700380 }
381
Andreas Huberafed0e12011-09-20 15:39:58 -0700382 status_t finalResult;
383 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
Lajos Molnarcc227032014-07-17 15:33:06 -0700384 return (finalResult == OK ? -EWOULDBLOCK : finalResult);
Andreas Huberafed0e12011-09-20 15:39:58 -0700385 }
386
387 status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
388
Robert Shih3423bbd2014-07-16 15:47:09 -0700389 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
390 readBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO, -1ll);
391 }
392
Lajos Molnare26940f2014-07-31 10:31:26 -0700393 if (mSubtitleTrack.mSource == NULL && mTimedTextTrack.mSource == NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700394 return result;
395 }
396
Lajos Molnare26940f2014-07-31 10:31:26 -0700397 if (mSubtitleTrack.mSource != NULL) {
398 CHECK(mSubtitleTrack.mPackets != NULL);
399 }
400 if (mTimedTextTrack.mSource != NULL) {
401 CHECK(mTimedTextTrack.mPackets != NULL);
402 }
403
Robert Shih3423bbd2014-07-16 15:47:09 -0700404 if (result != OK) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700405 if (mSubtitleTrack.mSource != NULL) {
406 mSubtitleTrack.mPackets->clear();
407 mFetchSubtitleDataGeneration++;
408 }
409 if (mTimedTextTrack.mSource != NULL) {
410 mTimedTextTrack.mPackets->clear();
411 mFetchTimedTextDataGeneration++;
412 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700413 return result;
414 }
415
416 int64_t timeUs;
417 status_t eosResult; // ignored
418 CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
Lajos Molnare26940f2014-07-31 10:31:26 -0700419
420 if (mSubtitleTrack.mSource != NULL
421 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700422 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, id());
423 msg->setInt64("timeUs", timeUs);
424 msg->setInt32("generation", mFetchSubtitleDataGeneration);
425 msg->post();
426 }
Robert Shiheb1735e2014-07-23 15:53:14 -0700427
Lajos Molnare26940f2014-07-31 10:31:26 -0700428 if (mTimedTextTrack.mSource != NULL
429 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
430 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, id());
431 msg->setInt64("timeUs", timeUs);
432 msg->setInt32("generation", mFetchTimedTextDataGeneration);
433 msg->post();
434 }
435
Andreas Huberafed0e12011-09-20 15:39:58 -0700436 return result;
437}
438
439status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
440 *durationUs = mDurationUs;
441 return OK;
442}
443
Robert Shihdd235722014-06-12 14:49:23 -0700444size_t NuPlayer::GenericSource::getTrackCount() const {
445 return mSources.size();
446}
447
448sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const {
449 size_t trackCount = mSources.size();
450 if (trackIndex >= trackCount) {
451 return NULL;
452 }
453
454 sp<AMessage> format = new AMessage();
455 sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat();
456
457 const char *mime;
458 CHECK(meta->findCString(kKeyMIMEType, &mime));
459
460 int32_t trackType;
461 if (!strncasecmp(mime, "video/", 6)) {
462 trackType = MEDIA_TRACK_TYPE_VIDEO;
463 } else if (!strncasecmp(mime, "audio/", 6)) {
464 trackType = MEDIA_TRACK_TYPE_AUDIO;
465 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
466 trackType = MEDIA_TRACK_TYPE_TIMEDTEXT;
467 } else {
468 trackType = MEDIA_TRACK_TYPE_UNKNOWN;
469 }
470 format->setInt32("type", trackType);
471
472 const char *lang;
473 if (!meta->findCString(kKeyMediaLanguage, &lang)) {
474 lang = "und";
475 }
476 format->setString("language", lang);
477
478 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
479 format->setString("mime", mime);
480
481 int32_t isAutoselect = 1, isDefault = 0, isForced = 0;
482 meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect);
483 meta->findInt32(kKeyTrackIsDefault, &isDefault);
484 meta->findInt32(kKeyTrackIsForced, &isForced);
485
486 format->setInt32("auto", !!isAutoselect);
487 format->setInt32("default", !!isDefault);
488 format->setInt32("forced", !!isForced);
489 }
490
491 return format;
492}
493
Lajos Molnare26940f2014-07-31 10:31:26 -0700494ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const {
495 const Track *track = NULL;
496 switch (type) {
497 case MEDIA_TRACK_TYPE_VIDEO:
498 track = &mVideoTrack;
499 break;
500 case MEDIA_TRACK_TYPE_AUDIO:
501 track = &mAudioTrack;
502 break;
503 case MEDIA_TRACK_TYPE_TIMEDTEXT:
504 track = &mTimedTextTrack;
505 break;
506 case MEDIA_TRACK_TYPE_SUBTITLE:
507 track = &mSubtitleTrack;
508 break;
509 default:
510 break;
511 }
512
513 if (track != NULL && track->mSource != NULL) {
514 return track->mIndex;
515 }
516
517 return -1;
518}
519
Robert Shih3423bbd2014-07-16 15:47:09 -0700520status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700521 ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
Robert Shih3423bbd2014-07-16 15:47:09 -0700522 if (trackIndex >= mSources.size()) {
523 return BAD_INDEX;
524 }
525
526 if (!select) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700527 Track* track = NULL;
528 if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) {
529 track = &mSubtitleTrack;
530 mFetchSubtitleDataGeneration++;
531 } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) {
532 track = &mTimedTextTrack;
533 mFetchTimedTextDataGeneration++;
534 }
535 if (track == NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700536 return INVALID_OPERATION;
537 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700538 track->mSource->stop();
539 track->mSource = NULL;
540 track->mPackets->clear();
Robert Shih3423bbd2014-07-16 15:47:09 -0700541 return OK;
542 }
543
544 const sp<MediaSource> source = mSources.itemAt(trackIndex);
545 sp<MetaData> meta = source->getFormat();
546 const char *mime;
547 CHECK(meta->findCString(kKeyMIMEType, &mime));
548 if (!strncasecmp(mime, "text/", 5)) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700549 bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP);
550 Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack;
551 if (track->mSource != NULL && track->mIndex == trackIndex) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700552 return OK;
553 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700554 track->mIndex = trackIndex;
555 if (track->mSource != NULL) {
556 track->mSource->stop();
Robert Shih3423bbd2014-07-16 15:47:09 -0700557 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700558 track->mSource = mSources.itemAt(trackIndex);
559 track->mSource->start();
560 if (track->mPackets == NULL) {
561 track->mPackets = new AnotherPacketSource(track->mSource->getFormat());
Robert Shih3423bbd2014-07-16 15:47:09 -0700562 } else {
Lajos Molnare26940f2014-07-31 10:31:26 -0700563 track->mPackets->clear();
564 track->mPackets->setFormat(track->mSource->getFormat());
Robert Shih3423bbd2014-07-16 15:47:09 -0700565
566 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700567
568 if (isSubtitle) {
569 mFetchSubtitleDataGeneration++;
570 } else {
571 mFetchTimedTextDataGeneration++;
572 }
573
Robert Shih3423bbd2014-07-16 15:47:09 -0700574 return OK;
575 } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
576 bool audio = !strncasecmp(mime, "audio/", 6);
577 Track *track = audio ? &mAudioTrack : &mVideoTrack;
578 if (track->mSource != NULL && track->mIndex == trackIndex) {
579 return OK;
580 }
581
582 sp<AMessage> msg = new AMessage(kWhatChangeAVSource, id());
583 msg->setInt32("trackIndex", trackIndex);
584 msg->post();
585 return OK;
586 }
587
588 return INVALID_OPERATION;
589}
590
Andreas Huberafed0e12011-09-20 15:39:58 -0700591status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs) {
592 if (mVideoTrack.mSource != NULL) {
593 int64_t actualTimeUs;
Robert Shih3423bbd2014-07-16 15:47:09 -0700594 readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, &actualTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -0700595
596 seekTimeUs = actualTimeUs;
597 }
598
599 if (mAudioTrack.mSource != NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700600 readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -0700601 }
602
603 return OK;
604}
605
Robert Shih3423bbd2014-07-16 15:47:09 -0700606sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
607 MediaBuffer* mb,
608 media_track_type trackType,
609 int64_t *actualTimeUs) {
610 bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
611 size_t outLength = mb->range_length();
612
613 if (audio && mAudioIsVorbis) {
614 outLength += sizeof(int32_t);
615 }
616
617 sp<ABuffer> ab;
618 if (mIsWidevine && !audio) {
619 // data is already provided in the buffer
620 ab = new ABuffer(NULL, mb->range_length());
621 ab->meta()->setPointer("mediaBuffer", mb);
622 mb->add_ref();
623 } else {
624 ab = new ABuffer(outLength);
625 memcpy(ab->data(),
626 (const uint8_t *)mb->data() + mb->range_offset(),
627 mb->range_length());
628 }
629
630 if (audio && mAudioIsVorbis) {
631 int32_t numPageSamples;
632 if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
633 numPageSamples = -1;
634 }
635
636 uint8_t* abEnd = ab->data() + mb->range_length();
637 memcpy(abEnd, &numPageSamples, sizeof(numPageSamples));
638 }
639
Lajos Molnare26940f2014-07-31 10:31:26 -0700640 sp<AMessage> meta = ab->meta();
641
Robert Shih3423bbd2014-07-16 15:47:09 -0700642 int64_t timeUs;
643 CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs));
Robert Shih3423bbd2014-07-16 15:47:09 -0700644 meta->setInt64("timeUs", timeUs);
645
Lajos Molnare26940f2014-07-31 10:31:26 -0700646 if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
647 const char *mime;
648 CHECK(mTimedTextTrack.mSource != NULL
649 && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime));
650 meta->setString("mime", mime);
651 }
652
Robert Shih3423bbd2014-07-16 15:47:09 -0700653 int64_t durationUs;
654 if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) {
655 meta->setInt64("durationUs", durationUs);
656 }
657
658 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
659 meta->setInt32("trackIndex", mSubtitleTrack.mIndex);
660 }
661
662 if (actualTimeUs) {
663 *actualTimeUs = timeUs;
664 }
665
666 mb->release();
667 mb = NULL;
668
669 return ab;
670}
671
Andreas Huberafed0e12011-09-20 15:39:58 -0700672void NuPlayer::GenericSource::readBuffer(
Robert Shih3423bbd2014-07-16 15:47:09 -0700673 media_track_type trackType, int64_t seekTimeUs, int64_t *actualTimeUs, bool formatChange) {
674 Track *track;
675 switch (trackType) {
676 case MEDIA_TRACK_TYPE_VIDEO:
677 track = &mVideoTrack;
678 break;
679 case MEDIA_TRACK_TYPE_AUDIO:
680 track = &mAudioTrack;
681 break;
682 case MEDIA_TRACK_TYPE_SUBTITLE:
683 track = &mSubtitleTrack;
684 break;
Lajos Molnare26940f2014-07-31 10:31:26 -0700685 case MEDIA_TRACK_TYPE_TIMEDTEXT:
686 track = &mTimedTextTrack;
687 break;
Robert Shih3423bbd2014-07-16 15:47:09 -0700688 default:
689 TRESPASS();
690 }
691
692 if (track->mSource == NULL) {
693 return;
694 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700695
696 if (actualTimeUs) {
697 *actualTimeUs = seekTimeUs;
698 }
699
700 MediaSource::ReadOptions options;
701
702 bool seeking = false;
703
704 if (seekTimeUs >= 0) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700705 options.setSeekTo(seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
Andreas Huberafed0e12011-09-20 15:39:58 -0700706 seeking = true;
707 }
708
Robert Shih3423bbd2014-07-16 15:47:09 -0700709 if (mIsWidevine && trackType != MEDIA_TRACK_TYPE_AUDIO) {
Lajos Molnarcc227032014-07-17 15:33:06 -0700710 options.setNonBlocking();
711 }
712
Andreas Huberafed0e12011-09-20 15:39:58 -0700713 for (;;) {
714 MediaBuffer *mbuf;
715 status_t err = track->mSource->read(&mbuf, &options);
716
717 options.clearSeekTo();
718
719 if (err == OK) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700720 // formatChange && seeking: track whose source is changed during selection
721 // formatChange && !seeking: track whose source is not changed during selection
722 // !formatChange: normal seek
Lajos Molnare26940f2014-07-31 10:31:26 -0700723 if ((seeking || formatChange)
724 && (trackType == MEDIA_TRACK_TYPE_AUDIO
725 || trackType == MEDIA_TRACK_TYPE_VIDEO)) {
Robert Shih3423bbd2014-07-16 15:47:09 -0700726 ATSParser::DiscontinuityType type = formatChange
727 ? (seeking
728 ? ATSParser::DISCONTINUITY_FORMATCHANGE
729 : ATSParser::DISCONTINUITY_NONE)
730 : ATSParser::DISCONTINUITY_SEEK;
731 track->mPackets->queueDiscontinuity( type, NULL, true /* discard */);
Andreas Huberafed0e12011-09-20 15:39:58 -0700732 }
733
Robert Shih3423bbd2014-07-16 15:47:09 -0700734 sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType, actualTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -0700735 track->mPackets->queueAccessUnit(buffer);
736 break;
Lajos Molnarcc227032014-07-17 15:33:06 -0700737 } else if (err == WOULD_BLOCK) {
738 break;
Andreas Huberafed0e12011-09-20 15:39:58 -0700739 } else if (err == INFO_FORMAT_CHANGED) {
740#if 0
741 track->mPackets->queueDiscontinuity(
Chong Zhang632740c2014-06-26 13:03:47 -0700742 ATSParser::DISCONTINUITY_FORMATCHANGE,
743 NULL,
744 false /* discard */);
Andreas Huberafed0e12011-09-20 15:39:58 -0700745#endif
746 } else {
747 track->mPackets->signalEOS(err);
748 break;
749 }
750 }
751}
752
Andreas Huberafed0e12011-09-20 15:39:58 -0700753} // namespace android