1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2012 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "GenericSource"
19*ec779b8eSAndroid Build Coastguard Worker
20*ec779b8eSAndroid Build Coastguard Worker #include "GenericSource.h"
21*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayerDrm.h"
22*ec779b8eSAndroid Build Coastguard Worker
23*ec779b8eSAndroid Build Coastguard Worker #include <binder/IServiceManager.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <cutils/properties.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <datasource/PlayerServiceDataSourceFactory.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <datasource/PlayerServiceFileSource.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <datasource/HTTPBase.h>
28*ec779b8eSAndroid Build Coastguard Worker #include <datasource/NuCachedSource2.h>
29*ec779b8eSAndroid Build Coastguard Worker #include <media/DataSource.h>
30*ec779b8eSAndroid Build Coastguard Worker #include <media/MediaBufferHolder.h>
31*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaSource.h>
32*ec779b8eSAndroid Build Coastguard Worker #include <android/IMediaExtractorService.h>
33*ec779b8eSAndroid Build Coastguard Worker #include <media/IMediaHTTPService.h>
34*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ABuffer.h>
35*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
36*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/AMessage.h>
37*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/InterfaceUtils.h>
38*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/FoundationUtils.h>
39*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaBuffer.h>
40*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaClock.h>
41*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaDefs.h>
42*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaExtractor.h>
43*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaExtractorFactory.h>
44*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MetaData.h>
45*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/Utils.h>
46*ec779b8eSAndroid Build Coastguard Worker #include <mpeg2ts/AnotherPacketSource.h>
47*ec779b8eSAndroid Build Coastguard Worker
48*ec779b8eSAndroid Build Coastguard Worker namespace android {
49*ec779b8eSAndroid Build Coastguard Worker
50*ec779b8eSAndroid Build Coastguard Worker static const int kInitialMarkMs = 5000; // 5secs
51*ec779b8eSAndroid Build Coastguard Worker
52*ec779b8eSAndroid Build Coastguard Worker //static const int kPausePlaybackMarkMs = 2000; // 2secs
53*ec779b8eSAndroid Build Coastguard Worker static const int kResumePlaybackMarkMs = 15000; // 15secs
54*ec779b8eSAndroid Build Coastguard Worker
GenericSource(const sp<AMessage> & notify,bool uidValid,uid_t uid,const sp<MediaClock> & mediaClock)55*ec779b8eSAndroid Build Coastguard Worker NuPlayer::GenericSource::GenericSource(
56*ec779b8eSAndroid Build Coastguard Worker const sp<AMessage> ¬ify,
57*ec779b8eSAndroid Build Coastguard Worker bool uidValid,
58*ec779b8eSAndroid Build Coastguard Worker uid_t uid,
59*ec779b8eSAndroid Build Coastguard Worker const sp<MediaClock> &mediaClock)
60*ec779b8eSAndroid Build Coastguard Worker : Source(notify),
61*ec779b8eSAndroid Build Coastguard Worker mAudioTimeUs(0),
62*ec779b8eSAndroid Build Coastguard Worker mAudioLastDequeueTimeUs(0),
63*ec779b8eSAndroid Build Coastguard Worker mVideoTimeUs(0),
64*ec779b8eSAndroid Build Coastguard Worker mVideoLastDequeueTimeUs(0),
65*ec779b8eSAndroid Build Coastguard Worker mPrevBufferPercentage(-1),
66*ec779b8eSAndroid Build Coastguard Worker mPollBufferingGeneration(0),
67*ec779b8eSAndroid Build Coastguard Worker mSentPauseOnBuffering(false),
68*ec779b8eSAndroid Build Coastguard Worker mAudioDataGeneration(0),
69*ec779b8eSAndroid Build Coastguard Worker mVideoDataGeneration(0),
70*ec779b8eSAndroid Build Coastguard Worker mFetchSubtitleDataGeneration(0),
71*ec779b8eSAndroid Build Coastguard Worker mFetchTimedTextDataGeneration(0),
72*ec779b8eSAndroid Build Coastguard Worker mDurationUs(-1LL),
73*ec779b8eSAndroid Build Coastguard Worker mAudioIsVorbis(false),
74*ec779b8eSAndroid Build Coastguard Worker mIsSecure(false),
75*ec779b8eSAndroid Build Coastguard Worker mIsStreaming(false),
76*ec779b8eSAndroid Build Coastguard Worker mUIDValid(uidValid),
77*ec779b8eSAndroid Build Coastguard Worker mUID(uid),
78*ec779b8eSAndroid Build Coastguard Worker mMediaClock(mediaClock),
79*ec779b8eSAndroid Build Coastguard Worker mBitrate(-1LL),
80*ec779b8eSAndroid Build Coastguard Worker mPendingReadBufferTypes(0) {
81*ec779b8eSAndroid Build Coastguard Worker ALOGV("GenericSource");
82*ec779b8eSAndroid Build Coastguard Worker CHECK(mediaClock != NULL);
83*ec779b8eSAndroid Build Coastguard Worker
84*ec779b8eSAndroid Build Coastguard Worker mBufferingSettings.mInitialMarkMs = kInitialMarkMs;
85*ec779b8eSAndroid Build Coastguard Worker mBufferingSettings.mResumePlaybackMarkMs = kResumePlaybackMarkMs;
86*ec779b8eSAndroid Build Coastguard Worker resetDataSource();
87*ec779b8eSAndroid Build Coastguard Worker }
88*ec779b8eSAndroid Build Coastguard Worker
resetDataSource()89*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::resetDataSource() {
90*ec779b8eSAndroid Build Coastguard Worker ALOGV("resetDataSource");
91*ec779b8eSAndroid Build Coastguard Worker
92*ec779b8eSAndroid Build Coastguard Worker mHTTPService.clear();
93*ec779b8eSAndroid Build Coastguard Worker {
94*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l_d(mDisconnectLock);
95*ec779b8eSAndroid Build Coastguard Worker mHttpSource.clear();
96*ec779b8eSAndroid Build Coastguard Worker mDisconnected = false;
97*ec779b8eSAndroid Build Coastguard Worker }
98*ec779b8eSAndroid Build Coastguard Worker mUri.clear();
99*ec779b8eSAndroid Build Coastguard Worker mUriHeaders.clear();
100*ec779b8eSAndroid Build Coastguard Worker mSources.clear();
101*ec779b8eSAndroid Build Coastguard Worker mFd.reset();
102*ec779b8eSAndroid Build Coastguard Worker mOffset = 0;
103*ec779b8eSAndroid Build Coastguard Worker mLength = 0;
104*ec779b8eSAndroid Build Coastguard Worker mStarted = false;
105*ec779b8eSAndroid Build Coastguard Worker mPreparing = false;
106*ec779b8eSAndroid Build Coastguard Worker
107*ec779b8eSAndroid Build Coastguard Worker mIsDrmProtected = false;
108*ec779b8eSAndroid Build Coastguard Worker mIsDrmReleased = false;
109*ec779b8eSAndroid Build Coastguard Worker mIsSecure = false;
110*ec779b8eSAndroid Build Coastguard Worker mMimes.clear();
111*ec779b8eSAndroid Build Coastguard Worker }
112*ec779b8eSAndroid Build Coastguard Worker
setDataSource(const sp<IMediaHTTPService> & httpService,const char * url,const KeyedVector<String8,String8> * headers)113*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::GenericSource::setDataSource(
114*ec779b8eSAndroid Build Coastguard Worker const sp<IMediaHTTPService> &httpService,
115*ec779b8eSAndroid Build Coastguard Worker const char *url,
116*ec779b8eSAndroid Build Coastguard Worker const KeyedVector<String8, String8> *headers) {
117*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
118*ec779b8eSAndroid Build Coastguard Worker ALOGV("setDataSource url: %s", url);
119*ec779b8eSAndroid Build Coastguard Worker
120*ec779b8eSAndroid Build Coastguard Worker resetDataSource();
121*ec779b8eSAndroid Build Coastguard Worker
122*ec779b8eSAndroid Build Coastguard Worker mHTTPService = httpService;
123*ec779b8eSAndroid Build Coastguard Worker mUri = url;
124*ec779b8eSAndroid Build Coastguard Worker
125*ec779b8eSAndroid Build Coastguard Worker if (headers) {
126*ec779b8eSAndroid Build Coastguard Worker mUriHeaders = *headers;
127*ec779b8eSAndroid Build Coastguard Worker }
128*ec779b8eSAndroid Build Coastguard Worker
129*ec779b8eSAndroid Build Coastguard Worker // delay data source creation to prepareAsync() to avoid blocking
130*ec779b8eSAndroid Build Coastguard Worker // the calling thread in setDataSource for any significant time.
131*ec779b8eSAndroid Build Coastguard Worker return OK;
132*ec779b8eSAndroid Build Coastguard Worker }
133*ec779b8eSAndroid Build Coastguard Worker
setDataSource(int fd,int64_t offset,int64_t length)134*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::GenericSource::setDataSource(
135*ec779b8eSAndroid Build Coastguard Worker int fd, int64_t offset, int64_t length) {
136*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
137*ec779b8eSAndroid Build Coastguard Worker ALOGV("setDataSource %d/%lld/%lld (%s)", fd, (long long)offset, (long long)length, nameForFd(fd).c_str());
138*ec779b8eSAndroid Build Coastguard Worker
139*ec779b8eSAndroid Build Coastguard Worker resetDataSource();
140*ec779b8eSAndroid Build Coastguard Worker
141*ec779b8eSAndroid Build Coastguard Worker mFd.reset(dup(fd));
142*ec779b8eSAndroid Build Coastguard Worker mOffset = offset;
143*ec779b8eSAndroid Build Coastguard Worker mLength = length;
144*ec779b8eSAndroid Build Coastguard Worker
145*ec779b8eSAndroid Build Coastguard Worker // delay data source creation to prepareAsync() to avoid blocking
146*ec779b8eSAndroid Build Coastguard Worker // the calling thread in setDataSource for any significant time.
147*ec779b8eSAndroid Build Coastguard Worker return OK;
148*ec779b8eSAndroid Build Coastguard Worker }
149*ec779b8eSAndroid Build Coastguard Worker
setDataSource(const sp<DataSource> & source)150*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::GenericSource::setDataSource(const sp<DataSource>& source) {
151*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
152*ec779b8eSAndroid Build Coastguard Worker ALOGV("setDataSource (source: %p)", source.get());
153*ec779b8eSAndroid Build Coastguard Worker
154*ec779b8eSAndroid Build Coastguard Worker resetDataSource();
155*ec779b8eSAndroid Build Coastguard Worker {
156*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l_d(mDisconnectLock);
157*ec779b8eSAndroid Build Coastguard Worker mDataSource = source;
158*ec779b8eSAndroid Build Coastguard Worker }
159*ec779b8eSAndroid Build Coastguard Worker return OK;
160*ec779b8eSAndroid Build Coastguard Worker }
161*ec779b8eSAndroid Build Coastguard Worker
getFileFormatMeta() const162*ec779b8eSAndroid Build Coastguard Worker sp<MetaData> NuPlayer::GenericSource::getFileFormatMeta() const {
163*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
164*ec779b8eSAndroid Build Coastguard Worker return mFileMeta;
165*ec779b8eSAndroid Build Coastguard Worker }
166*ec779b8eSAndroid Build Coastguard Worker
initFromDataSource()167*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::GenericSource::initFromDataSource() {
168*ec779b8eSAndroid Build Coastguard Worker sp<IMediaExtractor> extractor;
169*ec779b8eSAndroid Build Coastguard Worker sp<DataSource> dataSource;
170*ec779b8eSAndroid Build Coastguard Worker {
171*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l_d(mDisconnectLock);
172*ec779b8eSAndroid Build Coastguard Worker dataSource = mDataSource;
173*ec779b8eSAndroid Build Coastguard Worker }
174*ec779b8eSAndroid Build Coastguard Worker CHECK(dataSource != NULL);
175*ec779b8eSAndroid Build Coastguard Worker
176*ec779b8eSAndroid Build Coastguard Worker mLock.unlock();
177*ec779b8eSAndroid Build Coastguard Worker // This might take long time if data source is not reliable.
178*ec779b8eSAndroid Build Coastguard Worker extractor = MediaExtractorFactory::Create(dataSource, NULL);
179*ec779b8eSAndroid Build Coastguard Worker
180*ec779b8eSAndroid Build Coastguard Worker if (extractor == NULL) {
181*ec779b8eSAndroid Build Coastguard Worker ALOGE("initFromDataSource, cannot create extractor!");
182*ec779b8eSAndroid Build Coastguard Worker mLock.lock();
183*ec779b8eSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
184*ec779b8eSAndroid Build Coastguard Worker }
185*ec779b8eSAndroid Build Coastguard Worker
186*ec779b8eSAndroid Build Coastguard Worker sp<MetaData> fileMeta = extractor->getMetaData();
187*ec779b8eSAndroid Build Coastguard Worker
188*ec779b8eSAndroid Build Coastguard Worker size_t numtracks = extractor->countTracks();
189*ec779b8eSAndroid Build Coastguard Worker if (numtracks == 0) {
190*ec779b8eSAndroid Build Coastguard Worker ALOGE("initFromDataSource, source has no track!");
191*ec779b8eSAndroid Build Coastguard Worker mLock.lock();
192*ec779b8eSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
193*ec779b8eSAndroid Build Coastguard Worker }
194*ec779b8eSAndroid Build Coastguard Worker
195*ec779b8eSAndroid Build Coastguard Worker mLock.lock();
196*ec779b8eSAndroid Build Coastguard Worker mFileMeta = fileMeta;
197*ec779b8eSAndroid Build Coastguard Worker if (mFileMeta != NULL) {
198*ec779b8eSAndroid Build Coastguard Worker int64_t duration;
199*ec779b8eSAndroid Build Coastguard Worker if (mFileMeta->findInt64(kKeyDuration, &duration)) {
200*ec779b8eSAndroid Build Coastguard Worker mDurationUs = duration;
201*ec779b8eSAndroid Build Coastguard Worker }
202*ec779b8eSAndroid Build Coastguard Worker }
203*ec779b8eSAndroid Build Coastguard Worker
204*ec779b8eSAndroid Build Coastguard Worker int32_t totalBitrate = 0;
205*ec779b8eSAndroid Build Coastguard Worker
206*ec779b8eSAndroid Build Coastguard Worker mMimes.clear();
207*ec779b8eSAndroid Build Coastguard Worker
208*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < numtracks; ++i) {
209*ec779b8eSAndroid Build Coastguard Worker sp<IMediaSource> track = extractor->getTrack(i);
210*ec779b8eSAndroid Build Coastguard Worker if (track == NULL) {
211*ec779b8eSAndroid Build Coastguard Worker continue;
212*ec779b8eSAndroid Build Coastguard Worker }
213*ec779b8eSAndroid Build Coastguard Worker
214*ec779b8eSAndroid Build Coastguard Worker sp<MetaData> meta = extractor->getTrackMetaData(i);
215*ec779b8eSAndroid Build Coastguard Worker if (meta == NULL) {
216*ec779b8eSAndroid Build Coastguard Worker ALOGE("no metadata for track %zu", i);
217*ec779b8eSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
218*ec779b8eSAndroid Build Coastguard Worker }
219*ec779b8eSAndroid Build Coastguard Worker
220*ec779b8eSAndroid Build Coastguard Worker const char *mime;
221*ec779b8eSAndroid Build Coastguard Worker CHECK(meta->findCString(kKeyMIMEType, &mime));
222*ec779b8eSAndroid Build Coastguard Worker
223*ec779b8eSAndroid Build Coastguard Worker ALOGV("initFromDataSource track[%zu]: %s", i, mime);
224*ec779b8eSAndroid Build Coastguard Worker
225*ec779b8eSAndroid Build Coastguard Worker // Do the string compare immediately with "mime",
226*ec779b8eSAndroid Build Coastguard Worker // we can't assume "mime" would stay valid after another
227*ec779b8eSAndroid Build Coastguard Worker // extractor operation, some extractors might modify meta
228*ec779b8eSAndroid Build Coastguard Worker // during getTrack() and make it invalid.
229*ec779b8eSAndroid Build Coastguard Worker if (!strncasecmp(mime, "audio/", 6)) {
230*ec779b8eSAndroid Build Coastguard Worker if (mAudioTrack.mSource == NULL) {
231*ec779b8eSAndroid Build Coastguard Worker mAudioTrack.mIndex = i;
232*ec779b8eSAndroid Build Coastguard Worker mAudioTrack.mSource = track;
233*ec779b8eSAndroid Build Coastguard Worker mAudioTrack.mPackets =
234*ec779b8eSAndroid Build Coastguard Worker new AnotherPacketSource(mAudioTrack.mSource->getFormat());
235*ec779b8eSAndroid Build Coastguard Worker
236*ec779b8eSAndroid Build Coastguard Worker if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
237*ec779b8eSAndroid Build Coastguard Worker mAudioIsVorbis = true;
238*ec779b8eSAndroid Build Coastguard Worker } else {
239*ec779b8eSAndroid Build Coastguard Worker mAudioIsVorbis = false;
240*ec779b8eSAndroid Build Coastguard Worker }
241*ec779b8eSAndroid Build Coastguard Worker
242*ec779b8eSAndroid Build Coastguard Worker mMimes.add(String8(mime));
243*ec779b8eSAndroid Build Coastguard Worker }
244*ec779b8eSAndroid Build Coastguard Worker } else if (!strncasecmp(mime, "video/", 6)) {
245*ec779b8eSAndroid Build Coastguard Worker if (mVideoTrack.mSource == NULL) {
246*ec779b8eSAndroid Build Coastguard Worker mVideoTrack.mIndex = i;
247*ec779b8eSAndroid Build Coastguard Worker mVideoTrack.mSource = track;
248*ec779b8eSAndroid Build Coastguard Worker mVideoTrack.mPackets =
249*ec779b8eSAndroid Build Coastguard Worker new AnotherPacketSource(mVideoTrack.mSource->getFormat());
250*ec779b8eSAndroid Build Coastguard Worker
251*ec779b8eSAndroid Build Coastguard Worker // video always at the beginning
252*ec779b8eSAndroid Build Coastguard Worker mMimes.insertAt(String8(mime), 0);
253*ec779b8eSAndroid Build Coastguard Worker }
254*ec779b8eSAndroid Build Coastguard Worker }
255*ec779b8eSAndroid Build Coastguard Worker
256*ec779b8eSAndroid Build Coastguard Worker mSources.push(track);
257*ec779b8eSAndroid Build Coastguard Worker int64_t durationUs;
258*ec779b8eSAndroid Build Coastguard Worker if (meta->findInt64(kKeyDuration, &durationUs)) {
259*ec779b8eSAndroid Build Coastguard Worker if (durationUs > mDurationUs) {
260*ec779b8eSAndroid Build Coastguard Worker mDurationUs = durationUs;
261*ec779b8eSAndroid Build Coastguard Worker }
262*ec779b8eSAndroid Build Coastguard Worker }
263*ec779b8eSAndroid Build Coastguard Worker
264*ec779b8eSAndroid Build Coastguard Worker int32_t bitrate;
265*ec779b8eSAndroid Build Coastguard Worker if (totalBitrate >= 0 && meta->findInt32(kKeyBitRate, &bitrate)) {
266*ec779b8eSAndroid Build Coastguard Worker totalBitrate += bitrate;
267*ec779b8eSAndroid Build Coastguard Worker } else {
268*ec779b8eSAndroid Build Coastguard Worker totalBitrate = -1;
269*ec779b8eSAndroid Build Coastguard Worker }
270*ec779b8eSAndroid Build Coastguard Worker }
271*ec779b8eSAndroid Build Coastguard Worker
272*ec779b8eSAndroid Build Coastguard Worker ALOGV("initFromDataSource mSources.size(): %zu mIsSecure: %d mime[0]: %s", mSources.size(),
273*ec779b8eSAndroid Build Coastguard Worker mIsSecure, (mMimes.isEmpty() ? "NONE" : mMimes[0].c_str()));
274*ec779b8eSAndroid Build Coastguard Worker
275*ec779b8eSAndroid Build Coastguard Worker if (mSources.size() == 0) {
276*ec779b8eSAndroid Build Coastguard Worker ALOGE("b/23705695");
277*ec779b8eSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
278*ec779b8eSAndroid Build Coastguard Worker }
279*ec779b8eSAndroid Build Coastguard Worker
280*ec779b8eSAndroid Build Coastguard Worker // Modular DRM: The return value doesn't affect source initialization.
281*ec779b8eSAndroid Build Coastguard Worker (void)checkDrmInfo();
282*ec779b8eSAndroid Build Coastguard Worker
283*ec779b8eSAndroid Build Coastguard Worker mBitrate = totalBitrate;
284*ec779b8eSAndroid Build Coastguard Worker
285*ec779b8eSAndroid Build Coastguard Worker return OK;
286*ec779b8eSAndroid Build Coastguard Worker }
287*ec779b8eSAndroid Build Coastguard Worker
getBufferingSettings(BufferingSettings * buffering)288*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::GenericSource::getBufferingSettings(
289*ec779b8eSAndroid Build Coastguard Worker BufferingSettings* buffering /* nonnull */) {
290*ec779b8eSAndroid Build Coastguard Worker {
291*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
292*ec779b8eSAndroid Build Coastguard Worker *buffering = mBufferingSettings;
293*ec779b8eSAndroid Build Coastguard Worker }
294*ec779b8eSAndroid Build Coastguard Worker
295*ec779b8eSAndroid Build Coastguard Worker ALOGV("getBufferingSettings{%s}", buffering->toString().c_str());
296*ec779b8eSAndroid Build Coastguard Worker return OK;
297*ec779b8eSAndroid Build Coastguard Worker }
298*ec779b8eSAndroid Build Coastguard Worker
setBufferingSettings(const BufferingSettings & buffering)299*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::GenericSource::setBufferingSettings(const BufferingSettings& buffering) {
300*ec779b8eSAndroid Build Coastguard Worker ALOGV("setBufferingSettings{%s}", buffering.toString().c_str());
301*ec779b8eSAndroid Build Coastguard Worker
302*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
303*ec779b8eSAndroid Build Coastguard Worker mBufferingSettings = buffering;
304*ec779b8eSAndroid Build Coastguard Worker return OK;
305*ec779b8eSAndroid Build Coastguard Worker }
306*ec779b8eSAndroid Build Coastguard Worker
startSources()307*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::GenericSource::startSources() {
308*ec779b8eSAndroid Build Coastguard Worker // Start the selected A/V tracks now before we start buffering.
309*ec779b8eSAndroid Build Coastguard Worker // Widevine sources might re-initialize crypto when starting, if we delay
310*ec779b8eSAndroid Build Coastguard Worker // this to start(), all data buffered during prepare would be wasted.
311*ec779b8eSAndroid Build Coastguard Worker // (We don't actually start reading until start().)
312*ec779b8eSAndroid Build Coastguard Worker //
313*ec779b8eSAndroid Build Coastguard Worker // TODO: this logic may no longer be relevant after the removal of widevine
314*ec779b8eSAndroid Build Coastguard Worker // support
315*ec779b8eSAndroid Build Coastguard Worker if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) {
316*ec779b8eSAndroid Build Coastguard Worker ALOGE("failed to start audio track!");
317*ec779b8eSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
318*ec779b8eSAndroid Build Coastguard Worker }
319*ec779b8eSAndroid Build Coastguard Worker
320*ec779b8eSAndroid Build Coastguard Worker if (mVideoTrack.mSource != NULL && mVideoTrack.mSource->start() != OK) {
321*ec779b8eSAndroid Build Coastguard Worker ALOGE("failed to start video track!");
322*ec779b8eSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
323*ec779b8eSAndroid Build Coastguard Worker }
324*ec779b8eSAndroid Build Coastguard Worker
325*ec779b8eSAndroid Build Coastguard Worker return OK;
326*ec779b8eSAndroid Build Coastguard Worker }
327*ec779b8eSAndroid Build Coastguard Worker
getLastReadPosition()328*ec779b8eSAndroid Build Coastguard Worker int64_t NuPlayer::GenericSource::getLastReadPosition() {
329*ec779b8eSAndroid Build Coastguard Worker if (mAudioTrack.mSource != NULL) {
330*ec779b8eSAndroid Build Coastguard Worker return mAudioTimeUs;
331*ec779b8eSAndroid Build Coastguard Worker } else if (mVideoTrack.mSource != NULL) {
332*ec779b8eSAndroid Build Coastguard Worker return mVideoTimeUs;
333*ec779b8eSAndroid Build Coastguard Worker } else {
334*ec779b8eSAndroid Build Coastguard Worker return 0;
335*ec779b8eSAndroid Build Coastguard Worker }
336*ec779b8eSAndroid Build Coastguard Worker }
337*ec779b8eSAndroid Build Coastguard Worker
isStreaming() const338*ec779b8eSAndroid Build Coastguard Worker bool NuPlayer::GenericSource::isStreaming() const {
339*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
340*ec779b8eSAndroid Build Coastguard Worker return mIsStreaming;
341*ec779b8eSAndroid Build Coastguard Worker }
342*ec779b8eSAndroid Build Coastguard Worker
~GenericSource()343*ec779b8eSAndroid Build Coastguard Worker NuPlayer::GenericSource::~GenericSource() {
344*ec779b8eSAndroid Build Coastguard Worker ALOGV("~GenericSource");
345*ec779b8eSAndroid Build Coastguard Worker if (mLooper != NULL) {
346*ec779b8eSAndroid Build Coastguard Worker mLooper->unregisterHandler(id());
347*ec779b8eSAndroid Build Coastguard Worker mLooper->stop();
348*ec779b8eSAndroid Build Coastguard Worker }
349*ec779b8eSAndroid Build Coastguard Worker resetDataSource();
350*ec779b8eSAndroid Build Coastguard Worker }
351*ec779b8eSAndroid Build Coastguard Worker
prepareAsync()352*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::prepareAsync() {
353*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
354*ec779b8eSAndroid Build Coastguard Worker ALOGV("prepareAsync: (looper: %d)", (mLooper != NULL));
355*ec779b8eSAndroid Build Coastguard Worker
356*ec779b8eSAndroid Build Coastguard Worker if (mLooper == NULL) {
357*ec779b8eSAndroid Build Coastguard Worker mLooper = new ALooper;
358*ec779b8eSAndroid Build Coastguard Worker mLooper->setName("generic");
359*ec779b8eSAndroid Build Coastguard Worker mLooper->start();
360*ec779b8eSAndroid Build Coastguard Worker
361*ec779b8eSAndroid Build Coastguard Worker mLooper->registerHandler(this);
362*ec779b8eSAndroid Build Coastguard Worker }
363*ec779b8eSAndroid Build Coastguard Worker
364*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this);
365*ec779b8eSAndroid Build Coastguard Worker msg->post();
366*ec779b8eSAndroid Build Coastguard Worker }
367*ec779b8eSAndroid Build Coastguard Worker
onPrepareAsync()368*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::onPrepareAsync() {
369*ec779b8eSAndroid Build Coastguard Worker mDisconnectLock.lock();
370*ec779b8eSAndroid Build Coastguard Worker ALOGV("onPrepareAsync: mDataSource: %d", (mDataSource != NULL));
371*ec779b8eSAndroid Build Coastguard Worker
372*ec779b8eSAndroid Build Coastguard Worker // delayed data source creation
373*ec779b8eSAndroid Build Coastguard Worker if (mDataSource == NULL) {
374*ec779b8eSAndroid Build Coastguard Worker // set to false first, if the extractor
375*ec779b8eSAndroid Build Coastguard Worker // comes back as secure, set it to true then.
376*ec779b8eSAndroid Build Coastguard Worker mIsSecure = false;
377*ec779b8eSAndroid Build Coastguard Worker
378*ec779b8eSAndroid Build Coastguard Worker if (!mUri.empty()) {
379*ec779b8eSAndroid Build Coastguard Worker const char* uri = mUri.c_str();
380*ec779b8eSAndroid Build Coastguard Worker String8 contentType;
381*ec779b8eSAndroid Build Coastguard Worker
382*ec779b8eSAndroid Build Coastguard Worker if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
383*ec779b8eSAndroid Build Coastguard Worker sp<DataSource> httpSource;
384*ec779b8eSAndroid Build Coastguard Worker mDisconnectLock.unlock();
385*ec779b8eSAndroid Build Coastguard Worker httpSource = PlayerServiceDataSourceFactory::getInstance()
386*ec779b8eSAndroid Build Coastguard Worker ->CreateMediaHTTP(mHTTPService);
387*ec779b8eSAndroid Build Coastguard Worker if (httpSource == NULL) {
388*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to create http source!");
389*ec779b8eSAndroid Build Coastguard Worker notifyPreparedAndCleanup(UNKNOWN_ERROR);
390*ec779b8eSAndroid Build Coastguard Worker return;
391*ec779b8eSAndroid Build Coastguard Worker }
392*ec779b8eSAndroid Build Coastguard Worker mDisconnectLock.lock();
393*ec779b8eSAndroid Build Coastguard Worker
394*ec779b8eSAndroid Build Coastguard Worker if (!mDisconnected) {
395*ec779b8eSAndroid Build Coastguard Worker mHttpSource = httpSource;
396*ec779b8eSAndroid Build Coastguard Worker }
397*ec779b8eSAndroid Build Coastguard Worker }
398*ec779b8eSAndroid Build Coastguard Worker
399*ec779b8eSAndroid Build Coastguard Worker mLock.unlock();
400*ec779b8eSAndroid Build Coastguard Worker mDisconnectLock.unlock();
401*ec779b8eSAndroid Build Coastguard Worker // This might take long time if connection has some issue.
402*ec779b8eSAndroid Build Coastguard Worker sp<DataSource> dataSource = PlayerServiceDataSourceFactory::getInstance()
403*ec779b8eSAndroid Build Coastguard Worker ->CreateFromURI(mHTTPService, uri, &mUriHeaders, &contentType,
404*ec779b8eSAndroid Build Coastguard Worker static_cast<HTTPBase *>(mHttpSource.get()));
405*ec779b8eSAndroid Build Coastguard Worker mDisconnectLock.lock();
406*ec779b8eSAndroid Build Coastguard Worker mLock.lock();
407*ec779b8eSAndroid Build Coastguard Worker if (!mDisconnected) {
408*ec779b8eSAndroid Build Coastguard Worker mDataSource = dataSource;
409*ec779b8eSAndroid Build Coastguard Worker }
410*ec779b8eSAndroid Build Coastguard Worker } else {
411*ec779b8eSAndroid Build Coastguard Worker if (property_get_bool("media.stagefright.extractremote", true) &&
412*ec779b8eSAndroid Build Coastguard Worker !PlayerServiceFileSource::requiresDrm(
413*ec779b8eSAndroid Build Coastguard Worker mFd.get(), mOffset, mLength, nullptr /* mime */)) {
414*ec779b8eSAndroid Build Coastguard Worker sp<IBinder> binder =
415*ec779b8eSAndroid Build Coastguard Worker defaultServiceManager()->getService(String16("media.extractor"));
416*ec779b8eSAndroid Build Coastguard Worker if (binder != nullptr) {
417*ec779b8eSAndroid Build Coastguard Worker ALOGD("FileSource remote");
418*ec779b8eSAndroid Build Coastguard Worker sp<IMediaExtractorService> mediaExService(
419*ec779b8eSAndroid Build Coastguard Worker interface_cast<IMediaExtractorService>(binder));
420*ec779b8eSAndroid Build Coastguard Worker sp<IDataSource> source;
421*ec779b8eSAndroid Build Coastguard Worker mediaExService->makeIDataSource(base::unique_fd(dup(mFd.get())), mOffset, mLength, &source);
422*ec779b8eSAndroid Build Coastguard Worker ALOGV("IDataSource(FileSource): %p %d %lld %lld",
423*ec779b8eSAndroid Build Coastguard Worker source.get(), mFd.get(), (long long)mOffset, (long long)mLength);
424*ec779b8eSAndroid Build Coastguard Worker if (source.get() != nullptr) {
425*ec779b8eSAndroid Build Coastguard Worker mDataSource = CreateDataSourceFromIDataSource(source);
426*ec779b8eSAndroid Build Coastguard Worker } else {
427*ec779b8eSAndroid Build Coastguard Worker ALOGW("extractor service cannot make data source");
428*ec779b8eSAndroid Build Coastguard Worker }
429*ec779b8eSAndroid Build Coastguard Worker } else {
430*ec779b8eSAndroid Build Coastguard Worker ALOGW("extractor service not running");
431*ec779b8eSAndroid Build Coastguard Worker }
432*ec779b8eSAndroid Build Coastguard Worker }
433*ec779b8eSAndroid Build Coastguard Worker if (mDataSource == nullptr) {
434*ec779b8eSAndroid Build Coastguard Worker ALOGD("FileSource local");
435*ec779b8eSAndroid Build Coastguard Worker mDataSource = new PlayerServiceFileSource(dup(mFd.get()), mOffset, mLength);
436*ec779b8eSAndroid Build Coastguard Worker }
437*ec779b8eSAndroid Build Coastguard Worker }
438*ec779b8eSAndroid Build Coastguard Worker
439*ec779b8eSAndroid Build Coastguard Worker if (mDataSource == NULL) {
440*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to create data source!");
441*ec779b8eSAndroid Build Coastguard Worker mDisconnectLock.unlock();
442*ec779b8eSAndroid Build Coastguard Worker notifyPreparedAndCleanup(UNKNOWN_ERROR);
443*ec779b8eSAndroid Build Coastguard Worker return;
444*ec779b8eSAndroid Build Coastguard Worker }
445*ec779b8eSAndroid Build Coastguard Worker }
446*ec779b8eSAndroid Build Coastguard Worker
447*ec779b8eSAndroid Build Coastguard Worker if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
448*ec779b8eSAndroid Build Coastguard Worker mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
449*ec779b8eSAndroid Build Coastguard Worker }
450*ec779b8eSAndroid Build Coastguard Worker
451*ec779b8eSAndroid Build Coastguard Worker mDisconnectLock.unlock();
452*ec779b8eSAndroid Build Coastguard Worker
453*ec779b8eSAndroid Build Coastguard Worker // For cached streaming cases, we need to wait for enough
454*ec779b8eSAndroid Build Coastguard Worker // buffering before reporting prepared.
455*ec779b8eSAndroid Build Coastguard Worker mIsStreaming = (mCachedSource != NULL);
456*ec779b8eSAndroid Build Coastguard Worker
457*ec779b8eSAndroid Build Coastguard Worker // init extractor from data source
458*ec779b8eSAndroid Build Coastguard Worker status_t err = initFromDataSource();
459*ec779b8eSAndroid Build Coastguard Worker
460*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
461*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to init from data source!");
462*ec779b8eSAndroid Build Coastguard Worker notifyPreparedAndCleanup(err);
463*ec779b8eSAndroid Build Coastguard Worker return;
464*ec779b8eSAndroid Build Coastguard Worker }
465*ec779b8eSAndroid Build Coastguard Worker
466*ec779b8eSAndroid Build Coastguard Worker if (mVideoTrack.mSource != NULL) {
467*ec779b8eSAndroid Build Coastguard Worker sp<MetaData> meta = getFormatMeta_l(false /* audio */);
468*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage;
469*ec779b8eSAndroid Build Coastguard Worker err = convertMetaDataToMessage(meta, &msg);
470*ec779b8eSAndroid Build Coastguard Worker if(err != OK) {
471*ec779b8eSAndroid Build Coastguard Worker notifyPreparedAndCleanup(err);
472*ec779b8eSAndroid Build Coastguard Worker return;
473*ec779b8eSAndroid Build Coastguard Worker }
474*ec779b8eSAndroid Build Coastguard Worker notifyVideoSizeChanged(msg);
475*ec779b8eSAndroid Build Coastguard Worker }
476*ec779b8eSAndroid Build Coastguard Worker
477*ec779b8eSAndroid Build Coastguard Worker notifyFlagsChanged(
478*ec779b8eSAndroid Build Coastguard Worker // FLAG_SECURE will be known if/when prepareDrm is called by the app
479*ec779b8eSAndroid Build Coastguard Worker // FLAG_PROTECTED will be known if/when prepareDrm is called by the app
480*ec779b8eSAndroid Build Coastguard Worker FLAG_CAN_PAUSE |
481*ec779b8eSAndroid Build Coastguard Worker FLAG_CAN_SEEK_BACKWARD |
482*ec779b8eSAndroid Build Coastguard Worker FLAG_CAN_SEEK_FORWARD |
483*ec779b8eSAndroid Build Coastguard Worker FLAG_CAN_SEEK);
484*ec779b8eSAndroid Build Coastguard Worker
485*ec779b8eSAndroid Build Coastguard Worker finishPrepareAsync();
486*ec779b8eSAndroid Build Coastguard Worker
487*ec779b8eSAndroid Build Coastguard Worker ALOGV("onPrepareAsync: Done");
488*ec779b8eSAndroid Build Coastguard Worker }
489*ec779b8eSAndroid Build Coastguard Worker
finishPrepareAsync()490*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::finishPrepareAsync() {
491*ec779b8eSAndroid Build Coastguard Worker ALOGV("finishPrepareAsync");
492*ec779b8eSAndroid Build Coastguard Worker
493*ec779b8eSAndroid Build Coastguard Worker status_t err = startSources();
494*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
495*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to init start data source!");
496*ec779b8eSAndroid Build Coastguard Worker notifyPreparedAndCleanup(err);
497*ec779b8eSAndroid Build Coastguard Worker return;
498*ec779b8eSAndroid Build Coastguard Worker }
499*ec779b8eSAndroid Build Coastguard Worker
500*ec779b8eSAndroid Build Coastguard Worker if (mIsStreaming) {
501*ec779b8eSAndroid Build Coastguard Worker mCachedSource->resumeFetchingIfNecessary();
502*ec779b8eSAndroid Build Coastguard Worker mPreparing = true;
503*ec779b8eSAndroid Build Coastguard Worker schedulePollBuffering();
504*ec779b8eSAndroid Build Coastguard Worker } else {
505*ec779b8eSAndroid Build Coastguard Worker notifyPrepared();
506*ec779b8eSAndroid Build Coastguard Worker }
507*ec779b8eSAndroid Build Coastguard Worker
508*ec779b8eSAndroid Build Coastguard Worker if (mAudioTrack.mSource != NULL) {
509*ec779b8eSAndroid Build Coastguard Worker postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
510*ec779b8eSAndroid Build Coastguard Worker }
511*ec779b8eSAndroid Build Coastguard Worker
512*ec779b8eSAndroid Build Coastguard Worker if (mVideoTrack.mSource != NULL) {
513*ec779b8eSAndroid Build Coastguard Worker postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
514*ec779b8eSAndroid Build Coastguard Worker }
515*ec779b8eSAndroid Build Coastguard Worker }
516*ec779b8eSAndroid Build Coastguard Worker
notifyPreparedAndCleanup(status_t err)517*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
518*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
519*ec779b8eSAndroid Build Coastguard Worker {
520*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l_d(mDisconnectLock);
521*ec779b8eSAndroid Build Coastguard Worker mDataSource.clear();
522*ec779b8eSAndroid Build Coastguard Worker mHttpSource.clear();
523*ec779b8eSAndroid Build Coastguard Worker }
524*ec779b8eSAndroid Build Coastguard Worker
525*ec779b8eSAndroid Build Coastguard Worker mCachedSource.clear();
526*ec779b8eSAndroid Build Coastguard Worker
527*ec779b8eSAndroid Build Coastguard Worker mBitrate = -1;
528*ec779b8eSAndroid Build Coastguard Worker mPrevBufferPercentage = -1;
529*ec779b8eSAndroid Build Coastguard Worker ++mPollBufferingGeneration;
530*ec779b8eSAndroid Build Coastguard Worker }
531*ec779b8eSAndroid Build Coastguard Worker notifyPrepared(err);
532*ec779b8eSAndroid Build Coastguard Worker }
533*ec779b8eSAndroid Build Coastguard Worker
start()534*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::start() {
535*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
536*ec779b8eSAndroid Build Coastguard Worker ALOGI("start");
537*ec779b8eSAndroid Build Coastguard Worker
538*ec779b8eSAndroid Build Coastguard Worker if (mAudioTrack.mSource != NULL) {
539*ec779b8eSAndroid Build Coastguard Worker postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
540*ec779b8eSAndroid Build Coastguard Worker }
541*ec779b8eSAndroid Build Coastguard Worker
542*ec779b8eSAndroid Build Coastguard Worker if (mVideoTrack.mSource != NULL) {
543*ec779b8eSAndroid Build Coastguard Worker postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
544*ec779b8eSAndroid Build Coastguard Worker }
545*ec779b8eSAndroid Build Coastguard Worker
546*ec779b8eSAndroid Build Coastguard Worker mStarted = true;
547*ec779b8eSAndroid Build Coastguard Worker }
548*ec779b8eSAndroid Build Coastguard Worker
stop()549*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::stop() {
550*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
551*ec779b8eSAndroid Build Coastguard Worker mStarted = false;
552*ec779b8eSAndroid Build Coastguard Worker }
553*ec779b8eSAndroid Build Coastguard Worker
pause()554*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::pause() {
555*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
556*ec779b8eSAndroid Build Coastguard Worker mStarted = false;
557*ec779b8eSAndroid Build Coastguard Worker }
558*ec779b8eSAndroid Build Coastguard Worker
resume()559*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::resume() {
560*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
561*ec779b8eSAndroid Build Coastguard Worker mStarted = true;
562*ec779b8eSAndroid Build Coastguard Worker }
563*ec779b8eSAndroid Build Coastguard Worker
disconnect()564*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::disconnect() {
565*ec779b8eSAndroid Build Coastguard Worker sp<DataSource> dataSource, httpSource;
566*ec779b8eSAndroid Build Coastguard Worker {
567*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l_d(mDisconnectLock);
568*ec779b8eSAndroid Build Coastguard Worker dataSource = mDataSource;
569*ec779b8eSAndroid Build Coastguard Worker httpSource = mHttpSource;
570*ec779b8eSAndroid Build Coastguard Worker mDisconnected = true;
571*ec779b8eSAndroid Build Coastguard Worker }
572*ec779b8eSAndroid Build Coastguard Worker
573*ec779b8eSAndroid Build Coastguard Worker if (dataSource != NULL) {
574*ec779b8eSAndroid Build Coastguard Worker // disconnect data source
575*ec779b8eSAndroid Build Coastguard Worker if (dataSource->flags() & DataSource::kIsCachingDataSource) {
576*ec779b8eSAndroid Build Coastguard Worker static_cast<NuCachedSource2 *>(dataSource.get())->disconnect();
577*ec779b8eSAndroid Build Coastguard Worker }
578*ec779b8eSAndroid Build Coastguard Worker } else if (httpSource != NULL) {
579*ec779b8eSAndroid Build Coastguard Worker static_cast<HTTPBase *>(httpSource.get())->disconnect();
580*ec779b8eSAndroid Build Coastguard Worker }
581*ec779b8eSAndroid Build Coastguard Worker }
582*ec779b8eSAndroid Build Coastguard Worker
feedMoreTSData()583*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::GenericSource::feedMoreTSData() {
584*ec779b8eSAndroid Build Coastguard Worker return OK;
585*ec779b8eSAndroid Build Coastguard Worker }
586*ec779b8eSAndroid Build Coastguard Worker
sendCacheStats()587*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::sendCacheStats() {
588*ec779b8eSAndroid Build Coastguard Worker int32_t kbps = 0;
589*ec779b8eSAndroid Build Coastguard Worker status_t err = UNKNOWN_ERROR;
590*ec779b8eSAndroid Build Coastguard Worker
591*ec779b8eSAndroid Build Coastguard Worker if (mCachedSource != NULL) {
592*ec779b8eSAndroid Build Coastguard Worker err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
593*ec779b8eSAndroid Build Coastguard Worker }
594*ec779b8eSAndroid Build Coastguard Worker
595*ec779b8eSAndroid Build Coastguard Worker if (err == OK) {
596*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> notify = dupNotify();
597*ec779b8eSAndroid Build Coastguard Worker notify->setInt32("what", kWhatCacheStats);
598*ec779b8eSAndroid Build Coastguard Worker notify->setInt32("bandwidth", kbps);
599*ec779b8eSAndroid Build Coastguard Worker notify->post();
600*ec779b8eSAndroid Build Coastguard Worker }
601*ec779b8eSAndroid Build Coastguard Worker }
602*ec779b8eSAndroid Build Coastguard Worker
onMessageReceived(const sp<AMessage> & msg)603*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
604*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
605*ec779b8eSAndroid Build Coastguard Worker switch (msg->what()) {
606*ec779b8eSAndroid Build Coastguard Worker case kWhatPrepareAsync:
607*ec779b8eSAndroid Build Coastguard Worker {
608*ec779b8eSAndroid Build Coastguard Worker onPrepareAsync();
609*ec779b8eSAndroid Build Coastguard Worker break;
610*ec779b8eSAndroid Build Coastguard Worker }
611*ec779b8eSAndroid Build Coastguard Worker case kWhatFetchSubtitleData:
612*ec779b8eSAndroid Build Coastguard Worker {
613*ec779b8eSAndroid Build Coastguard Worker fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
614*ec779b8eSAndroid Build Coastguard Worker mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
615*ec779b8eSAndroid Build Coastguard Worker break;
616*ec779b8eSAndroid Build Coastguard Worker }
617*ec779b8eSAndroid Build Coastguard Worker
618*ec779b8eSAndroid Build Coastguard Worker case kWhatFetchTimedTextData:
619*ec779b8eSAndroid Build Coastguard Worker {
620*ec779b8eSAndroid Build Coastguard Worker fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
621*ec779b8eSAndroid Build Coastguard Worker mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
622*ec779b8eSAndroid Build Coastguard Worker break;
623*ec779b8eSAndroid Build Coastguard Worker }
624*ec779b8eSAndroid Build Coastguard Worker
625*ec779b8eSAndroid Build Coastguard Worker case kWhatSendSubtitleData:
626*ec779b8eSAndroid Build Coastguard Worker {
627*ec779b8eSAndroid Build Coastguard Worker sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE,
628*ec779b8eSAndroid Build Coastguard Worker mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg);
629*ec779b8eSAndroid Build Coastguard Worker break;
630*ec779b8eSAndroid Build Coastguard Worker }
631*ec779b8eSAndroid Build Coastguard Worker
632*ec779b8eSAndroid Build Coastguard Worker case kWhatSendGlobalTimedTextData:
633*ec779b8eSAndroid Build Coastguard Worker {
634*ec779b8eSAndroid Build Coastguard Worker sendGlobalTextData(kWhatTimedTextData, mFetchTimedTextDataGeneration, msg);
635*ec779b8eSAndroid Build Coastguard Worker break;
636*ec779b8eSAndroid Build Coastguard Worker }
637*ec779b8eSAndroid Build Coastguard Worker case kWhatSendTimedTextData:
638*ec779b8eSAndroid Build Coastguard Worker {
639*ec779b8eSAndroid Build Coastguard Worker sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT,
640*ec779b8eSAndroid Build Coastguard Worker mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg);
641*ec779b8eSAndroid Build Coastguard Worker break;
642*ec779b8eSAndroid Build Coastguard Worker }
643*ec779b8eSAndroid Build Coastguard Worker
644*ec779b8eSAndroid Build Coastguard Worker case kWhatChangeAVSource:
645*ec779b8eSAndroid Build Coastguard Worker {
646*ec779b8eSAndroid Build Coastguard Worker int32_t trackIndex;
647*ec779b8eSAndroid Build Coastguard Worker CHECK(msg->findInt32("trackIndex", &trackIndex));
648*ec779b8eSAndroid Build Coastguard Worker const sp<IMediaSource> source = mSources.itemAt(trackIndex);
649*ec779b8eSAndroid Build Coastguard Worker
650*ec779b8eSAndroid Build Coastguard Worker Track* track;
651*ec779b8eSAndroid Build Coastguard Worker const char *mime;
652*ec779b8eSAndroid Build Coastguard Worker media_track_type trackType, counterpartType;
653*ec779b8eSAndroid Build Coastguard Worker sp<MetaData> meta = source->getFormat();
654*ec779b8eSAndroid Build Coastguard Worker meta->findCString(kKeyMIMEType, &mime);
655*ec779b8eSAndroid Build Coastguard Worker if (!strncasecmp(mime, "audio/", 6)) {
656*ec779b8eSAndroid Build Coastguard Worker track = &mAudioTrack;
657*ec779b8eSAndroid Build Coastguard Worker trackType = MEDIA_TRACK_TYPE_AUDIO;
658*ec779b8eSAndroid Build Coastguard Worker counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
659*ec779b8eSAndroid Build Coastguard Worker } else {
660*ec779b8eSAndroid Build Coastguard Worker CHECK(!strncasecmp(mime, "video/", 6));
661*ec779b8eSAndroid Build Coastguard Worker track = &mVideoTrack;
662*ec779b8eSAndroid Build Coastguard Worker trackType = MEDIA_TRACK_TYPE_VIDEO;
663*ec779b8eSAndroid Build Coastguard Worker counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
664*ec779b8eSAndroid Build Coastguard Worker }
665*ec779b8eSAndroid Build Coastguard Worker
666*ec779b8eSAndroid Build Coastguard Worker
667*ec779b8eSAndroid Build Coastguard Worker if (track->mSource != NULL) {
668*ec779b8eSAndroid Build Coastguard Worker track->mSource->stop();
669*ec779b8eSAndroid Build Coastguard Worker }
670*ec779b8eSAndroid Build Coastguard Worker track->mSource = source;
671*ec779b8eSAndroid Build Coastguard Worker track->mSource->start();
672*ec779b8eSAndroid Build Coastguard Worker track->mIndex = trackIndex;
673*ec779b8eSAndroid Build Coastguard Worker ++mAudioDataGeneration;
674*ec779b8eSAndroid Build Coastguard Worker ++mVideoDataGeneration;
675*ec779b8eSAndroid Build Coastguard Worker
676*ec779b8eSAndroid Build Coastguard Worker int64_t timeUs, actualTimeUs;
677*ec779b8eSAndroid Build Coastguard Worker const bool formatChange = true;
678*ec779b8eSAndroid Build Coastguard Worker if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
679*ec779b8eSAndroid Build Coastguard Worker timeUs = mAudioLastDequeueTimeUs;
680*ec779b8eSAndroid Build Coastguard Worker } else {
681*ec779b8eSAndroid Build Coastguard Worker timeUs = mVideoLastDequeueTimeUs;
682*ec779b8eSAndroid Build Coastguard Worker }
683*ec779b8eSAndroid Build Coastguard Worker readBuffer(trackType, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
684*ec779b8eSAndroid Build Coastguard Worker &actualTimeUs, formatChange);
685*ec779b8eSAndroid Build Coastguard Worker readBuffer(counterpartType, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
686*ec779b8eSAndroid Build Coastguard Worker NULL, !formatChange);
687*ec779b8eSAndroid Build Coastguard Worker ALOGV("timeUs %lld actualTimeUs %lld", (long long)timeUs, (long long)actualTimeUs);
688*ec779b8eSAndroid Build Coastguard Worker
689*ec779b8eSAndroid Build Coastguard Worker break;
690*ec779b8eSAndroid Build Coastguard Worker }
691*ec779b8eSAndroid Build Coastguard Worker
692*ec779b8eSAndroid Build Coastguard Worker case kWhatSeek:
693*ec779b8eSAndroid Build Coastguard Worker {
694*ec779b8eSAndroid Build Coastguard Worker onSeek(msg);
695*ec779b8eSAndroid Build Coastguard Worker break;
696*ec779b8eSAndroid Build Coastguard Worker }
697*ec779b8eSAndroid Build Coastguard Worker
698*ec779b8eSAndroid Build Coastguard Worker case kWhatReadBuffer:
699*ec779b8eSAndroid Build Coastguard Worker {
700*ec779b8eSAndroid Build Coastguard Worker onReadBuffer(msg);
701*ec779b8eSAndroid Build Coastguard Worker break;
702*ec779b8eSAndroid Build Coastguard Worker }
703*ec779b8eSAndroid Build Coastguard Worker
704*ec779b8eSAndroid Build Coastguard Worker case kWhatPollBuffering:
705*ec779b8eSAndroid Build Coastguard Worker {
706*ec779b8eSAndroid Build Coastguard Worker int32_t generation;
707*ec779b8eSAndroid Build Coastguard Worker CHECK(msg->findInt32("generation", &generation));
708*ec779b8eSAndroid Build Coastguard Worker if (generation == mPollBufferingGeneration) {
709*ec779b8eSAndroid Build Coastguard Worker onPollBuffering();
710*ec779b8eSAndroid Build Coastguard Worker }
711*ec779b8eSAndroid Build Coastguard Worker break;
712*ec779b8eSAndroid Build Coastguard Worker }
713*ec779b8eSAndroid Build Coastguard Worker
714*ec779b8eSAndroid Build Coastguard Worker default:
715*ec779b8eSAndroid Build Coastguard Worker Source::onMessageReceived(msg);
716*ec779b8eSAndroid Build Coastguard Worker break;
717*ec779b8eSAndroid Build Coastguard Worker }
718*ec779b8eSAndroid Build Coastguard Worker }
719*ec779b8eSAndroid Build Coastguard Worker
fetchTextData(uint32_t sendWhat,media_track_type type,int32_t curGen,const sp<AnotherPacketSource> & packets,const sp<AMessage> & msg)720*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::fetchTextData(
721*ec779b8eSAndroid Build Coastguard Worker uint32_t sendWhat,
722*ec779b8eSAndroid Build Coastguard Worker media_track_type type,
723*ec779b8eSAndroid Build Coastguard Worker int32_t curGen,
724*ec779b8eSAndroid Build Coastguard Worker const sp<AnotherPacketSource>& packets,
725*ec779b8eSAndroid Build Coastguard Worker const sp<AMessage>& msg) {
726*ec779b8eSAndroid Build Coastguard Worker int32_t msgGeneration;
727*ec779b8eSAndroid Build Coastguard Worker CHECK(msg->findInt32("generation", &msgGeneration));
728*ec779b8eSAndroid Build Coastguard Worker if (msgGeneration != curGen) {
729*ec779b8eSAndroid Build Coastguard Worker // stale
730*ec779b8eSAndroid Build Coastguard Worker return;
731*ec779b8eSAndroid Build Coastguard Worker }
732*ec779b8eSAndroid Build Coastguard Worker
733*ec779b8eSAndroid Build Coastguard Worker int32_t avail;
734*ec779b8eSAndroid Build Coastguard Worker if (packets->hasBufferAvailable(&avail)) {
735*ec779b8eSAndroid Build Coastguard Worker return;
736*ec779b8eSAndroid Build Coastguard Worker }
737*ec779b8eSAndroid Build Coastguard Worker
738*ec779b8eSAndroid Build Coastguard Worker int64_t timeUs;
739*ec779b8eSAndroid Build Coastguard Worker CHECK(msg->findInt64("timeUs", &timeUs));
740*ec779b8eSAndroid Build Coastguard Worker
741*ec779b8eSAndroid Build Coastguard Worker int64_t subTimeUs = 0;
742*ec779b8eSAndroid Build Coastguard Worker readBuffer(type, timeUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &subTimeUs);
743*ec779b8eSAndroid Build Coastguard Worker
744*ec779b8eSAndroid Build Coastguard Worker status_t eosResult;
745*ec779b8eSAndroid Build Coastguard Worker if (!packets->hasBufferAvailable(&eosResult)) {
746*ec779b8eSAndroid Build Coastguard Worker return;
747*ec779b8eSAndroid Build Coastguard Worker }
748*ec779b8eSAndroid Build Coastguard Worker
749*ec779b8eSAndroid Build Coastguard Worker if (msg->what() == kWhatFetchSubtitleData) {
750*ec779b8eSAndroid Build Coastguard Worker subTimeUs -= 1000000LL; // send subtile data one second earlier
751*ec779b8eSAndroid Build Coastguard Worker }
752*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg2 = new AMessage(sendWhat, this);
753*ec779b8eSAndroid Build Coastguard Worker msg2->setInt32("generation", msgGeneration);
754*ec779b8eSAndroid Build Coastguard Worker mMediaClock->addTimer(msg2, subTimeUs);
755*ec779b8eSAndroid Build Coastguard Worker }
756*ec779b8eSAndroid Build Coastguard Worker
sendTextData(uint32_t what,media_track_type type,int32_t curGen,const sp<AnotherPacketSource> & packets,const sp<AMessage> & msg)757*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::sendTextData(
758*ec779b8eSAndroid Build Coastguard Worker uint32_t what,
759*ec779b8eSAndroid Build Coastguard Worker media_track_type type,
760*ec779b8eSAndroid Build Coastguard Worker int32_t curGen,
761*ec779b8eSAndroid Build Coastguard Worker const sp<AnotherPacketSource>& packets,
762*ec779b8eSAndroid Build Coastguard Worker const sp<AMessage>& msg) {
763*ec779b8eSAndroid Build Coastguard Worker int32_t msgGeneration;
764*ec779b8eSAndroid Build Coastguard Worker CHECK(msg->findInt32("generation", &msgGeneration));
765*ec779b8eSAndroid Build Coastguard Worker if (msgGeneration != curGen) {
766*ec779b8eSAndroid Build Coastguard Worker // stale
767*ec779b8eSAndroid Build Coastguard Worker return;
768*ec779b8eSAndroid Build Coastguard Worker }
769*ec779b8eSAndroid Build Coastguard Worker
770*ec779b8eSAndroid Build Coastguard Worker int64_t subTimeUs;
771*ec779b8eSAndroid Build Coastguard Worker if (packets->nextBufferTime(&subTimeUs) != OK) {
772*ec779b8eSAndroid Build Coastguard Worker return;
773*ec779b8eSAndroid Build Coastguard Worker }
774*ec779b8eSAndroid Build Coastguard Worker
775*ec779b8eSAndroid Build Coastguard Worker int64_t nextSubTimeUs = 0;
776*ec779b8eSAndroid Build Coastguard Worker readBuffer(type, -1, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */, &nextSubTimeUs);
777*ec779b8eSAndroid Build Coastguard Worker
778*ec779b8eSAndroid Build Coastguard Worker sp<ABuffer> buffer;
779*ec779b8eSAndroid Build Coastguard Worker status_t dequeueStatus = packets->dequeueAccessUnit(&buffer);
780*ec779b8eSAndroid Build Coastguard Worker if (dequeueStatus == OK) {
781*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> notify = dupNotify();
782*ec779b8eSAndroid Build Coastguard Worker notify->setInt32("what", what);
783*ec779b8eSAndroid Build Coastguard Worker notify->setBuffer("buffer", buffer);
784*ec779b8eSAndroid Build Coastguard Worker notify->post();
785*ec779b8eSAndroid Build Coastguard Worker
786*ec779b8eSAndroid Build Coastguard Worker if (msg->what() == kWhatSendSubtitleData) {
787*ec779b8eSAndroid Build Coastguard Worker nextSubTimeUs -= 1000000LL; // send subtile data one second earlier
788*ec779b8eSAndroid Build Coastguard Worker }
789*ec779b8eSAndroid Build Coastguard Worker mMediaClock->addTimer(msg, nextSubTimeUs);
790*ec779b8eSAndroid Build Coastguard Worker }
791*ec779b8eSAndroid Build Coastguard Worker }
792*ec779b8eSAndroid Build Coastguard Worker
sendGlobalTextData(uint32_t what,int32_t curGen,sp<AMessage> msg)793*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::sendGlobalTextData(
794*ec779b8eSAndroid Build Coastguard Worker uint32_t what,
795*ec779b8eSAndroid Build Coastguard Worker int32_t curGen,
796*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg) {
797*ec779b8eSAndroid Build Coastguard Worker int32_t msgGeneration;
798*ec779b8eSAndroid Build Coastguard Worker CHECK(msg->findInt32("generation", &msgGeneration));
799*ec779b8eSAndroid Build Coastguard Worker if (msgGeneration != curGen) {
800*ec779b8eSAndroid Build Coastguard Worker // stale
801*ec779b8eSAndroid Build Coastguard Worker return;
802*ec779b8eSAndroid Build Coastguard Worker }
803*ec779b8eSAndroid Build Coastguard Worker
804*ec779b8eSAndroid Build Coastguard Worker uint32_t textType;
805*ec779b8eSAndroid Build Coastguard Worker const void *data;
806*ec779b8eSAndroid Build Coastguard Worker size_t size = 0;
807*ec779b8eSAndroid Build Coastguard Worker if (mTimedTextTrack.mSource->getFormat()->findData(
808*ec779b8eSAndroid Build Coastguard Worker kKeyTextFormatData, &textType, &data, &size)) {
809*ec779b8eSAndroid Build Coastguard Worker mGlobalTimedText = new ABuffer(size);
810*ec779b8eSAndroid Build Coastguard Worker if (mGlobalTimedText->data()) {
811*ec779b8eSAndroid Build Coastguard Worker memcpy(mGlobalTimedText->data(), data, size);
812*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> globalMeta = mGlobalTimedText->meta();
813*ec779b8eSAndroid Build Coastguard Worker globalMeta->setInt64("timeUs", 0);
814*ec779b8eSAndroid Build Coastguard Worker globalMeta->setString("mime", MEDIA_MIMETYPE_TEXT_3GPP);
815*ec779b8eSAndroid Build Coastguard Worker globalMeta->setInt32("global", 1);
816*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> notify = dupNotify();
817*ec779b8eSAndroid Build Coastguard Worker notify->setInt32("what", what);
818*ec779b8eSAndroid Build Coastguard Worker notify->setBuffer("buffer", mGlobalTimedText);
819*ec779b8eSAndroid Build Coastguard Worker notify->post();
820*ec779b8eSAndroid Build Coastguard Worker }
821*ec779b8eSAndroid Build Coastguard Worker }
822*ec779b8eSAndroid Build Coastguard Worker }
823*ec779b8eSAndroid Build Coastguard Worker
getFormatMeta(bool audio)824*ec779b8eSAndroid Build Coastguard Worker sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
825*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
826*ec779b8eSAndroid Build Coastguard Worker return getFormatMeta_l(audio);
827*ec779b8eSAndroid Build Coastguard Worker }
828*ec779b8eSAndroid Build Coastguard Worker
getFormatMeta_l(bool audio)829*ec779b8eSAndroid Build Coastguard Worker sp<MetaData> NuPlayer::GenericSource::getFormatMeta_l(bool audio) {
830*ec779b8eSAndroid Build Coastguard Worker sp<IMediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
831*ec779b8eSAndroid Build Coastguard Worker
832*ec779b8eSAndroid Build Coastguard Worker if (source == NULL) {
833*ec779b8eSAndroid Build Coastguard Worker return NULL;
834*ec779b8eSAndroid Build Coastguard Worker }
835*ec779b8eSAndroid Build Coastguard Worker
836*ec779b8eSAndroid Build Coastguard Worker return source->getFormat();
837*ec779b8eSAndroid Build Coastguard Worker }
838*ec779b8eSAndroid Build Coastguard Worker
dequeueAccessUnit(bool audio,sp<ABuffer> * accessUnit)839*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::GenericSource::dequeueAccessUnit(
840*ec779b8eSAndroid Build Coastguard Worker bool audio, sp<ABuffer> *accessUnit) {
841*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
842*ec779b8eSAndroid Build Coastguard Worker // If has gone through stop/releaseDrm sequence, we no longer send down any buffer b/c
843*ec779b8eSAndroid Build Coastguard Worker // the codec's crypto object has gone away (b/37960096).
844*ec779b8eSAndroid Build Coastguard Worker // Note: This will be unnecessary when stop() changes behavior and releases codec (b/35248283).
845*ec779b8eSAndroid Build Coastguard Worker if (!mStarted && mIsDrmReleased) {
846*ec779b8eSAndroid Build Coastguard Worker return -EWOULDBLOCK;
847*ec779b8eSAndroid Build Coastguard Worker }
848*ec779b8eSAndroid Build Coastguard Worker
849*ec779b8eSAndroid Build Coastguard Worker Track *track = audio ? &mAudioTrack : &mVideoTrack;
850*ec779b8eSAndroid Build Coastguard Worker
851*ec779b8eSAndroid Build Coastguard Worker if (track->mSource == NULL) {
852*ec779b8eSAndroid Build Coastguard Worker return -EWOULDBLOCK;
853*ec779b8eSAndroid Build Coastguard Worker }
854*ec779b8eSAndroid Build Coastguard Worker
855*ec779b8eSAndroid Build Coastguard Worker status_t finalResult;
856*ec779b8eSAndroid Build Coastguard Worker if (!track->mPackets->hasBufferAvailable(&finalResult)) {
857*ec779b8eSAndroid Build Coastguard Worker if (finalResult == OK) {
858*ec779b8eSAndroid Build Coastguard Worker postReadBuffer(
859*ec779b8eSAndroid Build Coastguard Worker audio ? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
860*ec779b8eSAndroid Build Coastguard Worker return -EWOULDBLOCK;
861*ec779b8eSAndroid Build Coastguard Worker }
862*ec779b8eSAndroid Build Coastguard Worker return finalResult;
863*ec779b8eSAndroid Build Coastguard Worker }
864*ec779b8eSAndroid Build Coastguard Worker
865*ec779b8eSAndroid Build Coastguard Worker status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
866*ec779b8eSAndroid Build Coastguard Worker
867*ec779b8eSAndroid Build Coastguard Worker // start pulling in more buffers if cache is running low
868*ec779b8eSAndroid Build Coastguard Worker // so that decoder has less chance of being starved
869*ec779b8eSAndroid Build Coastguard Worker if (!mIsStreaming) {
870*ec779b8eSAndroid Build Coastguard Worker if (track->mPackets->getAvailableBufferCount(&finalResult) < 2) {
871*ec779b8eSAndroid Build Coastguard Worker postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
872*ec779b8eSAndroid Build Coastguard Worker }
873*ec779b8eSAndroid Build Coastguard Worker } else {
874*ec779b8eSAndroid Build Coastguard Worker int64_t durationUs = track->mPackets->getBufferedDurationUs(&finalResult);
875*ec779b8eSAndroid Build Coastguard Worker // TODO: maxRebufferingMarkMs could be larger than
876*ec779b8eSAndroid Build Coastguard Worker // mBufferingSettings.mResumePlaybackMarkMs
877*ec779b8eSAndroid Build Coastguard Worker int64_t restartBufferingMarkUs =
878*ec779b8eSAndroid Build Coastguard Worker mBufferingSettings.mResumePlaybackMarkMs * 1000LL / 2;
879*ec779b8eSAndroid Build Coastguard Worker if (finalResult == OK) {
880*ec779b8eSAndroid Build Coastguard Worker if (durationUs < restartBufferingMarkUs) {
881*ec779b8eSAndroid Build Coastguard Worker postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
882*ec779b8eSAndroid Build Coastguard Worker }
883*ec779b8eSAndroid Build Coastguard Worker if (track->mPackets->getAvailableBufferCount(&finalResult) < 2
884*ec779b8eSAndroid Build Coastguard Worker && !mSentPauseOnBuffering && !mPreparing) {
885*ec779b8eSAndroid Build Coastguard Worker mCachedSource->resumeFetchingIfNecessary();
886*ec779b8eSAndroid Build Coastguard Worker sendCacheStats();
887*ec779b8eSAndroid Build Coastguard Worker mSentPauseOnBuffering = true;
888*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> notify = dupNotify();
889*ec779b8eSAndroid Build Coastguard Worker notify->setInt32("what", kWhatPauseOnBufferingStart);
890*ec779b8eSAndroid Build Coastguard Worker notify->post();
891*ec779b8eSAndroid Build Coastguard Worker }
892*ec779b8eSAndroid Build Coastguard Worker }
893*ec779b8eSAndroid Build Coastguard Worker }
894*ec779b8eSAndroid Build Coastguard Worker
895*ec779b8eSAndroid Build Coastguard Worker if (result != OK) {
896*ec779b8eSAndroid Build Coastguard Worker if (mSubtitleTrack.mSource != NULL) {
897*ec779b8eSAndroid Build Coastguard Worker mSubtitleTrack.mPackets->clear();
898*ec779b8eSAndroid Build Coastguard Worker mFetchSubtitleDataGeneration++;
899*ec779b8eSAndroid Build Coastguard Worker }
900*ec779b8eSAndroid Build Coastguard Worker if (mTimedTextTrack.mSource != NULL) {
901*ec779b8eSAndroid Build Coastguard Worker mTimedTextTrack.mPackets->clear();
902*ec779b8eSAndroid Build Coastguard Worker mFetchTimedTextDataGeneration++;
903*ec779b8eSAndroid Build Coastguard Worker }
904*ec779b8eSAndroid Build Coastguard Worker return result;
905*ec779b8eSAndroid Build Coastguard Worker }
906*ec779b8eSAndroid Build Coastguard Worker
907*ec779b8eSAndroid Build Coastguard Worker int64_t timeUs;
908*ec779b8eSAndroid Build Coastguard Worker status_t eosResult; // ignored
909*ec779b8eSAndroid Build Coastguard Worker CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
910*ec779b8eSAndroid Build Coastguard Worker if (audio) {
911*ec779b8eSAndroid Build Coastguard Worker mAudioLastDequeueTimeUs = timeUs;
912*ec779b8eSAndroid Build Coastguard Worker } else {
913*ec779b8eSAndroid Build Coastguard Worker mVideoLastDequeueTimeUs = timeUs;
914*ec779b8eSAndroid Build Coastguard Worker }
915*ec779b8eSAndroid Build Coastguard Worker
916*ec779b8eSAndroid Build Coastguard Worker if (mSubtitleTrack.mSource != NULL
917*ec779b8eSAndroid Build Coastguard Worker && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
918*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
919*ec779b8eSAndroid Build Coastguard Worker msg->setInt64("timeUs", timeUs);
920*ec779b8eSAndroid Build Coastguard Worker msg->setInt32("generation", mFetchSubtitleDataGeneration);
921*ec779b8eSAndroid Build Coastguard Worker msg->post();
922*ec779b8eSAndroid Build Coastguard Worker }
923*ec779b8eSAndroid Build Coastguard Worker
924*ec779b8eSAndroid Build Coastguard Worker if (mTimedTextTrack.mSource != NULL
925*ec779b8eSAndroid Build Coastguard Worker && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
926*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
927*ec779b8eSAndroid Build Coastguard Worker msg->setInt64("timeUs", timeUs);
928*ec779b8eSAndroid Build Coastguard Worker msg->setInt32("generation", mFetchTimedTextDataGeneration);
929*ec779b8eSAndroid Build Coastguard Worker msg->post();
930*ec779b8eSAndroid Build Coastguard Worker }
931*ec779b8eSAndroid Build Coastguard Worker
932*ec779b8eSAndroid Build Coastguard Worker return result;
933*ec779b8eSAndroid Build Coastguard Worker }
934*ec779b8eSAndroid Build Coastguard Worker
getDuration(int64_t * durationUs)935*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
936*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
937*ec779b8eSAndroid Build Coastguard Worker *durationUs = mDurationUs;
938*ec779b8eSAndroid Build Coastguard Worker return OK;
939*ec779b8eSAndroid Build Coastguard Worker }
940*ec779b8eSAndroid Build Coastguard Worker
getTrackCount() const941*ec779b8eSAndroid Build Coastguard Worker size_t NuPlayer::GenericSource::getTrackCount() const {
942*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
943*ec779b8eSAndroid Build Coastguard Worker return mSources.size();
944*ec779b8eSAndroid Build Coastguard Worker }
945*ec779b8eSAndroid Build Coastguard Worker
getTrackInfo(size_t trackIndex) const946*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const {
947*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
948*ec779b8eSAndroid Build Coastguard Worker size_t trackCount = mSources.size();
949*ec779b8eSAndroid Build Coastguard Worker if (trackIndex >= trackCount) {
950*ec779b8eSAndroid Build Coastguard Worker return NULL;
951*ec779b8eSAndroid Build Coastguard Worker }
952*ec779b8eSAndroid Build Coastguard Worker
953*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> format = new AMessage();
954*ec779b8eSAndroid Build Coastguard Worker sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat();
955*ec779b8eSAndroid Build Coastguard Worker if (meta == NULL) {
956*ec779b8eSAndroid Build Coastguard Worker ALOGE("no metadata for track %zu", trackIndex);
957*ec779b8eSAndroid Build Coastguard Worker format->setInt32("type", MEDIA_TRACK_TYPE_UNKNOWN);
958*ec779b8eSAndroid Build Coastguard Worker format->setString("mime", "application/octet-stream");
959*ec779b8eSAndroid Build Coastguard Worker format->setString("language", "und");
960*ec779b8eSAndroid Build Coastguard Worker
961*ec779b8eSAndroid Build Coastguard Worker return format;
962*ec779b8eSAndroid Build Coastguard Worker }
963*ec779b8eSAndroid Build Coastguard Worker
964*ec779b8eSAndroid Build Coastguard Worker const char *mime;
965*ec779b8eSAndroid Build Coastguard Worker CHECK(meta->findCString(kKeyMIMEType, &mime));
966*ec779b8eSAndroid Build Coastguard Worker format->setString("mime", mime);
967*ec779b8eSAndroid Build Coastguard Worker
968*ec779b8eSAndroid Build Coastguard Worker int32_t trackType;
969*ec779b8eSAndroid Build Coastguard Worker if (!strncasecmp(mime, "video/", 6)) {
970*ec779b8eSAndroid Build Coastguard Worker trackType = MEDIA_TRACK_TYPE_VIDEO;
971*ec779b8eSAndroid Build Coastguard Worker } else if (!strncasecmp(mime, "audio/", 6)) {
972*ec779b8eSAndroid Build Coastguard Worker trackType = MEDIA_TRACK_TYPE_AUDIO;
973*ec779b8eSAndroid Build Coastguard Worker } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
974*ec779b8eSAndroid Build Coastguard Worker trackType = MEDIA_TRACK_TYPE_TIMEDTEXT;
975*ec779b8eSAndroid Build Coastguard Worker } else {
976*ec779b8eSAndroid Build Coastguard Worker trackType = MEDIA_TRACK_TYPE_UNKNOWN;
977*ec779b8eSAndroid Build Coastguard Worker }
978*ec779b8eSAndroid Build Coastguard Worker format->setInt32("type", trackType);
979*ec779b8eSAndroid Build Coastguard Worker
980*ec779b8eSAndroid Build Coastguard Worker const char *lang;
981*ec779b8eSAndroid Build Coastguard Worker if (!meta->findCString(kKeyMediaLanguage, &lang)) {
982*ec779b8eSAndroid Build Coastguard Worker lang = "und";
983*ec779b8eSAndroid Build Coastguard Worker }
984*ec779b8eSAndroid Build Coastguard Worker format->setString("language", lang);
985*ec779b8eSAndroid Build Coastguard Worker
986*ec779b8eSAndroid Build Coastguard Worker if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
987*ec779b8eSAndroid Build Coastguard Worker int32_t isAutoselect = 1, isDefault = 0, isForced = 0;
988*ec779b8eSAndroid Build Coastguard Worker meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect);
989*ec779b8eSAndroid Build Coastguard Worker meta->findInt32(kKeyTrackIsDefault, &isDefault);
990*ec779b8eSAndroid Build Coastguard Worker meta->findInt32(kKeyTrackIsForced, &isForced);
991*ec779b8eSAndroid Build Coastguard Worker
992*ec779b8eSAndroid Build Coastguard Worker format->setInt32("auto", !!isAutoselect);
993*ec779b8eSAndroid Build Coastguard Worker format->setInt32("default", !!isDefault);
994*ec779b8eSAndroid Build Coastguard Worker format->setInt32("forced", !!isForced);
995*ec779b8eSAndroid Build Coastguard Worker } else if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
996*ec779b8eSAndroid Build Coastguard Worker int32_t hapticChannelCount;
997*ec779b8eSAndroid Build Coastguard Worker if (meta->findInt32(kKeyHapticChannelCount, &hapticChannelCount)) {
998*ec779b8eSAndroid Build Coastguard Worker format->setInt32("haptic-channel-count", hapticChannelCount);
999*ec779b8eSAndroid Build Coastguard Worker }
1000*ec779b8eSAndroid Build Coastguard Worker }
1001*ec779b8eSAndroid Build Coastguard Worker
1002*ec779b8eSAndroid Build Coastguard Worker return format;
1003*ec779b8eSAndroid Build Coastguard Worker }
1004*ec779b8eSAndroid Build Coastguard Worker
getSelectedTrack(media_track_type type) const1005*ec779b8eSAndroid Build Coastguard Worker ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const {
1006*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
1007*ec779b8eSAndroid Build Coastguard Worker const Track *track = NULL;
1008*ec779b8eSAndroid Build Coastguard Worker switch (type) {
1009*ec779b8eSAndroid Build Coastguard Worker case MEDIA_TRACK_TYPE_VIDEO:
1010*ec779b8eSAndroid Build Coastguard Worker track = &mVideoTrack;
1011*ec779b8eSAndroid Build Coastguard Worker break;
1012*ec779b8eSAndroid Build Coastguard Worker case MEDIA_TRACK_TYPE_AUDIO:
1013*ec779b8eSAndroid Build Coastguard Worker track = &mAudioTrack;
1014*ec779b8eSAndroid Build Coastguard Worker break;
1015*ec779b8eSAndroid Build Coastguard Worker case MEDIA_TRACK_TYPE_TIMEDTEXT:
1016*ec779b8eSAndroid Build Coastguard Worker track = &mTimedTextTrack;
1017*ec779b8eSAndroid Build Coastguard Worker break;
1018*ec779b8eSAndroid Build Coastguard Worker case MEDIA_TRACK_TYPE_SUBTITLE:
1019*ec779b8eSAndroid Build Coastguard Worker track = &mSubtitleTrack;
1020*ec779b8eSAndroid Build Coastguard Worker break;
1021*ec779b8eSAndroid Build Coastguard Worker default:
1022*ec779b8eSAndroid Build Coastguard Worker break;
1023*ec779b8eSAndroid Build Coastguard Worker }
1024*ec779b8eSAndroid Build Coastguard Worker
1025*ec779b8eSAndroid Build Coastguard Worker if (track != NULL && track->mSource != NULL) {
1026*ec779b8eSAndroid Build Coastguard Worker return track->mIndex;
1027*ec779b8eSAndroid Build Coastguard Worker }
1028*ec779b8eSAndroid Build Coastguard Worker
1029*ec779b8eSAndroid Build Coastguard Worker return -1;
1030*ec779b8eSAndroid Build Coastguard Worker }
1031*ec779b8eSAndroid Build Coastguard Worker
selectTrack(size_t trackIndex,bool select,int64_t timeUs)1032*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
1033*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
1034*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
1035*ec779b8eSAndroid Build Coastguard Worker
1036*ec779b8eSAndroid Build Coastguard Worker if (trackIndex >= mSources.size()) {
1037*ec779b8eSAndroid Build Coastguard Worker return BAD_INDEX;
1038*ec779b8eSAndroid Build Coastguard Worker }
1039*ec779b8eSAndroid Build Coastguard Worker
1040*ec779b8eSAndroid Build Coastguard Worker if (!select) {
1041*ec779b8eSAndroid Build Coastguard Worker Track* track = NULL;
1042*ec779b8eSAndroid Build Coastguard Worker if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) {
1043*ec779b8eSAndroid Build Coastguard Worker track = &mSubtitleTrack;
1044*ec779b8eSAndroid Build Coastguard Worker mFetchSubtitleDataGeneration++;
1045*ec779b8eSAndroid Build Coastguard Worker } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) {
1046*ec779b8eSAndroid Build Coastguard Worker track = &mTimedTextTrack;
1047*ec779b8eSAndroid Build Coastguard Worker mFetchTimedTextDataGeneration++;
1048*ec779b8eSAndroid Build Coastguard Worker }
1049*ec779b8eSAndroid Build Coastguard Worker if (track == NULL) {
1050*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
1051*ec779b8eSAndroid Build Coastguard Worker }
1052*ec779b8eSAndroid Build Coastguard Worker track->mSource->stop();
1053*ec779b8eSAndroid Build Coastguard Worker track->mSource = NULL;
1054*ec779b8eSAndroid Build Coastguard Worker track->mPackets->clear();
1055*ec779b8eSAndroid Build Coastguard Worker return OK;
1056*ec779b8eSAndroid Build Coastguard Worker }
1057*ec779b8eSAndroid Build Coastguard Worker
1058*ec779b8eSAndroid Build Coastguard Worker const sp<IMediaSource> source = mSources.itemAt(trackIndex);
1059*ec779b8eSAndroid Build Coastguard Worker sp<MetaData> meta = source->getFormat();
1060*ec779b8eSAndroid Build Coastguard Worker const char *mime;
1061*ec779b8eSAndroid Build Coastguard Worker CHECK(meta->findCString(kKeyMIMEType, &mime));
1062*ec779b8eSAndroid Build Coastguard Worker if (!strncasecmp(mime, "text/", 5)) {
1063*ec779b8eSAndroid Build Coastguard Worker bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP);
1064*ec779b8eSAndroid Build Coastguard Worker Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack;
1065*ec779b8eSAndroid Build Coastguard Worker if (track->mSource != NULL && track->mIndex == trackIndex) {
1066*ec779b8eSAndroid Build Coastguard Worker return OK;
1067*ec779b8eSAndroid Build Coastguard Worker }
1068*ec779b8eSAndroid Build Coastguard Worker track->mIndex = trackIndex;
1069*ec779b8eSAndroid Build Coastguard Worker if (track->mSource != NULL) {
1070*ec779b8eSAndroid Build Coastguard Worker track->mSource->stop();
1071*ec779b8eSAndroid Build Coastguard Worker }
1072*ec779b8eSAndroid Build Coastguard Worker track->mSource = mSources.itemAt(trackIndex);
1073*ec779b8eSAndroid Build Coastguard Worker track->mSource->start();
1074*ec779b8eSAndroid Build Coastguard Worker if (track->mPackets == NULL) {
1075*ec779b8eSAndroid Build Coastguard Worker track->mPackets = new AnotherPacketSource(track->mSource->getFormat());
1076*ec779b8eSAndroid Build Coastguard Worker } else {
1077*ec779b8eSAndroid Build Coastguard Worker track->mPackets->clear();
1078*ec779b8eSAndroid Build Coastguard Worker track->mPackets->setFormat(track->mSource->getFormat());
1079*ec779b8eSAndroid Build Coastguard Worker
1080*ec779b8eSAndroid Build Coastguard Worker }
1081*ec779b8eSAndroid Build Coastguard Worker
1082*ec779b8eSAndroid Build Coastguard Worker if (isSubtitle) {
1083*ec779b8eSAndroid Build Coastguard Worker mFetchSubtitleDataGeneration++;
1084*ec779b8eSAndroid Build Coastguard Worker } else {
1085*ec779b8eSAndroid Build Coastguard Worker mFetchTimedTextDataGeneration++;
1086*ec779b8eSAndroid Build Coastguard Worker }
1087*ec779b8eSAndroid Build Coastguard Worker
1088*ec779b8eSAndroid Build Coastguard Worker status_t eosResult; // ignored
1089*ec779b8eSAndroid Build Coastguard Worker if (mSubtitleTrack.mSource != NULL
1090*ec779b8eSAndroid Build Coastguard Worker && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
1091*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
1092*ec779b8eSAndroid Build Coastguard Worker msg->setInt64("timeUs", timeUs);
1093*ec779b8eSAndroid Build Coastguard Worker msg->setInt32("generation", mFetchSubtitleDataGeneration);
1094*ec779b8eSAndroid Build Coastguard Worker msg->post();
1095*ec779b8eSAndroid Build Coastguard Worker }
1096*ec779b8eSAndroid Build Coastguard Worker
1097*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg2 = new AMessage(kWhatSendGlobalTimedTextData, this);
1098*ec779b8eSAndroid Build Coastguard Worker msg2->setInt32("generation", mFetchTimedTextDataGeneration);
1099*ec779b8eSAndroid Build Coastguard Worker msg2->post();
1100*ec779b8eSAndroid Build Coastguard Worker
1101*ec779b8eSAndroid Build Coastguard Worker if (mTimedTextTrack.mSource != NULL
1102*ec779b8eSAndroid Build Coastguard Worker && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
1103*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
1104*ec779b8eSAndroid Build Coastguard Worker msg->setInt64("timeUs", timeUs);
1105*ec779b8eSAndroid Build Coastguard Worker msg->setInt32("generation", mFetchTimedTextDataGeneration);
1106*ec779b8eSAndroid Build Coastguard Worker msg->post();
1107*ec779b8eSAndroid Build Coastguard Worker }
1108*ec779b8eSAndroid Build Coastguard Worker
1109*ec779b8eSAndroid Build Coastguard Worker return OK;
1110*ec779b8eSAndroid Build Coastguard Worker } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
1111*ec779b8eSAndroid Build Coastguard Worker bool audio = !strncasecmp(mime, "audio/", 6);
1112*ec779b8eSAndroid Build Coastguard Worker Track *track = audio ? &mAudioTrack : &mVideoTrack;
1113*ec779b8eSAndroid Build Coastguard Worker if (track->mSource != NULL && track->mIndex == trackIndex) {
1114*ec779b8eSAndroid Build Coastguard Worker return OK;
1115*ec779b8eSAndroid Build Coastguard Worker }
1116*ec779b8eSAndroid Build Coastguard Worker
1117*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage(kWhatChangeAVSource, this);
1118*ec779b8eSAndroid Build Coastguard Worker msg->setInt32("trackIndex", trackIndex);
1119*ec779b8eSAndroid Build Coastguard Worker msg->post();
1120*ec779b8eSAndroid Build Coastguard Worker return OK;
1121*ec779b8eSAndroid Build Coastguard Worker }
1122*ec779b8eSAndroid Build Coastguard Worker
1123*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
1124*ec779b8eSAndroid Build Coastguard Worker }
1125*ec779b8eSAndroid Build Coastguard Worker
seekTo(int64_t seekTimeUs,MediaPlayerSeekMode mode)1126*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
1127*ec779b8eSAndroid Build Coastguard Worker ALOGV("seekTo: %lld, %d", (long long)seekTimeUs, mode);
1128*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage(kWhatSeek, this);
1129*ec779b8eSAndroid Build Coastguard Worker msg->setInt64("seekTimeUs", seekTimeUs);
1130*ec779b8eSAndroid Build Coastguard Worker msg->setInt32("mode", mode);
1131*ec779b8eSAndroid Build Coastguard Worker
1132*ec779b8eSAndroid Build Coastguard Worker // Need to call readBuffer on |mLooper| to ensure the calls to
1133*ec779b8eSAndroid Build Coastguard Worker // IMediaSource::read* are serialized. Note that IMediaSource::read*
1134*ec779b8eSAndroid Build Coastguard Worker // is called without |mLock| acquired and MediaSource is not thread safe.
1135*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> response;
1136*ec779b8eSAndroid Build Coastguard Worker status_t err = msg->postAndAwaitResponse(&response);
1137*ec779b8eSAndroid Build Coastguard Worker if (err == OK && response != NULL) {
1138*ec779b8eSAndroid Build Coastguard Worker CHECK(response->findInt32("err", &err));
1139*ec779b8eSAndroid Build Coastguard Worker }
1140*ec779b8eSAndroid Build Coastguard Worker
1141*ec779b8eSAndroid Build Coastguard Worker return err;
1142*ec779b8eSAndroid Build Coastguard Worker }
1143*ec779b8eSAndroid Build Coastguard Worker
onSeek(const sp<AMessage> & msg)1144*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::onSeek(const sp<AMessage>& msg) {
1145*ec779b8eSAndroid Build Coastguard Worker int64_t seekTimeUs;
1146*ec779b8eSAndroid Build Coastguard Worker int32_t mode;
1147*ec779b8eSAndroid Build Coastguard Worker CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
1148*ec779b8eSAndroid Build Coastguard Worker CHECK(msg->findInt32("mode", &mode));
1149*ec779b8eSAndroid Build Coastguard Worker
1150*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> response = new AMessage;
1151*ec779b8eSAndroid Build Coastguard Worker status_t err = doSeek(seekTimeUs, (MediaPlayerSeekMode)mode);
1152*ec779b8eSAndroid Build Coastguard Worker response->setInt32("err", err);
1153*ec779b8eSAndroid Build Coastguard Worker
1154*ec779b8eSAndroid Build Coastguard Worker sp<AReplyToken> replyID;
1155*ec779b8eSAndroid Build Coastguard Worker CHECK(msg->senderAwaitsResponse(&replyID));
1156*ec779b8eSAndroid Build Coastguard Worker response->postReply(replyID);
1157*ec779b8eSAndroid Build Coastguard Worker }
1158*ec779b8eSAndroid Build Coastguard Worker
doSeek(int64_t seekTimeUs,MediaPlayerSeekMode mode)1159*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
1160*ec779b8eSAndroid Build Coastguard Worker if (mVideoTrack.mSource != NULL) {
1161*ec779b8eSAndroid Build Coastguard Worker ++mVideoDataGeneration;
1162*ec779b8eSAndroid Build Coastguard Worker
1163*ec779b8eSAndroid Build Coastguard Worker int64_t actualTimeUs;
1164*ec779b8eSAndroid Build Coastguard Worker readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, mode, &actualTimeUs);
1165*ec779b8eSAndroid Build Coastguard Worker
1166*ec779b8eSAndroid Build Coastguard Worker if (mode != MediaPlayerSeekMode::SEEK_CLOSEST) {
1167*ec779b8eSAndroid Build Coastguard Worker seekTimeUs = std::max<int64_t>(0, actualTimeUs);
1168*ec779b8eSAndroid Build Coastguard Worker }
1169*ec779b8eSAndroid Build Coastguard Worker mVideoLastDequeueTimeUs = actualTimeUs;
1170*ec779b8eSAndroid Build Coastguard Worker }
1171*ec779b8eSAndroid Build Coastguard Worker
1172*ec779b8eSAndroid Build Coastguard Worker if (mAudioTrack.mSource != NULL) {
1173*ec779b8eSAndroid Build Coastguard Worker ++mAudioDataGeneration;
1174*ec779b8eSAndroid Build Coastguard Worker readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs, MediaPlayerSeekMode::SEEK_CLOSEST);
1175*ec779b8eSAndroid Build Coastguard Worker mAudioLastDequeueTimeUs = seekTimeUs;
1176*ec779b8eSAndroid Build Coastguard Worker }
1177*ec779b8eSAndroid Build Coastguard Worker
1178*ec779b8eSAndroid Build Coastguard Worker if (mSubtitleTrack.mSource != NULL) {
1179*ec779b8eSAndroid Build Coastguard Worker mSubtitleTrack.mPackets->clear();
1180*ec779b8eSAndroid Build Coastguard Worker mFetchSubtitleDataGeneration++;
1181*ec779b8eSAndroid Build Coastguard Worker }
1182*ec779b8eSAndroid Build Coastguard Worker
1183*ec779b8eSAndroid Build Coastguard Worker if (mTimedTextTrack.mSource != NULL) {
1184*ec779b8eSAndroid Build Coastguard Worker mTimedTextTrack.mPackets->clear();
1185*ec779b8eSAndroid Build Coastguard Worker mFetchTimedTextDataGeneration++;
1186*ec779b8eSAndroid Build Coastguard Worker }
1187*ec779b8eSAndroid Build Coastguard Worker
1188*ec779b8eSAndroid Build Coastguard Worker ++mPollBufferingGeneration;
1189*ec779b8eSAndroid Build Coastguard Worker schedulePollBuffering();
1190*ec779b8eSAndroid Build Coastguard Worker return OK;
1191*ec779b8eSAndroid Build Coastguard Worker }
1192*ec779b8eSAndroid Build Coastguard Worker
mediaBufferToABuffer(MediaBufferBase * mb,media_track_type trackType)1193*ec779b8eSAndroid Build Coastguard Worker sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
1194*ec779b8eSAndroid Build Coastguard Worker MediaBufferBase* mb,
1195*ec779b8eSAndroid Build Coastguard Worker media_track_type trackType) {
1196*ec779b8eSAndroid Build Coastguard Worker bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
1197*ec779b8eSAndroid Build Coastguard Worker size_t outLength = mb->range_length();
1198*ec779b8eSAndroid Build Coastguard Worker
1199*ec779b8eSAndroid Build Coastguard Worker if (audio && mAudioIsVorbis) {
1200*ec779b8eSAndroid Build Coastguard Worker outLength += sizeof(int32_t);
1201*ec779b8eSAndroid Build Coastguard Worker }
1202*ec779b8eSAndroid Build Coastguard Worker
1203*ec779b8eSAndroid Build Coastguard Worker sp<ABuffer> ab;
1204*ec779b8eSAndroid Build Coastguard Worker
1205*ec779b8eSAndroid Build Coastguard Worker if (mIsDrmProtected) {
1206*ec779b8eSAndroid Build Coastguard Worker // Modular DRM
1207*ec779b8eSAndroid Build Coastguard Worker // Enabled for both video/audio so 1) media buffer is reused without extra copying
1208*ec779b8eSAndroid Build Coastguard Worker // 2) meta data can be retrieved in onInputBufferFetched for calling queueSecureInputBuffer.
1209*ec779b8eSAndroid Build Coastguard Worker
1210*ec779b8eSAndroid Build Coastguard Worker // data is already provided in the buffer
1211*ec779b8eSAndroid Build Coastguard Worker ab = new ABuffer(NULL, mb->range_length());
1212*ec779b8eSAndroid Build Coastguard Worker ab->meta()->setObject("mediaBufferHolder", new MediaBufferHolder(mb));
1213*ec779b8eSAndroid Build Coastguard Worker
1214*ec779b8eSAndroid Build Coastguard Worker // Modular DRM: Required b/c of the above add_ref.
1215*ec779b8eSAndroid Build Coastguard Worker // If ref>0, there must be an observer, or it'll crash at release().
1216*ec779b8eSAndroid Build Coastguard Worker // TODO: MediaBuffer might need to be revised to ease such need.
1217*ec779b8eSAndroid Build Coastguard Worker mb->setObserver(this);
1218*ec779b8eSAndroid Build Coastguard Worker // Extra increment (since we want to keep mb alive and attached to ab beyond this function
1219*ec779b8eSAndroid Build Coastguard Worker // call. This is to counter the effect of mb->release() towards the end.
1220*ec779b8eSAndroid Build Coastguard Worker mb->add_ref();
1221*ec779b8eSAndroid Build Coastguard Worker
1222*ec779b8eSAndroid Build Coastguard Worker } else {
1223*ec779b8eSAndroid Build Coastguard Worker ab = new ABuffer(outLength);
1224*ec779b8eSAndroid Build Coastguard Worker memcpy(ab->data(),
1225*ec779b8eSAndroid Build Coastguard Worker (const uint8_t *)mb->data() + mb->range_offset(),
1226*ec779b8eSAndroid Build Coastguard Worker mb->range_length());
1227*ec779b8eSAndroid Build Coastguard Worker }
1228*ec779b8eSAndroid Build Coastguard Worker
1229*ec779b8eSAndroid Build Coastguard Worker if (audio && mAudioIsVorbis) {
1230*ec779b8eSAndroid Build Coastguard Worker int32_t numPageSamples;
1231*ec779b8eSAndroid Build Coastguard Worker if (!mb->meta_data().findInt32(kKeyValidSamples, &numPageSamples)) {
1232*ec779b8eSAndroid Build Coastguard Worker numPageSamples = -1;
1233*ec779b8eSAndroid Build Coastguard Worker }
1234*ec779b8eSAndroid Build Coastguard Worker
1235*ec779b8eSAndroid Build Coastguard Worker uint8_t* abEnd = ab->data() + mb->range_length();
1236*ec779b8eSAndroid Build Coastguard Worker memcpy(abEnd, &numPageSamples, sizeof(numPageSamples));
1237*ec779b8eSAndroid Build Coastguard Worker }
1238*ec779b8eSAndroid Build Coastguard Worker
1239*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> meta = ab->meta();
1240*ec779b8eSAndroid Build Coastguard Worker
1241*ec779b8eSAndroid Build Coastguard Worker int64_t timeUs;
1242*ec779b8eSAndroid Build Coastguard Worker CHECK(mb->meta_data().findInt64(kKeyTime, &timeUs));
1243*ec779b8eSAndroid Build Coastguard Worker meta->setInt64("timeUs", timeUs);
1244*ec779b8eSAndroid Build Coastguard Worker
1245*ec779b8eSAndroid Build Coastguard Worker if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
1246*ec779b8eSAndroid Build Coastguard Worker int32_t layerId;
1247*ec779b8eSAndroid Build Coastguard Worker if (mb->meta_data().findInt32(kKeyTemporalLayerId, &layerId)) {
1248*ec779b8eSAndroid Build Coastguard Worker meta->setInt32("temporal-layer-id", layerId);
1249*ec779b8eSAndroid Build Coastguard Worker }
1250*ec779b8eSAndroid Build Coastguard Worker }
1251*ec779b8eSAndroid Build Coastguard Worker
1252*ec779b8eSAndroid Build Coastguard Worker if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
1253*ec779b8eSAndroid Build Coastguard Worker const char *mime;
1254*ec779b8eSAndroid Build Coastguard Worker CHECK(mTimedTextTrack.mSource != NULL
1255*ec779b8eSAndroid Build Coastguard Worker && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime));
1256*ec779b8eSAndroid Build Coastguard Worker meta->setString("mime", mime);
1257*ec779b8eSAndroid Build Coastguard Worker }
1258*ec779b8eSAndroid Build Coastguard Worker
1259*ec779b8eSAndroid Build Coastguard Worker int64_t durationUs;
1260*ec779b8eSAndroid Build Coastguard Worker if (mb->meta_data().findInt64(kKeyDuration, &durationUs)) {
1261*ec779b8eSAndroid Build Coastguard Worker meta->setInt64("durationUs", durationUs);
1262*ec779b8eSAndroid Build Coastguard Worker }
1263*ec779b8eSAndroid Build Coastguard Worker
1264*ec779b8eSAndroid Build Coastguard Worker if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
1265*ec779b8eSAndroid Build Coastguard Worker meta->setInt32("track-index", mSubtitleTrack.mIndex);
1266*ec779b8eSAndroid Build Coastguard Worker }
1267*ec779b8eSAndroid Build Coastguard Worker
1268*ec779b8eSAndroid Build Coastguard Worker uint32_t dataType; // unused
1269*ec779b8eSAndroid Build Coastguard Worker const void *seiData;
1270*ec779b8eSAndroid Build Coastguard Worker size_t seiLength;
1271*ec779b8eSAndroid Build Coastguard Worker if (mb->meta_data().findData(kKeySEI, &dataType, &seiData, &seiLength)) {
1272*ec779b8eSAndroid Build Coastguard Worker sp<ABuffer> sei = ABuffer::CreateAsCopy(seiData, seiLength);;
1273*ec779b8eSAndroid Build Coastguard Worker meta->setBuffer("sei", sei);
1274*ec779b8eSAndroid Build Coastguard Worker }
1275*ec779b8eSAndroid Build Coastguard Worker
1276*ec779b8eSAndroid Build Coastguard Worker const void *mpegUserDataPointer;
1277*ec779b8eSAndroid Build Coastguard Worker size_t mpegUserDataLength;
1278*ec779b8eSAndroid Build Coastguard Worker if (mb->meta_data().findData(
1279*ec779b8eSAndroid Build Coastguard Worker kKeyMpegUserData, &dataType, &mpegUserDataPointer, &mpegUserDataLength)) {
1280*ec779b8eSAndroid Build Coastguard Worker sp<ABuffer> mpegUserData = ABuffer::CreateAsCopy(mpegUserDataPointer, mpegUserDataLength);
1281*ec779b8eSAndroid Build Coastguard Worker meta->setBuffer("mpeg-user-data", mpegUserData);
1282*ec779b8eSAndroid Build Coastguard Worker }
1283*ec779b8eSAndroid Build Coastguard Worker
1284*ec779b8eSAndroid Build Coastguard Worker mb->release();
1285*ec779b8eSAndroid Build Coastguard Worker mb = NULL;
1286*ec779b8eSAndroid Build Coastguard Worker
1287*ec779b8eSAndroid Build Coastguard Worker return ab;
1288*ec779b8eSAndroid Build Coastguard Worker }
1289*ec779b8eSAndroid Build Coastguard Worker
getDataGeneration(media_track_type type) const1290*ec779b8eSAndroid Build Coastguard Worker int32_t NuPlayer::GenericSource::getDataGeneration(media_track_type type) const {
1291*ec779b8eSAndroid Build Coastguard Worker int32_t generation = -1;
1292*ec779b8eSAndroid Build Coastguard Worker switch (type) {
1293*ec779b8eSAndroid Build Coastguard Worker case MEDIA_TRACK_TYPE_VIDEO:
1294*ec779b8eSAndroid Build Coastguard Worker generation = mVideoDataGeneration;
1295*ec779b8eSAndroid Build Coastguard Worker break;
1296*ec779b8eSAndroid Build Coastguard Worker case MEDIA_TRACK_TYPE_AUDIO:
1297*ec779b8eSAndroid Build Coastguard Worker generation = mAudioDataGeneration;
1298*ec779b8eSAndroid Build Coastguard Worker break;
1299*ec779b8eSAndroid Build Coastguard Worker case MEDIA_TRACK_TYPE_TIMEDTEXT:
1300*ec779b8eSAndroid Build Coastguard Worker generation = mFetchTimedTextDataGeneration;
1301*ec779b8eSAndroid Build Coastguard Worker break;
1302*ec779b8eSAndroid Build Coastguard Worker case MEDIA_TRACK_TYPE_SUBTITLE:
1303*ec779b8eSAndroid Build Coastguard Worker generation = mFetchSubtitleDataGeneration;
1304*ec779b8eSAndroid Build Coastguard Worker break;
1305*ec779b8eSAndroid Build Coastguard Worker default:
1306*ec779b8eSAndroid Build Coastguard Worker break;
1307*ec779b8eSAndroid Build Coastguard Worker }
1308*ec779b8eSAndroid Build Coastguard Worker
1309*ec779b8eSAndroid Build Coastguard Worker return generation;
1310*ec779b8eSAndroid Build Coastguard Worker }
1311*ec779b8eSAndroid Build Coastguard Worker
postReadBuffer(media_track_type trackType)1312*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::postReadBuffer(media_track_type trackType) {
1313*ec779b8eSAndroid Build Coastguard Worker if ((mPendingReadBufferTypes & (1 << trackType)) == 0) {
1314*ec779b8eSAndroid Build Coastguard Worker mPendingReadBufferTypes |= (1 << trackType);
1315*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage(kWhatReadBuffer, this);
1316*ec779b8eSAndroid Build Coastguard Worker msg->setInt32("trackType", trackType);
1317*ec779b8eSAndroid Build Coastguard Worker msg->post();
1318*ec779b8eSAndroid Build Coastguard Worker }
1319*ec779b8eSAndroid Build Coastguard Worker }
1320*ec779b8eSAndroid Build Coastguard Worker
onReadBuffer(const sp<AMessage> & msg)1321*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::onReadBuffer(const sp<AMessage>& msg) {
1322*ec779b8eSAndroid Build Coastguard Worker int32_t tmpType;
1323*ec779b8eSAndroid Build Coastguard Worker CHECK(msg->findInt32("trackType", &tmpType));
1324*ec779b8eSAndroid Build Coastguard Worker media_track_type trackType = (media_track_type)tmpType;
1325*ec779b8eSAndroid Build Coastguard Worker mPendingReadBufferTypes &= ~(1 << trackType);
1326*ec779b8eSAndroid Build Coastguard Worker readBuffer(trackType);
1327*ec779b8eSAndroid Build Coastguard Worker }
1328*ec779b8eSAndroid Build Coastguard Worker
readBuffer(media_track_type trackType,int64_t seekTimeUs,MediaPlayerSeekMode mode,int64_t * actualTimeUs,bool formatChange)1329*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::readBuffer(
1330*ec779b8eSAndroid Build Coastguard Worker media_track_type trackType, int64_t seekTimeUs, MediaPlayerSeekMode mode,
1331*ec779b8eSAndroid Build Coastguard Worker int64_t *actualTimeUs, bool formatChange) {
1332*ec779b8eSAndroid Build Coastguard Worker Track *track;
1333*ec779b8eSAndroid Build Coastguard Worker size_t maxBuffers = 1;
1334*ec779b8eSAndroid Build Coastguard Worker switch (trackType) {
1335*ec779b8eSAndroid Build Coastguard Worker case MEDIA_TRACK_TYPE_VIDEO:
1336*ec779b8eSAndroid Build Coastguard Worker track = &mVideoTrack;
1337*ec779b8eSAndroid Build Coastguard Worker maxBuffers = 8; // too large of a number may influence seeks
1338*ec779b8eSAndroid Build Coastguard Worker break;
1339*ec779b8eSAndroid Build Coastguard Worker case MEDIA_TRACK_TYPE_AUDIO:
1340*ec779b8eSAndroid Build Coastguard Worker track = &mAudioTrack;
1341*ec779b8eSAndroid Build Coastguard Worker maxBuffers = 64;
1342*ec779b8eSAndroid Build Coastguard Worker break;
1343*ec779b8eSAndroid Build Coastguard Worker case MEDIA_TRACK_TYPE_SUBTITLE:
1344*ec779b8eSAndroid Build Coastguard Worker track = &mSubtitleTrack;
1345*ec779b8eSAndroid Build Coastguard Worker break;
1346*ec779b8eSAndroid Build Coastguard Worker case MEDIA_TRACK_TYPE_TIMEDTEXT:
1347*ec779b8eSAndroid Build Coastguard Worker track = &mTimedTextTrack;
1348*ec779b8eSAndroid Build Coastguard Worker break;
1349*ec779b8eSAndroid Build Coastguard Worker default:
1350*ec779b8eSAndroid Build Coastguard Worker TRESPASS();
1351*ec779b8eSAndroid Build Coastguard Worker }
1352*ec779b8eSAndroid Build Coastguard Worker
1353*ec779b8eSAndroid Build Coastguard Worker if (track->mSource == NULL) {
1354*ec779b8eSAndroid Build Coastguard Worker return;
1355*ec779b8eSAndroid Build Coastguard Worker }
1356*ec779b8eSAndroid Build Coastguard Worker
1357*ec779b8eSAndroid Build Coastguard Worker if (actualTimeUs) {
1358*ec779b8eSAndroid Build Coastguard Worker *actualTimeUs = seekTimeUs;
1359*ec779b8eSAndroid Build Coastguard Worker }
1360*ec779b8eSAndroid Build Coastguard Worker
1361*ec779b8eSAndroid Build Coastguard Worker MediaSource::ReadOptions options;
1362*ec779b8eSAndroid Build Coastguard Worker
1363*ec779b8eSAndroid Build Coastguard Worker bool seeking = false;
1364*ec779b8eSAndroid Build Coastguard Worker if (seekTimeUs >= 0) {
1365*ec779b8eSAndroid Build Coastguard Worker options.setSeekTo(seekTimeUs, mode);
1366*ec779b8eSAndroid Build Coastguard Worker seeking = true;
1367*ec779b8eSAndroid Build Coastguard Worker }
1368*ec779b8eSAndroid Build Coastguard Worker
1369*ec779b8eSAndroid Build Coastguard Worker const bool couldReadMultiple = (track->mSource->supportReadMultiple());
1370*ec779b8eSAndroid Build Coastguard Worker
1371*ec779b8eSAndroid Build Coastguard Worker if (couldReadMultiple) {
1372*ec779b8eSAndroid Build Coastguard Worker options.setNonBlocking();
1373*ec779b8eSAndroid Build Coastguard Worker }
1374*ec779b8eSAndroid Build Coastguard Worker
1375*ec779b8eSAndroid Build Coastguard Worker int32_t generation = getDataGeneration(trackType);
1376*ec779b8eSAndroid Build Coastguard Worker for (size_t numBuffers = 0; numBuffers < maxBuffers; ) {
1377*ec779b8eSAndroid Build Coastguard Worker Vector<MediaBufferBase *> mediaBuffers;
1378*ec779b8eSAndroid Build Coastguard Worker status_t err = NO_ERROR;
1379*ec779b8eSAndroid Build Coastguard Worker
1380*ec779b8eSAndroid Build Coastguard Worker sp<IMediaSource> source = track->mSource;
1381*ec779b8eSAndroid Build Coastguard Worker mLock.unlock();
1382*ec779b8eSAndroid Build Coastguard Worker if (couldReadMultiple) {
1383*ec779b8eSAndroid Build Coastguard Worker err = source->readMultiple(
1384*ec779b8eSAndroid Build Coastguard Worker &mediaBuffers, maxBuffers - numBuffers, &options);
1385*ec779b8eSAndroid Build Coastguard Worker } else {
1386*ec779b8eSAndroid Build Coastguard Worker MediaBufferBase *mbuf = NULL;
1387*ec779b8eSAndroid Build Coastguard Worker err = source->read(&mbuf, &options);
1388*ec779b8eSAndroid Build Coastguard Worker if (err == OK && mbuf != NULL) {
1389*ec779b8eSAndroid Build Coastguard Worker mediaBuffers.push_back(mbuf);
1390*ec779b8eSAndroid Build Coastguard Worker }
1391*ec779b8eSAndroid Build Coastguard Worker }
1392*ec779b8eSAndroid Build Coastguard Worker mLock.lock();
1393*ec779b8eSAndroid Build Coastguard Worker
1394*ec779b8eSAndroid Build Coastguard Worker options.clearNonPersistent();
1395*ec779b8eSAndroid Build Coastguard Worker
1396*ec779b8eSAndroid Build Coastguard Worker size_t id = 0;
1397*ec779b8eSAndroid Build Coastguard Worker size_t count = mediaBuffers.size();
1398*ec779b8eSAndroid Build Coastguard Worker
1399*ec779b8eSAndroid Build Coastguard Worker // in case track has been changed since we don't have lock for some time.
1400*ec779b8eSAndroid Build Coastguard Worker if (generation != getDataGeneration(trackType)) {
1401*ec779b8eSAndroid Build Coastguard Worker for (; id < count; ++id) {
1402*ec779b8eSAndroid Build Coastguard Worker mediaBuffers[id]->release();
1403*ec779b8eSAndroid Build Coastguard Worker }
1404*ec779b8eSAndroid Build Coastguard Worker break;
1405*ec779b8eSAndroid Build Coastguard Worker }
1406*ec779b8eSAndroid Build Coastguard Worker
1407*ec779b8eSAndroid Build Coastguard Worker for (; id < count; ++id) {
1408*ec779b8eSAndroid Build Coastguard Worker int64_t timeUs;
1409*ec779b8eSAndroid Build Coastguard Worker MediaBufferBase *mbuf = mediaBuffers[id];
1410*ec779b8eSAndroid Build Coastguard Worker if (!mbuf->meta_data().findInt64(kKeyTime, &timeUs)) {
1411*ec779b8eSAndroid Build Coastguard Worker mbuf->meta_data().dumpToLog();
1412*ec779b8eSAndroid Build Coastguard Worker track->mPackets->signalEOS(ERROR_MALFORMED);
1413*ec779b8eSAndroid Build Coastguard Worker break;
1414*ec779b8eSAndroid Build Coastguard Worker }
1415*ec779b8eSAndroid Build Coastguard Worker if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
1416*ec779b8eSAndroid Build Coastguard Worker mAudioTimeUs = timeUs;
1417*ec779b8eSAndroid Build Coastguard Worker } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
1418*ec779b8eSAndroid Build Coastguard Worker mVideoTimeUs = timeUs;
1419*ec779b8eSAndroid Build Coastguard Worker }
1420*ec779b8eSAndroid Build Coastguard Worker
1421*ec779b8eSAndroid Build Coastguard Worker queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
1422*ec779b8eSAndroid Build Coastguard Worker
1423*ec779b8eSAndroid Build Coastguard Worker sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType);
1424*ec779b8eSAndroid Build Coastguard Worker if (numBuffers == 0 && actualTimeUs != nullptr) {
1425*ec779b8eSAndroid Build Coastguard Worker *actualTimeUs = timeUs;
1426*ec779b8eSAndroid Build Coastguard Worker }
1427*ec779b8eSAndroid Build Coastguard Worker if (seeking && buffer != nullptr) {
1428*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> meta = buffer->meta();
1429*ec779b8eSAndroid Build Coastguard Worker if (meta != nullptr && mode == MediaPlayerSeekMode::SEEK_CLOSEST
1430*ec779b8eSAndroid Build Coastguard Worker && seekTimeUs > timeUs) {
1431*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> extra = new AMessage;
1432*ec779b8eSAndroid Build Coastguard Worker extra->setInt64("resume-at-mediaTimeUs", seekTimeUs);
1433*ec779b8eSAndroid Build Coastguard Worker meta->setMessage("extra", extra);
1434*ec779b8eSAndroid Build Coastguard Worker }
1435*ec779b8eSAndroid Build Coastguard Worker }
1436*ec779b8eSAndroid Build Coastguard Worker
1437*ec779b8eSAndroid Build Coastguard Worker track->mPackets->queueAccessUnit(buffer);
1438*ec779b8eSAndroid Build Coastguard Worker formatChange = false;
1439*ec779b8eSAndroid Build Coastguard Worker seeking = false;
1440*ec779b8eSAndroid Build Coastguard Worker ++numBuffers;
1441*ec779b8eSAndroid Build Coastguard Worker }
1442*ec779b8eSAndroid Build Coastguard Worker if (id < count) {
1443*ec779b8eSAndroid Build Coastguard Worker // Error, some mediaBuffer doesn't have kKeyTime.
1444*ec779b8eSAndroid Build Coastguard Worker for (; id < count; ++id) {
1445*ec779b8eSAndroid Build Coastguard Worker mediaBuffers[id]->release();
1446*ec779b8eSAndroid Build Coastguard Worker }
1447*ec779b8eSAndroid Build Coastguard Worker break;
1448*ec779b8eSAndroid Build Coastguard Worker }
1449*ec779b8eSAndroid Build Coastguard Worker
1450*ec779b8eSAndroid Build Coastguard Worker if (err == WOULD_BLOCK) {
1451*ec779b8eSAndroid Build Coastguard Worker break;
1452*ec779b8eSAndroid Build Coastguard Worker } else if (err == INFO_FORMAT_CHANGED) {
1453*ec779b8eSAndroid Build Coastguard Worker #if 0
1454*ec779b8eSAndroid Build Coastguard Worker track->mPackets->queueDiscontinuity(
1455*ec779b8eSAndroid Build Coastguard Worker ATSParser::DISCONTINUITY_FORMATCHANGE,
1456*ec779b8eSAndroid Build Coastguard Worker NULL,
1457*ec779b8eSAndroid Build Coastguard Worker false /* discard */);
1458*ec779b8eSAndroid Build Coastguard Worker #endif
1459*ec779b8eSAndroid Build Coastguard Worker } else if (err != OK) {
1460*ec779b8eSAndroid Build Coastguard Worker queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
1461*ec779b8eSAndroid Build Coastguard Worker track->mPackets->signalEOS(err);
1462*ec779b8eSAndroid Build Coastguard Worker break;
1463*ec779b8eSAndroid Build Coastguard Worker }
1464*ec779b8eSAndroid Build Coastguard Worker }
1465*ec779b8eSAndroid Build Coastguard Worker
1466*ec779b8eSAndroid Build Coastguard Worker if (mIsStreaming
1467*ec779b8eSAndroid Build Coastguard Worker && (trackType == MEDIA_TRACK_TYPE_VIDEO || trackType == MEDIA_TRACK_TYPE_AUDIO)) {
1468*ec779b8eSAndroid Build Coastguard Worker status_t finalResult;
1469*ec779b8eSAndroid Build Coastguard Worker int64_t durationUs = track->mPackets->getBufferedDurationUs(&finalResult);
1470*ec779b8eSAndroid Build Coastguard Worker
1471*ec779b8eSAndroid Build Coastguard Worker // TODO: maxRebufferingMarkMs could be larger than
1472*ec779b8eSAndroid Build Coastguard Worker // mBufferingSettings.mResumePlaybackMarkMs
1473*ec779b8eSAndroid Build Coastguard Worker int64_t markUs = (mPreparing ? mBufferingSettings.mInitialMarkMs
1474*ec779b8eSAndroid Build Coastguard Worker : mBufferingSettings.mResumePlaybackMarkMs) * 1000LL;
1475*ec779b8eSAndroid Build Coastguard Worker if (finalResult == ERROR_END_OF_STREAM || durationUs >= markUs) {
1476*ec779b8eSAndroid Build Coastguard Worker if (mPreparing || mSentPauseOnBuffering) {
1477*ec779b8eSAndroid Build Coastguard Worker Track *counterTrack =
1478*ec779b8eSAndroid Build Coastguard Worker (trackType == MEDIA_TRACK_TYPE_VIDEO ? &mAudioTrack : &mVideoTrack);
1479*ec779b8eSAndroid Build Coastguard Worker if (counterTrack->mSource != NULL) {
1480*ec779b8eSAndroid Build Coastguard Worker durationUs = counterTrack->mPackets->getBufferedDurationUs(&finalResult);
1481*ec779b8eSAndroid Build Coastguard Worker }
1482*ec779b8eSAndroid Build Coastguard Worker if (finalResult == ERROR_END_OF_STREAM || durationUs >= markUs) {
1483*ec779b8eSAndroid Build Coastguard Worker if (mPreparing) {
1484*ec779b8eSAndroid Build Coastguard Worker notifyPrepared();
1485*ec779b8eSAndroid Build Coastguard Worker mPreparing = false;
1486*ec779b8eSAndroid Build Coastguard Worker } else {
1487*ec779b8eSAndroid Build Coastguard Worker sendCacheStats();
1488*ec779b8eSAndroid Build Coastguard Worker mSentPauseOnBuffering = false;
1489*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> notify = dupNotify();
1490*ec779b8eSAndroid Build Coastguard Worker notify->setInt32("what", kWhatResumeOnBufferingEnd);
1491*ec779b8eSAndroid Build Coastguard Worker notify->post();
1492*ec779b8eSAndroid Build Coastguard Worker }
1493*ec779b8eSAndroid Build Coastguard Worker }
1494*ec779b8eSAndroid Build Coastguard Worker }
1495*ec779b8eSAndroid Build Coastguard Worker return;
1496*ec779b8eSAndroid Build Coastguard Worker }
1497*ec779b8eSAndroid Build Coastguard Worker
1498*ec779b8eSAndroid Build Coastguard Worker postReadBuffer(trackType);
1499*ec779b8eSAndroid Build Coastguard Worker }
1500*ec779b8eSAndroid Build Coastguard Worker }
1501*ec779b8eSAndroid Build Coastguard Worker
queueDiscontinuityIfNeeded(bool seeking,bool formatChange,media_track_type trackType,Track * track)1502*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::queueDiscontinuityIfNeeded(
1503*ec779b8eSAndroid Build Coastguard Worker bool seeking, bool formatChange, media_track_type trackType, Track *track) {
1504*ec779b8eSAndroid Build Coastguard Worker // formatChange && seeking: track whose source is changed during selection
1505*ec779b8eSAndroid Build Coastguard Worker // formatChange && !seeking: track whose source is not changed during selection
1506*ec779b8eSAndroid Build Coastguard Worker // !formatChange: normal seek
1507*ec779b8eSAndroid Build Coastguard Worker if ((seeking || formatChange)
1508*ec779b8eSAndroid Build Coastguard Worker && (trackType == MEDIA_TRACK_TYPE_AUDIO
1509*ec779b8eSAndroid Build Coastguard Worker || trackType == MEDIA_TRACK_TYPE_VIDEO)) {
1510*ec779b8eSAndroid Build Coastguard Worker ATSParser::DiscontinuityType type = (formatChange && seeking)
1511*ec779b8eSAndroid Build Coastguard Worker ? ATSParser::DISCONTINUITY_FORMATCHANGE
1512*ec779b8eSAndroid Build Coastguard Worker : ATSParser::DISCONTINUITY_NONE;
1513*ec779b8eSAndroid Build Coastguard Worker track->mPackets->queueDiscontinuity(type, NULL /* extra */, true /* discard */);
1514*ec779b8eSAndroid Build Coastguard Worker }
1515*ec779b8eSAndroid Build Coastguard Worker }
1516*ec779b8eSAndroid Build Coastguard Worker
notifyBufferingUpdate(int32_t percentage)1517*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::notifyBufferingUpdate(int32_t percentage) {
1518*ec779b8eSAndroid Build Coastguard Worker // Buffering percent could go backward as it's estimated from remaining
1519*ec779b8eSAndroid Build Coastguard Worker // data and last access time. This could cause the buffering position
1520*ec779b8eSAndroid Build Coastguard Worker // drawn on media control to jitter slightly. Remember previously reported
1521*ec779b8eSAndroid Build Coastguard Worker // percentage and don't allow it to go backward.
1522*ec779b8eSAndroid Build Coastguard Worker if (percentage < mPrevBufferPercentage) {
1523*ec779b8eSAndroid Build Coastguard Worker percentage = mPrevBufferPercentage;
1524*ec779b8eSAndroid Build Coastguard Worker } else if (percentage > 100) {
1525*ec779b8eSAndroid Build Coastguard Worker percentage = 100;
1526*ec779b8eSAndroid Build Coastguard Worker }
1527*ec779b8eSAndroid Build Coastguard Worker
1528*ec779b8eSAndroid Build Coastguard Worker mPrevBufferPercentage = percentage;
1529*ec779b8eSAndroid Build Coastguard Worker
1530*ec779b8eSAndroid Build Coastguard Worker ALOGV("notifyBufferingUpdate: buffering %d%%", percentage);
1531*ec779b8eSAndroid Build Coastguard Worker
1532*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> notify = dupNotify();
1533*ec779b8eSAndroid Build Coastguard Worker notify->setInt32("what", kWhatBufferingUpdate);
1534*ec779b8eSAndroid Build Coastguard Worker notify->setInt32("percentage", percentage);
1535*ec779b8eSAndroid Build Coastguard Worker notify->post();
1536*ec779b8eSAndroid Build Coastguard Worker }
1537*ec779b8eSAndroid Build Coastguard Worker
schedulePollBuffering()1538*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::schedulePollBuffering() {
1539*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
1540*ec779b8eSAndroid Build Coastguard Worker msg->setInt32("generation", mPollBufferingGeneration);
1541*ec779b8eSAndroid Build Coastguard Worker // Enquires buffering status every second.
1542*ec779b8eSAndroid Build Coastguard Worker msg->post(1000000LL);
1543*ec779b8eSAndroid Build Coastguard Worker }
1544*ec779b8eSAndroid Build Coastguard Worker
onPollBuffering()1545*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::onPollBuffering() {
1546*ec779b8eSAndroid Build Coastguard Worker status_t finalStatus = UNKNOWN_ERROR;
1547*ec779b8eSAndroid Build Coastguard Worker int64_t cachedDurationUs = -1LL;
1548*ec779b8eSAndroid Build Coastguard Worker ssize_t cachedDataRemaining = -1;
1549*ec779b8eSAndroid Build Coastguard Worker
1550*ec779b8eSAndroid Build Coastguard Worker if (mCachedSource != NULL) {
1551*ec779b8eSAndroid Build Coastguard Worker cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
1552*ec779b8eSAndroid Build Coastguard Worker
1553*ec779b8eSAndroid Build Coastguard Worker if (finalStatus == OK) {
1554*ec779b8eSAndroid Build Coastguard Worker off64_t size;
1555*ec779b8eSAndroid Build Coastguard Worker int64_t bitrate = 0LL;
1556*ec779b8eSAndroid Build Coastguard Worker if (mDurationUs > 0 && mCachedSource->getSize(&size) == OK) {
1557*ec779b8eSAndroid Build Coastguard Worker // |bitrate| uses bits/second unit, while size is number of bytes.
1558*ec779b8eSAndroid Build Coastguard Worker bitrate = size * 8000000LL / mDurationUs;
1559*ec779b8eSAndroid Build Coastguard Worker } else if (mBitrate > 0) {
1560*ec779b8eSAndroid Build Coastguard Worker bitrate = mBitrate;
1561*ec779b8eSAndroid Build Coastguard Worker }
1562*ec779b8eSAndroid Build Coastguard Worker if (bitrate > 0) {
1563*ec779b8eSAndroid Build Coastguard Worker cachedDurationUs = cachedDataRemaining * 8000000LL / bitrate;
1564*ec779b8eSAndroid Build Coastguard Worker }
1565*ec779b8eSAndroid Build Coastguard Worker }
1566*ec779b8eSAndroid Build Coastguard Worker }
1567*ec779b8eSAndroid Build Coastguard Worker
1568*ec779b8eSAndroid Build Coastguard Worker if (finalStatus != OK) {
1569*ec779b8eSAndroid Build Coastguard Worker ALOGV("onPollBuffering: EOS (finalStatus = %d)", finalStatus);
1570*ec779b8eSAndroid Build Coastguard Worker
1571*ec779b8eSAndroid Build Coastguard Worker if (finalStatus == ERROR_END_OF_STREAM) {
1572*ec779b8eSAndroid Build Coastguard Worker notifyBufferingUpdate(100);
1573*ec779b8eSAndroid Build Coastguard Worker }
1574*ec779b8eSAndroid Build Coastguard Worker
1575*ec779b8eSAndroid Build Coastguard Worker if (mPreparing) {
1576*ec779b8eSAndroid Build Coastguard Worker notifyPreparedAndCleanup(finalStatus == ERROR_END_OF_STREAM ? OK : finalStatus);
1577*ec779b8eSAndroid Build Coastguard Worker mPreparing = false;
1578*ec779b8eSAndroid Build Coastguard Worker } else if (mSentPauseOnBuffering) {
1579*ec779b8eSAndroid Build Coastguard Worker sendCacheStats();
1580*ec779b8eSAndroid Build Coastguard Worker mSentPauseOnBuffering = false;
1581*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> notify = dupNotify();
1582*ec779b8eSAndroid Build Coastguard Worker notify->setInt32("what", kWhatResumeOnBufferingEnd);
1583*ec779b8eSAndroid Build Coastguard Worker notify->post();
1584*ec779b8eSAndroid Build Coastguard Worker }
1585*ec779b8eSAndroid Build Coastguard Worker return;
1586*ec779b8eSAndroid Build Coastguard Worker }
1587*ec779b8eSAndroid Build Coastguard Worker
1588*ec779b8eSAndroid Build Coastguard Worker if (cachedDurationUs >= 0LL) {
1589*ec779b8eSAndroid Build Coastguard Worker if (mDurationUs > 0LL) {
1590*ec779b8eSAndroid Build Coastguard Worker int64_t cachedPosUs = getLastReadPosition() + cachedDurationUs;
1591*ec779b8eSAndroid Build Coastguard Worker int percentage = 100.0 * cachedPosUs / mDurationUs;
1592*ec779b8eSAndroid Build Coastguard Worker if (percentage > 100) {
1593*ec779b8eSAndroid Build Coastguard Worker percentage = 100;
1594*ec779b8eSAndroid Build Coastguard Worker }
1595*ec779b8eSAndroid Build Coastguard Worker
1596*ec779b8eSAndroid Build Coastguard Worker notifyBufferingUpdate(percentage);
1597*ec779b8eSAndroid Build Coastguard Worker }
1598*ec779b8eSAndroid Build Coastguard Worker
1599*ec779b8eSAndroid Build Coastguard Worker ALOGV("onPollBuffering: cachedDurationUs %.1f sec", cachedDurationUs / 1000000.0f);
1600*ec779b8eSAndroid Build Coastguard Worker }
1601*ec779b8eSAndroid Build Coastguard Worker
1602*ec779b8eSAndroid Build Coastguard Worker schedulePollBuffering();
1603*ec779b8eSAndroid Build Coastguard Worker }
1604*ec779b8eSAndroid Build Coastguard Worker
1605*ec779b8eSAndroid Build Coastguard Worker // Modular DRM
prepareDrm(const uint8_t uuid[16],const Vector<uint8_t> & drmSessionId,sp<ICrypto> * outCrypto)1606*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::GenericSource::prepareDrm(
1607*ec779b8eSAndroid Build Coastguard Worker const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId, sp<ICrypto> *outCrypto) {
1608*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
1609*ec779b8eSAndroid Build Coastguard Worker ALOGV("prepareDrm");
1610*ec779b8eSAndroid Build Coastguard Worker
1611*ec779b8eSAndroid Build Coastguard Worker mIsDrmProtected = false;
1612*ec779b8eSAndroid Build Coastguard Worker mIsDrmReleased = false;
1613*ec779b8eSAndroid Build Coastguard Worker mIsSecure = false;
1614*ec779b8eSAndroid Build Coastguard Worker
1615*ec779b8eSAndroid Build Coastguard Worker status_t status = OK;
1616*ec779b8eSAndroid Build Coastguard Worker sp<ICrypto> crypto = NuPlayerDrm::createCryptoAndPlugin(uuid, drmSessionId, status);
1617*ec779b8eSAndroid Build Coastguard Worker if (crypto == NULL) {
1618*ec779b8eSAndroid Build Coastguard Worker ALOGE("prepareDrm: createCrypto failed. status: %d", status);
1619*ec779b8eSAndroid Build Coastguard Worker return status;
1620*ec779b8eSAndroid Build Coastguard Worker }
1621*ec779b8eSAndroid Build Coastguard Worker ALOGV("prepareDrm: createCryptoAndPlugin succeeded for uuid: %s",
1622*ec779b8eSAndroid Build Coastguard Worker DrmUUID::toHexString(uuid).c_str());
1623*ec779b8eSAndroid Build Coastguard Worker
1624*ec779b8eSAndroid Build Coastguard Worker *outCrypto = crypto;
1625*ec779b8eSAndroid Build Coastguard Worker // as long a there is an active crypto
1626*ec779b8eSAndroid Build Coastguard Worker mIsDrmProtected = true;
1627*ec779b8eSAndroid Build Coastguard Worker
1628*ec779b8eSAndroid Build Coastguard Worker if (mMimes.size() == 0) {
1629*ec779b8eSAndroid Build Coastguard Worker status = UNKNOWN_ERROR;
1630*ec779b8eSAndroid Build Coastguard Worker ALOGE("prepareDrm: Unexpected. Must have at least one track. status: %d", status);
1631*ec779b8eSAndroid Build Coastguard Worker return status;
1632*ec779b8eSAndroid Build Coastguard Worker }
1633*ec779b8eSAndroid Build Coastguard Worker
1634*ec779b8eSAndroid Build Coastguard Worker // first mime in this list is either the video track, or the first audio track
1635*ec779b8eSAndroid Build Coastguard Worker const char *mime = mMimes[0].c_str();
1636*ec779b8eSAndroid Build Coastguard Worker mIsSecure = crypto->requiresSecureDecoderComponent(mime);
1637*ec779b8eSAndroid Build Coastguard Worker ALOGV("prepareDrm: requiresSecureDecoderComponent mime: %s isSecure: %d",
1638*ec779b8eSAndroid Build Coastguard Worker mime, mIsSecure);
1639*ec779b8eSAndroid Build Coastguard Worker
1640*ec779b8eSAndroid Build Coastguard Worker // Checking the member flags while in the looper to send out the notification.
1641*ec779b8eSAndroid Build Coastguard Worker // The legacy mDecryptHandle!=NULL check (for FLAG_PROTECTED) is equivalent to mIsDrmProtected.
1642*ec779b8eSAndroid Build Coastguard Worker notifyFlagsChanged(
1643*ec779b8eSAndroid Build Coastguard Worker (mIsSecure ? FLAG_SECURE : 0) |
1644*ec779b8eSAndroid Build Coastguard Worker // Setting "protected screen" only for L1: b/38390836
1645*ec779b8eSAndroid Build Coastguard Worker (mIsSecure ? FLAG_PROTECTED : 0) |
1646*ec779b8eSAndroid Build Coastguard Worker FLAG_CAN_PAUSE |
1647*ec779b8eSAndroid Build Coastguard Worker FLAG_CAN_SEEK_BACKWARD |
1648*ec779b8eSAndroid Build Coastguard Worker FLAG_CAN_SEEK_FORWARD |
1649*ec779b8eSAndroid Build Coastguard Worker FLAG_CAN_SEEK);
1650*ec779b8eSAndroid Build Coastguard Worker
1651*ec779b8eSAndroid Build Coastguard Worker if (status == OK) {
1652*ec779b8eSAndroid Build Coastguard Worker ALOGV("prepareDrm: mCrypto: %p (%d)", outCrypto->get(),
1653*ec779b8eSAndroid Build Coastguard Worker (*outCrypto != NULL ? (*outCrypto)->getStrongCount() : 0));
1654*ec779b8eSAndroid Build Coastguard Worker ALOGD("prepareDrm ret: %d ", status);
1655*ec779b8eSAndroid Build Coastguard Worker } else {
1656*ec779b8eSAndroid Build Coastguard Worker ALOGE("prepareDrm err: %d", status);
1657*ec779b8eSAndroid Build Coastguard Worker }
1658*ec779b8eSAndroid Build Coastguard Worker return status;
1659*ec779b8eSAndroid Build Coastguard Worker }
1660*ec779b8eSAndroid Build Coastguard Worker
releaseDrm()1661*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::GenericSource::releaseDrm() {
1662*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
1663*ec779b8eSAndroid Build Coastguard Worker ALOGV("releaseDrm");
1664*ec779b8eSAndroid Build Coastguard Worker
1665*ec779b8eSAndroid Build Coastguard Worker if (mIsDrmProtected) {
1666*ec779b8eSAndroid Build Coastguard Worker mIsDrmProtected = false;
1667*ec779b8eSAndroid Build Coastguard Worker // to prevent returning any more buffer after stop/releaseDrm (b/37960096)
1668*ec779b8eSAndroid Build Coastguard Worker mIsDrmReleased = true;
1669*ec779b8eSAndroid Build Coastguard Worker ALOGV("releaseDrm: mIsDrmProtected is reset.");
1670*ec779b8eSAndroid Build Coastguard Worker } else {
1671*ec779b8eSAndroid Build Coastguard Worker ALOGE("releaseDrm: mIsDrmProtected is already false.");
1672*ec779b8eSAndroid Build Coastguard Worker }
1673*ec779b8eSAndroid Build Coastguard Worker
1674*ec779b8eSAndroid Build Coastguard Worker return OK;
1675*ec779b8eSAndroid Build Coastguard Worker }
1676*ec779b8eSAndroid Build Coastguard Worker
checkDrmInfo()1677*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::GenericSource::checkDrmInfo()
1678*ec779b8eSAndroid Build Coastguard Worker {
1679*ec779b8eSAndroid Build Coastguard Worker // clearing the flag at prepare in case the player is reused after stop/releaseDrm with the
1680*ec779b8eSAndroid Build Coastguard Worker // same source without being reset (called by prepareAsync/initFromDataSource)
1681*ec779b8eSAndroid Build Coastguard Worker mIsDrmReleased = false;
1682*ec779b8eSAndroid Build Coastguard Worker
1683*ec779b8eSAndroid Build Coastguard Worker if (mFileMeta == NULL) {
1684*ec779b8eSAndroid Build Coastguard Worker ALOGI("checkDrmInfo: No metadata");
1685*ec779b8eSAndroid Build Coastguard Worker return OK; // letting the caller responds accordingly
1686*ec779b8eSAndroid Build Coastguard Worker }
1687*ec779b8eSAndroid Build Coastguard Worker
1688*ec779b8eSAndroid Build Coastguard Worker uint32_t type;
1689*ec779b8eSAndroid Build Coastguard Worker const void *pssh;
1690*ec779b8eSAndroid Build Coastguard Worker size_t psshsize;
1691*ec779b8eSAndroid Build Coastguard Worker
1692*ec779b8eSAndroid Build Coastguard Worker if (!mFileMeta->findData(kKeyPssh, &type, &pssh, &psshsize)) {
1693*ec779b8eSAndroid Build Coastguard Worker ALOGV("checkDrmInfo: No PSSH");
1694*ec779b8eSAndroid Build Coastguard Worker return OK; // source without DRM info
1695*ec779b8eSAndroid Build Coastguard Worker }
1696*ec779b8eSAndroid Build Coastguard Worker
1697*ec779b8eSAndroid Build Coastguard Worker Parcel parcel;
1698*ec779b8eSAndroid Build Coastguard Worker NuPlayerDrm::retrieveDrmInfo(pssh, psshsize, &parcel);
1699*ec779b8eSAndroid Build Coastguard Worker ALOGV("checkDrmInfo: MEDIA_DRM_INFO PSSH size: %d Parcel size: %d objects#: %d",
1700*ec779b8eSAndroid Build Coastguard Worker (int)psshsize, (int)parcel.dataSize(), (int)parcel.objectsCount());
1701*ec779b8eSAndroid Build Coastguard Worker
1702*ec779b8eSAndroid Build Coastguard Worker if (parcel.dataSize() == 0) {
1703*ec779b8eSAndroid Build Coastguard Worker ALOGE("checkDrmInfo: Unexpected parcel size: 0");
1704*ec779b8eSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
1705*ec779b8eSAndroid Build Coastguard Worker }
1706*ec779b8eSAndroid Build Coastguard Worker
1707*ec779b8eSAndroid Build Coastguard Worker // Can't pass parcel as a message to the player. Converting Parcel->ABuffer to pass it
1708*ec779b8eSAndroid Build Coastguard Worker // to the Player's onSourceNotify then back to Parcel for calling driver's notifyListener.
1709*ec779b8eSAndroid Build Coastguard Worker sp<ABuffer> drmInfoBuffer = ABuffer::CreateAsCopy(parcel.data(), parcel.dataSize());
1710*ec779b8eSAndroid Build Coastguard Worker notifyDrmInfo(drmInfoBuffer);
1711*ec779b8eSAndroid Build Coastguard Worker
1712*ec779b8eSAndroid Build Coastguard Worker return OK;
1713*ec779b8eSAndroid Build Coastguard Worker }
1714*ec779b8eSAndroid Build Coastguard Worker
signalBufferReturned(MediaBufferBase * buffer)1715*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::GenericSource::signalBufferReturned(MediaBufferBase *buffer)
1716*ec779b8eSAndroid Build Coastguard Worker {
1717*ec779b8eSAndroid Build Coastguard Worker //ALOGV("signalBufferReturned %p refCount: %d", buffer, buffer->localRefcount());
1718*ec779b8eSAndroid Build Coastguard Worker
1719*ec779b8eSAndroid Build Coastguard Worker buffer->setObserver(NULL);
1720*ec779b8eSAndroid Build Coastguard Worker buffer->release(); // this leads to delete since that there is no observor
1721*ec779b8eSAndroid Build Coastguard Worker }
1722*ec779b8eSAndroid Build Coastguard Worker
1723*ec779b8eSAndroid Build Coastguard Worker } // namespace android
1724