blob: 5027e01e3abadfbbe9928afa53a16bfce5de0a4f [file] [log] [blame]
Andreas Huber5bc087c2010-12-23 10:27:40 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "HTTPLiveSource"
19#include <utils/Log.h>
20
21#include "HTTPLiveSource.h"
22
Andreas Huber5bc087c2010-12-23 10:27:40 -080023#include "AnotherPacketSource.h"
24#include "LiveDataSource.h"
Andreas Huber5bc087c2010-12-23 10:27:40 -080025
Andreas Huber1b86fe02014-01-29 11:13:26 -080026#include <media/IMediaHTTPService.h>
Andreas Huber5bc087c2010-12-23 10:27:40 -080027#include <media/stagefright/foundation/ABuffer.h>
28#include <media/stagefright/foundation/ADebug.h>
29#include <media/stagefright/foundation/AMessage.h>
30#include <media/stagefright/MediaErrors.h>
31#include <media/stagefright/MetaData.h>
Robert Shih08528432015-04-08 09:06:54 -070032#include <media/stagefright/MediaDefs.h>
Robert Shiha83eebb2016-10-13 15:10:42 -070033#include <media/stagefright/Utils.h>
Andreas Huber5bc087c2010-12-23 10:27:40 -080034
35namespace android {
36
Andreas Huberad0d9c92011-04-19 11:50:27 -070037NuPlayer::HTTPLiveSource::HTTPLiveSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080038 const sp<AMessage> &notify,
Andreas Huber1b86fe02014-01-29 11:13:26 -080039 const sp<IMediaHTTPService> &httpService,
Andreas Huberad0d9c92011-04-19 11:50:27 -070040 const char *url,
Andreas Huber81e68442014-02-05 11:52:33 -080041 const KeyedVector<String8, String8> *headers)
Andreas Huberb5f25f02013-02-05 10:14:26 -080042 : Source(notify),
Andreas Huber1b86fe02014-01-29 11:13:26 -080043 mHTTPService(httpService),
Andreas Huberb5f25f02013-02-05 10:14:26 -080044 mURL(url),
Andreas Huberad0d9c92011-04-19 11:50:27 -070045 mFlags(0),
Andreas Hubereac68ba2011-09-27 12:12:25 -070046 mFinalResult(OK),
Chong Zhangdcb89b32013-08-06 09:44:47 -070047 mOffset(0),
Robert Shih08528432015-04-08 09:06:54 -070048 mFetchSubtitleDataGeneration(0),
49 mFetchMetaDataGeneration(0),
50 mHasMetadata(false),
51 mMetadataSelected(false) {
Andreas Huberad0d9c92011-04-19 11:50:27 -070052 if (headers) {
53 mExtraHeaders = *headers;
54
55 ssize_t index =
56 mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
57
58 if (index >= 0) {
59 mFlags |= kFlagIncognito;
60
61 mExtraHeaders.removeItemsAt(index);
62 }
63 }
Andreas Huber5bc087c2010-12-23 10:27:40 -080064}
65
66NuPlayer::HTTPLiveSource::~HTTPLiveSource() {
Andreas Huber2048d0c2011-07-15 16:25:41 -070067 if (mLiveSession != NULL) {
68 mLiveSession->disconnect();
Andreas Huber14f76722013-01-15 09:04:18 -080069
Chong Zhang1228d6b2014-08-12 21:25:48 -070070 mLiveLooper->unregisterHandler(mLiveSession->id());
71 mLiveLooper->unregisterHandler(id());
Andreas Huber2048d0c2011-07-15 16:25:41 -070072 mLiveLooper->stop();
Chong Zhang1228d6b2014-08-12 21:25:48 -070073
74 mLiveSession.clear();
Andreas Huber14f76722013-01-15 09:04:18 -080075 mLiveLooper.clear();
Andreas Huber2048d0c2011-07-15 16:25:41 -070076 }
Andreas Huber5bc087c2010-12-23 10:27:40 -080077}
78
Andreas Huber9575c962013-02-05 13:59:56 -080079void NuPlayer::HTTPLiveSource::prepareAsync() {
Chong Zhang1228d6b2014-08-12 21:25:48 -070080 if (mLiveLooper == NULL) {
81 mLiveLooper = new ALooper;
82 mLiveLooper->setName("http live");
83 mLiveLooper->start();
84
85 mLiveLooper->registerHandler(this);
86 }
Andreas Huber5bc087c2010-12-23 10:27:40 -080087
Lajos Molnar1d15ab52015-03-04 16:46:34 -080088 sp<AMessage> notify = new AMessage(kWhatSessionNotify, this);
Andreas Huber0df36ec2013-02-06 10:44:39 -080089
Andreas Huber7314fa12011-02-24 14:42:48 -080090 mLiveSession = new LiveSession(
Andreas Huber0df36ec2013-02-06 10:44:39 -080091 notify,
Andreas Huber9b80c2b2011-06-30 15:47:02 -070092 (mFlags & kFlagIncognito) ? LiveSession::kFlagIncognito : 0,
Andreas Huber81e68442014-02-05 11:52:33 -080093 mHTTPService);
Andreas Huber7314fa12011-02-24 14:42:48 -080094
Andreas Huber5bc087c2010-12-23 10:27:40 -080095 mLiveLooper->registerHandler(mLiveSession);
96
Andreas Huber14f76722013-01-15 09:04:18 -080097 mLiveSession->connectAsync(
Andreas Huberad0d9c92011-04-19 11:50:27 -070098 mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
Andreas Huber9575c962013-02-05 13:59:56 -080099}
100
101void NuPlayer::HTTPLiveSource::start() {
Andreas Huber5bc087c2010-12-23 10:27:40 -0800102}
103
Robert Shiha83eebb2016-10-13 15:10:42 -0700104sp<MetaData> NuPlayer::HTTPLiveSource::getFormatMeta(bool audio) {
105 sp<MetaData> meta;
Robert Shih7350b052015-10-01 15:50:14 -0700106 if (mLiveSession != NULL) {
Robert Shiha83eebb2016-10-13 15:10:42 -0700107 mLiveSession->getStreamFormatMeta(
Robert Shih7350b052015-10-01 15:50:14 -0700108 audio ? LiveSession::STREAMTYPE_AUDIO
109 : LiveSession::STREAMTYPE_VIDEO,
Robert Shiha83eebb2016-10-13 15:10:42 -0700110 &meta);
Robert Shih1098d872014-11-06 13:58:48 -0800111 }
112
Robert Shiha83eebb2016-10-13 15:10:42 -0700113 return meta;
114}
115
116sp<AMessage> NuPlayer::HTTPLiveSource::getFormat(bool audio) {
117 sp<MetaData> meta;
118 status_t err = -EWOULDBLOCK;
119 if (mLiveSession != NULL) {
120 err = mLiveSession->getStreamFormatMeta(
121 audio ? LiveSession::STREAMTYPE_AUDIO
122 : LiveSession::STREAMTYPE_VIDEO,
123 &meta);
124 }
125
126 sp<AMessage> format;
Robert Shih7350b052015-10-01 15:50:14 -0700127 if (err == -EWOULDBLOCK) {
128 format = new AMessage();
129 format->setInt32("err", err);
130 return format;
131 }
Andreas Huber5bc087c2010-12-23 10:27:40 -0800132
Robert Shiha83eebb2016-10-13 15:10:42 -0700133 if (err != OK || convertMetaDataToMessage(meta, &format) != OK) {
Andreas Huber5bc087c2010-12-23 10:27:40 -0800134 return NULL;
135 }
Andreas Huber14f76722013-01-15 09:04:18 -0800136 return format;
Andreas Huber5bc087c2010-12-23 10:27:40 -0800137}
138
Andreas Hubereac68ba2011-09-27 12:12:25 -0700139status_t NuPlayer::HTTPLiveSource::feedMoreTSData() {
Andreas Hubereac68ba2011-09-27 12:12:25 -0700140 return OK;
Andreas Huber5bc087c2010-12-23 10:27:40 -0800141}
142
143status_t NuPlayer::HTTPLiveSource::dequeueAccessUnit(
144 bool audio, sp<ABuffer> *accessUnit) {
Andreas Huber14f76722013-01-15 09:04:18 -0800145 return mLiveSession->dequeueAccessUnit(
146 audio ? LiveSession::STREAMTYPE_AUDIO
147 : LiveSession::STREAMTYPE_VIDEO,
148 accessUnit);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800149}
150
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800151status_t NuPlayer::HTTPLiveSource::getDuration(int64_t *durationUs) {
152 return mLiveSession->getDuration(durationUs);
153}
154
Chong Zhang404fced2014-06-11 14:45:31 -0700155size_t NuPlayer::HTTPLiveSource::getTrackCount() const {
156 return mLiveSession->getTrackCount();
157}
158
159sp<AMessage> NuPlayer::HTTPLiveSource::getTrackInfo(size_t trackIndex) const {
160 return mLiveSession->getTrackInfo(trackIndex);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700161}
162
Robert Shih89bf2522014-07-29 19:25:10 -0700163ssize_t NuPlayer::HTTPLiveSource::getSelectedTrack(media_track_type type) const {
164 if (mLiveSession == NULL) {
165 return -1;
Robert Shih08528432015-04-08 09:06:54 -0700166 } else if (type == MEDIA_TRACK_TYPE_METADATA) {
167 // MEDIA_TRACK_TYPE_METADATA is always last track
168 // mMetadataSelected can only be true when mHasMetadata is true
169 return mMetadataSelected ? (mLiveSession->getTrackCount() - 1) : -1;
Robert Shih89bf2522014-07-29 19:25:10 -0700170 } else {
171 return mLiveSession->getSelectedTrack(type);
172 }
173}
174
Robert Shih6ffb1fd2014-10-29 16:24:32 -0700175status_t NuPlayer::HTTPLiveSource::selectTrack(size_t trackIndex, bool select, int64_t /*timeUs*/) {
Robert Shih08528432015-04-08 09:06:54 -0700176 if (mLiveSession == NULL) {
177 return INVALID_OPERATION;
178 }
179
180 status_t err = INVALID_OPERATION;
181 bool postFetchMsg = false, isSub = false;
Robert Shih055404e2015-05-15 10:12:21 -0700182 if (!mHasMetadata || trackIndex != mLiveSession->getTrackCount() - 1) {
Robert Shih08528432015-04-08 09:06:54 -0700183 err = mLiveSession->selectTrack(trackIndex, select);
184 postFetchMsg = select;
185 isSub = true;
186 } else {
Robert Shih055404e2015-05-15 10:12:21 -0700187 // metadata track; i.e. (mHasMetadata && trackIndex == mLiveSession->getTrackCount() - 1)
188 if (mMetadataSelected && !select) {
189 err = OK;
190 } else if (!mMetadataSelected && select) {
191 postFetchMsg = true;
192 err = OK;
193 } else {
194 err = BAD_VALUE; // behave as LiveSession::selectTrack
Robert Shih08528432015-04-08 09:06:54 -0700195 }
Robert Shih055404e2015-05-15 10:12:21 -0700196
197 mMetadataSelected = select;
Robert Shih08528432015-04-08 09:06:54 -0700198 }
Chong Zhangdcb89b32013-08-06 09:44:47 -0700199
200 if (err == OK) {
Robert Shih08528432015-04-08 09:06:54 -0700201 int32_t &generation = isSub ? mFetchSubtitleDataGeneration : mFetchMetaDataGeneration;
202 generation++;
203 if (postFetchMsg) {
204 int32_t what = isSub ? kWhatFetchSubtitleData : kWhatFetchMetaData;
205 sp<AMessage> msg = new AMessage(what, this);
206 msg->setInt32("generation", generation);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700207 msg->post();
208 }
209 }
210
211 // LiveSession::selectTrack returns BAD_VALUE when selecting the currently
212 // selected track, or unselecting a non-selected track. In this case it's an
213 // no-op so we return OK.
Andreas Huber84333e02014-02-07 15:36:10 -0800214 return (err == OK || err == BAD_VALUE) ? (status_t)OK : err;
Chong Zhangdcb89b32013-08-06 09:44:47 -0700215}
216
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800217status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) {
Andreas Huber14f76722013-01-15 09:04:18 -0800218 return mLiveSession->seekTo(seekTimeUs);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800219}
220
Robert Shih08528432015-04-08 09:06:54 -0700221void NuPlayer::HTTPLiveSource::pollForRawData(
222 const sp<AMessage> &msg, int32_t currentGeneration,
223 LiveSession::StreamType fetchType, int32_t pushWhat) {
224
225 int32_t generation;
226 CHECK(msg->findInt32("generation", &generation));
227
228 if (generation != currentGeneration) {
229 return;
230 }
231
232 sp<ABuffer> buffer;
233 while (mLiveSession->dequeueAccessUnit(fetchType, &buffer) == OK) {
234
235 sp<AMessage> notify = dupNotify();
236 notify->setInt32("what", pushWhat);
237 notify->setBuffer("buffer", buffer);
238
239 int64_t timeUs, baseUs, delayUs;
240 CHECK(buffer->meta()->findInt64("baseUs", &baseUs));
241 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
242 delayUs = baseUs + timeUs - ALooper::GetNowUs();
243
244 if (fetchType == LiveSession::STREAMTYPE_SUBTITLES) {
245 notify->post();
246 msg->post(delayUs > 0ll ? delayUs : 0ll);
247 return;
248 } else if (fetchType == LiveSession::STREAMTYPE_METADATA) {
249 if (delayUs < -1000000ll) { // 1 second
250 continue;
251 }
252 notify->post();
253 // push all currently available metadata buffers in each invocation of pollForRawData
254 // continue;
255 } else {
256 TRESPASS();
257 }
258 }
259
260 // try again in 1 second
261 msg->post(1000000ll);
262}
263
Andreas Huber0df36ec2013-02-06 10:44:39 -0800264void NuPlayer::HTTPLiveSource::onMessageReceived(const sp<AMessage> &msg) {
265 switch (msg->what()) {
266 case kWhatSessionNotify:
267 {
268 onSessionNotify(msg);
269 break;
270 }
271
Chong Zhangdcb89b32013-08-06 09:44:47 -0700272 case kWhatFetchSubtitleData:
273 {
Robert Shih08528432015-04-08 09:06:54 -0700274 pollForRawData(
275 msg, mFetchSubtitleDataGeneration,
276 /* fetch */ LiveSession::STREAMTYPE_SUBTITLES,
277 /* push */ kWhatSubtitleData);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700278
Robert Shih08528432015-04-08 09:06:54 -0700279 break;
280 }
281
282 case kWhatFetchMetaData:
283 {
284 if (!mMetadataSelected) {
Chong Zhangdcb89b32013-08-06 09:44:47 -0700285 break;
286 }
287
Robert Shih08528432015-04-08 09:06:54 -0700288 pollForRawData(
289 msg, mFetchMetaDataGeneration,
290 /* fetch */ LiveSession::STREAMTYPE_METADATA,
291 /* push */ kWhatTimedMetaData);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700292
293 break;
294 }
295
Andreas Huber0df36ec2013-02-06 10:44:39 -0800296 default:
297 Source::onMessageReceived(msg);
298 break;
299 }
300}
301
302void NuPlayer::HTTPLiveSource::onSessionNotify(const sp<AMessage> &msg) {
303 int32_t what;
304 CHECK(msg->findInt32("what", &what));
305
306 switch (what) {
307 case LiveSession::kWhatPrepared:
308 {
Marco Nelissen3e518fd2013-11-01 10:33:18 -0700309 // notify the current size here if we have it, otherwise report an initial size of (0,0)
310 sp<AMessage> format = getFormat(false /* audio */);
311 int32_t width;
312 int32_t height;
313 if (format != NULL &&
314 format->findInt32("width", &width) && format->findInt32("height", &height)) {
Chong Zhangced1c2f2014-08-08 15:22:35 -0700315 notifyVideoSizeChanged(format);
Marco Nelissen3e518fd2013-11-01 10:33:18 -0700316 } else {
Chong Zhangced1c2f2014-08-08 15:22:35 -0700317 notifyVideoSizeChanged();
Marco Nelissen3e518fd2013-11-01 10:33:18 -0700318 }
Andreas Huber0df36ec2013-02-06 10:44:39 -0800319
320 uint32_t flags = FLAG_CAN_PAUSE;
321 if (mLiveSession->isSeekable()) {
322 flags |= FLAG_CAN_SEEK;
323 flags |= FLAG_CAN_SEEK_BACKWARD;
324 flags |= FLAG_CAN_SEEK_FORWARD;
325 }
326
327 if (mLiveSession->hasDynamicDuration()) {
328 flags |= FLAG_DYNAMIC_DURATION;
329 }
330
331 notifyFlagsChanged(flags);
332
333 notifyPrepared();
334 break;
335 }
336
337 case LiveSession::kWhatPreparationFailed:
338 {
339 status_t err;
340 CHECK(msg->findInt32("err", &err));
341
342 notifyPrepared(err);
343 break;
344 }
345
Andreas Huber14f76722013-01-15 09:04:18 -0800346 case LiveSession::kWhatStreamsChanged:
347 {
348 uint32_t changedMask;
349 CHECK(msg->findInt32(
350 "changedMask", (int32_t *)&changedMask));
351
352 bool audio = changedMask & LiveSession::STREAMTYPE_AUDIO;
353 bool video = changedMask & LiveSession::STREAMTYPE_VIDEO;
354
355 sp<AMessage> reply;
356 CHECK(msg->findMessage("reply", &reply));
357
358 sp<AMessage> notify = dupNotify();
359 notify->setInt32("what", kWhatQueueDecoderShutdown);
360 notify->setInt32("audio", audio);
361 notify->setInt32("video", video);
362 notify->setMessage("reply", reply);
363 notify->post();
364 break;
365 }
366
Chong Zhang7c870802015-03-17 16:27:56 -0700367 case LiveSession::kWhatBufferingStart:
368 {
369 sp<AMessage> notify = dupNotify();
370 notify->setInt32("what", kWhatPauseOnBufferingStart);
371 notify->post();
372 break;
373 }
374
375 case LiveSession::kWhatBufferingEnd:
376 {
377 sp<AMessage> notify = dupNotify();
378 notify->setInt32("what", kWhatResumeOnBufferingEnd);
379 notify->post();
380 break;
381 }
382
383
384 case LiveSession::kWhatBufferingUpdate:
385 {
386 sp<AMessage> notify = dupNotify();
387 int32_t percentage;
388 CHECK(msg->findInt32("percentage", &percentage));
389 notify->setInt32("what", kWhatBufferingUpdate);
390 notify->setInt32("percentage", percentage);
391 notify->post();
392 break;
393 }
394
Robert Shih08528432015-04-08 09:06:54 -0700395 case LiveSession::kWhatMetadataDetected:
396 {
397 if (!mHasMetadata) {
398 mHasMetadata = true;
399
400 sp<AMessage> notify = dupNotify();
401 // notification without buffer triggers MEDIA_INFO_METADATA_UPDATE
402 notify->setInt32("what", kWhatTimedMetaData);
403 notify->post();
404 }
405 break;
406 }
407
Andreas Huber14f76722013-01-15 09:04:18 -0800408 case LiveSession::kWhatError:
409 {
410 break;
411 }
412
Andreas Huber0df36ec2013-02-06 10:44:39 -0800413 default:
414 TRESPASS();
415 }
416}
417
Andreas Huber5bc087c2010-12-23 10:27:40 -0800418} // namespace android
419