xref: /aosp_15_r20/frameworks/av/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2010 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 "HTTPLiveSource"
19*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
20*ec779b8eSAndroid Build Coastguard Worker 
21*ec779b8eSAndroid Build Coastguard Worker #include "HTTPLiveSource.h"
22*ec779b8eSAndroid Build Coastguard Worker #include "LiveDataSource.h"
23*ec779b8eSAndroid Build Coastguard Worker 
24*ec779b8eSAndroid Build Coastguard Worker #include <media/IMediaHTTPService.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ABuffer.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/AMessage.h>
28*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaErrors.h>
29*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MetaData.h>
30*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaDefs.h>
31*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/Utils.h>
32*ec779b8eSAndroid Build Coastguard Worker #include <mpeg2ts/AnotherPacketSource.h>
33*ec779b8eSAndroid Build Coastguard Worker 
34*ec779b8eSAndroid Build Coastguard Worker // default buffer prepare/ready/underflow marks
35*ec779b8eSAndroid Build Coastguard Worker static const int kReadyMarkMs     = 5000;  // 5 seconds
36*ec779b8eSAndroid Build Coastguard Worker static const int kPrepareMarkMs   = 1500;  // 1.5 seconds
37*ec779b8eSAndroid Build Coastguard Worker 
38*ec779b8eSAndroid Build Coastguard Worker namespace android {
39*ec779b8eSAndroid Build Coastguard Worker 
HTTPLiveSource(const sp<AMessage> & notify,const sp<IMediaHTTPService> & httpService,const char * url,const KeyedVector<String8,String8> * headers)40*ec779b8eSAndroid Build Coastguard Worker NuPlayer::HTTPLiveSource::HTTPLiveSource(
41*ec779b8eSAndroid Build Coastguard Worker         const sp<AMessage> &notify,
42*ec779b8eSAndroid Build Coastguard Worker         const sp<IMediaHTTPService> &httpService,
43*ec779b8eSAndroid Build Coastguard Worker         const char *url,
44*ec779b8eSAndroid Build Coastguard Worker         const KeyedVector<String8, String8> *headers)
45*ec779b8eSAndroid Build Coastguard Worker     : Source(notify),
46*ec779b8eSAndroid Build Coastguard Worker       mHTTPService(httpService),
47*ec779b8eSAndroid Build Coastguard Worker       mURL(url),
48*ec779b8eSAndroid Build Coastguard Worker       mFlags(0),
49*ec779b8eSAndroid Build Coastguard Worker       mFinalResult(OK),
50*ec779b8eSAndroid Build Coastguard Worker       mOffset(0),
51*ec779b8eSAndroid Build Coastguard Worker       mFetchSubtitleDataGeneration(0),
52*ec779b8eSAndroid Build Coastguard Worker       mFetchMetaDataGeneration(0),
53*ec779b8eSAndroid Build Coastguard Worker       mHasMetadata(false),
54*ec779b8eSAndroid Build Coastguard Worker       mMetadataSelected(false) {
55*ec779b8eSAndroid Build Coastguard Worker     mBufferingSettings.mInitialMarkMs = kPrepareMarkMs;
56*ec779b8eSAndroid Build Coastguard Worker     mBufferingSettings.mResumePlaybackMarkMs = kReadyMarkMs;
57*ec779b8eSAndroid Build Coastguard Worker     if (headers) {
58*ec779b8eSAndroid Build Coastguard Worker         mExtraHeaders = *headers;
59*ec779b8eSAndroid Build Coastguard Worker 
60*ec779b8eSAndroid Build Coastguard Worker         ssize_t index =
61*ec779b8eSAndroid Build Coastguard Worker             mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
62*ec779b8eSAndroid Build Coastguard Worker 
63*ec779b8eSAndroid Build Coastguard Worker         if (index >= 0) {
64*ec779b8eSAndroid Build Coastguard Worker             mFlags |= kFlagIncognito;
65*ec779b8eSAndroid Build Coastguard Worker 
66*ec779b8eSAndroid Build Coastguard Worker             mExtraHeaders.removeItemsAt(index);
67*ec779b8eSAndroid Build Coastguard Worker         }
68*ec779b8eSAndroid Build Coastguard Worker     }
69*ec779b8eSAndroid Build Coastguard Worker }
70*ec779b8eSAndroid Build Coastguard Worker 
~HTTPLiveSource()71*ec779b8eSAndroid Build Coastguard Worker NuPlayer::HTTPLiveSource::~HTTPLiveSource() {
72*ec779b8eSAndroid Build Coastguard Worker     if (mLiveSession != NULL) {
73*ec779b8eSAndroid Build Coastguard Worker         mLiveSession->disconnect();
74*ec779b8eSAndroid Build Coastguard Worker 
75*ec779b8eSAndroid Build Coastguard Worker         mLiveLooper->unregisterHandler(mLiveSession->id());
76*ec779b8eSAndroid Build Coastguard Worker         mLiveLooper->unregisterHandler(id());
77*ec779b8eSAndroid Build Coastguard Worker         mLiveLooper->stop();
78*ec779b8eSAndroid Build Coastguard Worker 
79*ec779b8eSAndroid Build Coastguard Worker         mLiveSession.clear();
80*ec779b8eSAndroid Build Coastguard Worker         mLiveLooper.clear();
81*ec779b8eSAndroid Build Coastguard Worker     }
82*ec779b8eSAndroid Build Coastguard Worker }
83*ec779b8eSAndroid Build Coastguard Worker 
getBufferingSettings(BufferingSettings * buffering)84*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::HTTPLiveSource::getBufferingSettings(
85*ec779b8eSAndroid Build Coastguard Worker             BufferingSettings* buffering /* nonnull */) {
86*ec779b8eSAndroid Build Coastguard Worker     *buffering = mBufferingSettings;
87*ec779b8eSAndroid Build Coastguard Worker 
88*ec779b8eSAndroid Build Coastguard Worker     return OK;
89*ec779b8eSAndroid Build Coastguard Worker }
90*ec779b8eSAndroid Build Coastguard Worker 
setBufferingSettings(const BufferingSettings & buffering)91*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::HTTPLiveSource::setBufferingSettings(const BufferingSettings& buffering) {
92*ec779b8eSAndroid Build Coastguard Worker     mBufferingSettings = buffering;
93*ec779b8eSAndroid Build Coastguard Worker 
94*ec779b8eSAndroid Build Coastguard Worker     if (mLiveSession != NULL) {
95*ec779b8eSAndroid Build Coastguard Worker         mLiveSession->setBufferingSettings(mBufferingSettings);
96*ec779b8eSAndroid Build Coastguard Worker     }
97*ec779b8eSAndroid Build Coastguard Worker 
98*ec779b8eSAndroid Build Coastguard Worker     return OK;
99*ec779b8eSAndroid Build Coastguard Worker }
100*ec779b8eSAndroid Build Coastguard Worker 
prepareAsync()101*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::HTTPLiveSource::prepareAsync() {
102*ec779b8eSAndroid Build Coastguard Worker     if (mLiveLooper == NULL) {
103*ec779b8eSAndroid Build Coastguard Worker         mLiveLooper = new ALooper;
104*ec779b8eSAndroid Build Coastguard Worker         mLiveLooper->setName("http live");
105*ec779b8eSAndroid Build Coastguard Worker         mLiveLooper->start();
106*ec779b8eSAndroid Build Coastguard Worker 
107*ec779b8eSAndroid Build Coastguard Worker         mLiveLooper->registerHandler(this);
108*ec779b8eSAndroid Build Coastguard Worker     }
109*ec779b8eSAndroid Build Coastguard Worker 
110*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> notify = new AMessage(kWhatSessionNotify, this);
111*ec779b8eSAndroid Build Coastguard Worker 
112*ec779b8eSAndroid Build Coastguard Worker     mLiveSession = new LiveSession(
113*ec779b8eSAndroid Build Coastguard Worker             notify,
114*ec779b8eSAndroid Build Coastguard Worker             (mFlags & kFlagIncognito) ? LiveSession::kFlagIncognito : 0,
115*ec779b8eSAndroid Build Coastguard Worker             mHTTPService);
116*ec779b8eSAndroid Build Coastguard Worker 
117*ec779b8eSAndroid Build Coastguard Worker     mLiveLooper->registerHandler(mLiveSession);
118*ec779b8eSAndroid Build Coastguard Worker 
119*ec779b8eSAndroid Build Coastguard Worker     mLiveSession->setBufferingSettings(mBufferingSettings);
120*ec779b8eSAndroid Build Coastguard Worker     mLiveSession->connectAsync(
121*ec779b8eSAndroid Build Coastguard Worker             mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
122*ec779b8eSAndroid Build Coastguard Worker }
123*ec779b8eSAndroid Build Coastguard Worker 
start()124*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::HTTPLiveSource::start() {
125*ec779b8eSAndroid Build Coastguard Worker }
126*ec779b8eSAndroid Build Coastguard Worker 
getFormatMeta(bool audio)127*ec779b8eSAndroid Build Coastguard Worker sp<MetaData> NuPlayer::HTTPLiveSource::getFormatMeta(bool audio) {
128*ec779b8eSAndroid Build Coastguard Worker     sp<MetaData> meta;
129*ec779b8eSAndroid Build Coastguard Worker     if (mLiveSession != NULL) {
130*ec779b8eSAndroid Build Coastguard Worker         mLiveSession->getStreamFormatMeta(
131*ec779b8eSAndroid Build Coastguard Worker                 audio ? LiveSession::STREAMTYPE_AUDIO
132*ec779b8eSAndroid Build Coastguard Worker                       : LiveSession::STREAMTYPE_VIDEO,
133*ec779b8eSAndroid Build Coastguard Worker                 &meta);
134*ec779b8eSAndroid Build Coastguard Worker     }
135*ec779b8eSAndroid Build Coastguard Worker 
136*ec779b8eSAndroid Build Coastguard Worker     return meta;
137*ec779b8eSAndroid Build Coastguard Worker }
138*ec779b8eSAndroid Build Coastguard Worker 
getFormat(bool audio)139*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> NuPlayer::HTTPLiveSource::getFormat(bool audio) {
140*ec779b8eSAndroid Build Coastguard Worker     sp<MetaData> meta;
141*ec779b8eSAndroid Build Coastguard Worker     status_t err = -EWOULDBLOCK;
142*ec779b8eSAndroid Build Coastguard Worker     if (mLiveSession != NULL) {
143*ec779b8eSAndroid Build Coastguard Worker         err = mLiveSession->getStreamFormatMeta(
144*ec779b8eSAndroid Build Coastguard Worker                 audio ? LiveSession::STREAMTYPE_AUDIO
145*ec779b8eSAndroid Build Coastguard Worker                       : LiveSession::STREAMTYPE_VIDEO,
146*ec779b8eSAndroid Build Coastguard Worker                 &meta);
147*ec779b8eSAndroid Build Coastguard Worker     }
148*ec779b8eSAndroid Build Coastguard Worker 
149*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> format;
150*ec779b8eSAndroid Build Coastguard Worker     if (err == -EWOULDBLOCK) {
151*ec779b8eSAndroid Build Coastguard Worker         format = new AMessage();
152*ec779b8eSAndroid Build Coastguard Worker         format->setInt32("err", err);
153*ec779b8eSAndroid Build Coastguard Worker         return format;
154*ec779b8eSAndroid Build Coastguard Worker     }
155*ec779b8eSAndroid Build Coastguard Worker 
156*ec779b8eSAndroid Build Coastguard Worker     if (err != OK || convertMetaDataToMessage(meta, &format) != OK) {
157*ec779b8eSAndroid Build Coastguard Worker         return NULL;
158*ec779b8eSAndroid Build Coastguard Worker     }
159*ec779b8eSAndroid Build Coastguard Worker     return format;
160*ec779b8eSAndroid Build Coastguard Worker }
161*ec779b8eSAndroid Build Coastguard Worker 
feedMoreTSData()162*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::HTTPLiveSource::feedMoreTSData() {
163*ec779b8eSAndroid Build Coastguard Worker     return OK;
164*ec779b8eSAndroid Build Coastguard Worker }
165*ec779b8eSAndroid Build Coastguard Worker 
dequeueAccessUnit(bool audio,sp<ABuffer> * accessUnit)166*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::HTTPLiveSource::dequeueAccessUnit(
167*ec779b8eSAndroid Build Coastguard Worker         bool audio, sp<ABuffer> *accessUnit) {
168*ec779b8eSAndroid Build Coastguard Worker     return mLiveSession->dequeueAccessUnit(
169*ec779b8eSAndroid Build Coastguard Worker             audio ? LiveSession::STREAMTYPE_AUDIO
170*ec779b8eSAndroid Build Coastguard Worker                   : LiveSession::STREAMTYPE_VIDEO,
171*ec779b8eSAndroid Build Coastguard Worker             accessUnit);
172*ec779b8eSAndroid Build Coastguard Worker }
173*ec779b8eSAndroid Build Coastguard Worker 
getDuration(int64_t * durationUs)174*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::HTTPLiveSource::getDuration(int64_t *durationUs) {
175*ec779b8eSAndroid Build Coastguard Worker     return mLiveSession->getDuration(durationUs);
176*ec779b8eSAndroid Build Coastguard Worker }
177*ec779b8eSAndroid Build Coastguard Worker 
getTrackCount() const178*ec779b8eSAndroid Build Coastguard Worker size_t NuPlayer::HTTPLiveSource::getTrackCount() const {
179*ec779b8eSAndroid Build Coastguard Worker     return mLiveSession->getTrackCount();
180*ec779b8eSAndroid Build Coastguard Worker }
181*ec779b8eSAndroid Build Coastguard Worker 
getTrackInfo(size_t trackIndex) const182*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> NuPlayer::HTTPLiveSource::getTrackInfo(size_t trackIndex) const {
183*ec779b8eSAndroid Build Coastguard Worker     return mLiveSession->getTrackInfo(trackIndex);
184*ec779b8eSAndroid Build Coastguard Worker }
185*ec779b8eSAndroid Build Coastguard Worker 
getSelectedTrack(media_track_type type) const186*ec779b8eSAndroid Build Coastguard Worker ssize_t NuPlayer::HTTPLiveSource::getSelectedTrack(media_track_type type) const {
187*ec779b8eSAndroid Build Coastguard Worker     if (mLiveSession == NULL) {
188*ec779b8eSAndroid Build Coastguard Worker         return -1;
189*ec779b8eSAndroid Build Coastguard Worker     } else if (type == MEDIA_TRACK_TYPE_METADATA) {
190*ec779b8eSAndroid Build Coastguard Worker         // MEDIA_TRACK_TYPE_METADATA is always last track
191*ec779b8eSAndroid Build Coastguard Worker         // mMetadataSelected can only be true when mHasMetadata is true
192*ec779b8eSAndroid Build Coastguard Worker         return mMetadataSelected ? (mLiveSession->getTrackCount() - 1) : -1;
193*ec779b8eSAndroid Build Coastguard Worker     } else {
194*ec779b8eSAndroid Build Coastguard Worker         return mLiveSession->getSelectedTrack(type);
195*ec779b8eSAndroid Build Coastguard Worker     }
196*ec779b8eSAndroid Build Coastguard Worker }
197*ec779b8eSAndroid Build Coastguard Worker 
selectTrack(size_t trackIndex,bool select,int64_t)198*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::HTTPLiveSource::selectTrack(size_t trackIndex, bool select, int64_t /*timeUs*/) {
199*ec779b8eSAndroid Build Coastguard Worker     if (mLiveSession == NULL) {
200*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
201*ec779b8eSAndroid Build Coastguard Worker     }
202*ec779b8eSAndroid Build Coastguard Worker 
203*ec779b8eSAndroid Build Coastguard Worker     status_t err = INVALID_OPERATION;
204*ec779b8eSAndroid Build Coastguard Worker     bool postFetchMsg = false, isSub = false;
205*ec779b8eSAndroid Build Coastguard Worker     if (!mHasMetadata || trackIndex != mLiveSession->getTrackCount() - 1) {
206*ec779b8eSAndroid Build Coastguard Worker         err = mLiveSession->selectTrack(trackIndex, select);
207*ec779b8eSAndroid Build Coastguard Worker         postFetchMsg = select;
208*ec779b8eSAndroid Build Coastguard Worker         isSub = true;
209*ec779b8eSAndroid Build Coastguard Worker     } else {
210*ec779b8eSAndroid Build Coastguard Worker         // metadata track; i.e. (mHasMetadata && trackIndex == mLiveSession->getTrackCount() - 1)
211*ec779b8eSAndroid Build Coastguard Worker         if (mMetadataSelected && !select) {
212*ec779b8eSAndroid Build Coastguard Worker             err = OK;
213*ec779b8eSAndroid Build Coastguard Worker         } else if (!mMetadataSelected && select) {
214*ec779b8eSAndroid Build Coastguard Worker             postFetchMsg = true;
215*ec779b8eSAndroid Build Coastguard Worker             err = OK;
216*ec779b8eSAndroid Build Coastguard Worker         } else {
217*ec779b8eSAndroid Build Coastguard Worker             err = BAD_VALUE; // behave as LiveSession::selectTrack
218*ec779b8eSAndroid Build Coastguard Worker         }
219*ec779b8eSAndroid Build Coastguard Worker 
220*ec779b8eSAndroid Build Coastguard Worker         mMetadataSelected = select;
221*ec779b8eSAndroid Build Coastguard Worker     }
222*ec779b8eSAndroid Build Coastguard Worker 
223*ec779b8eSAndroid Build Coastguard Worker     if (err == OK) {
224*ec779b8eSAndroid Build Coastguard Worker         int32_t &generation = isSub ? mFetchSubtitleDataGeneration : mFetchMetaDataGeneration;
225*ec779b8eSAndroid Build Coastguard Worker         generation++;
226*ec779b8eSAndroid Build Coastguard Worker         if (postFetchMsg) {
227*ec779b8eSAndroid Build Coastguard Worker             int32_t what = isSub ? kWhatFetchSubtitleData : kWhatFetchMetaData;
228*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> msg = new AMessage(what, this);
229*ec779b8eSAndroid Build Coastguard Worker             msg->setInt32("generation", generation);
230*ec779b8eSAndroid Build Coastguard Worker             msg->post();
231*ec779b8eSAndroid Build Coastguard Worker         }
232*ec779b8eSAndroid Build Coastguard Worker     }
233*ec779b8eSAndroid Build Coastguard Worker 
234*ec779b8eSAndroid Build Coastguard Worker     // LiveSession::selectTrack returns BAD_VALUE when selecting the currently
235*ec779b8eSAndroid Build Coastguard Worker     // selected track, or unselecting a non-selected track. In this case it's an
236*ec779b8eSAndroid Build Coastguard Worker     // no-op so we return OK.
237*ec779b8eSAndroid Build Coastguard Worker     return (err == OK || err == BAD_VALUE) ? (status_t)OK : err;
238*ec779b8eSAndroid Build Coastguard Worker }
239*ec779b8eSAndroid Build Coastguard Worker 
seekTo(int64_t seekTimeUs,MediaPlayerSeekMode mode)240*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
241*ec779b8eSAndroid Build Coastguard Worker     if (mLiveSession->isSeekable()) {
242*ec779b8eSAndroid Build Coastguard Worker         return mLiveSession->seekTo(seekTimeUs, mode);
243*ec779b8eSAndroid Build Coastguard Worker     } else {
244*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
245*ec779b8eSAndroid Build Coastguard Worker     }
246*ec779b8eSAndroid Build Coastguard Worker }
247*ec779b8eSAndroid Build Coastguard Worker 
pollForRawData(const sp<AMessage> & msg,int32_t currentGeneration,LiveSession::StreamType fetchType,int32_t pushWhat)248*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::HTTPLiveSource::pollForRawData(
249*ec779b8eSAndroid Build Coastguard Worker         const sp<AMessage> &msg, int32_t currentGeneration,
250*ec779b8eSAndroid Build Coastguard Worker         LiveSession::StreamType fetchType, int32_t pushWhat) {
251*ec779b8eSAndroid Build Coastguard Worker 
252*ec779b8eSAndroid Build Coastguard Worker     int32_t generation;
253*ec779b8eSAndroid Build Coastguard Worker     CHECK(msg->findInt32("generation", &generation));
254*ec779b8eSAndroid Build Coastguard Worker 
255*ec779b8eSAndroid Build Coastguard Worker     if (generation != currentGeneration) {
256*ec779b8eSAndroid Build Coastguard Worker         return;
257*ec779b8eSAndroid Build Coastguard Worker     }
258*ec779b8eSAndroid Build Coastguard Worker 
259*ec779b8eSAndroid Build Coastguard Worker     sp<ABuffer> buffer;
260*ec779b8eSAndroid Build Coastguard Worker     while (mLiveSession->dequeueAccessUnit(fetchType, &buffer) == OK) {
261*ec779b8eSAndroid Build Coastguard Worker 
262*ec779b8eSAndroid Build Coastguard Worker         sp<AMessage> notify = dupNotify();
263*ec779b8eSAndroid Build Coastguard Worker         notify->setInt32("what", pushWhat);
264*ec779b8eSAndroid Build Coastguard Worker         notify->setBuffer("buffer", buffer);
265*ec779b8eSAndroid Build Coastguard Worker 
266*ec779b8eSAndroid Build Coastguard Worker         int64_t timeUs, baseUs, delayUs;
267*ec779b8eSAndroid Build Coastguard Worker         CHECK(buffer->meta()->findInt64("baseUs", &baseUs));
268*ec779b8eSAndroid Build Coastguard Worker         CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
269*ec779b8eSAndroid Build Coastguard Worker         delayUs = baseUs + timeUs - ALooper::GetNowUs();
270*ec779b8eSAndroid Build Coastguard Worker 
271*ec779b8eSAndroid Build Coastguard Worker         if (fetchType == LiveSession::STREAMTYPE_SUBTITLES) {
272*ec779b8eSAndroid Build Coastguard Worker             notify->post();
273*ec779b8eSAndroid Build Coastguard Worker             msg->post(delayUs > 0LL ? delayUs : 0LL);
274*ec779b8eSAndroid Build Coastguard Worker             return;
275*ec779b8eSAndroid Build Coastguard Worker         } else if (fetchType == LiveSession::STREAMTYPE_METADATA) {
276*ec779b8eSAndroid Build Coastguard Worker             if (delayUs < -1000000LL) { // 1 second
277*ec779b8eSAndroid Build Coastguard Worker                 continue;
278*ec779b8eSAndroid Build Coastguard Worker             }
279*ec779b8eSAndroid Build Coastguard Worker             notify->post();
280*ec779b8eSAndroid Build Coastguard Worker             // push all currently available metadata buffers in each invocation of pollForRawData
281*ec779b8eSAndroid Build Coastguard Worker             // continue;
282*ec779b8eSAndroid Build Coastguard Worker         } else {
283*ec779b8eSAndroid Build Coastguard Worker             TRESPASS();
284*ec779b8eSAndroid Build Coastguard Worker         }
285*ec779b8eSAndroid Build Coastguard Worker     }
286*ec779b8eSAndroid Build Coastguard Worker 
287*ec779b8eSAndroid Build Coastguard Worker     // try again in 1 second
288*ec779b8eSAndroid Build Coastguard Worker     msg->post(1000000LL);
289*ec779b8eSAndroid Build Coastguard Worker }
290*ec779b8eSAndroid Build Coastguard Worker 
onMessageReceived(const sp<AMessage> & msg)291*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::HTTPLiveSource::onMessageReceived(const sp<AMessage> &msg) {
292*ec779b8eSAndroid Build Coastguard Worker     switch (msg->what()) {
293*ec779b8eSAndroid Build Coastguard Worker         case kWhatSessionNotify:
294*ec779b8eSAndroid Build Coastguard Worker         {
295*ec779b8eSAndroid Build Coastguard Worker             onSessionNotify(msg);
296*ec779b8eSAndroid Build Coastguard Worker             break;
297*ec779b8eSAndroid Build Coastguard Worker         }
298*ec779b8eSAndroid Build Coastguard Worker 
299*ec779b8eSAndroid Build Coastguard Worker         case kWhatFetchSubtitleData:
300*ec779b8eSAndroid Build Coastguard Worker         {
301*ec779b8eSAndroid Build Coastguard Worker             pollForRawData(
302*ec779b8eSAndroid Build Coastguard Worker                     msg, mFetchSubtitleDataGeneration,
303*ec779b8eSAndroid Build Coastguard Worker                     /* fetch */ LiveSession::STREAMTYPE_SUBTITLES,
304*ec779b8eSAndroid Build Coastguard Worker                     /* push */ kWhatSubtitleData);
305*ec779b8eSAndroid Build Coastguard Worker 
306*ec779b8eSAndroid Build Coastguard Worker             break;
307*ec779b8eSAndroid Build Coastguard Worker         }
308*ec779b8eSAndroid Build Coastguard Worker 
309*ec779b8eSAndroid Build Coastguard Worker         case kWhatFetchMetaData:
310*ec779b8eSAndroid Build Coastguard Worker         {
311*ec779b8eSAndroid Build Coastguard Worker             if (!mMetadataSelected) {
312*ec779b8eSAndroid Build Coastguard Worker                 break;
313*ec779b8eSAndroid Build Coastguard Worker             }
314*ec779b8eSAndroid Build Coastguard Worker 
315*ec779b8eSAndroid Build Coastguard Worker             pollForRawData(
316*ec779b8eSAndroid Build Coastguard Worker                     msg, mFetchMetaDataGeneration,
317*ec779b8eSAndroid Build Coastguard Worker                     /* fetch */ LiveSession::STREAMTYPE_METADATA,
318*ec779b8eSAndroid Build Coastguard Worker                     /* push */ kWhatTimedMetaData);
319*ec779b8eSAndroid Build Coastguard Worker 
320*ec779b8eSAndroid Build Coastguard Worker             break;
321*ec779b8eSAndroid Build Coastguard Worker         }
322*ec779b8eSAndroid Build Coastguard Worker 
323*ec779b8eSAndroid Build Coastguard Worker         default:
324*ec779b8eSAndroid Build Coastguard Worker             Source::onMessageReceived(msg);
325*ec779b8eSAndroid Build Coastguard Worker             break;
326*ec779b8eSAndroid Build Coastguard Worker     }
327*ec779b8eSAndroid Build Coastguard Worker }
328*ec779b8eSAndroid Build Coastguard Worker 
onSessionNotify(const sp<AMessage> & msg)329*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::HTTPLiveSource::onSessionNotify(const sp<AMessage> &msg) {
330*ec779b8eSAndroid Build Coastguard Worker     int32_t what;
331*ec779b8eSAndroid Build Coastguard Worker     CHECK(msg->findInt32("what", &what));
332*ec779b8eSAndroid Build Coastguard Worker 
333*ec779b8eSAndroid Build Coastguard Worker     switch (what) {
334*ec779b8eSAndroid Build Coastguard Worker         case LiveSession::kWhatPrepared:
335*ec779b8eSAndroid Build Coastguard Worker         {
336*ec779b8eSAndroid Build Coastguard Worker             // notify the current size here if we have it, otherwise report an initial size of (0,0)
337*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> format = getFormat(false /* audio */);
338*ec779b8eSAndroid Build Coastguard Worker             int32_t width;
339*ec779b8eSAndroid Build Coastguard Worker             int32_t height;
340*ec779b8eSAndroid Build Coastguard Worker             if (format != NULL &&
341*ec779b8eSAndroid Build Coastguard Worker                     format->findInt32("width", &width) && format->findInt32("height", &height)) {
342*ec779b8eSAndroid Build Coastguard Worker                 notifyVideoSizeChanged(format);
343*ec779b8eSAndroid Build Coastguard Worker             } else {
344*ec779b8eSAndroid Build Coastguard Worker                 notifyVideoSizeChanged();
345*ec779b8eSAndroid Build Coastguard Worker             }
346*ec779b8eSAndroid Build Coastguard Worker 
347*ec779b8eSAndroid Build Coastguard Worker             uint32_t flags = 0;
348*ec779b8eSAndroid Build Coastguard Worker             if (mLiveSession->isSeekable()) {
349*ec779b8eSAndroid Build Coastguard Worker                 flags |= FLAG_CAN_PAUSE;
350*ec779b8eSAndroid Build Coastguard Worker                 flags |= FLAG_CAN_SEEK;
351*ec779b8eSAndroid Build Coastguard Worker                 flags |= FLAG_CAN_SEEK_BACKWARD;
352*ec779b8eSAndroid Build Coastguard Worker                 flags |= FLAG_CAN_SEEK_FORWARD;
353*ec779b8eSAndroid Build Coastguard Worker             }
354*ec779b8eSAndroid Build Coastguard Worker 
355*ec779b8eSAndroid Build Coastguard Worker             if (mLiveSession->hasDynamicDuration()) {
356*ec779b8eSAndroid Build Coastguard Worker                 flags |= FLAG_DYNAMIC_DURATION;
357*ec779b8eSAndroid Build Coastguard Worker             }
358*ec779b8eSAndroid Build Coastguard Worker 
359*ec779b8eSAndroid Build Coastguard Worker             notifyFlagsChanged(flags);
360*ec779b8eSAndroid Build Coastguard Worker 
361*ec779b8eSAndroid Build Coastguard Worker             notifyPrepared();
362*ec779b8eSAndroid Build Coastguard Worker             break;
363*ec779b8eSAndroid Build Coastguard Worker         }
364*ec779b8eSAndroid Build Coastguard Worker 
365*ec779b8eSAndroid Build Coastguard Worker         case LiveSession::kWhatPreparationFailed:
366*ec779b8eSAndroid Build Coastguard Worker         {
367*ec779b8eSAndroid Build Coastguard Worker             status_t err;
368*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("err", &err));
369*ec779b8eSAndroid Build Coastguard Worker 
370*ec779b8eSAndroid Build Coastguard Worker             notifyPrepared(err);
371*ec779b8eSAndroid Build Coastguard Worker             break;
372*ec779b8eSAndroid Build Coastguard Worker         }
373*ec779b8eSAndroid Build Coastguard Worker 
374*ec779b8eSAndroid Build Coastguard Worker         case LiveSession::kWhatStreamsChanged:
375*ec779b8eSAndroid Build Coastguard Worker         {
376*ec779b8eSAndroid Build Coastguard Worker             uint32_t changedMask;
377*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32(
378*ec779b8eSAndroid Build Coastguard Worker                         "changedMask", (int32_t *)&changedMask));
379*ec779b8eSAndroid Build Coastguard Worker 
380*ec779b8eSAndroid Build Coastguard Worker             bool audio = changedMask & LiveSession::STREAMTYPE_AUDIO;
381*ec779b8eSAndroid Build Coastguard Worker             bool video = changedMask & LiveSession::STREAMTYPE_VIDEO;
382*ec779b8eSAndroid Build Coastguard Worker 
383*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> reply;
384*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findMessage("reply", &reply));
385*ec779b8eSAndroid Build Coastguard Worker 
386*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> notify = dupNotify();
387*ec779b8eSAndroid Build Coastguard Worker             notify->setInt32("what", kWhatQueueDecoderShutdown);
388*ec779b8eSAndroid Build Coastguard Worker             notify->setInt32("audio", audio);
389*ec779b8eSAndroid Build Coastguard Worker             notify->setInt32("video", video);
390*ec779b8eSAndroid Build Coastguard Worker             notify->setMessage("reply", reply);
391*ec779b8eSAndroid Build Coastguard Worker             notify->post();
392*ec779b8eSAndroid Build Coastguard Worker             break;
393*ec779b8eSAndroid Build Coastguard Worker         }
394*ec779b8eSAndroid Build Coastguard Worker 
395*ec779b8eSAndroid Build Coastguard Worker         case LiveSession::kWhatBufferingStart:
396*ec779b8eSAndroid Build Coastguard Worker         {
397*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> notify = dupNotify();
398*ec779b8eSAndroid Build Coastguard Worker             notify->setInt32("what", kWhatPauseOnBufferingStart);
399*ec779b8eSAndroid Build Coastguard Worker             notify->post();
400*ec779b8eSAndroid Build Coastguard Worker             break;
401*ec779b8eSAndroid Build Coastguard Worker         }
402*ec779b8eSAndroid Build Coastguard Worker 
403*ec779b8eSAndroid Build Coastguard Worker         case LiveSession::kWhatBufferingEnd:
404*ec779b8eSAndroid Build Coastguard Worker         {
405*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> notify = dupNotify();
406*ec779b8eSAndroid Build Coastguard Worker             notify->setInt32("what", kWhatResumeOnBufferingEnd);
407*ec779b8eSAndroid Build Coastguard Worker             notify->post();
408*ec779b8eSAndroid Build Coastguard Worker             break;
409*ec779b8eSAndroid Build Coastguard Worker         }
410*ec779b8eSAndroid Build Coastguard Worker 
411*ec779b8eSAndroid Build Coastguard Worker 
412*ec779b8eSAndroid Build Coastguard Worker         case LiveSession::kWhatBufferingUpdate:
413*ec779b8eSAndroid Build Coastguard Worker         {
414*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> notify = dupNotify();
415*ec779b8eSAndroid Build Coastguard Worker             int32_t percentage;
416*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("percentage", &percentage));
417*ec779b8eSAndroid Build Coastguard Worker             notify->setInt32("what", kWhatBufferingUpdate);
418*ec779b8eSAndroid Build Coastguard Worker             notify->setInt32("percentage", percentage);
419*ec779b8eSAndroid Build Coastguard Worker             notify->post();
420*ec779b8eSAndroid Build Coastguard Worker             break;
421*ec779b8eSAndroid Build Coastguard Worker         }
422*ec779b8eSAndroid Build Coastguard Worker 
423*ec779b8eSAndroid Build Coastguard Worker         case LiveSession::kWhatMetadataDetected:
424*ec779b8eSAndroid Build Coastguard Worker         {
425*ec779b8eSAndroid Build Coastguard Worker             if (!mHasMetadata) {
426*ec779b8eSAndroid Build Coastguard Worker                 mHasMetadata = true;
427*ec779b8eSAndroid Build Coastguard Worker 
428*ec779b8eSAndroid Build Coastguard Worker                 sp<AMessage> notify = dupNotify();
429*ec779b8eSAndroid Build Coastguard Worker                 // notification without buffer triggers MEDIA_INFO_METADATA_UPDATE
430*ec779b8eSAndroid Build Coastguard Worker                 notify->setInt32("what", kWhatTimedMetaData);
431*ec779b8eSAndroid Build Coastguard Worker                 notify->post();
432*ec779b8eSAndroid Build Coastguard Worker             }
433*ec779b8eSAndroid Build Coastguard Worker             break;
434*ec779b8eSAndroid Build Coastguard Worker         }
435*ec779b8eSAndroid Build Coastguard Worker 
436*ec779b8eSAndroid Build Coastguard Worker         case LiveSession::kWhatError:
437*ec779b8eSAndroid Build Coastguard Worker         {
438*ec779b8eSAndroid Build Coastguard Worker             break;
439*ec779b8eSAndroid Build Coastguard Worker         }
440*ec779b8eSAndroid Build Coastguard Worker 
441*ec779b8eSAndroid Build Coastguard Worker         default:
442*ec779b8eSAndroid Build Coastguard Worker             TRESPASS();
443*ec779b8eSAndroid Build Coastguard Worker     }
444*ec779b8eSAndroid Build Coastguard Worker }
445*ec779b8eSAndroid Build Coastguard Worker 
446*ec779b8eSAndroid Build Coastguard Worker }  // namespace android
447*ec779b8eSAndroid Build Coastguard Worker 
448