blob: 9552580d73793d184177f2936ceeaccb82a1528b [file] [log] [blame]
Wei Jia53692fa2017-12-11 10:33:46 -08001/*
2 * Copyright 2017 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//#define LOG_NDEBUG 0
Wei Jia2409c872018-02-02 10:34:33 -080018#define LOG_TAG "GenericSource2"
Wei Jia53692fa2017-12-11 10:33:46 -080019
Wei Jia2409c872018-02-02 10:34:33 -080020#include "GenericSource2.h"
Wei Jia53692fa2017-12-11 10:33:46 -080021#include "NuPlayer2Drm.h"
22
23#include "AnotherPacketSource.h"
Wei Jia53692fa2017-12-11 10:33:46 -080024#include <cutils/properties.h>
25#include <media/DataSource.h>
Dongwon Kangbc8f53b2018-01-25 17:01:44 -080026#include <media/MediaBufferHolder.h>
Wei Jia28288fb2017-12-15 13:45:29 -080027#include <media/NdkWrapper.h>
Wei Jia53692fa2017-12-11 10:33:46 -080028#include <media/stagefright/foundation/ABuffer.h>
29#include <media/stagefright/foundation/ADebug.h>
30#include <media/stagefright/foundation/AMessage.h>
Wei Jia53692fa2017-12-11 10:33:46 -080031#include <media/stagefright/MediaBuffer.h>
32#include <media/stagefright/MediaClock.h>
33#include <media/stagefright/MediaDefs.h>
Wei Jia53692fa2017-12-11 10:33:46 -080034#include <media/stagefright/MetaData.h>
Robert Shih0cd95062018-01-21 17:41:16 -080035#include <media/stagefright/NdkUtils.h>
Wei Jia53692fa2017-12-11 10:33:46 -080036#include <media/stagefright/Utils.h>
Wei Jia53692fa2017-12-11 10:33:46 -080037
38namespace android {
39
40static const int kInitialMarkMs = 5000; // 5secs
41
42//static const int kPausePlaybackMarkMs = 2000; // 2secs
43static const int kResumePlaybackMarkMs = 15000; // 15secs
44
Wei Jia2409c872018-02-02 10:34:33 -080045NuPlayer2::GenericSource2::GenericSource2(
Wei Jia53692fa2017-12-11 10:33:46 -080046 const sp<AMessage> &notify,
Wei Jia53692fa2017-12-11 10:33:46 -080047 uid_t uid,
48 const sp<MediaClock> &mediaClock)
49 : Source(notify),
50 mAudioTimeUs(0),
51 mAudioLastDequeueTimeUs(0),
52 mVideoTimeUs(0),
53 mVideoLastDequeueTimeUs(0),
54 mPrevBufferPercentage(-1),
55 mPollBufferingGeneration(0),
56 mSentPauseOnBuffering(false),
57 mAudioDataGeneration(0),
58 mVideoDataGeneration(0),
59 mFetchSubtitleDataGeneration(0),
60 mFetchTimedTextDataGeneration(0),
61 mDurationUs(-1ll),
62 mAudioIsVorbis(false),
63 mIsSecure(false),
64 mIsStreaming(false),
Wei Jia53692fa2017-12-11 10:33:46 -080065 mUID(uid),
66 mMediaClock(mediaClock),
67 mFd(-1),
68 mBitrate(-1ll),
69 mPendingReadBufferTypes(0) {
Wei Jia2409c872018-02-02 10:34:33 -080070 ALOGV("GenericSource2");
Wei Jia53692fa2017-12-11 10:33:46 -080071 CHECK(mediaClock != NULL);
72
73 mBufferingSettings.mInitialMarkMs = kInitialMarkMs;
74 mBufferingSettings.mResumePlaybackMarkMs = kResumePlaybackMarkMs;
75 resetDataSource();
76}
77
Wei Jia2409c872018-02-02 10:34:33 -080078void NuPlayer2::GenericSource2::resetDataSource() {
Wei Jia53692fa2017-12-11 10:33:46 -080079 ALOGV("resetDataSource");
80
Robert Shih3d2b89b2018-10-24 17:53:23 -070081 mDisconnected = false;
Wei Jia53692fa2017-12-11 10:33:46 -080082 mUri.clear();
83 mUriHeaders.clear();
84 if (mFd >= 0) {
85 close(mFd);
86 mFd = -1;
87 }
88 mOffset = 0;
89 mLength = 0;
90 mStarted = false;
91 mPreparing = false;
92
93 mIsDrmProtected = false;
94 mIsDrmReleased = false;
95 mIsSecure = false;
96 mMimes.clear();
97}
98
Wei Jia2409c872018-02-02 10:34:33 -080099status_t NuPlayer2::GenericSource2::setDataSource(
Wei Jia53692fa2017-12-11 10:33:46 -0800100 const char *url,
101 const KeyedVector<String8, String8> *headers) {
102 Mutex::Autolock _l(mLock);
103 ALOGV("setDataSource url: %s", url);
104
105 resetDataSource();
106
Wei Jia53692fa2017-12-11 10:33:46 -0800107 mUri = url;
108
109 if (headers) {
110 mUriHeaders = *headers;
111 }
112
113 // delay data source creation to prepareAsync() to avoid blocking
114 // the calling thread in setDataSource for any significant time.
115 return OK;
116}
117
Wei Jia2409c872018-02-02 10:34:33 -0800118status_t NuPlayer2::GenericSource2::setDataSource(
Wei Jia53692fa2017-12-11 10:33:46 -0800119 int fd, int64_t offset, int64_t length) {
120 Mutex::Autolock _l(mLock);
121 ALOGV("setDataSource %d/%lld/%lld", fd, (long long)offset, (long long)length);
122
123 resetDataSource();
124
125 mFd = dup(fd);
126 mOffset = offset;
127 mLength = length;
128
129 // delay data source creation to prepareAsync() to avoid blocking
130 // the calling thread in setDataSource for any significant time.
131 return OK;
132}
133
Wei Jia2409c872018-02-02 10:34:33 -0800134status_t NuPlayer2::GenericSource2::setDataSource(const sp<DataSource>& source) {
Wei Jia53692fa2017-12-11 10:33:46 -0800135 Mutex::Autolock _l(mLock);
136 ALOGV("setDataSource (source: %p)", source.get());
137
138 resetDataSource();
Robert Shih4d432f12018-11-01 12:29:06 -0700139 mDataSourceWrapper = new AMediaDataSourceWrapper(source);
Wei Jia53692fa2017-12-11 10:33:46 -0800140 return OK;
141}
142
Wei Jia2409c872018-02-02 10:34:33 -0800143sp<MetaData> NuPlayer2::GenericSource2::getFileFormatMeta() const {
Wei Jia53692fa2017-12-11 10:33:46 -0800144 Mutex::Autolock _l(mLock);
145 return mFileMeta;
146}
147
Wei Jia2409c872018-02-02 10:34:33 -0800148status_t NuPlayer2::GenericSource2::initFromDataSource() {
Robert Shih0cd95062018-01-21 17:41:16 -0800149 mExtractor = new AMediaExtractorWrapper(AMediaExtractor_new());
Robert Shih49fb89d2018-01-31 17:53:19 -0800150 CHECK(mFd >=0 || mDataSourceWrapper != NULL);
151 sp<AMediaDataSourceWrapper> aSourceWrapper = mDataSourceWrapper;
Robert Shih0cd95062018-01-21 17:41:16 -0800152 const int fd = mFd;
Wei Jia53692fa2017-12-11 10:33:46 -0800153
154 mLock.unlock();
155 // This might take long time if data source is not reliable.
Robert Shih0cd95062018-01-21 17:41:16 -0800156 status_t err;
Robert Shih49fb89d2018-01-31 17:53:19 -0800157 if (aSourceWrapper != NULL) {
158 err = mExtractor->setDataSource(aSourceWrapper->getAMediaDataSource());
Robert Shih0cd95062018-01-21 17:41:16 -0800159 } else {
Robert Shih49fb89d2018-01-31 17:53:19 -0800160 err = mExtractor->setDataSource(fd, mOffset, mLength);
Robert Shih0cd95062018-01-21 17:41:16 -0800161 }
Wei Jia53692fa2017-12-11 10:33:46 -0800162
Robert Shih0cd95062018-01-21 17:41:16 -0800163 if (err != OK) {
Robert Shih49fb89d2018-01-31 17:53:19 -0800164 ALOGE("initFromDataSource, failed to set extractor data source!");
Robert Shih0cd95062018-01-21 17:41:16 -0800165 mLock.lock();
Wei Jia53692fa2017-12-11 10:33:46 -0800166 return UNKNOWN_ERROR;
167 }
168
Robert Shih0cd95062018-01-21 17:41:16 -0800169 size_t numtracks = mExtractor->getTrackCount();
Wei Jia53692fa2017-12-11 10:33:46 -0800170 if (numtracks == 0) {
171 ALOGE("initFromDataSource, source has no track!");
Robert Shih0cd95062018-01-21 17:41:16 -0800172 mLock.lock();
Wei Jia53692fa2017-12-11 10:33:46 -0800173 return UNKNOWN_ERROR;
174 }
175
Robert Shih0cd95062018-01-21 17:41:16 -0800176 mFileMeta = convertMediaFormatWrapperToMetaData(mExtractor->getFormat());
Robert Shih49fb89d2018-01-31 17:53:19 -0800177 mLock.lock();
Wei Jia53692fa2017-12-11 10:33:46 -0800178 if (mFileMeta != NULL) {
179 int64_t duration;
180 if (mFileMeta->findInt64(kKeyDuration, &duration)) {
181 mDurationUs = duration;
182 }
183 }
184
185 int32_t totalBitrate = 0;
186
187 mMimes.clear();
188
189 for (size_t i = 0; i < numtracks; ++i) {
Wei Jia53692fa2017-12-11 10:33:46 -0800190
Robert Shih0cd95062018-01-21 17:41:16 -0800191 sp<AMediaFormatWrapper> trackFormat = mExtractor->getTrackFormat(i);
192 if (trackFormat == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800193 ALOGE("no metadata for track %zu", i);
194 return UNKNOWN_ERROR;
195 }
196
Robert Shih0cd95062018-01-21 17:41:16 -0800197 sp<AMediaExtractorWrapper> trackExtractor = new AMediaExtractorWrapper(AMediaExtractor_new());
Robert Shih3d2b89b2018-10-24 17:53:23 -0700198 if (aSourceWrapper != NULL) {
199 trackExtractor->setDataSource(aSourceWrapper->getAMediaDataSource());
200 } else {
201 trackExtractor->setDataSource(fd, mOffset, mLength);
202 }
Robert Shih0cd95062018-01-21 17:41:16 -0800203
Wei Jia53692fa2017-12-11 10:33:46 -0800204 const char *mime;
Robert Shih0cd95062018-01-21 17:41:16 -0800205 sp<MetaData> meta = convertMediaFormatWrapperToMetaData(trackFormat);
Wei Jia53692fa2017-12-11 10:33:46 -0800206 CHECK(meta->findCString(kKeyMIMEType, &mime));
207
208 ALOGV("initFromDataSource track[%zu]: %s", i, mime);
209
210 // Do the string compare immediately with "mime",
211 // we can't assume "mime" would stay valid after another
212 // extractor operation, some extractors might modify meta
213 // during getTrack() and make it invalid.
214 if (!strncasecmp(mime, "audio/", 6)) {
Robert Shih0cd95062018-01-21 17:41:16 -0800215 if (mAudioTrack.mExtractor == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800216 mAudioTrack.mIndex = i;
Robert Shih0cd95062018-01-21 17:41:16 -0800217 mAudioTrack.mExtractor = trackExtractor;
218 mAudioTrack.mExtractor->selectTrack(i);
219 mAudioTrack.mPackets = new AnotherPacketSource(meta);
Wei Jia53692fa2017-12-11 10:33:46 -0800220
221 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
222 mAudioIsVorbis = true;
223 } else {
224 mAudioIsVorbis = false;
225 }
226
227 mMimes.add(String8(mime));
228 }
229 } else if (!strncasecmp(mime, "video/", 6)) {
Robert Shih0cd95062018-01-21 17:41:16 -0800230 if (mVideoTrack.mExtractor == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800231 mVideoTrack.mIndex = i;
Robert Shih0cd95062018-01-21 17:41:16 -0800232 mVideoTrack.mExtractor = trackExtractor;
233 mVideoTrack.mExtractor->selectTrack(i);
234 mVideoTrack.mPackets = new AnotherPacketSource(meta);
Wei Jia53692fa2017-12-11 10:33:46 -0800235
236 // video always at the beginning
237 mMimes.insertAt(String8(mime), 0);
238 }
239 }
240
Robert Shih0cd95062018-01-21 17:41:16 -0800241 mExtractors.push(trackExtractor);
Wei Jia53692fa2017-12-11 10:33:46 -0800242 int64_t durationUs;
243 if (meta->findInt64(kKeyDuration, &durationUs)) {
244 if (durationUs > mDurationUs) {
245 mDurationUs = durationUs;
246 }
247 }
248
249 int32_t bitrate;
250 if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) {
251 totalBitrate += bitrate;
252 } else {
253 totalBitrate = -1;
254 }
255 }
256
Robert Shih0cd95062018-01-21 17:41:16 -0800257 ALOGV("initFromDataSource mExtractors.size(): %zu mIsSecure: %d mime[0]: %s", mExtractors.size(),
Wei Jia53692fa2017-12-11 10:33:46 -0800258 mIsSecure, (mMimes.isEmpty() ? "NONE" : mMimes[0].string()));
259
Robert Shih0cd95062018-01-21 17:41:16 -0800260 if (mExtractors.size() == 0) {
Wei Jia53692fa2017-12-11 10:33:46 -0800261 ALOGE("b/23705695");
262 return UNKNOWN_ERROR;
263 }
264
265 // Modular DRM: The return value doesn't affect source initialization.
266 (void)checkDrmInfo();
267
268 mBitrate = totalBitrate;
269
270 return OK;
271}
272
Wei Jia2409c872018-02-02 10:34:33 -0800273status_t NuPlayer2::GenericSource2::getBufferingSettings(
Wei Jia53692fa2017-12-11 10:33:46 -0800274 BufferingSettings* buffering /* nonnull */) {
275 {
276 Mutex::Autolock _l(mLock);
277 *buffering = mBufferingSettings;
278 }
279
280 ALOGV("getBufferingSettings{%s}", buffering->toString().string());
281 return OK;
282}
283
Wei Jia2409c872018-02-02 10:34:33 -0800284status_t NuPlayer2::GenericSource2::setBufferingSettings(const BufferingSettings& buffering) {
Wei Jia53692fa2017-12-11 10:33:46 -0800285 ALOGV("setBufferingSettings{%s}", buffering.toString().string());
286
287 Mutex::Autolock _l(mLock);
288 mBufferingSettings = buffering;
289 return OK;
290}
291
Wei Jia2409c872018-02-02 10:34:33 -0800292int64_t NuPlayer2::GenericSource2::getLastReadPosition() {
Robert Shih0cd95062018-01-21 17:41:16 -0800293 if (mAudioTrack.mExtractor != NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800294 return mAudioTimeUs;
Robert Shih0cd95062018-01-21 17:41:16 -0800295 } else if (mVideoTrack.mExtractor != NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800296 return mVideoTimeUs;
297 } else {
298 return 0;
299 }
300}
301
Wei Jia2409c872018-02-02 10:34:33 -0800302bool NuPlayer2::GenericSource2::isStreaming() const {
Wei Jia53692fa2017-12-11 10:33:46 -0800303 Mutex::Autolock _l(mLock);
304 return mIsStreaming;
305}
306
Wei Jia2409c872018-02-02 10:34:33 -0800307NuPlayer2::GenericSource2::~GenericSource2() {
308 ALOGV("~GenericSource2");
Wei Jia53692fa2017-12-11 10:33:46 -0800309 if (mLooper != NULL) {
310 mLooper->unregisterHandler(id());
311 mLooper->stop();
312 }
Robert Shih49fb89d2018-01-31 17:53:19 -0800313 if (mDataSourceWrapper != NULL) {
314 mDataSourceWrapper->close();
Wei Jia17459332018-01-09 14:21:23 -0800315 }
Wei Jia53692fa2017-12-11 10:33:46 -0800316 resetDataSource();
317}
318
Wei Jiaf01e3122018-10-18 11:49:44 -0700319void NuPlayer2::GenericSource2::prepareAsync(int64_t startTimeUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800320 Mutex::Autolock _l(mLock);
321 ALOGV("prepareAsync: (looper: %d)", (mLooper != NULL));
322
323 if (mLooper == NULL) {
324 mLooper = new ALooper;
Wei Jia8c8b57a2018-11-28 11:09:50 -0800325 mLooper->setName("generic2");
Wei Jiac5c79da2017-12-21 18:03:05 -0800326 mLooper->start(false, /* runOnCallingThread */
327 true, /* canCallJava */
328 PRIORITY_DEFAULT);
Wei Jia53692fa2017-12-11 10:33:46 -0800329
330 mLooper->registerHandler(this);
331 }
332
333 sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this);
Wei Jiaf01e3122018-10-18 11:49:44 -0700334 msg->setInt64("startTimeUs", startTimeUs);
335
Wei Jia53692fa2017-12-11 10:33:46 -0800336 msg->post();
337}
338
Wei Jiaf01e3122018-10-18 11:49:44 -0700339void NuPlayer2::GenericSource2::onPrepareAsync(int64_t startTimeUs) {
Robert Shih49fb89d2018-01-31 17:53:19 -0800340 ALOGV("onPrepareAsync: mFd %d mUri %s mDataSourceWrapper: %p",
341 mFd, mUri.c_str(), mDataSourceWrapper.get());
Wei Jia53692fa2017-12-11 10:33:46 -0800342
Robert Shih49fb89d2018-01-31 17:53:19 -0800343 if (!mUri.empty()) {
344 const char* uri = mUri.c_str();
345 size_t numheaders = mUriHeaders.size();
346 const char **key_values = numheaders ? new const char *[numheaders * 2] : NULL;
347 for (size_t i = 0; i < numheaders; ++i) {
348 key_values[i * 2] = mUriHeaders.keyAt(i).c_str();
349 key_values[i * 2 + 1] = mUriHeaders.valueAt(i).c_str();
Wei Jia53692fa2017-12-11 10:33:46 -0800350 }
Robert Shih49fb89d2018-01-31 17:53:19 -0800351 mLock.unlock();
352 AMediaDataSource *aSource = AMediaDataSource_newUri(uri, numheaders, key_values);
353 mLock.lock();
354 mDataSourceWrapper = aSource ? new AMediaDataSourceWrapper(aSource) : NULL;
355 delete[] key_values;
356 // For cached streaming cases, we need to wait for enough
357 // buffering before reporting prepared.
358 mIsStreaming = !strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8);
Wei Jia53692fa2017-12-11 10:33:46 -0800359 }
360
Robert Shih49fb89d2018-01-31 17:53:19 -0800361 if (mDisconnected || (mFd < 0 && mDataSourceWrapper == NULL)) {
362 ALOGE("mDisconnected(%d) or Failed to create data source!", mDisconnected);
363 notifyPreparedAndCleanup(UNKNOWN_ERROR);
364 return;
Wei Jia53692fa2017-12-11 10:33:46 -0800365 }
366
Wei Jia53692fa2017-12-11 10:33:46 -0800367 // init extractor from data source
368 status_t err = initFromDataSource();
Robert Shih49fb89d2018-01-31 17:53:19 -0800369 if (mFd >= 0) {
370 close(mFd);
371 mFd = -1;
372 }
Wei Jia53692fa2017-12-11 10:33:46 -0800373
374 if (err != OK) {
375 ALOGE("Failed to init from data source!");
376 notifyPreparedAndCleanup(err);
377 return;
378 }
379
Robert Shih0cd95062018-01-21 17:41:16 -0800380 if (mVideoTrack.mExtractor != NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800381 sp<MetaData> meta = getFormatMeta_l(false /* audio */);
382 sp<AMessage> msg = new AMessage;
383 err = convertMetaDataToMessage(meta, &msg);
384 if(err != OK) {
385 notifyPreparedAndCleanup(err);
386 return;
387 }
388 notifyVideoSizeChanged(msg);
389 }
390
391 notifyFlagsChanged(
392 // FLAG_SECURE will be known if/when prepareDrm is called by the app
393 // FLAG_PROTECTED will be known if/when prepareDrm is called by the app
394 FLAG_CAN_PAUSE |
395 FLAG_CAN_SEEK_BACKWARD |
396 FLAG_CAN_SEEK_FORWARD |
397 FLAG_CAN_SEEK);
398
Wei Jiaf01e3122018-10-18 11:49:44 -0700399 doSeek(startTimeUs, MediaPlayer2SeekMode::SEEK_CLOSEST);
Wei Jia53692fa2017-12-11 10:33:46 -0800400 finishPrepareAsync();
401
402 ALOGV("onPrepareAsync: Done");
403}
404
Wei Jia2409c872018-02-02 10:34:33 -0800405void NuPlayer2::GenericSource2::finishPrepareAsync() {
Wei Jia53692fa2017-12-11 10:33:46 -0800406 ALOGV("finishPrepareAsync");
407
Wei Jia53692fa2017-12-11 10:33:46 -0800408 if (mIsStreaming) {
Wei Jia53692fa2017-12-11 10:33:46 -0800409 mPreparing = true;
Wei Jiaf01e3122018-10-18 11:49:44 -0700410 ++mPollBufferingGeneration;
Wei Jia53692fa2017-12-11 10:33:46 -0800411 schedulePollBuffering();
412 } else {
413 notifyPrepared();
414 }
415
Robert Shih0cd95062018-01-21 17:41:16 -0800416 if (mAudioTrack.mExtractor != NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800417 postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
418 }
419
Robert Shih0cd95062018-01-21 17:41:16 -0800420 if (mVideoTrack.mExtractor != NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800421 postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
422 }
423}
424
Wei Jia2409c872018-02-02 10:34:33 -0800425void NuPlayer2::GenericSource2::notifyPreparedAndCleanup(status_t err) {
Wei Jia53692fa2017-12-11 10:33:46 -0800426 if (err != OK) {
Robert Shih49fb89d2018-01-31 17:53:19 -0800427 mDataSourceWrapper.clear();
Wei Jia53692fa2017-12-11 10:33:46 -0800428
429 mBitrate = -1;
430 mPrevBufferPercentage = -1;
431 ++mPollBufferingGeneration;
432 }
433 notifyPrepared(err);
434}
435
Wei Jia2409c872018-02-02 10:34:33 -0800436void NuPlayer2::GenericSource2::start() {
Wei Jia53692fa2017-12-11 10:33:46 -0800437 Mutex::Autolock _l(mLock);
438 ALOGI("start");
439
Robert Shih0cd95062018-01-21 17:41:16 -0800440 if (mAudioTrack.mExtractor != NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800441 postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
442 }
443
Robert Shih0cd95062018-01-21 17:41:16 -0800444 if (mVideoTrack.mExtractor != NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800445 postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
446 }
447
448 mStarted = true;
449}
450
Wei Jia2409c872018-02-02 10:34:33 -0800451void NuPlayer2::GenericSource2::stop() {
Wei Jia53692fa2017-12-11 10:33:46 -0800452 Mutex::Autolock _l(mLock);
453 mStarted = false;
454}
455
Wei Jia2409c872018-02-02 10:34:33 -0800456void NuPlayer2::GenericSource2::pause() {
Wei Jia53692fa2017-12-11 10:33:46 -0800457 Mutex::Autolock _l(mLock);
458 mStarted = false;
459}
460
Wei Jia2409c872018-02-02 10:34:33 -0800461void NuPlayer2::GenericSource2::resume() {
Wei Jia53692fa2017-12-11 10:33:46 -0800462 Mutex::Autolock _l(mLock);
463 mStarted = true;
464}
465
Wei Jia2409c872018-02-02 10:34:33 -0800466void NuPlayer2::GenericSource2::disconnect() {
Wei Jia53692fa2017-12-11 10:33:46 -0800467 {
468 Mutex::Autolock _l(mLock);
Wei Jia53692fa2017-12-11 10:33:46 -0800469 mDisconnected = true;
470 }
Robert Shih49fb89d2018-01-31 17:53:19 -0800471 if (mDataSourceWrapper != NULL) {
472 mDataSourceWrapper->close();
Wei Jia53692fa2017-12-11 10:33:46 -0800473 }
474}
475
Wei Jia2409c872018-02-02 10:34:33 -0800476status_t NuPlayer2::GenericSource2::feedMoreTSData() {
Wei Jia53692fa2017-12-11 10:33:46 -0800477 return OK;
478}
479
Wei Jia2409c872018-02-02 10:34:33 -0800480void NuPlayer2::GenericSource2::onMessageReceived(const sp<AMessage> &msg) {
Wei Jia53692fa2017-12-11 10:33:46 -0800481 Mutex::Autolock _l(mLock);
482 switch (msg->what()) {
483 case kWhatPrepareAsync:
484 {
Wei Jiaf01e3122018-10-18 11:49:44 -0700485 int64_t startTimeUs;
486 CHECK(msg->findInt64("startTimeUs", &startTimeUs));
487 onPrepareAsync(startTimeUs);
Wei Jia53692fa2017-12-11 10:33:46 -0800488 break;
489 }
490 case kWhatFetchSubtitleData:
491 {
492 fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
493 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
494 break;
495 }
496
497 case kWhatFetchTimedTextData:
498 {
499 fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
500 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
501 break;
502 }
503
504 case kWhatSendSubtitleData:
505 {
506 sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
507 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
508 break;
509 }
510
511 case kWhatSendGlobalTimedTextData:
512 {
513 sendGlobalTextData(kWhatTimedTextData, mFetchTimedTextDataGeneration, msg);
514 break;
515 }
516 case kWhatSendTimedTextData:
517 {
518 sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
519 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
520 break;
521 }
522
523 case kWhatChangeAVSource:
524 {
525 int32_t trackIndex;
526 CHECK(msg->findInt32("trackIndex", &trackIndex));
Robert Shih0cd95062018-01-21 17:41:16 -0800527 const sp<AMediaExtractorWrapper> extractor = mExtractors.itemAt(trackIndex);
Wei Jia53692fa2017-12-11 10:33:46 -0800528
529 Track* track;
Robert Shih0cd95062018-01-21 17:41:16 -0800530 AString mime;
Wei Jia53692fa2017-12-11 10:33:46 -0800531 media_track_type trackType, counterpartType;
Robert Shih0cd95062018-01-21 17:41:16 -0800532 sp<AMediaFormatWrapper> format = extractor->getTrackFormat(trackIndex);
533 format->getString(AMEDIAFORMAT_KEY_MIME, &mime);
534 if (!strncasecmp(mime.c_str(), "audio/", 6)) {
Wei Jia53692fa2017-12-11 10:33:46 -0800535 track = &mAudioTrack;
536 trackType = MEDIA_TRACK_TYPE_AUDIO;
537 counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
538 } else {
Robert Shih0cd95062018-01-21 17:41:16 -0800539 CHECK(!strncasecmp(mime.c_str(), "video/", 6));
Wei Jia53692fa2017-12-11 10:33:46 -0800540 track = &mVideoTrack;
541 trackType = MEDIA_TRACK_TYPE_VIDEO;
542 counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
543 }
544
545
Robert Shih0cd95062018-01-21 17:41:16 -0800546 track->mExtractor = extractor;
547 track->mExtractor->selectSingleTrack(trackIndex);
Wei Jia53692fa2017-12-11 10:33:46 -0800548 track->mIndex = trackIndex;
549 ++mAudioDataGeneration;
550 ++mVideoDataGeneration;
551
552 int64_t timeUs, actualTimeUs;
553 const bool formatChange = true;
554 if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
555 timeUs = mAudioLastDequeueTimeUs;
556 } else {
557 timeUs = mVideoLastDequeueTimeUs;
558 }
559 readBuffer(trackType, timeUs, MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC /* mode */,
560 &actualTimeUs, formatChange);
561 readBuffer(counterpartType, -1, MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC /* mode */,
562 NULL, !formatChange);
563 ALOGV("timeUs %lld actualTimeUs %lld", (long long)timeUs, (long long)actualTimeUs);
564
565 break;
566 }
567
568 case kWhatSeek:
569 {
570 onSeek(msg);
571 break;
572 }
573
574 case kWhatReadBuffer:
575 {
576 onReadBuffer(msg);
577 break;
578 }
579
580 case kWhatPollBuffering:
581 {
582 int32_t generation;
583 CHECK(msg->findInt32("generation", &generation));
584 if (generation == mPollBufferingGeneration) {
585 onPollBuffering();
586 }
587 break;
588 }
589
590 default:
591 Source::onMessageReceived(msg);
592 break;
593 }
594}
595
Wei Jia2409c872018-02-02 10:34:33 -0800596void NuPlayer2::GenericSource2::fetchTextData(
Wei Jia53692fa2017-12-11 10:33:46 -0800597 uint32_t sendWhat,
598 media_track_type type,
599 int32_t curGen,
600 const sp<AnotherPacketSource>& packets,
601 const sp<AMessage>& msg) {
602 int32_t msgGeneration;
603 CHECK(msg->findInt32("generation", &msgGeneration));
604 if (msgGeneration != curGen) {
605 // stale
606 return;
607 }
608
609 int32_t avail;
610 if (packets->hasBufferAvailable(&avail)) {
611 return;
612 }
613
614 int64_t timeUs;
615 CHECK(msg->findInt64("timeUs", &timeUs));
616
617 int64_t subTimeUs = 0;
618 readBuffer(type, timeUs, MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC /* mode */, &subTimeUs);
619
620 status_t eosResult;
621 if (!packets->hasBufferAvailable(&eosResult)) {
622 return;
623 }
624
625 if (msg->what() == kWhatFetchSubtitleData) {
626 subTimeUs -= 1000000ll; // send subtile data one second earlier
627 }
628 sp<AMessage> msg2 = new AMessage(sendWhat, this);
629 msg2->setInt32("generation", msgGeneration);
630 mMediaClock->addTimer(msg2, subTimeUs);
631}
632
Wei Jia2409c872018-02-02 10:34:33 -0800633void NuPlayer2::GenericSource2::sendTextData(
Wei Jia53692fa2017-12-11 10:33:46 -0800634 uint32_t what,
635 media_track_type type,
636 int32_t curGen,
637 const sp<AnotherPacketSource>& packets,
638 const sp<AMessage>& msg) {
639 int32_t msgGeneration;
640 CHECK(msg->findInt32("generation", &msgGeneration));
641 if (msgGeneration != curGen) {
642 // stale
643 return;
644 }
645
646 int64_t subTimeUs;
647 if (packets->nextBufferTime(&subTimeUs) != OK) {
648 return;
649 }
650
651 int64_t nextSubTimeUs;
652 readBuffer(type, -1, MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC /* mode */, &nextSubTimeUs);
653
654 sp<ABuffer> buffer;
655 status_t dequeueStatus = packets->dequeueAccessUnit(&buffer);
656 if (dequeueStatus == OK) {
657 sp<AMessage> notify = dupNotify();
658 notify->setInt32("what", what);
659 notify->setBuffer("buffer", buffer);
660 notify->post();
661
662 if (msg->what() == kWhatSendSubtitleData) {
663 nextSubTimeUs -= 1000000ll; // send subtile data one second earlier
664 }
665 mMediaClock->addTimer(msg, nextSubTimeUs);
666 }
667}
668
Wei Jia2409c872018-02-02 10:34:33 -0800669void NuPlayer2::GenericSource2::sendGlobalTextData(
Wei Jia53692fa2017-12-11 10:33:46 -0800670 uint32_t what,
671 int32_t curGen,
672 sp<AMessage> msg) {
673 int32_t msgGeneration;
674 CHECK(msg->findInt32("generation", &msgGeneration));
675 if (msgGeneration != curGen) {
676 // stale
677 return;
678 }
679
Robert Shih0cd95062018-01-21 17:41:16 -0800680 void *data = NULL;
Wei Jia53692fa2017-12-11 10:33:46 -0800681 size_t size = 0;
Robert Shih0cd95062018-01-21 17:41:16 -0800682 if (mTimedTextTrack.mExtractor->getTrackFormat(mTimedTextTrack.mIndex)->getBuffer(
683 "text", &data, &size)) {
Wei Jia53692fa2017-12-11 10:33:46 -0800684 mGlobalTimedText = new ABuffer(size);
685 if (mGlobalTimedText->data()) {
686 memcpy(mGlobalTimedText->data(), data, size);
687 sp<AMessage> globalMeta = mGlobalTimedText->meta();
688 globalMeta->setInt64("timeUs", 0);
689 globalMeta->setString("mime", MEDIA_MIMETYPE_TEXT_3GPP);
690 globalMeta->setInt32("global", 1);
691 sp<AMessage> notify = dupNotify();
692 notify->setInt32("what", what);
693 notify->setBuffer("buffer", mGlobalTimedText);
694 notify->post();
695 }
696 }
697}
698
Robert Shih0cd95062018-01-21 17:41:16 -0800699sp<AMessage> NuPlayer2::GenericSource2::getFormat(bool audio) {
700 Mutex::Autolock _l(mLock);
701 return getFormat_l(audio);
702}
703
Wei Jia2409c872018-02-02 10:34:33 -0800704sp<MetaData> NuPlayer2::GenericSource2::getFormatMeta(bool audio) {
Wei Jia53692fa2017-12-11 10:33:46 -0800705 Mutex::Autolock _l(mLock);
706 return getFormatMeta_l(audio);
707}
708
Robert Shih0cd95062018-01-21 17:41:16 -0800709sp<AMessage> NuPlayer2::GenericSource2::getFormat_l(bool audio) {
710 sp<AMediaExtractorWrapper> extractor = audio ? mAudioTrack.mExtractor : mVideoTrack.mExtractor;
711 size_t trackIndex = audio ? mAudioTrack.mIndex : mVideoTrack.mIndex;
Wei Jia53692fa2017-12-11 10:33:46 -0800712
Robert Shih0cd95062018-01-21 17:41:16 -0800713 if (extractor == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800714 return NULL;
715 }
716
Robert Shih0cd95062018-01-21 17:41:16 -0800717 return extractor->getTrackFormat(trackIndex)->toAMessage();
718}
719
720sp<MetaData> NuPlayer2::GenericSource2::getFormatMeta_l(bool audio) {
721 sp<AMediaExtractorWrapper> extractor = audio ? mAudioTrack.mExtractor : mVideoTrack.mExtractor;
722 size_t trackIndex = audio ? mAudioTrack.mIndex : mVideoTrack.mIndex;
723
724 if (extractor == NULL) {
725 return NULL;
726 }
727
728 return convertMediaFormatWrapperToMetaData(extractor->getTrackFormat(trackIndex));
Wei Jia53692fa2017-12-11 10:33:46 -0800729}
730
Wei Jia2409c872018-02-02 10:34:33 -0800731status_t NuPlayer2::GenericSource2::dequeueAccessUnit(
Wei Jia53692fa2017-12-11 10:33:46 -0800732 bool audio, sp<ABuffer> *accessUnit) {
733 Mutex::Autolock _l(mLock);
734 // If has gone through stop/releaseDrm sequence, we no longer send down any buffer b/c
735 // the codec's crypto object has gone away (b/37960096).
736 // Note: This will be unnecessary when stop() changes behavior and releases codec (b/35248283).
737 if (!mStarted && mIsDrmReleased) {
738 return -EWOULDBLOCK;
739 }
740
741 Track *track = audio ? &mAudioTrack : &mVideoTrack;
742
Robert Shih0cd95062018-01-21 17:41:16 -0800743 if (track->mExtractor == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800744 return -EWOULDBLOCK;
745 }
746
747 status_t finalResult;
748 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
749 if (finalResult == OK) {
750 postReadBuffer(
751 audio ? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
752 return -EWOULDBLOCK;
753 }
754 return finalResult;
755 }
756
757 status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
758
759 // start pulling in more buffers if cache is running low
760 // so that decoder has less chance of being starved
761 if (!mIsStreaming) {
762 if (track->mPackets->getAvailableBufferCount(&finalResult) < 2) {
763 postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
764 }
765 } else {
766 int64_t durationUs = track->mPackets->getBufferedDurationUs(&finalResult);
767 // TODO: maxRebufferingMarkMs could be larger than
768 // mBufferingSettings.mResumePlaybackMarkMs
769 int64_t restartBufferingMarkUs =
770 mBufferingSettings.mResumePlaybackMarkMs * 1000ll / 2;
771 if (finalResult == OK) {
772 if (durationUs < restartBufferingMarkUs) {
773 postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
774 }
775 if (track->mPackets->getAvailableBufferCount(&finalResult) < 2
776 && !mSentPauseOnBuffering && !mPreparing) {
Wei Jia53692fa2017-12-11 10:33:46 -0800777 mSentPauseOnBuffering = true;
778 sp<AMessage> notify = dupNotify();
779 notify->setInt32("what", kWhatPauseOnBufferingStart);
780 notify->post();
781 }
782 }
783 }
784
785 if (result != OK) {
Robert Shih0cd95062018-01-21 17:41:16 -0800786 if (mSubtitleTrack.mExtractor != NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800787 mSubtitleTrack.mPackets->clear();
788 mFetchSubtitleDataGeneration++;
789 }
Robert Shih0cd95062018-01-21 17:41:16 -0800790 if (mTimedTextTrack.mExtractor != NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800791 mTimedTextTrack.mPackets->clear();
792 mFetchTimedTextDataGeneration++;
793 }
794 return result;
795 }
796
797 int64_t timeUs;
798 status_t eosResult; // ignored
799 CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
800 if (audio) {
801 mAudioLastDequeueTimeUs = timeUs;
802 } else {
803 mVideoLastDequeueTimeUs = timeUs;
804 }
805
Robert Shih0cd95062018-01-21 17:41:16 -0800806 if (mSubtitleTrack.mExtractor != NULL
Wei Jia53692fa2017-12-11 10:33:46 -0800807 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
808 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
809 msg->setInt64("timeUs", timeUs);
810 msg->setInt32("generation", mFetchSubtitleDataGeneration);
811 msg->post();
812 }
813
Robert Shih0cd95062018-01-21 17:41:16 -0800814 if (mTimedTextTrack.mExtractor != NULL
Wei Jia53692fa2017-12-11 10:33:46 -0800815 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
816 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
817 msg->setInt64("timeUs", timeUs);
818 msg->setInt32("generation", mFetchTimedTextDataGeneration);
819 msg->post();
820 }
821
822 return result;
823}
824
Wei Jia2409c872018-02-02 10:34:33 -0800825status_t NuPlayer2::GenericSource2::getDuration(int64_t *durationUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800826 Mutex::Autolock _l(mLock);
827 *durationUs = mDurationUs;
828 return OK;
829}
830
Wei Jia2409c872018-02-02 10:34:33 -0800831size_t NuPlayer2::GenericSource2::getTrackCount() const {
Wei Jia53692fa2017-12-11 10:33:46 -0800832 Mutex::Autolock _l(mLock);
Robert Shih0cd95062018-01-21 17:41:16 -0800833 return mExtractors.size();
Wei Jia53692fa2017-12-11 10:33:46 -0800834}
835
Wei Jia2409c872018-02-02 10:34:33 -0800836sp<AMessage> NuPlayer2::GenericSource2::getTrackInfo(size_t trackIndex) const {
Wei Jia53692fa2017-12-11 10:33:46 -0800837 Mutex::Autolock _l(mLock);
Robert Shih0cd95062018-01-21 17:41:16 -0800838 size_t trackCount = mExtractors.size();
Wei Jia53692fa2017-12-11 10:33:46 -0800839 if (trackIndex >= trackCount) {
840 return NULL;
841 }
842
Robert Shih0cd95062018-01-21 17:41:16 -0800843 sp<AMessage> format = mExtractors.itemAt(trackIndex)->getTrackFormat(trackIndex)->toAMessage();
844 if (format == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800845 ALOGE("no metadata for track %zu", trackIndex);
846 return NULL;
847 }
848
Robert Shih0cd95062018-01-21 17:41:16 -0800849 AString mime;
850 CHECK(format->findString(AMEDIAFORMAT_KEY_MIME, &mime));
Wei Jia53692fa2017-12-11 10:33:46 -0800851
852 int32_t trackType;
Robert Shih0cd95062018-01-21 17:41:16 -0800853 if (!strncasecmp(mime.c_str(), "video/", 6)) {
Wei Jia53692fa2017-12-11 10:33:46 -0800854 trackType = MEDIA_TRACK_TYPE_VIDEO;
Robert Shih0cd95062018-01-21 17:41:16 -0800855 } else if (!strncasecmp(mime.c_str(), "audio/", 6)) {
Wei Jia53692fa2017-12-11 10:33:46 -0800856 trackType = MEDIA_TRACK_TYPE_AUDIO;
Robert Shih0cd95062018-01-21 17:41:16 -0800857 } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_TEXT_3GPP)) {
Wei Jia53692fa2017-12-11 10:33:46 -0800858 trackType = MEDIA_TRACK_TYPE_TIMEDTEXT;
859 } else {
860 trackType = MEDIA_TRACK_TYPE_UNKNOWN;
861 }
862 format->setInt32("type", trackType);
863
Robert Shih0cd95062018-01-21 17:41:16 -0800864 AString lang;
865 if (!format->findString("language", &lang)) {
866 format->setString("language", "und");
Wei Jia53692fa2017-12-11 10:33:46 -0800867 }
Wei Jia53692fa2017-12-11 10:33:46 -0800868
869 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
870 int32_t isAutoselect = 1, isDefault = 0, isForced = 0;
Robert Shih0cd95062018-01-21 17:41:16 -0800871 format->findInt32(AMEDIAFORMAT_KEY_IS_AUTOSELECT, &isAutoselect);
872 format->findInt32(AMEDIAFORMAT_KEY_IS_DEFAULT, &isDefault);
873 format->findInt32(AMEDIAFORMAT_KEY_IS_FORCED_SUBTITLE, &isForced);
Wei Jia53692fa2017-12-11 10:33:46 -0800874
875 format->setInt32("auto", !!isAutoselect);
876 format->setInt32("default", !!isDefault);
877 format->setInt32("forced", !!isForced);
878 }
879
880 return format;
881}
882
Wei Jia2409c872018-02-02 10:34:33 -0800883ssize_t NuPlayer2::GenericSource2::getSelectedTrack(media_track_type type) const {
Wei Jia53692fa2017-12-11 10:33:46 -0800884 Mutex::Autolock _l(mLock);
885 const Track *track = NULL;
886 switch (type) {
887 case MEDIA_TRACK_TYPE_VIDEO:
888 track = &mVideoTrack;
889 break;
890 case MEDIA_TRACK_TYPE_AUDIO:
891 track = &mAudioTrack;
892 break;
893 case MEDIA_TRACK_TYPE_TIMEDTEXT:
894 track = &mTimedTextTrack;
895 break;
896 case MEDIA_TRACK_TYPE_SUBTITLE:
897 track = &mSubtitleTrack;
898 break;
899 default:
900 break;
901 }
902
Robert Shih0cd95062018-01-21 17:41:16 -0800903 if (track != NULL && track->mExtractor != NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -0800904 return track->mIndex;
905 }
906
907 return -1;
908}
909
Wei Jia2409c872018-02-02 10:34:33 -0800910status_t NuPlayer2::GenericSource2::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
Wei Jia53692fa2017-12-11 10:33:46 -0800911 Mutex::Autolock _l(mLock);
912 ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
913
Robert Shih0cd95062018-01-21 17:41:16 -0800914 if (trackIndex >= mExtractors.size()) {
Wei Jia53692fa2017-12-11 10:33:46 -0800915 return BAD_INDEX;
916 }
917
918 if (!select) {
919 Track* track = NULL;
Robert Shih0cd95062018-01-21 17:41:16 -0800920 if (mSubtitleTrack.mExtractor != NULL && trackIndex == mSubtitleTrack.mIndex) {
Wei Jia53692fa2017-12-11 10:33:46 -0800921 track = &mSubtitleTrack;
922 mFetchSubtitleDataGeneration++;
Robert Shih0cd95062018-01-21 17:41:16 -0800923 } else if (mTimedTextTrack.mExtractor != NULL && trackIndex == mTimedTextTrack.mIndex) {
Wei Jia53692fa2017-12-11 10:33:46 -0800924 track = &mTimedTextTrack;
925 mFetchTimedTextDataGeneration++;
926 }
927 if (track == NULL) {
928 return INVALID_OPERATION;
929 }
Robert Shih0cd95062018-01-21 17:41:16 -0800930 track->mExtractor = NULL;
Wei Jia53692fa2017-12-11 10:33:46 -0800931 track->mPackets->clear();
932 return OK;
933 }
934
Robert Shih0cd95062018-01-21 17:41:16 -0800935 const sp<AMediaExtractorWrapper> extractor = mExtractors.itemAt(trackIndex);
936 sp<MetaData> meta = convertMediaFormatWrapperToMetaData(extractor->getTrackFormat(trackIndex));
Wei Jia53692fa2017-12-11 10:33:46 -0800937 const char *mime;
938 CHECK(meta->findCString(kKeyMIMEType, &mime));
939 if (!strncasecmp(mime, "text/", 5)) {
940 bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP);
941 Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack;
Robert Shih0cd95062018-01-21 17:41:16 -0800942 if (track->mExtractor != NULL && track->mIndex == trackIndex) {
Wei Jia53692fa2017-12-11 10:33:46 -0800943 return OK;
944 }
945 track->mIndex = trackIndex;
Robert Shih0cd95062018-01-21 17:41:16 -0800946 track->mExtractor = mExtractors.itemAt(trackIndex);
947 track->mExtractor->selectSingleTrack(trackIndex);
Wei Jia53692fa2017-12-11 10:33:46 -0800948 if (track->mPackets == NULL) {
Robert Shih0cd95062018-01-21 17:41:16 -0800949 track->mPackets = new AnotherPacketSource(meta);
Wei Jia53692fa2017-12-11 10:33:46 -0800950 } else {
951 track->mPackets->clear();
Robert Shih0cd95062018-01-21 17:41:16 -0800952 track->mPackets->setFormat(meta);
Wei Jia53692fa2017-12-11 10:33:46 -0800953
954 }
955
956 if (isSubtitle) {
957 mFetchSubtitleDataGeneration++;
958 } else {
959 mFetchTimedTextDataGeneration++;
960 }
961
962 status_t eosResult; // ignored
Robert Shih0cd95062018-01-21 17:41:16 -0800963 if (mSubtitleTrack.mExtractor != NULL
Wei Jia53692fa2017-12-11 10:33:46 -0800964 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
965 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
966 msg->setInt64("timeUs", timeUs);
967 msg->setInt32("generation", mFetchSubtitleDataGeneration);
968 msg->post();
969 }
970
971 sp<AMessage> msg2 = new AMessage(kWhatSendGlobalTimedTextData, this);
972 msg2->setInt32("generation", mFetchTimedTextDataGeneration);
973 msg2->post();
974
Robert Shih0cd95062018-01-21 17:41:16 -0800975 if (mTimedTextTrack.mExtractor != NULL
Wei Jia53692fa2017-12-11 10:33:46 -0800976 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
977 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
978 msg->setInt64("timeUs", timeUs);
979 msg->setInt32("generation", mFetchTimedTextDataGeneration);
980 msg->post();
981 }
982
983 return OK;
984 } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
985 bool audio = !strncasecmp(mime, "audio/", 6);
986 Track *track = audio ? &mAudioTrack : &mVideoTrack;
Robert Shih0cd95062018-01-21 17:41:16 -0800987 if (track->mExtractor != NULL && track->mIndex == trackIndex) {
Wei Jia53692fa2017-12-11 10:33:46 -0800988 return OK;
989 }
990
991 sp<AMessage> msg = new AMessage(kWhatChangeAVSource, this);
992 msg->setInt32("trackIndex", trackIndex);
993 msg->post();
994 return OK;
995 }
996
997 return INVALID_OPERATION;
998}
999
Wei Jia2409c872018-02-02 10:34:33 -08001000status_t NuPlayer2::GenericSource2::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
Wei Jia53692fa2017-12-11 10:33:46 -08001001 ALOGV("seekTo: %lld, %d", (long long)seekTimeUs, mode);
1002 sp<AMessage> msg = new AMessage(kWhatSeek, this);
1003 msg->setInt64("seekTimeUs", seekTimeUs);
1004 msg->setInt32("mode", mode);
1005
1006 // Need to call readBuffer on |mLooper| to ensure the calls to
1007 // IMediaSource::read* are serialized. Note that IMediaSource::read*
1008 // is called without |mLock| acquired and MediaSource is not thread safe.
1009 sp<AMessage> response;
1010 status_t err = msg->postAndAwaitResponse(&response);
1011 if (err == OK && response != NULL) {
1012 CHECK(response->findInt32("err", &err));
1013 }
1014
1015 return err;
1016}
1017
Wei Jia2409c872018-02-02 10:34:33 -08001018void NuPlayer2::GenericSource2::onSeek(const sp<AMessage>& msg) {
Wei Jia53692fa2017-12-11 10:33:46 -08001019 int64_t seekTimeUs;
1020 int32_t mode;
1021 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
1022 CHECK(msg->findInt32("mode", &mode));
1023
1024 sp<AMessage> response = new AMessage;
1025 status_t err = doSeek(seekTimeUs, (MediaPlayer2SeekMode)mode);
1026 response->setInt32("err", err);
1027
1028 sp<AReplyToken> replyID;
1029 CHECK(msg->senderAwaitsResponse(&replyID));
1030 response->postReply(replyID);
1031}
1032
Wei Jia2409c872018-02-02 10:34:33 -08001033status_t NuPlayer2::GenericSource2::doSeek(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
Robert Shih0cd95062018-01-21 17:41:16 -08001034 if (mVideoTrack.mExtractor != NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -08001035 ++mVideoDataGeneration;
1036
1037 int64_t actualTimeUs;
1038 readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, mode, &actualTimeUs);
1039
1040 if (mode != MediaPlayer2SeekMode::SEEK_CLOSEST) {
1041 seekTimeUs = actualTimeUs;
1042 }
1043 mVideoLastDequeueTimeUs = actualTimeUs;
1044 }
1045
Robert Shih0cd95062018-01-21 17:41:16 -08001046 if (mAudioTrack.mExtractor != NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -08001047 ++mAudioDataGeneration;
1048 readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs, MediaPlayer2SeekMode::SEEK_CLOSEST);
1049 mAudioLastDequeueTimeUs = seekTimeUs;
1050 }
1051
Robert Shih0cd95062018-01-21 17:41:16 -08001052 if (mSubtitleTrack.mExtractor != NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -08001053 mSubtitleTrack.mPackets->clear();
1054 mFetchSubtitleDataGeneration++;
1055 }
1056
Robert Shih0cd95062018-01-21 17:41:16 -08001057 if (mTimedTextTrack.mExtractor != NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -08001058 mTimedTextTrack.mPackets->clear();
1059 mFetchTimedTextDataGeneration++;
1060 }
1061
1062 ++mPollBufferingGeneration;
1063 schedulePollBuffering();
1064 return OK;
1065}
1066
Wei Jia2409c872018-02-02 10:34:33 -08001067sp<ABuffer> NuPlayer2::GenericSource2::mediaBufferToABuffer(
Dongwon Kang1889c3e2018-02-01 13:44:57 -08001068 MediaBufferBase* mb,
Wei Jia53692fa2017-12-11 10:33:46 -08001069 media_track_type trackType) {
1070 bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
1071 size_t outLength = mb->range_length();
1072
1073 if (audio && mAudioIsVorbis) {
1074 outLength += sizeof(int32_t);
1075 }
1076
1077 sp<ABuffer> ab;
1078
1079 if (mIsDrmProtected) {
1080 // Modular DRM
1081 // Enabled for both video/audio so 1) media buffer is reused without extra copying
1082 // 2) meta data can be retrieved in onInputBufferFetched for calling queueSecureInputBuffer.
1083
1084 // data is already provided in the buffer
1085 ab = new ABuffer(NULL, mb->range_length());
Dongwon Kangbc8f53b2018-01-25 17:01:44 -08001086 ab->meta()->setObject("mediaBufferHolder", new MediaBufferHolder(mb));
Wei Jia53692fa2017-12-11 10:33:46 -08001087
1088 // Modular DRM: Required b/c of the above add_ref.
1089 // If ref>0, there must be an observer, or it'll crash at release().
1090 // TODO: MediaBuffer might need to be revised to ease such need.
1091 mb->setObserver(this);
1092 // setMediaBufferBase() interestingly doesn't increment the ref count on its own.
1093 // Extra increment (since we want to keep mb alive and attached to ab beyond this function
1094 // call. This is to counter the effect of mb->release() towards the end.
1095 mb->add_ref();
1096
1097 } else {
1098 ab = new ABuffer(outLength);
1099 memcpy(ab->data(),
1100 (const uint8_t *)mb->data() + mb->range_offset(),
1101 mb->range_length());
1102 }
1103
1104 if (audio && mAudioIsVorbis) {
1105 int32_t numPageSamples;
Marco Nelissen3d21ae32018-02-16 08:24:08 -08001106 if (!mb->meta_data().findInt32(kKeyValidSamples, &numPageSamples)) {
Wei Jia53692fa2017-12-11 10:33:46 -08001107 numPageSamples = -1;
1108 }
1109
1110 uint8_t* abEnd = ab->data() + mb->range_length();
1111 memcpy(abEnd, &numPageSamples, sizeof(numPageSamples));
1112 }
1113
1114 sp<AMessage> meta = ab->meta();
1115
1116 int64_t timeUs;
Marco Nelissen3d21ae32018-02-16 08:24:08 -08001117 CHECK(mb->meta_data().findInt64(kKeyTime, &timeUs));
Wei Jia53692fa2017-12-11 10:33:46 -08001118 meta->setInt64("timeUs", timeUs);
1119
1120 if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
1121 int32_t layerId;
Marco Nelissen3d21ae32018-02-16 08:24:08 -08001122 if (mb->meta_data().findInt32(kKeyTemporalLayerId, &layerId)) {
Wei Jia53692fa2017-12-11 10:33:46 -08001123 meta->setInt32("temporal-layer-id", layerId);
1124 }
1125 }
1126
1127 if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
Robert Shih0cd95062018-01-21 17:41:16 -08001128 AString mime;
1129 sp<AMediaExtractorWrapper> extractor = mTimedTextTrack.mExtractor;
1130 size_t trackIndex = mTimedTextTrack.mIndex;
1131 CHECK(extractor != NULL
1132 && extractor->getTrackFormat(trackIndex)->getString(AMEDIAFORMAT_KEY_MIME, &mime));
1133 meta->setString("mime", mime.c_str());
Wei Jia53692fa2017-12-11 10:33:46 -08001134 }
1135
1136 int64_t durationUs;
Marco Nelissen3d21ae32018-02-16 08:24:08 -08001137 if (mb->meta_data().findInt64(kKeyDuration, &durationUs)) {
Wei Jia53692fa2017-12-11 10:33:46 -08001138 meta->setInt64("durationUs", durationUs);
1139 }
1140
1141 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
Robert Shihd83d4f42018-02-24 19:02:46 -08001142 meta->setInt32(AMEDIAFORMAT_KEY_TRACK_INDEX, mSubtitleTrack.mIndex);
Wei Jia53692fa2017-12-11 10:33:46 -08001143 }
1144
1145 uint32_t dataType; // unused
1146 const void *seiData;
1147 size_t seiLength;
Marco Nelissen3d21ae32018-02-16 08:24:08 -08001148 if (mb->meta_data().findData(kKeySEI, &dataType, &seiData, &seiLength)) {
Wei Jia53692fa2017-12-11 10:33:46 -08001149 sp<ABuffer> sei = ABuffer::CreateAsCopy(seiData, seiLength);;
1150 meta->setBuffer("sei", sei);
1151 }
1152
1153 const void *mpegUserDataPointer;
1154 size_t mpegUserDataLength;
Marco Nelissen3d21ae32018-02-16 08:24:08 -08001155 if (mb->meta_data().findData(
Wei Jia53692fa2017-12-11 10:33:46 -08001156 kKeyMpegUserData, &dataType, &mpegUserDataPointer, &mpegUserDataLength)) {
1157 sp<ABuffer> mpegUserData = ABuffer::CreateAsCopy(mpegUserDataPointer, mpegUserDataLength);
Robert Shihd83d4f42018-02-24 19:02:46 -08001158 meta->setBuffer(AMEDIAFORMAT_KEY_MPEG_USER_DATA, mpegUserData);
Wei Jia53692fa2017-12-11 10:33:46 -08001159 }
1160
1161 mb->release();
1162 mb = NULL;
1163
1164 return ab;
1165}
1166
Wei Jia2409c872018-02-02 10:34:33 -08001167int32_t NuPlayer2::GenericSource2::getDataGeneration(media_track_type type) const {
Wei Jia53692fa2017-12-11 10:33:46 -08001168 int32_t generation = -1;
1169 switch (type) {
1170 case MEDIA_TRACK_TYPE_VIDEO:
1171 generation = mVideoDataGeneration;
1172 break;
1173 case MEDIA_TRACK_TYPE_AUDIO:
1174 generation = mAudioDataGeneration;
1175 break;
1176 case MEDIA_TRACK_TYPE_TIMEDTEXT:
1177 generation = mFetchTimedTextDataGeneration;
1178 break;
1179 case MEDIA_TRACK_TYPE_SUBTITLE:
1180 generation = mFetchSubtitleDataGeneration;
1181 break;
1182 default:
1183 break;
1184 }
1185
1186 return generation;
1187}
1188
Wei Jia2409c872018-02-02 10:34:33 -08001189void NuPlayer2::GenericSource2::postReadBuffer(media_track_type trackType) {
Wei Jia53692fa2017-12-11 10:33:46 -08001190 if ((mPendingReadBufferTypes & (1 << trackType)) == 0) {
1191 mPendingReadBufferTypes |= (1 << trackType);
1192 sp<AMessage> msg = new AMessage(kWhatReadBuffer, this);
1193 msg->setInt32("trackType", trackType);
1194 msg->post();
1195 }
1196}
1197
Wei Jia2409c872018-02-02 10:34:33 -08001198void NuPlayer2::GenericSource2::onReadBuffer(const sp<AMessage>& msg) {
Wei Jia53692fa2017-12-11 10:33:46 -08001199 int32_t tmpType;
1200 CHECK(msg->findInt32("trackType", &tmpType));
1201 media_track_type trackType = (media_track_type)tmpType;
1202 mPendingReadBufferTypes &= ~(1 << trackType);
1203 readBuffer(trackType);
1204}
1205
Wei Jia2409c872018-02-02 10:34:33 -08001206void NuPlayer2::GenericSource2::readBuffer(
Wei Jia53692fa2017-12-11 10:33:46 -08001207 media_track_type trackType, int64_t seekTimeUs, MediaPlayer2SeekMode mode,
1208 int64_t *actualTimeUs, bool formatChange) {
1209 Track *track;
1210 size_t maxBuffers = 1;
1211 switch (trackType) {
1212 case MEDIA_TRACK_TYPE_VIDEO:
1213 track = &mVideoTrack;
1214 maxBuffers = 8; // too large of a number may influence seeks
1215 break;
1216 case MEDIA_TRACK_TYPE_AUDIO:
1217 track = &mAudioTrack;
1218 maxBuffers = 64;
1219 break;
1220 case MEDIA_TRACK_TYPE_SUBTITLE:
1221 track = &mSubtitleTrack;
1222 break;
1223 case MEDIA_TRACK_TYPE_TIMEDTEXT:
1224 track = &mTimedTextTrack;
1225 break;
1226 default:
1227 TRESPASS();
1228 }
1229
Robert Shih0cd95062018-01-21 17:41:16 -08001230 if (track->mExtractor == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -08001231 return;
1232 }
1233
1234 if (actualTimeUs) {
1235 *actualTimeUs = seekTimeUs;
1236 }
1237
Wei Jia53692fa2017-12-11 10:33:46 -08001238
1239 bool seeking = false;
Robert Shih0cd95062018-01-21 17:41:16 -08001240 sp<AMediaExtractorWrapper> extractor = track->mExtractor;
Wei Jia53692fa2017-12-11 10:33:46 -08001241 if (seekTimeUs >= 0) {
Robert Shih0cd95062018-01-21 17:41:16 -08001242 extractor->seekTo(seekTimeUs, mode);
Wei Jia53692fa2017-12-11 10:33:46 -08001243 seeking = true;
1244 }
1245
Wei Jia53692fa2017-12-11 10:33:46 -08001246 int32_t generation = getDataGeneration(trackType);
1247 for (size_t numBuffers = 0; numBuffers < maxBuffers; ) {
Robert Shih0cd95062018-01-21 17:41:16 -08001248 Vector<sp<ABuffer> > aBuffers;
Wei Jia53692fa2017-12-11 10:33:46 -08001249
Wei Jia53692fa2017-12-11 10:33:46 -08001250 mLock.unlock();
Robert Shih0cd95062018-01-21 17:41:16 -08001251
1252 sp<AMediaFormatWrapper> format;
1253 ssize_t sampleSize = -1;
1254 status_t err = extractor->getSampleFormat(format);
1255 if (err == OK) {
1256 sampleSize = extractor->getSampleSize();
Wei Jia53692fa2017-12-11 10:33:46 -08001257 }
Robert Shih0cd95062018-01-21 17:41:16 -08001258
1259 if (err != OK || sampleSize < 0) {
1260 mLock.lock();
1261 track->mPackets->signalEOS(err != OK ? err : ERROR_END_OF_STREAM);
1262 break;
1263 }
1264
1265 sp<ABuffer> abuf = new ABuffer(sampleSize);
1266 sampleSize = extractor->readSampleData(abuf);
Wei Jia53692fa2017-12-11 10:33:46 -08001267 mLock.lock();
1268
Wei Jia53692fa2017-12-11 10:33:46 -08001269 // in case track has been changed since we don't have lock for some time.
1270 if (generation != getDataGeneration(trackType)) {
Wei Jia53692fa2017-12-11 10:33:46 -08001271 break;
1272 }
1273
Robert Shih0cd95062018-01-21 17:41:16 -08001274 int64_t timeUs = extractor->getSampleTime();
1275 if (timeUs < 0) {
1276 track->mPackets->signalEOS(ERROR_MALFORMED);
Wei Jia53692fa2017-12-11 10:33:46 -08001277 break;
1278 }
1279
Robert Shih0cd95062018-01-21 17:41:16 -08001280 sp<AMessage> meta = abuf->meta();
1281 format->writeToAMessage(meta);
1282 meta->setInt64("timeUs", timeUs);
1283 if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
1284 mAudioTimeUs = timeUs;
1285 } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
1286 mVideoTimeUs = timeUs;
Wei Jia53692fa2017-12-11 10:33:46 -08001287 }
Robert Shih0cd95062018-01-21 17:41:16 -08001288
Robert Shihf60cbe52018-12-21 13:32:36 -08001289 sp<AMediaCodecCryptoInfoWrapper> cryptInfo = extractor->getSampleCryptoInfo();
1290 if (cryptInfo != NULL) {
1291 meta->setObject("cryptInfo", cryptInfo);
1292 }
1293
Robert Shih0cd95062018-01-21 17:41:16 -08001294 queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
1295
1296 if (numBuffers == 0 && actualTimeUs != nullptr) {
1297 *actualTimeUs = timeUs;
1298 }
1299 if (seeking) {
1300 if (meta != nullptr && mode == MediaPlayer2SeekMode::SEEK_CLOSEST
1301 && seekTimeUs > timeUs) {
1302 sp<AMessage> extra = new AMessage;
1303 extra->setInt64("resume-at-mediaTimeUs", seekTimeUs);
1304 meta->setMessage("extra", extra);
1305 }
1306 }
1307
1308 track->mPackets->queueAccessUnit(abuf);
1309 formatChange = false;
1310 seeking = false;
1311 ++numBuffers;
1312 extractor->advance();
1313
Wei Jia53692fa2017-12-11 10:33:46 -08001314 }
1315
1316 if (mIsStreaming
1317 && (trackType == MEDIA_TRACK_TYPE_VIDEO || trackType == MEDIA_TRACK_TYPE_AUDIO)) {
1318 status_t finalResult;
1319 int64_t durationUs = track->mPackets->getBufferedDurationUs(&finalResult);
1320
1321 // TODO: maxRebufferingMarkMs could be larger than
1322 // mBufferingSettings.mResumePlaybackMarkMs
1323 int64_t markUs = (mPreparing ? mBufferingSettings.mInitialMarkMs
1324 : mBufferingSettings.mResumePlaybackMarkMs) * 1000ll;
1325 if (finalResult == ERROR_END_OF_STREAM || durationUs >= markUs) {
1326 if (mPreparing || mSentPauseOnBuffering) {
1327 Track *counterTrack =
1328 (trackType == MEDIA_TRACK_TYPE_VIDEO ? &mAudioTrack : &mVideoTrack);
Robert Shih0cd95062018-01-21 17:41:16 -08001329 if (counterTrack->mExtractor != NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -08001330 durationUs = counterTrack->mPackets->getBufferedDurationUs(&finalResult);
1331 }
1332 if (finalResult == ERROR_END_OF_STREAM || durationUs >= markUs) {
1333 if (mPreparing) {
1334 notifyPrepared();
1335 mPreparing = false;
1336 } else {
Wei Jia53692fa2017-12-11 10:33:46 -08001337 mSentPauseOnBuffering = false;
1338 sp<AMessage> notify = dupNotify();
1339 notify->setInt32("what", kWhatResumeOnBufferingEnd);
1340 notify->post();
1341 }
1342 }
1343 }
1344 return;
1345 }
1346
1347 postReadBuffer(trackType);
1348 }
1349}
1350
Wei Jia2409c872018-02-02 10:34:33 -08001351void NuPlayer2::GenericSource2::queueDiscontinuityIfNeeded(
Wei Jia53692fa2017-12-11 10:33:46 -08001352 bool seeking, bool formatChange, media_track_type trackType, Track *track) {
1353 // formatChange && seeking: track whose source is changed during selection
1354 // formatChange && !seeking: track whose source is not changed during selection
1355 // !formatChange: normal seek
1356 if ((seeking || formatChange)
1357 && (trackType == MEDIA_TRACK_TYPE_AUDIO
1358 || trackType == MEDIA_TRACK_TYPE_VIDEO)) {
1359 ATSParser::DiscontinuityType type = (formatChange && seeking)
1360 ? ATSParser::DISCONTINUITY_FORMATCHANGE
1361 : ATSParser::DISCONTINUITY_NONE;
1362 track->mPackets->queueDiscontinuity(type, NULL /* extra */, true /* discard */);
1363 }
1364}
1365
Wei Jia2409c872018-02-02 10:34:33 -08001366void NuPlayer2::GenericSource2::notifyBufferingUpdate(int32_t percentage) {
Wei Jia53692fa2017-12-11 10:33:46 -08001367 // Buffering percent could go backward as it's estimated from remaining
1368 // data and last access time. This could cause the buffering position
1369 // drawn on media control to jitter slightly. Remember previously reported
1370 // percentage and don't allow it to go backward.
1371 if (percentage < mPrevBufferPercentage) {
1372 percentage = mPrevBufferPercentage;
1373 } else if (percentage > 100) {
1374 percentage = 100;
1375 }
1376
1377 mPrevBufferPercentage = percentage;
1378
1379 ALOGV("notifyBufferingUpdate: buffering %d%%", percentage);
1380
1381 sp<AMessage> notify = dupNotify();
1382 notify->setInt32("what", kWhatBufferingUpdate);
1383 notify->setInt32("percentage", percentage);
1384 notify->post();
1385}
1386
Wei Jia2409c872018-02-02 10:34:33 -08001387void NuPlayer2::GenericSource2::schedulePollBuffering() {
Wei Jiaf01e3122018-10-18 11:49:44 -07001388 if (mIsStreaming) {
1389 sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
1390 msg->setInt32("generation", mPollBufferingGeneration);
1391 // Enquires buffering status every second.
1392 msg->post(1000000ll);
1393 }
Wei Jia53692fa2017-12-11 10:33:46 -08001394}
1395
Wei Jia2409c872018-02-02 10:34:33 -08001396void NuPlayer2::GenericSource2::onPollBuffering() {
Wei Jia53692fa2017-12-11 10:33:46 -08001397 int64_t cachedDurationUs = -1ll;
Wei Jia53692fa2017-12-11 10:33:46 -08001398
Robert Shih49fb89d2018-01-31 17:53:19 -08001399 sp<AMediaExtractorWrapper> extractor;
1400 if (mVideoTrack.mExtractor != NULL) {
1401 extractor = mVideoTrack.mExtractor;
1402 } else if (mAudioTrack.mExtractor != NULL) {
1403 extractor = mAudioTrack.mExtractor;
Wei Jia53692fa2017-12-11 10:33:46 -08001404 }
1405
Robert Shih49fb89d2018-01-31 17:53:19 -08001406 if (extractor != NULL) {
1407 cachedDurationUs = extractor->getCachedDuration();
Wei Jia53692fa2017-12-11 10:33:46 -08001408 }
1409
1410 if (cachedDurationUs >= 0ll) {
Robert Shih49fb89d2018-01-31 17:53:19 -08001411 ssize_t sampleSize = extractor->getSampleSize();
1412 if (sampleSize >= 0ll) {
Wei Jia53692fa2017-12-11 10:33:46 -08001413 int64_t cachedPosUs = getLastReadPosition() + cachedDurationUs;
1414 int percentage = 100.0 * cachedPosUs / mDurationUs;
1415 if (percentage > 100) {
1416 percentage = 100;
1417 }
1418
1419 notifyBufferingUpdate(percentage);
Robert Shih49fb89d2018-01-31 17:53:19 -08001420 ALOGV("onPollBuffering: cachedDurationUs %.1f sec", cachedDurationUs / 1000000.0f);
1421 } else {
1422 notifyBufferingUpdate(100);
1423 ALOGV("onPollBuffering: EOS");
Wei Jia53692fa2017-12-11 10:33:46 -08001424 }
Wei Jia53692fa2017-12-11 10:33:46 -08001425 }
1426
1427 schedulePollBuffering();
1428}
1429
1430// Modular DRM
Wei Jia2409c872018-02-02 10:34:33 -08001431status_t NuPlayer2::GenericSource2::prepareDrm(
Wei Jia53692fa2017-12-11 10:33:46 -08001432 const uint8_t uuid[16],
1433 const Vector<uint8_t> &drmSessionId,
1434 sp<AMediaCryptoWrapper> *outCrypto) {
1435 Mutex::Autolock _l(mLock);
1436 ALOGV("prepareDrm");
1437
1438 mIsDrmProtected = false;
1439 mIsDrmReleased = false;
1440 mIsSecure = false;
1441
1442 status_t status = OK;
1443 sp<AMediaCryptoWrapper> crypto =
1444 new AMediaCryptoWrapper(uuid, drmSessionId.array(), drmSessionId.size());
1445 if (crypto == NULL) {
1446 ALOGE("prepareDrm: failed to create crypto.");
1447 return UNKNOWN_ERROR;
1448 }
1449 ALOGV("prepareDrm: crypto created for uuid: %s",
1450 DrmUUID::toHexString(uuid).string());
1451
1452 *outCrypto = crypto;
1453 // as long a there is an active crypto
1454 mIsDrmProtected = true;
1455
1456 if (mMimes.size() == 0) {
1457 status = UNKNOWN_ERROR;
1458 ALOGE("prepareDrm: Unexpected. Must have at least one track. status: %d", status);
1459 return status;
1460 }
1461
1462 // first mime in this list is either the video track, or the first audio track
1463 const char *mime = mMimes[0].string();
1464 mIsSecure = crypto->requiresSecureDecoderComponent(mime);
1465 ALOGV("prepareDrm: requiresSecureDecoderComponent mime: %s isSecure: %d",
1466 mime, mIsSecure);
1467
1468 // Checking the member flags while in the looper to send out the notification.
1469 // The legacy mDecryptHandle!=NULL check (for FLAG_PROTECTED) is equivalent to mIsDrmProtected.
1470 notifyFlagsChanged(
1471 (mIsSecure ? FLAG_SECURE : 0) |
1472 // Setting "protected screen" only for L1: b/38390836
1473 (mIsSecure ? FLAG_PROTECTED : 0) |
1474 FLAG_CAN_PAUSE |
1475 FLAG_CAN_SEEK_BACKWARD |
1476 FLAG_CAN_SEEK_FORWARD |
1477 FLAG_CAN_SEEK);
1478
1479 if (status == OK) {
1480 ALOGV("prepareDrm: mCrypto: %p", outCrypto->get());
1481 ALOGD("prepareDrm ret: %d ", status);
1482 } else {
1483 ALOGE("prepareDrm err: %d", status);
1484 }
1485 return status;
1486}
1487
Wei Jia2409c872018-02-02 10:34:33 -08001488status_t NuPlayer2::GenericSource2::releaseDrm() {
Wei Jia53692fa2017-12-11 10:33:46 -08001489 Mutex::Autolock _l(mLock);
1490 ALOGV("releaseDrm");
1491
1492 if (mIsDrmProtected) {
1493 mIsDrmProtected = false;
1494 // to prevent returning any more buffer after stop/releaseDrm (b/37960096)
1495 mIsDrmReleased = true;
1496 ALOGV("releaseDrm: mIsDrmProtected is reset.");
1497 } else {
1498 ALOGE("releaseDrm: mIsDrmProtected is already false.");
1499 }
1500
1501 return OK;
1502}
1503
Wei Jia2409c872018-02-02 10:34:33 -08001504status_t NuPlayer2::GenericSource2::checkDrmInfo()
Wei Jia53692fa2017-12-11 10:33:46 -08001505{
1506 // clearing the flag at prepare in case the player is reused after stop/releaseDrm with the
1507 // same source without being reset (called by prepareAsync/initFromDataSource)
1508 mIsDrmReleased = false;
1509
Robert Shih0cd95062018-01-21 17:41:16 -08001510 if (mExtractor == NULL) {
1511 ALOGV("checkDrmInfo: No extractor");
Wei Jia53692fa2017-12-11 10:33:46 -08001512 return OK; // letting the caller responds accordingly
1513 }
1514
Robert Shih0cd95062018-01-21 17:41:16 -08001515 PsshInfo *psshInfo = mExtractor->getPsshInfo();
1516 if (psshInfo == NULL) {
Wei Jia53692fa2017-12-11 10:33:46 -08001517 ALOGV("checkDrmInfo: No PSSH");
1518 return OK; // source without DRM info
1519 }
1520
Dongwon Kang41929fb2018-09-09 08:29:56 -07001521 PlayerMessage playerMsg;
1522 status_t ret = NuPlayer2Drm::retrieveDrmInfo(psshInfo, &playerMsg);
1523 ALOGV("checkDrmInfo: MEDIA_DRM_INFO PSSH drm info size: %d", (int)playerMsg.ByteSize());
Wei Jia53692fa2017-12-11 10:33:46 -08001524
Dongwon Kang41929fb2018-09-09 08:29:56 -07001525 if (ret != OK) {
1526 ALOGE("checkDrmInfo: failed to retrive DrmInfo %d", ret);
Wei Jia53692fa2017-12-11 10:33:46 -08001527 return UNKNOWN_ERROR;
1528 }
1529
Dongwon Kang41929fb2018-09-09 08:29:56 -07001530 int size = playerMsg.ByteSize();
1531 sp<ABuffer> drmInfoBuf = new ABuffer(size);
1532 playerMsg.SerializeToArray(drmInfoBuf->data(), size);
1533 drmInfoBuf->setRange(0, size);
1534 notifyDrmInfo(drmInfoBuf);
Wei Jia53692fa2017-12-11 10:33:46 -08001535
1536 return OK;
1537}
1538
Dongwon Kang1889c3e2018-02-01 13:44:57 -08001539void NuPlayer2::GenericSource2::signalBufferReturned(MediaBufferBase *buffer)
Wei Jia53692fa2017-12-11 10:33:46 -08001540{
1541 //ALOGV("signalBufferReturned %p refCount: %d", buffer, buffer->localRefcount());
1542
1543 buffer->setObserver(NULL);
1544 buffer->release(); // this leads to delete since that there is no observor
1545}
1546
1547} // namespace android