xref: /aosp_15_r20/frameworks/av/media/libmediaplayerservice/nuplayer/GenericSource.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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> &notify,
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