blob: 33c3094053158ec44bb1f7fe0e1cf7f6d5c5a8db [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"
Hassan Shojaniacefac142017-02-06 21:02:02 -080021#include "NuPlayerDrm.h"
Andreas Huberafed0e12011-09-20 15:39:58 -070022
23#include "AnotherPacketSource.h"
Andy Hungd49dbd62016-07-07 14:20:35 -070024#include <binder/IServiceManager.h>
25#include <cutils/properties.h>
Dongwon Kangd91dc5a2017-10-10 00:07:09 -070026#include <media/DataSource.h>
27#include <media/MediaExtractor.h>
28#include <media/MediaSource.h>
Chong Zhanga19f33e2014-08-07 15:35:07 -070029#include <media/IMediaHTTPService.h>
Andreas Huberafed0e12011-09-20 15:39:58 -070030#include <media/stagefright/foundation/ABuffer.h>
31#include <media/stagefright/foundation/ADebug.h>
32#include <media/stagefright/foundation/AMessage.h>
Dongwon Kangd91dc5a2017-10-10 00:07:09 -070033#include <media/stagefright/DataSourceFactory.h>
Andreas Huberafed0e12011-09-20 15:39:58 -070034#include <media/stagefright/FileSource.h>
Dongwon Kangd91dc5a2017-10-10 00:07:09 -070035#include <media/stagefright/InterfaceUtils.h>
Andreas Huberafed0e12011-09-20 15:39:58 -070036#include <media/stagefright/MediaBuffer.h>
Wei Jia992c5592017-09-01 14:20:23 -070037#include <media/stagefright/MediaClock.h>
Andreas Huberafed0e12011-09-20 15:39:58 -070038#include <media/stagefright/MediaDefs.h>
Dongwon Kangd91dc5a2017-10-10 00:07:09 -070039#include <media/stagefright/MediaExtractorFactory.h>
Andreas Huberafed0e12011-09-20 15:39:58 -070040#include <media/stagefright/MetaData.h>
Robert Shih17f6dd62014-08-20 17:00:21 -070041#include <media/stagefright/Utils.h>
Chong Zhangd354d8d2014-08-20 13:09:58 -070042#include "../../libstagefright/include/NuCachedSource2.h"
Robert Shih360d6d02014-09-29 14:42:35 -070043#include "../../libstagefright/include/HTTPBase.h"
Andreas Huberafed0e12011-09-20 15:39:58 -070044
45namespace android {
46
Wei Jia9bb38032017-03-23 18:00:38 -070047static const int kInitialMarkMs = 5000; // 5secs
48
49//static const int kPausePlaybackMarkMs = 2000; // 2secs
50static const int kResumePlaybackMarkMs = 15000; // 15secs
Wei Jia48fa06d2016-12-20 15:30:49 -080051
Andreas Huberafed0e12011-09-20 15:39:58 -070052NuPlayer::GenericSource::GenericSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080053 const sp<AMessage> &notify,
Lajos Molnarcc227032014-07-17 15:33:06 -070054 bool uidValid,
Wei Jia992c5592017-09-01 14:20:23 -070055 uid_t uid,
56 const sp<MediaClock> &mediaClock)
Andreas Huberb5f25f02013-02-05 10:14:26 -080057 : Source(notify),
Robert Shih5c67ddc2014-11-04 17:46:05 -080058 mAudioTimeUs(0),
59 mAudioLastDequeueTimeUs(0),
60 mVideoTimeUs(0),
61 mVideoLastDequeueTimeUs(0),
Wei Jia542a81a2017-10-16 10:31:29 -070062 mPrevBufferPercentage(-1),
63 mPollBufferingGeneration(0),
64 mSentPauseOnBuffering(false),
65 mAudioDataGeneration(0),
66 mVideoDataGeneration(0),
Robert Shih3423bbd2014-07-16 15:47:09 -070067 mFetchSubtitleDataGeneration(0),
Lajos Molnare26940f2014-07-31 10:31:26 -070068 mFetchTimedTextDataGeneration(0),
Marco Nelissen02fc5e32015-05-27 11:20:41 -070069 mDurationUs(-1ll),
Lajos Molnarcc227032014-07-17 15:33:06 -070070 mAudioIsVorbis(false),
Chong Zhang42e81532014-12-01 13:44:26 -080071 mIsSecure(false),
Chong Zhangefbb6192015-01-30 17:13:27 -080072 mIsStreaming(false),
Lajos Molnarcc227032014-07-17 15:33:06 -070073 mUIDValid(uidValid),
Chong Zhangd354d8d2014-08-20 13:09:58 -070074 mUID(uid),
Wei Jia992c5592017-09-01 14:20:23 -070075 mMediaClock(mediaClock),
Chong Zhanga6bf21f2014-11-19 20:26:34 -080076 mFd(-1),
Chong Zhang2a3cc9a2014-08-21 17:48:26 -070077 mBitrate(-1ll),
Wei Jia14532f22015-12-29 11:28:15 -080078 mPendingReadBufferTypes(0) {
Hassan Shojaniacefac142017-02-06 21:02:02 -080079 ALOGV("GenericSource");
Wei Jia992c5592017-09-01 14:20:23 -070080 CHECK(mediaClock != NULL);
Hassan Shojaniacefac142017-02-06 21:02:02 -080081
Wei Jia9bb38032017-03-23 18:00:38 -070082 mBufferingSettings.mInitialMarkMs = kInitialMarkMs;
83 mBufferingSettings.mResumePlaybackMarkMs = kResumePlaybackMarkMs;
Chong Zhanga19f33e2014-08-07 15:35:07 -070084 resetDataSource();
Chong Zhang3de157d2014-08-05 20:54:44 -070085}
86
Chong Zhanga19f33e2014-08-07 15:35:07 -070087void NuPlayer::GenericSource::resetDataSource() {
Hassan Shojaniacefac142017-02-06 21:02:02 -080088 ALOGV("resetDataSource");
89
Chong Zhanga19f33e2014-08-07 15:35:07 -070090 mHTTPService.clear();
Robert Shih360d6d02014-09-29 14:42:35 -070091 mHttpSource.clear();
Wei Jia67744bd2017-11-10 11:27:04 -080092 mDisconnected = false;
Chong Zhanga19f33e2014-08-07 15:35:07 -070093 mUri.clear();
94 mUriHeaders.clear();
Chong Zhanga6bf21f2014-11-19 20:26:34 -080095 if (mFd >= 0) {
96 close(mFd);
97 mFd = -1;
98 }
Chong Zhanga19f33e2014-08-07 15:35:07 -070099 mOffset = 0;
100 mLength = 0;
Ronghua Wu80276872014-08-28 15:50:29 -0700101 mStarted = false;
Wei Jia542a81a2017-10-16 10:31:29 -0700102 mPreparing = false;
Hassan Shojaniacefac142017-02-06 21:02:02 -0800103
104 mIsDrmProtected = false;
Hassan Shojania355e8472017-05-12 10:33:16 -0700105 mIsDrmReleased = false;
Hassan Shojaniacefac142017-02-06 21:02:02 -0800106 mIsSecure = false;
107 mMimes.clear();
Chong Zhanga19f33e2014-08-07 15:35:07 -0700108}
109
110status_t NuPlayer::GenericSource::setDataSource(
Chong Zhang3de157d2014-08-05 20:54:44 -0700111 const sp<IMediaHTTPService> &httpService,
112 const char *url,
113 const KeyedVector<String8, String8> *headers) {
Wei Jia542a81a2017-10-16 10:31:29 -0700114 Mutex::Autolock _l(mLock);
Hassan Shojaniacefac142017-02-06 21:02:02 -0800115 ALOGV("setDataSource url: %s", url);
116
Chong Zhanga19f33e2014-08-07 15:35:07 -0700117 resetDataSource();
Chong Zhang3de157d2014-08-05 20:54:44 -0700118
Chong Zhanga19f33e2014-08-07 15:35:07 -0700119 mHTTPService = httpService;
120 mUri = url;
Andreas Huberafed0e12011-09-20 15:39:58 -0700121
Chong Zhanga19f33e2014-08-07 15:35:07 -0700122 if (headers) {
123 mUriHeaders = *headers;
Chong Zhang3de157d2014-08-05 20:54:44 -0700124 }
125
Chong Zhanga19f33e2014-08-07 15:35:07 -0700126 // delay data source creation to prepareAsync() to avoid blocking
127 // the calling thread in setDataSource for any significant time.
128 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700129}
130
Chong Zhanga19f33e2014-08-07 15:35:07 -0700131status_t NuPlayer::GenericSource::setDataSource(
Chong Zhang3de157d2014-08-05 20:54:44 -0700132 int fd, int64_t offset, int64_t length) {
Wei Jia542a81a2017-10-16 10:31:29 -0700133 Mutex::Autolock _l(mLock);
Hassan Shojaniacefac142017-02-06 21:02:02 -0800134 ALOGV("setDataSource %d/%lld/%lld", fd, (long long)offset, (long long)length);
135
Chong Zhanga19f33e2014-08-07 15:35:07 -0700136 resetDataSource();
Andreas Huberafed0e12011-09-20 15:39:58 -0700137
Chong Zhanga19f33e2014-08-07 15:35:07 -0700138 mFd = dup(fd);
139 mOffset = offset;
140 mLength = length;
141
142 // delay data source creation to prepareAsync() to avoid blocking
143 // the calling thread in setDataSource for any significant time.
144 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700145}
146
Chris Watkins99f31602015-03-20 13:06:33 -0700147status_t NuPlayer::GenericSource::setDataSource(const sp<DataSource>& source) {
Wei Jia542a81a2017-10-16 10:31:29 -0700148 Mutex::Autolock _l(mLock);
Hassan Shojaniacefac142017-02-06 21:02:02 -0800149 ALOGV("setDataSource (source: %p)", source.get());
150
Chris Watkins99f31602015-03-20 13:06:33 -0700151 resetDataSource();
152 mDataSource = source;
153 return OK;
154}
155
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700156sp<MetaData> NuPlayer::GenericSource::getFileFormatMeta() const {
Wei Jia542a81a2017-10-16 10:31:29 -0700157 Mutex::Autolock _l(mLock);
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700158 return mFileMeta;
159}
160
Chong Zhangd354d8d2014-08-20 13:09:58 -0700161status_t NuPlayer::GenericSource::initFromDataSource() {
Marco Nelissenb2487f02015-09-01 13:23:23 -0700162 sp<IMediaExtractor> extractor;
Dongwon Kang51467422017-12-08 06:07:16 -0800163 CHECK(mDataSource != NULL || mFd != -1);
Wei Jia67744bd2017-11-10 11:27:04 -0800164 sp<DataSource> dataSource = mDataSource;
Dongwon Kang51467422017-12-08 06:07:16 -0800165 const int fd = mFd;
166 const int64_t offset = mOffset;
167 const int64_t length = mLength;
Chong Zhangd354d8d2014-08-20 13:09:58 -0700168
Wei Jia67744bd2017-11-10 11:27:04 -0800169 mLock.unlock();
170 // This might take long time if data source is not reliable.
Dongwon Kang51467422017-12-08 06:07:16 -0800171 if (dataSource != nullptr) {
172 extractor = MediaExtractorFactory::Create(dataSource, NULL /* mime */);
173 } else {
174 extractor = MediaExtractorFactory::CreateFromFd(
175 fd, offset, length, NULL /* mime */, &dataSource);
176 }
177
178 if (dataSource == nullptr) {
179 ALOGE("initFromDataSource, failed to create data source!");
180 mLock.lock();
181 return UNKNOWN_ERROR;
182 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700183
Chong Zhang3de157d2014-08-05 20:54:44 -0700184 if (extractor == NULL) {
Wei Jia161dc692017-04-20 16:40:06 -0700185 ALOGE("initFromDataSource, cannot create extractor!");
Dongwon Kang51467422017-12-08 06:07:16 -0800186 mLock.lock();
Chong Zhang3de157d2014-08-05 20:54:44 -0700187 return UNKNOWN_ERROR;
188 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700189
Wei Jia67744bd2017-11-10 11:27:04 -0800190 sp<MetaData> fileMeta = extractor->getMetaData();
191
192 size_t numtracks = extractor->countTracks();
193 if (numtracks == 0) {
194 ALOGE("initFromDataSource, source has no track!");
Dongwon Kang51467422017-12-08 06:07:16 -0800195 mLock.lock();
Wei Jia67744bd2017-11-10 11:27:04 -0800196 return UNKNOWN_ERROR;
197 }
198
199 mLock.lock();
Dongwon Kang51467422017-12-08 06:07:16 -0800200 mFd = -1;
201 mDataSource = dataSource;
Wei Jia67744bd2017-11-10 11:27:04 -0800202 mFileMeta = fileMeta;
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700203 if (mFileMeta != NULL) {
Marco Nelissenc1f4b2b2014-06-17 14:48:32 -0700204 int64_t duration;
Marco Nelissenf0b72b52014-09-16 15:43:44 -0700205 if (mFileMeta->findInt64(kKeyDuration, &duration)) {
Marco Nelissenc1f4b2b2014-06-17 14:48:32 -0700206 mDurationUs = duration;
207 }
208 }
209
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700210 int32_t totalBitrate = 0;
211
Hassan Shojaniacefac142017-02-06 21:02:02 -0800212 mMimes.clear();
213
Marco Nelissen705d3292014-09-19 15:14:37 -0700214 for (size_t i = 0; i < numtracks; ++i) {
Marco Nelissenb2487f02015-09-01 13:23:23 -0700215 sp<IMediaSource> track = extractor->getTrack(i);
Wei Jia0386c912015-08-28 10:35:35 -0700216 if (track == NULL) {
217 continue;
218 }
Chong Zhangafc0a872014-08-26 09:56:52 -0700219
Andreas Huberafed0e12011-09-20 15:39:58 -0700220 sp<MetaData> meta = extractor->getTrackMetaData(i);
Marco Nelissenc367ca12015-09-15 09:51:59 -0700221 if (meta == NULL) {
222 ALOGE("no metadata for track %zu", i);
223 return UNKNOWN_ERROR;
224 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700225
226 const char *mime;
227 CHECK(meta->findCString(kKeyMIMEType, &mime));
228
Hassan Shojania06a70812017-02-15 21:57:45 -0800229 ALOGV("initFromDataSource track[%zu]: %s", i, mime);
Hassan Shojaniacefac142017-02-06 21:02:02 -0800230
Chong Zhangafc0a872014-08-26 09:56:52 -0700231 // Do the string compare immediately with "mime",
232 // we can't assume "mime" would stay valid after another
233 // extractor operation, some extractors might modify meta
234 // during getTrack() and make it invalid.
Andreas Huberafed0e12011-09-20 15:39:58 -0700235 if (!strncasecmp(mime, "audio/", 6)) {
236 if (mAudioTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700237 mAudioTrack.mIndex = i;
238 mAudioTrack.mSource = track;
Robert Shihaf52c1a2014-09-11 15:38:54 -0700239 mAudioTrack.mPackets =
240 new AnotherPacketSource(mAudioTrack.mSource->getFormat());
Andreas Huberafed0e12011-09-20 15:39:58 -0700241
242 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
243 mAudioIsVorbis = true;
244 } else {
245 mAudioIsVorbis = false;
246 }
Hassan Shojaniacefac142017-02-06 21:02:02 -0800247
248 mMimes.add(String8(mime));
Andreas Huberafed0e12011-09-20 15:39:58 -0700249 }
250 } else if (!strncasecmp(mime, "video/", 6)) {
251 if (mVideoTrack.mSource == NULL) {
Robert Shihdd235722014-06-12 14:49:23 -0700252 mVideoTrack.mIndex = i;
253 mVideoTrack.mSource = track;
Robert Shihaf52c1a2014-09-11 15:38:54 -0700254 mVideoTrack.mPackets =
255 new AnotherPacketSource(mVideoTrack.mSource->getFormat());
Chong Zhang7e892182014-08-05 11:58:21 -0700256
Hassan Shojaniacefac142017-02-06 21:02:02 -0800257 // video always at the beginning
258 mMimes.insertAt(String8(mime), 0);
Andreas Huberafed0e12011-09-20 15:39:58 -0700259 }
260 }
261
Wei Jia0386c912015-08-28 10:35:35 -0700262 mSources.push(track);
263 int64_t durationUs;
264 if (meta->findInt64(kKeyDuration, &durationUs)) {
265 if (durationUs > mDurationUs) {
266 mDurationUs = durationUs;
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700267 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700268 }
Wei Jia0386c912015-08-28 10:35:35 -0700269
270 int32_t bitrate;
271 if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) {
272 totalBitrate += bitrate;
273 } else {
274 totalBitrate = -1;
275 }
276 }
277
Hassan Shojaniacefac142017-02-06 21:02:02 -0800278 ALOGV("initFromDataSource mSources.size(): %zu mIsSecure: %d mime[0]: %s", mSources.size(),
279 mIsSecure, (mMimes.isEmpty() ? "NONE" : mMimes[0].string()));
280
Wei Jia0386c912015-08-28 10:35:35 -0700281 if (mSources.size() == 0) {
282 ALOGE("b/23705695");
283 return UNKNOWN_ERROR;
Andreas Huberafed0e12011-09-20 15:39:58 -0700284 }
Chong Zhang3de157d2014-08-05 20:54:44 -0700285
Hassan Shojaniacefac142017-02-06 21:02:02 -0800286 // Modular DRM: The return value doesn't affect source initialization.
287 (void)checkDrmInfo();
288
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700289 mBitrate = totalBitrate;
290
291 return OK;
292}
293
Wei Jia9bb38032017-03-23 18:00:38 -0700294status_t NuPlayer::GenericSource::getBufferingSettings(
Wei Jia48fa06d2016-12-20 15:30:49 -0800295 BufferingSettings* buffering /* nonnull */) {
Wei Jia9bb38032017-03-23 18:00:38 -0700296 {
297 Mutex::Autolock _l(mLock);
298 *buffering = mBufferingSettings;
299 }
Wei Jia542a81a2017-10-16 10:31:29 -0700300
Wei Jia9bb38032017-03-23 18:00:38 -0700301 ALOGV("getBufferingSettings{%s}", buffering->toString().string());
Wei Jia48fa06d2016-12-20 15:30:49 -0800302 return OK;
303}
304
305status_t NuPlayer::GenericSource::setBufferingSettings(const BufferingSettings& buffering) {
Wei Jia542a81a2017-10-16 10:31:29 -0700306 ALOGV("setBufferingSettings{%s}", buffering.toString().string());
307
Wei Jia542a81a2017-10-16 10:31:29 -0700308 Mutex::Autolock _l(mLock);
309 mBufferingSettings = buffering;
Wei Jia542a81a2017-10-16 10:31:29 -0700310 return OK;
Wei Jia48fa06d2016-12-20 15:30:49 -0800311}
312
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700313status_t NuPlayer::GenericSource::startSources() {
Chong Zhangefbb6192015-01-30 17:13:27 -0800314 // Start the selected A/V tracks now before we start buffering.
315 // Widevine sources might re-initialize crypto when starting, if we delay
316 // this to start(), all data buffered during prepare would be wasted.
317 // (We don't actually start reading until start().)
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700318 //
319 // TODO: this logic may no longer be relevant after the removal of widevine
320 // support
Chong Zhangefbb6192015-01-30 17:13:27 -0800321 if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) {
322 ALOGE("failed to start audio track!");
323 return UNKNOWN_ERROR;
324 }
325
326 if (mVideoTrack.mSource != NULL && mVideoTrack.mSource->start() != OK) {
327 ALOGE("failed to start video track!");
328 return UNKNOWN_ERROR;
329 }
330
Chong Zhang3de157d2014-08-05 20:54:44 -0700331 return OK;
Andreas Huberafed0e12011-09-20 15:39:58 -0700332}
333
Ronghua Wu80276872014-08-28 15:50:29 -0700334int64_t NuPlayer::GenericSource::getLastReadPosition() {
335 if (mAudioTrack.mSource != NULL) {
336 return mAudioTimeUs;
337 } else if (mVideoTrack.mSource != NULL) {
338 return mVideoTimeUs;
339 } else {
340 return 0;
341 }
342}
343
Ronghua Wu02cb98d2015-05-27 11:02:54 -0700344bool NuPlayer::GenericSource::isStreaming() const {
Wei Jia542a81a2017-10-16 10:31:29 -0700345 Mutex::Autolock _l(mLock);
Ronghua Wu02cb98d2015-05-27 11:02:54 -0700346 return mIsStreaming;
347}
348
Andreas Huberafed0e12011-09-20 15:39:58 -0700349NuPlayer::GenericSource::~GenericSource() {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800350 ALOGV("~GenericSource");
Chong Zhang1228d6b2014-08-12 21:25:48 -0700351 if (mLooper != NULL) {
352 mLooper->unregisterHandler(id());
353 mLooper->stop();
354 }
Chong Zhanga6bf21f2014-11-19 20:26:34 -0800355 resetDataSource();
Andreas Huberafed0e12011-09-20 15:39:58 -0700356}
357
Andreas Huber9575c962013-02-05 13:59:56 -0800358void NuPlayer::GenericSource::prepareAsync() {
Wei Jia542a81a2017-10-16 10:31:29 -0700359 Mutex::Autolock _l(mLock);
Hassan Shojaniacefac142017-02-06 21:02:02 -0800360 ALOGV("prepareAsync: (looper: %d)", (mLooper != NULL));
361
Chong Zhang1228d6b2014-08-12 21:25:48 -0700362 if (mLooper == NULL) {
363 mLooper = new ALooper;
364 mLooper->setName("generic");
365 mLooper->start();
366
367 mLooper->registerHandler(this);
368 }
369
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800370 sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this);
Chong Zhang1228d6b2014-08-12 21:25:48 -0700371 msg->post();
372}
373
374void NuPlayer::GenericSource::onPrepareAsync() {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800375 ALOGV("onPrepareAsync: mDataSource: %d", (mDataSource != NULL));
376
Chong Zhanga19f33e2014-08-07 15:35:07 -0700377 // delayed data source creation
Chong Zhangd354d8d2014-08-20 13:09:58 -0700378 if (mDataSource == NULL) {
Chong Zhang42e81532014-12-01 13:44:26 -0800379 // set to false first, if the extractor
380 // comes back as secure, set it to true then.
381 mIsSecure = false;
382
Chong Zhangd354d8d2014-08-20 13:09:58 -0700383 if (!mUri.empty()) {
Robert Shih360d6d02014-09-29 14:42:35 -0700384 const char* uri = mUri.c_str();
Chong Zhangc287cad2015-02-19 18:30:30 -0800385 String8 contentType;
Robert Shih360d6d02014-09-29 14:42:35 -0700386
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700387 if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
Dongwon Kangd91dc5a2017-10-10 00:07:09 -0700388 mHttpSource = DataSourceFactory::CreateMediaHTTP(mHTTPService);
Robert Shih360d6d02014-09-29 14:42:35 -0700389 if (mHttpSource == NULL) {
390 ALOGE("Failed to create http source!");
391 notifyPreparedAndCleanup(UNKNOWN_ERROR);
392 return;
393 }
394 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700395
Wei Jia67744bd2017-11-10 11:27:04 -0800396 mLock.unlock();
397 // This might take long time if connection has some issue.
398 sp<DataSource> dataSource = DataSourceFactory::CreateFromURI(
Chong Zhangc287cad2015-02-19 18:30:30 -0800399 mHTTPService, uri, &mUriHeaders, &contentType,
Robert Shih360d6d02014-09-29 14:42:35 -0700400 static_cast<HTTPBase *>(mHttpSource.get()));
Wei Jia67744bd2017-11-10 11:27:04 -0800401 mLock.lock();
402 if (!mDisconnected) {
403 mDataSource = dataSource;
404 }
Chong Zhangd354d8d2014-08-20 13:09:58 -0700405 }
Dongwon Kang51467422017-12-08 06:07:16 -0800406 if (mFd == -1 && mDataSource == NULL) {
Chong Zhangd354d8d2014-08-20 13:09:58 -0700407 ALOGE("Failed to create data source!");
408 notifyPreparedAndCleanup(UNKNOWN_ERROR);
409 return;
410 }
Chong Zhanga19f33e2014-08-07 15:35:07 -0700411 }
412
Dongwon Kang51467422017-12-08 06:07:16 -0800413 if (mDataSource != nullptr && mDataSource->flags() & DataSource::kIsCachingDataSource) {
Chris Watkins99f31602015-03-20 13:06:33 -0700414 mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
415 }
416
Jeff Tinker29b7dcf2016-10-24 10:28:30 -0700417 // For cached streaming cases, we need to wait for enough
418 // buffering before reporting prepared.
419 mIsStreaming = (mCachedSource != NULL);
Chris Watkins99f31602015-03-20 13:06:33 -0700420
Chong Zhangc287cad2015-02-19 18:30:30 -0800421 // init extractor from data source
422 status_t err = initFromDataSource();
Chong Zhanga19f33e2014-08-07 15:35:07 -0700423
424 if (err != OK) {
425 ALOGE("Failed to init from data source!");
Chong Zhangd354d8d2014-08-20 13:09:58 -0700426 notifyPreparedAndCleanup(err);
Chong Zhanga19f33e2014-08-07 15:35:07 -0700427 return;
428 }
429
Andreas Huber9575c962013-02-05 13:59:56 -0800430 if (mVideoTrack.mSource != NULL) {
Wei Jia542a81a2017-10-16 10:31:29 -0700431 sp<MetaData> meta = getFormatMeta_l(false /* audio */);
Robert Shih17f6dd62014-08-20 17:00:21 -0700432 sp<AMessage> msg = new AMessage;
433 err = convertMetaDataToMessage(meta, &msg);
434 if(err != OK) {
435 notifyPreparedAndCleanup(err);
436 return;
437 }
438 notifyVideoSizeChanged(msg);
Andreas Huber9575c962013-02-05 13:59:56 -0800439 }
440
441 notifyFlagsChanged(
Hassan Shojaniacefac142017-02-06 21:02:02 -0800442 // FLAG_SECURE will be known if/when prepareDrm is called by the app
443 // FLAG_PROTECTED will be known if/when prepareDrm is called by the app
444 FLAG_CAN_PAUSE |
445 FLAG_CAN_SEEK_BACKWARD |
446 FLAG_CAN_SEEK_FORWARD |
447 FLAG_CAN_SEEK);
Andreas Huber9575c962013-02-05 13:59:56 -0800448
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700449 finishPrepareAsync();
Hassan Shojaniacefac142017-02-06 21:02:02 -0800450
451 ALOGV("onPrepareAsync: Done");
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700452}
453
454void NuPlayer::GenericSource::finishPrepareAsync() {
Hassan Shojaniacefac142017-02-06 21:02:02 -0800455 ALOGV("finishPrepareAsync");
456
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700457 status_t err = startSources();
458 if (err != OK) {
459 ALOGE("Failed to init start data source!");
460 notifyPreparedAndCleanup(err);
461 return;
462 }
463
Chong Zhangefbb6192015-01-30 17:13:27 -0800464 if (mIsStreaming) {
Wei Jia542a81a2017-10-16 10:31:29 -0700465 mCachedSource->resumeFetchingIfNecessary();
466 mPreparing = true;
467 schedulePollBuffering();
Chong Zhangefbb6192015-01-30 17:13:27 -0800468 } else {
469 notifyPrepared();
470 }
Wei Jia542a81a2017-10-16 10:31:29 -0700471
472 if (mAudioTrack.mSource != NULL) {
473 postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
474 }
475
476 if (mVideoTrack.mSource != NULL) {
477 postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
478 }
Andreas Huber9575c962013-02-05 13:59:56 -0800479}
480
Chong Zhangd354d8d2014-08-20 13:09:58 -0700481void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
482 if (err != OK) {
Wei Jia542a81a2017-10-16 10:31:29 -0700483 mDataSource.clear();
484 mCachedSource.clear();
485 mHttpSource.clear();
Chong Zhang2a3cc9a2014-08-21 17:48:26 -0700486
Wei Jia542a81a2017-10-16 10:31:29 -0700487 mBitrate = -1;
488 mPrevBufferPercentage = -1;
489 ++mPollBufferingGeneration;
Chong Zhangd354d8d2014-08-20 13:09:58 -0700490 }
491 notifyPrepared(err);
492}
493
Andreas Huberafed0e12011-09-20 15:39:58 -0700494void NuPlayer::GenericSource::start() {
Wei Jia542a81a2017-10-16 10:31:29 -0700495 Mutex::Autolock _l(mLock);
Andreas Huberafed0e12011-09-20 15:39:58 -0700496 ALOGI("start");
497
498 if (mAudioTrack.mSource != NULL) {
Robert Shih17f6dd62014-08-20 17:00:21 -0700499 postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700500 }
501
502 if (mVideoTrack.mSource != NULL) {
Robert Shih17f6dd62014-08-20 17:00:21 -0700503 postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
Andreas Huberafed0e12011-09-20 15:39:58 -0700504 }
Ronghua Wu80276872014-08-28 15:50:29 -0700505
Ronghua Wu80276872014-08-28 15:50:29 -0700506 mStarted = true;
507}
508
509void NuPlayer::GenericSource::stop() {
Wei Jia542a81a2017-10-16 10:31:29 -0700510 Mutex::Autolock _l(mLock);
Ronghua Wu80276872014-08-28 15:50:29 -0700511 mStarted = false;
512}
513
514void NuPlayer::GenericSource::pause() {
Wei Jia542a81a2017-10-16 10:31:29 -0700515 Mutex::Autolock _l(mLock);
Ronghua Wu80276872014-08-28 15:50:29 -0700516 mStarted = false;
517}
518
519void NuPlayer::GenericSource::resume() {
Wei Jia542a81a2017-10-16 10:31:29 -0700520 Mutex::Autolock _l(mLock);
Ronghua Wu80276872014-08-28 15:50:29 -0700521 mStarted = true;
522}
523
Chong Zhang48296b72014-09-14 14:28:45 -0700524void NuPlayer::GenericSource::disconnect() {
Robert Shihebc27122015-09-02 14:02:47 -0700525 sp<DataSource> dataSource, httpSource;
526 {
Wei Jia542a81a2017-10-16 10:31:29 -0700527 Mutex::Autolock _l(mLock);
Robert Shihebc27122015-09-02 14:02:47 -0700528 dataSource = mDataSource;
529 httpSource = mHttpSource;
Wei Jia67744bd2017-11-10 11:27:04 -0800530 mDisconnected = true;
Robert Shihebc27122015-09-02 14:02:47 -0700531 }
532
533 if (dataSource != NULL) {
Chong Zhang48296b72014-09-14 14:28:45 -0700534 // disconnect data source
Robert Shihebc27122015-09-02 14:02:47 -0700535 if (dataSource->flags() & DataSource::kIsCachingDataSource) {
536 static_cast<NuCachedSource2 *>(dataSource.get())->disconnect();
Chong Zhang48296b72014-09-14 14:28:45 -0700537 }
Robert Shihebc27122015-09-02 14:02:47 -0700538 } else if (httpSource != NULL) {
539 static_cast<HTTPBase *>(httpSource.get())->disconnect();
Chong Zhang48296b72014-09-14 14:28:45 -0700540 }
541}
542
Andreas Huberafed0e12011-09-20 15:39:58 -0700543status_t NuPlayer::GenericSource::feedMoreTSData() {
544 return OK;
545}
546
Wei Jia542a81a2017-10-16 10:31:29 -0700547void NuPlayer::GenericSource::sendCacheStats() {
548 int32_t kbps = 0;
549 status_t err = UNKNOWN_ERROR;
550
551 if (mCachedSource != NULL) {
552 err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
553 }
554
555 if (err == OK) {
556 sp<AMessage> notify = dupNotify();
557 notify->setInt32("what", kWhatCacheStats);
558 notify->setInt32("bandwidth", kbps);
559 notify->post();
560 }
561}
562
Robert Shih3423bbd2014-07-16 15:47:09 -0700563void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
Wei Jia542a81a2017-10-16 10:31:29 -0700564 Mutex::Autolock _l(mLock);
Robert Shih3423bbd2014-07-16 15:47:09 -0700565 switch (msg->what()) {
Chong Zhang1228d6b2014-08-12 21:25:48 -0700566 case kWhatPrepareAsync:
567 {
568 onPrepareAsync();
569 break;
570 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700571 case kWhatFetchSubtitleData:
572 {
Lajos Molnare26940f2014-07-31 10:31:26 -0700573 fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
574 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
575 break;
576 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700577
Lajos Molnare26940f2014-07-31 10:31:26 -0700578 case kWhatFetchTimedTextData:
579 {
580 fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
581 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih3423bbd2014-07-16 15:47:09 -0700582 break;
583 }
584
585 case kWhatSendSubtitleData:
586 {
Lajos Molnare26940f2014-07-31 10:31:26 -0700587 sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
588 mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
589 break;
590 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700591
Marco Nelissen55e2f4c2015-09-04 15:57:15 -0700592 case kWhatSendGlobalTimedTextData:
593 {
594 sendGlobalTextData(kWhatTimedTextData, mFetchTimedTextDataGeneration, msg);
595 break;
596 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700597 case kWhatSendTimedTextData:
598 {
599 sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
600 mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
Robert Shih3423bbd2014-07-16 15:47:09 -0700601 break;
602 }
603
604 case kWhatChangeAVSource:
605 {
606 int32_t trackIndex;
607 CHECK(msg->findInt32("trackIndex", &trackIndex));
Marco Nelissenb2487f02015-09-01 13:23:23 -0700608 const sp<IMediaSource> source = mSources.itemAt(trackIndex);
Robert Shih3423bbd2014-07-16 15:47:09 -0700609
610 Track* track;
611 const char *mime;
612 media_track_type trackType, counterpartType;
613 sp<MetaData> meta = source->getFormat();
614 meta->findCString(kKeyMIMEType, &mime);
615 if (!strncasecmp(mime, "audio/", 6)) {
616 track = &mAudioTrack;
617 trackType = MEDIA_TRACK_TYPE_AUDIO;
618 counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
619 } else {
620 CHECK(!strncasecmp(mime, "video/", 6));
621 track = &mVideoTrack;
622 trackType = MEDIA_TRACK_TYPE_VIDEO;
623 counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
624 }
625
626
627 if (track->mSource != NULL) {
628 track->mSource->stop();
629 }
630 track->mSource = source;
631 track->mSource->start();
632 track->mIndex = trackIndex;
Wei Jia542a81a2017-10-16 10:31:29 -0700633 ++mAudioDataGeneration;
634 ++mVideoDataGeneration;
Robert Shih3423bbd2014-07-16 15:47:09 -0700635
Robert Shih3423bbd2014-07-16 15:47:09 -0700636 int64_t timeUs, actualTimeUs;
637 const bool formatChange = true;
Robert Shih5c67ddc2014-11-04 17:46:05 -0800638 if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
639 timeUs = mAudioLastDequeueTimeUs;
640 } else {
641 timeUs = mVideoLastDequeueTimeUs;
642 }
Wei Jiac5de0912016-11-18 10:22:14 -0800643 readBuffer(trackType, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
644 &actualTimeUs, formatChange);
645 readBuffer(counterpartType, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
646 NULL, !formatChange);
Lajos Molnar6d339f12015-04-17 16:15:53 -0700647 ALOGV("timeUs %lld actualTimeUs %lld", (long long)timeUs, (long long)actualTimeUs);
Robert Shih3423bbd2014-07-16 15:47:09 -0700648
649 break;
650 }
Chong Zhangefbb6192015-01-30 17:13:27 -0800651
Wei Jiac899fc02017-11-15 17:28:53 -0800652 case kWhatSeek:
653 {
654 onSeek(msg);
655 break;
656 }
657
Robert Shih17f6dd62014-08-20 17:00:21 -0700658 case kWhatReadBuffer:
659 {
660 onReadBuffer(msg);
661 break;
662 }
663
Wei Jia542a81a2017-10-16 10:31:29 -0700664 case kWhatPollBuffering:
Lajos Molnarfcd3e942015-03-31 10:06:48 -0700665 {
Wei Jia542a81a2017-10-16 10:31:29 -0700666 int32_t generation;
667 CHECK(msg->findInt32("generation", &generation));
668 if (generation == mPollBufferingGeneration) {
669 onPollBuffering();
670 }
Hassan Shojania355e8472017-05-12 10:33:16 -0700671 break;
672 }
673
Robert Shih3423bbd2014-07-16 15:47:09 -0700674 default:
675 Source::onMessageReceived(msg);
676 break;
677 }
678}
679
Lajos Molnare26940f2014-07-31 10:31:26 -0700680void NuPlayer::GenericSource::fetchTextData(
681 uint32_t sendWhat,
682 media_track_type type,
683 int32_t curGen,
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -0700684 const sp<AnotherPacketSource>& packets,
685 const sp<AMessage>& msg) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700686 int32_t msgGeneration;
687 CHECK(msg->findInt32("generation", &msgGeneration));
688 if (msgGeneration != curGen) {
689 // stale
690 return;
691 }
692
693 int32_t avail;
694 if (packets->hasBufferAvailable(&avail)) {
695 return;
696 }
697
698 int64_t timeUs;
699 CHECK(msg->findInt64("timeUs", &timeUs));
700
Wei Jia992c5592017-09-01 14:20:23 -0700701 int64_t subTimeUs = 0;
Wei Jiac5de0912016-11-18 10:22:14 -0800702 readBuffer(type, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &subTimeUs);
Lajos Molnare26940f2014-07-31 10:31:26 -0700703
Wei Jia992c5592017-09-01 14:20:23 -0700704 status_t eosResult;
705 if (!packets->hasBufferAvailable(&eosResult)) {
706 return;
707 }
708
Lajos Molnare26940f2014-07-31 10:31:26 -0700709 if (msg->what() == kWhatFetchSubtitleData) {
Wei Jia992c5592017-09-01 14:20:23 -0700710 subTimeUs -= 1000000ll; // send subtile data one second earlier
Lajos Molnare26940f2014-07-31 10:31:26 -0700711 }
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800712 sp<AMessage> msg2 = new AMessage(sendWhat, this);
Lajos Molnare26940f2014-07-31 10:31:26 -0700713 msg2->setInt32("generation", msgGeneration);
Wei Jia992c5592017-09-01 14:20:23 -0700714 mMediaClock->addTimer(msg2, subTimeUs);
Lajos Molnare26940f2014-07-31 10:31:26 -0700715}
716
717void NuPlayer::GenericSource::sendTextData(
718 uint32_t what,
719 media_track_type type,
720 int32_t curGen,
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -0700721 const sp<AnotherPacketSource>& packets,
722 const sp<AMessage>& msg) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700723 int32_t msgGeneration;
724 CHECK(msg->findInt32("generation", &msgGeneration));
725 if (msgGeneration != curGen) {
726 // stale
727 return;
728 }
729
730 int64_t subTimeUs;
731 if (packets->nextBufferTime(&subTimeUs) != OK) {
732 return;
733 }
734
735 int64_t nextSubTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -0800736 readBuffer(type, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &nextSubTimeUs);
Lajos Molnare26940f2014-07-31 10:31:26 -0700737
738 sp<ABuffer> buffer;
739 status_t dequeueStatus = packets->dequeueAccessUnit(&buffer);
740 if (dequeueStatus == OK) {
741 sp<AMessage> notify = dupNotify();
742 notify->setInt32("what", what);
743 notify->setBuffer("buffer", buffer);
744 notify->post();
745
Wei Jia992c5592017-09-01 14:20:23 -0700746 if (msg->what() == kWhatSendSubtitleData) {
747 nextSubTimeUs -= 1000000ll; // send subtile data one second earlier
748 }
749 mMediaClock->addTimer(msg, nextSubTimeUs);
Lajos Molnare26940f2014-07-31 10:31:26 -0700750 }
751}
752
Marco Nelissen55e2f4c2015-09-04 15:57:15 -0700753void NuPlayer::GenericSource::sendGlobalTextData(
754 uint32_t what,
755 int32_t curGen,
756 sp<AMessage> msg) {
757 int32_t msgGeneration;
758 CHECK(msg->findInt32("generation", &msgGeneration));
759 if (msgGeneration != curGen) {
760 // stale
761 return;
762 }
763
764 uint32_t textType;
765 const void *data;
766 size_t size = 0;
767 if (mTimedTextTrack.mSource->getFormat()->findData(
768 kKeyTextFormatData, &textType, &data, &size)) {
769 mGlobalTimedText = new ABuffer(size);
770 if (mGlobalTimedText->data()) {
771 memcpy(mGlobalTimedText->data(), data, size);
772 sp<AMessage> globalMeta = mGlobalTimedText->meta();
773 globalMeta->setInt64("timeUs", 0);
774 globalMeta->setString("mime", MEDIA_MIMETYPE_TEXT_3GPP);
775 globalMeta->setInt32("global", 1);
776 sp<AMessage> notify = dupNotify();
777 notify->setInt32("what", what);
778 notify->setBuffer("buffer", mGlobalTimedText);
779 notify->post();
780 }
781 }
782}
783
Andreas Huber84066782011-08-16 09:34:26 -0700784sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
Wei Jia542a81a2017-10-16 10:31:29 -0700785 Mutex::Autolock _l(mLock);
786 return getFormatMeta_l(audio);
Robert Shih17f6dd62014-08-20 17:00:21 -0700787}
788
Wei Jia542a81a2017-10-16 10:31:29 -0700789sp<MetaData> NuPlayer::GenericSource::getFormatMeta_l(bool audio) {
Marco Nelissenb2487f02015-09-01 13:23:23 -0700790 sp<IMediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
Andreas Huberafed0e12011-09-20 15:39:58 -0700791
792 if (source == NULL) {
793 return NULL;
794 }
795
796 return source->getFormat();
797}
798
799status_t NuPlayer::GenericSource::dequeueAccessUnit(
800 bool audio, sp<ABuffer> *accessUnit) {
Wei Jia542a81a2017-10-16 10:31:29 -0700801 Mutex::Autolock _l(mLock);
Hassan Shojania355e8472017-05-12 10:33:16 -0700802 // If has gone through stop/releaseDrm sequence, we no longer send down any buffer b/c
803 // the codec's crypto object has gone away (b/37960096).
804 // Note: This will be unnecessary when stop() changes behavior and releases codec (b/35248283).
805 if (!mStarted && mIsDrmReleased) {
806 return -EWOULDBLOCK;
807 }
808
Andreas Huberafed0e12011-09-20 15:39:58 -0700809 Track *track = audio ? &mAudioTrack : &mVideoTrack;
810
811 if (track->mSource == NULL) {
812 return -EWOULDBLOCK;
813 }
814
815 status_t finalResult;
816 if (!track->mPackets->hasBufferAvailable(&finalResult)) {
Chong Zhang42e81532014-12-01 13:44:26 -0800817 if (finalResult == OK) {
818 postReadBuffer(
819 audio ? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
820 return -EWOULDBLOCK;
821 }
822 return finalResult;
Andreas Huberafed0e12011-09-20 15:39:58 -0700823 }
824
825 status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
826
Wei Jia542a81a2017-10-16 10:31:29 -0700827 // start pulling in more buffers if cache is running low
Chong Zhangfcf044a2015-07-14 15:58:51 -0700828 // so that decoder has less chance of being starved
Wei Jia542a81a2017-10-16 10:31:29 -0700829 if (!mIsStreaming) {
830 if (track->mPackets->getAvailableBufferCount(&finalResult) < 2) {
831 postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
832 }
833 } else {
834 int64_t durationUs = track->mPackets->getBufferedDurationUs(&finalResult);
Wei Jia9bb38032017-03-23 18:00:38 -0700835 // TODO: maxRebufferingMarkMs could be larger than
836 // mBufferingSettings.mResumePlaybackMarkMs
Wei Jia542a81a2017-10-16 10:31:29 -0700837 int64_t restartBufferingMarkUs =
Wei Jia9bb38032017-03-23 18:00:38 -0700838 mBufferingSettings.mResumePlaybackMarkMs * 1000ll / 2;
Wei Jia542a81a2017-10-16 10:31:29 -0700839 if (finalResult == OK) {
840 if (durationUs < restartBufferingMarkUs) {
841 postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
842 }
843 if (track->mPackets->getAvailableBufferCount(&finalResult) < 2
844 && !mSentPauseOnBuffering && !mPreparing) {
845 mCachedSource->resumeFetchingIfNecessary();
846 sendCacheStats();
847 mSentPauseOnBuffering = true;
848 sp<AMessage> notify = dupNotify();
849 notify->setInt32("what", kWhatPauseOnBufferingStart);
850 notify->post();
851 }
852 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700853 }
854
Robert Shih3423bbd2014-07-16 15:47:09 -0700855 if (result != OK) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700856 if (mSubtitleTrack.mSource != NULL) {
857 mSubtitleTrack.mPackets->clear();
858 mFetchSubtitleDataGeneration++;
859 }
860 if (mTimedTextTrack.mSource != NULL) {
861 mTimedTextTrack.mPackets->clear();
862 mFetchTimedTextDataGeneration++;
863 }
Robert Shih3423bbd2014-07-16 15:47:09 -0700864 return result;
865 }
866
867 int64_t timeUs;
868 status_t eosResult; // ignored
869 CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
Robert Shih5c67ddc2014-11-04 17:46:05 -0800870 if (audio) {
871 mAudioLastDequeueTimeUs = timeUs;
872 } else {
873 mVideoLastDequeueTimeUs = timeUs;
874 }
Lajos Molnare26940f2014-07-31 10:31:26 -0700875
876 if (mSubtitleTrack.mSource != NULL
877 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800878 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
Robert Shih3423bbd2014-07-16 15:47:09 -0700879 msg->setInt64("timeUs", timeUs);
880 msg->setInt32("generation", mFetchSubtitleDataGeneration);
881 msg->post();
882 }
Robert Shiheb1735e2014-07-23 15:53:14 -0700883
Lajos Molnare26940f2014-07-31 10:31:26 -0700884 if (mTimedTextTrack.mSource != NULL
885 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800886 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
Lajos Molnare26940f2014-07-31 10:31:26 -0700887 msg->setInt64("timeUs", timeUs);
888 msg->setInt32("generation", mFetchTimedTextDataGeneration);
889 msg->post();
890 }
891
Andreas Huberafed0e12011-09-20 15:39:58 -0700892 return result;
893}
894
895status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
Wei Jia542a81a2017-10-16 10:31:29 -0700896 Mutex::Autolock _l(mLock);
Andreas Huberafed0e12011-09-20 15:39:58 -0700897 *durationUs = mDurationUs;
898 return OK;
899}
900
Robert Shihdd235722014-06-12 14:49:23 -0700901size_t NuPlayer::GenericSource::getTrackCount() const {
Wei Jia542a81a2017-10-16 10:31:29 -0700902 Mutex::Autolock _l(mLock);
Robert Shihdd235722014-06-12 14:49:23 -0700903 return mSources.size();
904}
905
906sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const {
Wei Jia542a81a2017-10-16 10:31:29 -0700907 Mutex::Autolock _l(mLock);
Robert Shihdd235722014-06-12 14:49:23 -0700908 size_t trackCount = mSources.size();
909 if (trackIndex >= trackCount) {
910 return NULL;
911 }
912
913 sp<AMessage> format = new AMessage();
914 sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat();
Marco Nelissenc367ca12015-09-15 09:51:59 -0700915 if (meta == NULL) {
916 ALOGE("no metadata for track %zu", trackIndex);
917 return NULL;
918 }
Robert Shihdd235722014-06-12 14:49:23 -0700919
920 const char *mime;
921 CHECK(meta->findCString(kKeyMIMEType, &mime));
Robert Shih755106e2015-04-30 14:36:45 -0700922 format->setString("mime", mime);
Robert Shihdd235722014-06-12 14:49:23 -0700923
924 int32_t trackType;
925 if (!strncasecmp(mime, "video/", 6)) {
926 trackType = MEDIA_TRACK_TYPE_VIDEO;
927 } else if (!strncasecmp(mime, "audio/", 6)) {
928 trackType = MEDIA_TRACK_TYPE_AUDIO;
929 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
930 trackType = MEDIA_TRACK_TYPE_TIMEDTEXT;
931 } else {
932 trackType = MEDIA_TRACK_TYPE_UNKNOWN;
933 }
934 format->setInt32("type", trackType);
935
936 const char *lang;
937 if (!meta->findCString(kKeyMediaLanguage, &lang)) {
938 lang = "und";
939 }
940 format->setString("language", lang);
941
942 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
Robert Shihdd235722014-06-12 14:49:23 -0700943 int32_t isAutoselect = 1, isDefault = 0, isForced = 0;
944 meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect);
945 meta->findInt32(kKeyTrackIsDefault, &isDefault);
946 meta->findInt32(kKeyTrackIsForced, &isForced);
947
948 format->setInt32("auto", !!isAutoselect);
949 format->setInt32("default", !!isDefault);
950 format->setInt32("forced", !!isForced);
951 }
952
953 return format;
954}
955
Lajos Molnare26940f2014-07-31 10:31:26 -0700956ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const {
Wei Jia542a81a2017-10-16 10:31:29 -0700957 Mutex::Autolock _l(mLock);
Lajos Molnare26940f2014-07-31 10:31:26 -0700958 const Track *track = NULL;
959 switch (type) {
960 case MEDIA_TRACK_TYPE_VIDEO:
961 track = &mVideoTrack;
962 break;
963 case MEDIA_TRACK_TYPE_AUDIO:
964 track = &mAudioTrack;
965 break;
966 case MEDIA_TRACK_TYPE_TIMEDTEXT:
967 track = &mTimedTextTrack;
968 break;
969 case MEDIA_TRACK_TYPE_SUBTITLE:
970 track = &mSubtitleTrack;
971 break;
972 default:
973 break;
974 }
975
976 if (track != NULL && track->mSource != NULL) {
977 return track->mIndex;
978 }
979
980 return -1;
981}
982
Robert Shih6ffb1fd2014-10-29 16:24:32 -0700983status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
Wei Jia542a81a2017-10-16 10:31:29 -0700984 Mutex::Autolock _l(mLock);
Lajos Molnare26940f2014-07-31 10:31:26 -0700985 ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
Robert Shih17f6dd62014-08-20 17:00:21 -0700986
Robert Shih3423bbd2014-07-16 15:47:09 -0700987 if (trackIndex >= mSources.size()) {
988 return BAD_INDEX;
989 }
990
991 if (!select) {
Lajos Molnare26940f2014-07-31 10:31:26 -0700992 Track* track = NULL;
993 if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) {
994 track = &mSubtitleTrack;
995 mFetchSubtitleDataGeneration++;
996 } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) {
997 track = &mTimedTextTrack;
998 mFetchTimedTextDataGeneration++;
999 }
1000 if (track == NULL) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001001 return INVALID_OPERATION;
1002 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001003 track->mSource->stop();
1004 track->mSource = NULL;
1005 track->mPackets->clear();
Robert Shih3423bbd2014-07-16 15:47:09 -07001006 return OK;
1007 }
1008
Marco Nelissenb2487f02015-09-01 13:23:23 -07001009 const sp<IMediaSource> source = mSources.itemAt(trackIndex);
Robert Shih3423bbd2014-07-16 15:47:09 -07001010 sp<MetaData> meta = source->getFormat();
1011 const char *mime;
1012 CHECK(meta->findCString(kKeyMIMEType, &mime));
1013 if (!strncasecmp(mime, "text/", 5)) {
Lajos Molnare26940f2014-07-31 10:31:26 -07001014 bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP);
1015 Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack;
1016 if (track->mSource != NULL && track->mIndex == trackIndex) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001017 return OK;
1018 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001019 track->mIndex = trackIndex;
1020 if (track->mSource != NULL) {
1021 track->mSource->stop();
Robert Shih3423bbd2014-07-16 15:47:09 -07001022 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001023 track->mSource = mSources.itemAt(trackIndex);
1024 track->mSource->start();
1025 if (track->mPackets == NULL) {
1026 track->mPackets = new AnotherPacketSource(track->mSource->getFormat());
Robert Shih3423bbd2014-07-16 15:47:09 -07001027 } else {
Lajos Molnare26940f2014-07-31 10:31:26 -07001028 track->mPackets->clear();
1029 track->mPackets->setFormat(track->mSource->getFormat());
Robert Shih3423bbd2014-07-16 15:47:09 -07001030
1031 }
Lajos Molnare26940f2014-07-31 10:31:26 -07001032
1033 if (isSubtitle) {
1034 mFetchSubtitleDataGeneration++;
1035 } else {
1036 mFetchTimedTextDataGeneration++;
1037 }
1038
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001039 status_t eosResult; // ignored
1040 if (mSubtitleTrack.mSource != NULL
1041 && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001042 sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001043 msg->setInt64("timeUs", timeUs);
1044 msg->setInt32("generation", mFetchSubtitleDataGeneration);
1045 msg->post();
1046 }
1047
Marco Nelissen55e2f4c2015-09-04 15:57:15 -07001048 sp<AMessage> msg2 = new AMessage(kWhatSendGlobalTimedTextData, this);
1049 msg2->setInt32("generation", mFetchTimedTextDataGeneration);
1050 msg2->post();
1051
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001052 if (mTimedTextTrack.mSource != NULL
1053 && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001054 sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001055 msg->setInt64("timeUs", timeUs);
1056 msg->setInt32("generation", mFetchTimedTextDataGeneration);
1057 msg->post();
1058 }
1059
Robert Shih3423bbd2014-07-16 15:47:09 -07001060 return OK;
1061 } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
1062 bool audio = !strncasecmp(mime, "audio/", 6);
1063 Track *track = audio ? &mAudioTrack : &mVideoTrack;
1064 if (track->mSource != NULL && track->mIndex == trackIndex) {
1065 return OK;
1066 }
1067
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001068 sp<AMessage> msg = new AMessage(kWhatChangeAVSource, this);
Robert Shih3423bbd2014-07-16 15:47:09 -07001069 msg->setInt32("trackIndex", trackIndex);
1070 msg->post();
1071 return OK;
1072 }
1073
1074 return INVALID_OPERATION;
1075}
1076
Wei Jiac5de0912016-11-18 10:22:14 -08001077status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
Wei Jia542a81a2017-10-16 10:31:29 -07001078 ALOGV("seekTo: %lld, %d", (long long)seekTimeUs, mode);
Wei Jiac899fc02017-11-15 17:28:53 -08001079 sp<AMessage> msg = new AMessage(kWhatSeek, this);
1080 msg->setInt64("seekTimeUs", seekTimeUs);
1081 msg->setInt32("mode", mode);
1082
1083 // Need to call readBuffer on |mLooper| to ensure the calls to
1084 // IMediaSource::read* are serialized. Note that IMediaSource::read*
1085 // is called without |mLock| acquired and MediaSource is not thread safe.
1086 sp<AMessage> response;
1087 status_t err = msg->postAndAwaitResponse(&response);
1088 if (err == OK && response != NULL) {
1089 CHECK(response->findInt32("err", &err));
1090 }
1091
1092 return err;
1093}
1094
1095void NuPlayer::GenericSource::onSeek(const sp<AMessage>& msg) {
1096 int64_t seekTimeUs;
1097 int32_t mode;
1098 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
1099 CHECK(msg->findInt32("mode", &mode));
1100
1101 sp<AMessage> response = new AMessage;
1102 status_t err = doSeek(seekTimeUs, (MediaPlayerSeekMode)mode);
1103 response->setInt32("err", err);
1104
1105 sp<AReplyToken> replyID;
1106 CHECK(msg->senderAwaitsResponse(&replyID));
1107 response->postReply(replyID);
1108}
1109
1110status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
Andreas Huberafed0e12011-09-20 15:39:58 -07001111 if (mVideoTrack.mSource != NULL) {
Wei Jia542a81a2017-10-16 10:31:29 -07001112 ++mVideoDataGeneration;
1113
Andreas Huberafed0e12011-09-20 15:39:58 -07001114 int64_t actualTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -08001115 readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, mode, &actualTimeUs);
Andreas Huberafed0e12011-09-20 15:39:58 -07001116
Wei Jiac5de0912016-11-18 10:22:14 -08001117 if (mode != MediaPlayerSeekMode::SEEK_CLOSEST) {
Wei Jia5ec347f2016-11-01 17:07:54 -07001118 seekTimeUs = actualTimeUs;
1119 }
1120 mVideoLastDequeueTimeUs = actualTimeUs;
Andreas Huberafed0e12011-09-20 15:39:58 -07001121 }
1122
1123 if (mAudioTrack.mSource != NULL) {
Wei Jia542a81a2017-10-16 10:31:29 -07001124 ++mAudioDataGeneration;
Wei Jiaaec8d822017-08-25 15:27:57 -07001125 readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs, MediaPlayerSeekMode::SEEK_CLOSEST);
Robert Shih5c67ddc2014-11-04 17:46:05 -08001126 mAudioLastDequeueTimeUs = seekTimeUs;
Andreas Huberafed0e12011-09-20 15:39:58 -07001127 }
1128
Robert Shih40296722017-07-31 16:44:39 -07001129 if (mSubtitleTrack.mSource != NULL) {
1130 mSubtitleTrack.mPackets->clear();
1131 mFetchSubtitleDataGeneration++;
1132 }
1133
1134 if (mTimedTextTrack.mSource != NULL) {
1135 mTimedTextTrack.mPackets->clear();
1136 mFetchTimedTextDataGeneration++;
1137 }
1138
Wei Jia542a81a2017-10-16 10:31:29 -07001139 ++mPollBufferingGeneration;
1140 schedulePollBuffering();
Andreas Huberafed0e12011-09-20 15:39:58 -07001141 return OK;
1142}
1143
Robert Shih3423bbd2014-07-16 15:47:09 -07001144sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
1145 MediaBuffer* mb,
Wei Jia14486822016-11-02 17:51:30 -07001146 media_track_type trackType) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001147 bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
1148 size_t outLength = mb->range_length();
1149
1150 if (audio && mAudioIsVorbis) {
1151 outLength += sizeof(int32_t);
1152 }
1153
1154 sp<ABuffer> ab;
Hassan Shojaniacefac142017-02-06 21:02:02 -08001155
1156 if (mIsDrmProtected) {
1157 // Modular DRM
1158 // Enabled for both video/audio so 1) media buffer is reused without extra copying
1159 // 2) meta data can be retrieved in onInputBufferFetched for calling queueSecureInputBuffer.
1160
Robert Shih3423bbd2014-07-16 15:47:09 -07001161 // data is already provided in the buffer
1162 ab = new ABuffer(NULL, mb->range_length());
Dongwon Kang4b780702018-01-25 11:21:26 -08001163 mb->add_ref();
1164 ab->setMediaBufferBase(mb);
Hassan Shojaniacefac142017-02-06 21:02:02 -08001165
1166 // Modular DRM: Required b/c of the above add_ref.
1167 // If ref>0, there must be an observer, or it'll crash at release().
1168 // TODO: MediaBuffer might need to be revised to ease such need.
1169 mb->setObserver(this);
Dongwon Kang4b780702018-01-25 11:21:26 -08001170 // setMediaBufferBase() interestingly doesn't increment the ref count on its own.
Hassan Shojaniacefac142017-02-06 21:02:02 -08001171 // Extra increment (since we want to keep mb alive and attached to ab beyond this function
1172 // call. This is to counter the effect of mb->release() towards the end.
1173 mb->add_ref();
1174
Robert Shih3423bbd2014-07-16 15:47:09 -07001175 } else {
1176 ab = new ABuffer(outLength);
1177 memcpy(ab->data(),
1178 (const uint8_t *)mb->data() + mb->range_offset(),
1179 mb->range_length());
1180 }
1181
1182 if (audio && mAudioIsVorbis) {
1183 int32_t numPageSamples;
1184 if (!mb->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
1185 numPageSamples = -1;
1186 }
1187
1188 uint8_t* abEnd = ab->data() + mb->range_length();
1189 memcpy(abEnd, &numPageSamples, sizeof(numPageSamples));
1190 }
1191
Lajos Molnare26940f2014-07-31 10:31:26 -07001192 sp<AMessage> meta = ab->meta();
1193
Robert Shih3423bbd2014-07-16 15:47:09 -07001194 int64_t timeUs;
1195 CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs));
Robert Shih3423bbd2014-07-16 15:47:09 -07001196 meta->setInt64("timeUs", timeUs);
1197
Praveen Chavanbbaa1442016-04-08 13:33:49 -07001198 if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
1199 int32_t layerId;
1200 if (mb->meta_data()->findInt32(kKeyTemporalLayerId, &layerId)) {
1201 meta->setInt32("temporal-layer-id", layerId);
1202 }
1203 }
1204
Lajos Molnare26940f2014-07-31 10:31:26 -07001205 if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
1206 const char *mime;
1207 CHECK(mTimedTextTrack.mSource != NULL
1208 && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime));
1209 meta->setString("mime", mime);
1210 }
1211
Robert Shih3423bbd2014-07-16 15:47:09 -07001212 int64_t durationUs;
1213 if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) {
1214 meta->setInt64("durationUs", durationUs);
1215 }
1216
1217 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
1218 meta->setInt32("trackIndex", mSubtitleTrack.mIndex);
1219 }
1220
Robert Shihf8bd8512015-04-23 16:39:18 -07001221 uint32_t dataType; // unused
1222 const void *seiData;
1223 size_t seiLength;
1224 if (mb->meta_data()->findData(kKeySEI, &dataType, &seiData, &seiLength)) {
1225 sp<ABuffer> sei = ABuffer::CreateAsCopy(seiData, seiLength);;
1226 meta->setBuffer("sei", sei);
1227 }
1228
Jaesung Chung3694d7c2015-10-21 11:41:38 +09001229 const void *mpegUserDataPointer;
1230 size_t mpegUserDataLength;
1231 if (mb->meta_data()->findData(
1232 kKeyMpegUserData, &dataType, &mpegUserDataPointer, &mpegUserDataLength)) {
1233 sp<ABuffer> mpegUserData = ABuffer::CreateAsCopy(mpegUserDataPointer, mpegUserDataLength);
1234 meta->setBuffer("mpegUserData", mpegUserData);
1235 }
1236
Robert Shih3423bbd2014-07-16 15:47:09 -07001237 mb->release();
1238 mb = NULL;
1239
1240 return ab;
1241}
1242
Wei Jia542a81a2017-10-16 10:31:29 -07001243int32_t NuPlayer::GenericSource::getDataGeneration(media_track_type type) const {
1244 int32_t generation = -1;
1245 switch (type) {
1246 case MEDIA_TRACK_TYPE_VIDEO:
1247 generation = mVideoDataGeneration;
1248 break;
1249 case MEDIA_TRACK_TYPE_AUDIO:
1250 generation = mAudioDataGeneration;
1251 break;
1252 case MEDIA_TRACK_TYPE_TIMEDTEXT:
1253 generation = mFetchTimedTextDataGeneration;
1254 break;
1255 case MEDIA_TRACK_TYPE_SUBTITLE:
1256 generation = mFetchSubtitleDataGeneration;
1257 break;
1258 default:
1259 break;
1260 }
Lajos Molnar84f52782014-09-11 10:01:55 -07001261
Wei Jia542a81a2017-10-16 10:31:29 -07001262 return generation;
1263}
1264
1265void NuPlayer::GenericSource::postReadBuffer(media_track_type trackType) {
Lajos Molnar84f52782014-09-11 10:01:55 -07001266 if ((mPendingReadBufferTypes & (1 << trackType)) == 0) {
1267 mPendingReadBufferTypes |= (1 << trackType);
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001268 sp<AMessage> msg = new AMessage(kWhatReadBuffer, this);
Lajos Molnar84f52782014-09-11 10:01:55 -07001269 msg->setInt32("trackType", trackType);
1270 msg->post();
1271 }
Robert Shih17f6dd62014-08-20 17:00:21 -07001272}
1273
Chih-Hung Hsiehe964d4e2016-08-09 14:31:32 -07001274void NuPlayer::GenericSource::onReadBuffer(const sp<AMessage>& msg) {
Robert Shih17f6dd62014-08-20 17:00:21 -07001275 int32_t tmpType;
1276 CHECK(msg->findInt32("trackType", &tmpType));
1277 media_track_type trackType = (media_track_type)tmpType;
Wei Jia542a81a2017-10-16 10:31:29 -07001278 mPendingReadBufferTypes &= ~(1 << trackType);
Chong Zhang42e81532014-12-01 13:44:26 -08001279 readBuffer(trackType);
Robert Shih17f6dd62014-08-20 17:00:21 -07001280}
1281
Andreas Huberafed0e12011-09-20 15:39:58 -07001282void NuPlayer::GenericSource::readBuffer(
Wei Jiac5de0912016-11-18 10:22:14 -08001283 media_track_type trackType, int64_t seekTimeUs, MediaPlayerSeekMode mode,
Wei Jia5ec347f2016-11-01 17:07:54 -07001284 int64_t *actualTimeUs, bool formatChange) {
Robert Shih3423bbd2014-07-16 15:47:09 -07001285 Track *track;
Phil Burkc5cc2e22014-09-09 20:08:39 -07001286 size_t maxBuffers = 1;
Robert Shih3423bbd2014-07-16 15:47:09 -07001287 switch (trackType) {
1288 case MEDIA_TRACK_TYPE_VIDEO:
1289 track = &mVideoTrack;
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001290 maxBuffers = 8; // too large of a number may influence seeks
Robert Shih3423bbd2014-07-16 15:47:09 -07001291 break;
1292 case MEDIA_TRACK_TYPE_AUDIO:
1293 track = &mAudioTrack;
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001294 maxBuffers = 64;
Robert Shih3423bbd2014-07-16 15:47:09 -07001295 break;
1296 case MEDIA_TRACK_TYPE_SUBTITLE:
1297 track = &mSubtitleTrack;
1298 break;
Lajos Molnare26940f2014-07-31 10:31:26 -07001299 case MEDIA_TRACK_TYPE_TIMEDTEXT:
1300 track = &mTimedTextTrack;
1301 break;
Robert Shih3423bbd2014-07-16 15:47:09 -07001302 default:
1303 TRESPASS();
1304 }
1305
1306 if (track->mSource == NULL) {
1307 return;
1308 }
Andreas Huberafed0e12011-09-20 15:39:58 -07001309
1310 if (actualTimeUs) {
1311 *actualTimeUs = seekTimeUs;
1312 }
1313
1314 MediaSource::ReadOptions options;
1315
1316 bool seeking = false;
Andreas Huberafed0e12011-09-20 15:39:58 -07001317 if (seekTimeUs >= 0) {
Wei Jiac5de0912016-11-18 10:22:14 -08001318 options.setSeekTo(seekTimeUs, mode);
Andreas Huberafed0e12011-09-20 15:39:58 -07001319 seeking = true;
1320 }
1321
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001322 const bool couldReadMultiple = (track->mSource->supportReadMultiple());
Andy Hungcdeb6602016-06-28 17:21:44 -07001323
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001324 if (couldReadMultiple) {
Lajos Molnarcc227032014-07-17 15:33:06 -07001325 options.setNonBlocking();
1326 }
1327
Wei Jia542a81a2017-10-16 10:31:29 -07001328 int32_t generation = getDataGeneration(trackType);
Phil Burkc5cc2e22014-09-09 20:08:39 -07001329 for (size_t numBuffers = 0; numBuffers < maxBuffers; ) {
Wei Jia1f1fc452016-05-11 16:17:22 -07001330 Vector<MediaBuffer *> mediaBuffers;
1331 status_t err = NO_ERROR;
1332
Wei Jiac899fc02017-11-15 17:28:53 -08001333 sp<IMediaSource> source = track->mSource;
Wei Jia542a81a2017-10-16 10:31:29 -07001334 mLock.unlock();
Andy Hungcdeb6602016-06-28 17:21:44 -07001335 if (couldReadMultiple) {
Wei Jiac899fc02017-11-15 17:28:53 -08001336 err = source->readMultiple(
Andy Hungcdeb6602016-06-28 17:21:44 -07001337 &mediaBuffers, maxBuffers - numBuffers, &options);
Wei Jia1f1fc452016-05-11 16:17:22 -07001338 } else {
1339 MediaBuffer *mbuf = NULL;
Wei Jiac899fc02017-11-15 17:28:53 -08001340 err = source->read(&mbuf, &options);
Wei Jia1f1fc452016-05-11 16:17:22 -07001341 if (err == OK && mbuf != NULL) {
1342 mediaBuffers.push_back(mbuf);
1343 }
1344 }
Wei Jia542a81a2017-10-16 10:31:29 -07001345 mLock.lock();
Andreas Huberafed0e12011-09-20 15:39:58 -07001346
Andy Hungf59c0ba2016-06-15 17:59:30 -07001347 options.clearNonPersistent();
Andreas Huberafed0e12011-09-20 15:39:58 -07001348
Wei Jia1f1fc452016-05-11 16:17:22 -07001349 size_t id = 0;
1350 size_t count = mediaBuffers.size();
Wei Jia542a81a2017-10-16 10:31:29 -07001351
1352 // in case track has been changed since we don't have lock for some time.
1353 if (generation != getDataGeneration(trackType)) {
1354 for (; id < count; ++id) {
1355 mediaBuffers[id]->release();
1356 }
1357 break;
1358 }
1359
Wei Jia1f1fc452016-05-11 16:17:22 -07001360 for (; id < count; ++id) {
Ronghua Wu80276872014-08-28 15:50:29 -07001361 int64_t timeUs;
Wei Jia1f1fc452016-05-11 16:17:22 -07001362 MediaBuffer *mbuf = mediaBuffers[id];
Robert Shih3b9912b2016-04-07 16:56:54 -07001363 if (!mbuf->meta_data()->findInt64(kKeyTime, &timeUs)) {
1364 mbuf->meta_data()->dumpToLog();
1365 track->mPackets->signalEOS(ERROR_MALFORMED);
1366 break;
1367 }
Ronghua Wu80276872014-08-28 15:50:29 -07001368 if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
1369 mAudioTimeUs = timeUs;
1370 } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
1371 mVideoTimeUs = timeUs;
1372 }
1373
Ronghua Wu8f291bc2015-05-19 10:11:53 -07001374 queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
Andreas Huberafed0e12011-09-20 15:39:58 -07001375
Wei Jia14486822016-11-02 17:51:30 -07001376 sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType);
1377 if (numBuffers == 0 && actualTimeUs != nullptr) {
1378 *actualTimeUs = timeUs;
1379 }
1380 if (seeking && buffer != nullptr) {
1381 sp<AMessage> meta = buffer->meta();
Wei Jiac5de0912016-11-18 10:22:14 -08001382 if (meta != nullptr && mode == MediaPlayerSeekMode::SEEK_CLOSEST
1383 && seekTimeUs > timeUs) {
Wei Jia14486822016-11-02 17:51:30 -07001384 sp<AMessage> extra = new AMessage;
1385 extra->setInt64("resume-at-mediaTimeUs", seekTimeUs);
1386 meta->setMessage("extra", extra);
1387 }
1388 }
1389
Andreas Huberafed0e12011-09-20 15:39:58 -07001390 track->mPackets->queueAccessUnit(buffer);
Marco Nelissen317a49a2014-09-16 21:32:33 -07001391 formatChange = false;
1392 seeking = false;
Phil Burkc5cc2e22014-09-09 20:08:39 -07001393 ++numBuffers;
Wei Jia1f1fc452016-05-11 16:17:22 -07001394 }
1395 if (id < count) {
1396 // Error, some mediaBuffer doesn't have kKeyTime.
1397 for (; id < count; ++id) {
1398 mediaBuffers[id]->release();
1399 }
1400 break;
1401 }
1402
1403 if (err == WOULD_BLOCK) {
Lajos Molnarcc227032014-07-17 15:33:06 -07001404 break;
Andreas Huberafed0e12011-09-20 15:39:58 -07001405 } else if (err == INFO_FORMAT_CHANGED) {
1406#if 0
1407 track->mPackets->queueDiscontinuity(
Chong Zhang632740c2014-06-26 13:03:47 -07001408 ATSParser::DISCONTINUITY_FORMATCHANGE,
1409 NULL,
1410 false /* discard */);
Andreas Huberafed0e12011-09-20 15:39:58 -07001411#endif
Wei Jia1f1fc452016-05-11 16:17:22 -07001412 } else if (err != OK) {
Ronghua Wu8f291bc2015-05-19 10:11:53 -07001413 queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
Andreas Huberafed0e12011-09-20 15:39:58 -07001414 track->mPackets->signalEOS(err);
1415 break;
1416 }
1417 }
Wei Jia542a81a2017-10-16 10:31:29 -07001418
1419 if (mIsStreaming
1420 && (trackType == MEDIA_TRACK_TYPE_VIDEO || trackType == MEDIA_TRACK_TYPE_AUDIO)) {
1421 status_t finalResult;
1422 int64_t durationUs = track->mPackets->getBufferedDurationUs(&finalResult);
1423
Wei Jia9bb38032017-03-23 18:00:38 -07001424 // TODO: maxRebufferingMarkMs could be larger than
1425 // mBufferingSettings.mResumePlaybackMarkMs
1426 int64_t markUs = (mPreparing ? mBufferingSettings.mInitialMarkMs
1427 : mBufferingSettings.mResumePlaybackMarkMs) * 1000ll;
Wei Jia542a81a2017-10-16 10:31:29 -07001428 if (finalResult == ERROR_END_OF_STREAM || durationUs >= markUs) {
1429 if (mPreparing || mSentPauseOnBuffering) {
1430 Track *counterTrack =
1431 (trackType == MEDIA_TRACK_TYPE_VIDEO ? &mAudioTrack : &mVideoTrack);
1432 if (counterTrack->mSource != NULL) {
1433 durationUs = counterTrack->mPackets->getBufferedDurationUs(&finalResult);
1434 }
1435 if (finalResult == ERROR_END_OF_STREAM || durationUs >= markUs) {
1436 if (mPreparing) {
1437 notifyPrepared();
1438 mPreparing = false;
1439 } else {
1440 sendCacheStats();
1441 mSentPauseOnBuffering = false;
1442 sp<AMessage> notify = dupNotify();
1443 notify->setInt32("what", kWhatResumeOnBufferingEnd);
1444 notify->post();
1445 }
1446 }
1447 }
1448 return;
1449 }
1450
1451 postReadBuffer(trackType);
1452 }
Andreas Huberafed0e12011-09-20 15:39:58 -07001453}
1454
Ronghua Wu8f291bc2015-05-19 10:11:53 -07001455void NuPlayer::GenericSource::queueDiscontinuityIfNeeded(
1456 bool seeking, bool formatChange, media_track_type trackType, Track *track) {
1457 // formatChange && seeking: track whose source is changed during selection
1458 // formatChange && !seeking: track whose source is not changed during selection
1459 // !formatChange: normal seek
1460 if ((seeking || formatChange)
1461 && (trackType == MEDIA_TRACK_TYPE_AUDIO
1462 || trackType == MEDIA_TRACK_TYPE_VIDEO)) {
1463 ATSParser::DiscontinuityType type = (formatChange && seeking)
1464 ? ATSParser::DISCONTINUITY_FORMATCHANGE
1465 : ATSParser::DISCONTINUITY_NONE;
1466 track->mPackets->queueDiscontinuity(type, NULL /* extra */, true /* discard */);
1467 }
1468}
1469
Wei Jia542a81a2017-10-16 10:31:29 -07001470void NuPlayer::GenericSource::notifyBufferingUpdate(int32_t percentage) {
Wei Jia14532f22015-12-29 11:28:15 -08001471 // Buffering percent could go backward as it's estimated from remaining
1472 // data and last access time. This could cause the buffering position
1473 // drawn on media control to jitter slightly. Remember previously reported
1474 // percentage and don't allow it to go backward.
1475 if (percentage < mPrevBufferPercentage) {
1476 percentage = mPrevBufferPercentage;
1477 } else if (percentage > 100) {
1478 percentage = 100;
1479 }
1480
1481 mPrevBufferPercentage = percentage;
1482
Wei Jia542a81a2017-10-16 10:31:29 -07001483 ALOGV("notifyBufferingUpdate: buffering %d%%", percentage);
Wei Jia14532f22015-12-29 11:28:15 -08001484
Wei Jia542a81a2017-10-16 10:31:29 -07001485 sp<AMessage> notify = dupNotify();
1486 notify->setInt32("what", kWhatBufferingUpdate);
1487 notify->setInt32("percentage", percentage);
1488 notify->post();
Wei Jia14532f22015-12-29 11:28:15 -08001489}
1490
Wei Jia542a81a2017-10-16 10:31:29 -07001491void NuPlayer::GenericSource::schedulePollBuffering() {
Wei Jia14532f22015-12-29 11:28:15 -08001492 sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
1493 msg->setInt32("generation", mPollBufferingGeneration);
1494 // Enquires buffering status every second.
1495 msg->post(1000000ll);
1496}
1497
Wei Jia542a81a2017-10-16 10:31:29 -07001498void NuPlayer::GenericSource::onPollBuffering() {
Wei Jia14532f22015-12-29 11:28:15 -08001499 status_t finalStatus = UNKNOWN_ERROR;
1500 int64_t cachedDurationUs = -1ll;
1501 ssize_t cachedDataRemaining = -1;
1502
Jeff Tinker29b7dcf2016-10-24 10:28:30 -07001503 if (mCachedSource != NULL) {
Wei Jia542a81a2017-10-16 10:31:29 -07001504 cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
Wei Jia14532f22015-12-29 11:28:15 -08001505
1506 if (finalStatus == OK) {
1507 off64_t size;
1508 int64_t bitrate = 0ll;
1509 if (mDurationUs > 0 && mCachedSource->getSize(&size) == OK) {
1510 // |bitrate| uses bits/second unit, while size is number of bytes.
1511 bitrate = size * 8000000ll / mDurationUs;
1512 } else if (mBitrate > 0) {
1513 bitrate = mBitrate;
1514 }
1515 if (bitrate > 0) {
1516 cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate;
1517 }
1518 }
1519 }
1520
1521 if (finalStatus != OK) {
Wei Jia542a81a2017-10-16 10:31:29 -07001522 ALOGV("onPollBuffering: EOS (finalStatus = %d)", finalStatus);
Wei Jia14532f22015-12-29 11:28:15 -08001523
1524 if (finalStatus == ERROR_END_OF_STREAM) {
Wei Jia542a81a2017-10-16 10:31:29 -07001525 notifyBufferingUpdate(100);
Wei Jia14532f22015-12-29 11:28:15 -08001526 }
1527
Wei Jia14532f22015-12-29 11:28:15 -08001528 return;
Wei Jia48fa06d2016-12-20 15:30:49 -08001529 }
1530
1531 if (cachedDurationUs >= 0ll) {
Wei Jia14532f22015-12-29 11:28:15 -08001532 if (mDurationUs > 0ll) {
Wei Jia542a81a2017-10-16 10:31:29 -07001533 int64_t cachedPosUs = getLastReadPosition() + cachedDurationUs;
Wei Jia14532f22015-12-29 11:28:15 -08001534 int percentage = 100.0 * cachedPosUs / mDurationUs;
1535 if (percentage > 100) {
1536 percentage = 100;
1537 }
1538
Wei Jia542a81a2017-10-16 10:31:29 -07001539 notifyBufferingUpdate(percentage);
Wei Jia14532f22015-12-29 11:28:15 -08001540 }
1541
Wei Jia542a81a2017-10-16 10:31:29 -07001542 ALOGV("onPollBuffering: cachedDurationUs %.1f sec", cachedDurationUs / 1000000.0f);
Wei Jia14532f22015-12-29 11:28:15 -08001543 }
1544
Wei Jia542a81a2017-10-16 10:31:29 -07001545 schedulePollBuffering();
Wei Jia14532f22015-12-29 11:28:15 -08001546}
1547
Hassan Shojaniacefac142017-02-06 21:02:02 -08001548// Modular DRM
1549status_t NuPlayer::GenericSource::prepareDrm(
Wei Jia542a81a2017-10-16 10:31:29 -07001550 const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId, sp<ICrypto> *outCrypto) {
1551 Mutex::Autolock _l(mLock);
Hassan Shojaniacefac142017-02-06 21:02:02 -08001552 ALOGV("prepareDrm");
1553
Hassan Shojaniacefac142017-02-06 21:02:02 -08001554 mIsDrmProtected = false;
Hassan Shojania355e8472017-05-12 10:33:16 -07001555 mIsDrmReleased = false;
Hassan Shojaniacefac142017-02-06 21:02:02 -08001556 mIsSecure = false;
1557
Hassan Shojaniacefac142017-02-06 21:02:02 -08001558 status_t status = OK;
Wei Jia542a81a2017-10-16 10:31:29 -07001559 sp<ICrypto> crypto = NuPlayerDrm::createCryptoAndPlugin(uuid, drmSessionId, status);
Hassan Shojaniacefac142017-02-06 21:02:02 -08001560 if (crypto == NULL) {
Wei Jia542a81a2017-10-16 10:31:29 -07001561 ALOGE("prepareDrm: createCrypto failed. status: %d", status);
Hassan Shojaniacefac142017-02-06 21:02:02 -08001562 return status;
1563 }
Wei Jia542a81a2017-10-16 10:31:29 -07001564 ALOGV("prepareDrm: createCryptoAndPlugin succeeded for uuid: %s",
Hassan Shojaniacefac142017-02-06 21:02:02 -08001565 DrmUUID::toHexString(uuid).string());
1566
1567 *outCrypto = crypto;
1568 // as long a there is an active crypto
1569 mIsDrmProtected = true;
1570
1571 if (mMimes.size() == 0) {
1572 status = UNKNOWN_ERROR;
Wei Jia542a81a2017-10-16 10:31:29 -07001573 ALOGE("prepareDrm: Unexpected. Must have at least one track. status: %d", status);
Hassan Shojaniacefac142017-02-06 21:02:02 -08001574 return status;
1575 }
1576
1577 // first mime in this list is either the video track, or the first audio track
1578 const char *mime = mMimes[0].string();
1579 mIsSecure = crypto->requiresSecureDecoderComponent(mime);
Wei Jia542a81a2017-10-16 10:31:29 -07001580 ALOGV("prepareDrm: requiresSecureDecoderComponent mime: %s isSecure: %d",
Hassan Shojaniacefac142017-02-06 21:02:02 -08001581 mime, mIsSecure);
1582
1583 // Checking the member flags while in the looper to send out the notification.
1584 // The legacy mDecryptHandle!=NULL check (for FLAG_PROTECTED) is equivalent to mIsDrmProtected.
1585 notifyFlagsChanged(
1586 (mIsSecure ? FLAG_SECURE : 0) |
Hassan Shojania838be392017-05-23 14:14:24 -07001587 // Setting "protected screen" only for L1: b/38390836
1588 (mIsSecure ? FLAG_PROTECTED : 0) |
Hassan Shojaniacefac142017-02-06 21:02:02 -08001589 FLAG_CAN_PAUSE |
1590 FLAG_CAN_SEEK_BACKWARD |
1591 FLAG_CAN_SEEK_FORWARD |
1592 FLAG_CAN_SEEK);
1593
Wei Jia542a81a2017-10-16 10:31:29 -07001594 if (status == OK) {
1595 ALOGV("prepareDrm: mCrypto: %p (%d)", outCrypto->get(),
1596 (*outCrypto != NULL ? (*outCrypto)->getStrongCount() : 0));
1597 ALOGD("prepareDrm ret: %d ", status);
1598 } else {
1599 ALOGE("prepareDrm err: %d", status);
1600 }
Hassan Shojaniacefac142017-02-06 21:02:02 -08001601 return status;
1602}
1603
Wei Jia542a81a2017-10-16 10:31:29 -07001604status_t NuPlayer::GenericSource::releaseDrm() {
1605 Mutex::Autolock _l(mLock);
1606 ALOGV("releaseDrm");
1607
Hassan Shojania355e8472017-05-12 10:33:16 -07001608 if (mIsDrmProtected) {
1609 mIsDrmProtected = false;
1610 // to prevent returning any more buffer after stop/releaseDrm (b/37960096)
1611 mIsDrmReleased = true;
Wei Jia542a81a2017-10-16 10:31:29 -07001612 ALOGV("releaseDrm: mIsDrmProtected is reset.");
Hassan Shojania355e8472017-05-12 10:33:16 -07001613 } else {
Wei Jia542a81a2017-10-16 10:31:29 -07001614 ALOGE("releaseDrm: mIsDrmProtected is already false.");
Hassan Shojania355e8472017-05-12 10:33:16 -07001615 }
1616
1617 return OK;
1618}
1619
Hassan Shojaniacefac142017-02-06 21:02:02 -08001620status_t NuPlayer::GenericSource::checkDrmInfo()
1621{
Hassan Shojania355e8472017-05-12 10:33:16 -07001622 // clearing the flag at prepare in case the player is reused after stop/releaseDrm with the
1623 // same source without being reset (called by prepareAsync/initFromDataSource)
1624 mIsDrmReleased = false;
1625
Hassan Shojaniacefac142017-02-06 21:02:02 -08001626 if (mFileMeta == NULL) {
Hassan Shojaniae7a1f6c2017-03-14 09:24:28 -07001627 ALOGI("checkDrmInfo: No metadata");
Hassan Shojaniacefac142017-02-06 21:02:02 -08001628 return OK; // letting the caller responds accordingly
1629 }
1630
1631 uint32_t type;
1632 const void *pssh;
1633 size_t psshsize;
1634
1635 if (!mFileMeta->findData(kKeyPssh, &type, &pssh, &psshsize)) {
Hassan Shojaniadd4ce182017-04-20 15:25:39 -07001636 ALOGV("checkDrmInfo: No PSSH");
Hassan Shojaniacefac142017-02-06 21:02:02 -08001637 return OK; // source without DRM info
1638 }
1639
1640 Parcel parcel;
Hassan Shojaniadd4ce182017-04-20 15:25:39 -07001641 NuPlayerDrm::retrieveDrmInfo(pssh, psshsize, &parcel);
Hassan Shojaniacefac142017-02-06 21:02:02 -08001642 ALOGV("checkDrmInfo: MEDIA_DRM_INFO PSSH size: %d Parcel size: %d objects#: %d",
Hassan Shojania06a70812017-02-15 21:57:45 -08001643 (int)psshsize, (int)parcel.dataSize(), (int)parcel.objectsCount());
Hassan Shojaniacefac142017-02-06 21:02:02 -08001644
1645 if (parcel.dataSize() == 0) {
1646 ALOGE("checkDrmInfo: Unexpected parcel size: 0");
1647 return UNKNOWN_ERROR;
1648 }
1649
1650 // Can't pass parcel as a message to the player. Converting Parcel->ABuffer to pass it
1651 // to the Player's onSourceNotify then back to Parcel for calling driver's notifyListener.
1652 sp<ABuffer> drmInfoBuffer = ABuffer::CreateAsCopy(parcel.data(), parcel.dataSize());
1653 notifyDrmInfo(drmInfoBuffer);
1654
1655 return OK;
1656}
1657
1658void NuPlayer::GenericSource::signalBufferReturned(MediaBuffer *buffer)
1659{
1660 //ALOGV("signalBufferReturned %p refCount: %d", buffer, buffer->localRefcount());
1661
1662 buffer->setObserver(NULL);
1663 buffer->release(); // this leads to delete since that there is no observor
1664}
1665
Andreas Huberafed0e12011-09-20 15:39:58 -07001666} // namespace android