blob: 4e71e89864fd0033198428e59e602688115560de [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"
Andreas Huber5bc087c2010-12-23 10:27:40 -080022#include "LiveDataSource.h"
Andreas Huber5bc087c2010-12-23 10:27:40 -080023
Andreas Huber1b86fe02014-01-29 11:13:26 -080024#include <media/IMediaHTTPService.h>
Andreas Huber5bc087c2010-12-23 10:27:40 -080025#include <media/stagefright/foundation/ABuffer.h>
26#include <media/stagefright/foundation/ADebug.h>
27#include <media/stagefright/foundation/AMessage.h>
28#include <media/stagefright/MediaErrors.h>
29#include <media/stagefright/MetaData.h>
Robert Shih08528432015-04-08 09:06:54 -070030#include <media/stagefright/MediaDefs.h>
Robert Shiha83eebb2016-10-13 15:10:42 -070031#include <media/stagefright/Utils.h>
Ray Essick64050722022-01-14 13:46:33 -080032#include <mpeg2ts/AnotherPacketSource.h>
Andreas Huber5bc087c2010-12-23 10:27:40 -080033
Wei Jia48fa06d2016-12-20 15:30:49 -080034// default buffer prepare/ready/underflow marks
35static const int kReadyMarkMs = 5000; // 5 seconds
36static const int kPrepareMarkMs = 1500; // 1.5 seconds
Wei Jia48fa06d2016-12-20 15:30:49 -080037
Andreas Huber5bc087c2010-12-23 10:27:40 -080038namespace android {
39
Andreas Huberad0d9c92011-04-19 11:50:27 -070040NuPlayer::HTTPLiveSource::HTTPLiveSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080041 const sp<AMessage> &notify,
Andreas Huber1b86fe02014-01-29 11:13:26 -080042 const sp<IMediaHTTPService> &httpService,
Andreas Huberad0d9c92011-04-19 11:50:27 -070043 const char *url,
Andreas Huber81e68442014-02-05 11:52:33 -080044 const KeyedVector<String8, String8> *headers)
Andreas Huberb5f25f02013-02-05 10:14:26 -080045 : Source(notify),
Andreas Huber1b86fe02014-01-29 11:13:26 -080046 mHTTPService(httpService),
Andreas Huberb5f25f02013-02-05 10:14:26 -080047 mURL(url),
Andreas Huberad0d9c92011-04-19 11:50:27 -070048 mFlags(0),
Andreas Hubereac68ba2011-09-27 12:12:25 -070049 mFinalResult(OK),
Chong Zhangdcb89b32013-08-06 09:44:47 -070050 mOffset(0),
Robert Shih08528432015-04-08 09:06:54 -070051 mFetchSubtitleDataGeneration(0),
52 mFetchMetaDataGeneration(0),
53 mHasMetadata(false),
54 mMetadataSelected(false) {
Wei Jia9bb38032017-03-23 18:00:38 -070055 mBufferingSettings.mInitialMarkMs = kPrepareMarkMs;
56 mBufferingSettings.mResumePlaybackMarkMs = kReadyMarkMs;
Andreas Huberad0d9c92011-04-19 11:50:27 -070057 if (headers) {
58 mExtraHeaders = *headers;
59
60 ssize_t index =
61 mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
62
63 if (index >= 0) {
64 mFlags |= kFlagIncognito;
65
66 mExtraHeaders.removeItemsAt(index);
67 }
68 }
Andreas Huber5bc087c2010-12-23 10:27:40 -080069}
70
71NuPlayer::HTTPLiveSource::~HTTPLiveSource() {
Andreas Huber2048d0c2011-07-15 16:25:41 -070072 if (mLiveSession != NULL) {
73 mLiveSession->disconnect();
Andreas Huber14f76722013-01-15 09:04:18 -080074
Chong Zhang1228d6b2014-08-12 21:25:48 -070075 mLiveLooper->unregisterHandler(mLiveSession->id());
76 mLiveLooper->unregisterHandler(id());
Andreas Huber2048d0c2011-07-15 16:25:41 -070077 mLiveLooper->stop();
Chong Zhang1228d6b2014-08-12 21:25:48 -070078
79 mLiveSession.clear();
Andreas Huber14f76722013-01-15 09:04:18 -080080 mLiveLooper.clear();
Andreas Huber2048d0c2011-07-15 16:25:41 -070081 }
Andreas Huber5bc087c2010-12-23 10:27:40 -080082}
83
Wei Jia9bb38032017-03-23 18:00:38 -070084status_t NuPlayer::HTTPLiveSource::getBufferingSettings(
Wei Jia48fa06d2016-12-20 15:30:49 -080085 BufferingSettings* buffering /* nonnull */) {
Wei Jia9bb38032017-03-23 18:00:38 -070086 *buffering = mBufferingSettings;
Wei Jia48fa06d2016-12-20 15:30:49 -080087
88 return OK;
89}
90
91status_t NuPlayer::HTTPLiveSource::setBufferingSettings(const BufferingSettings& buffering) {
Wei Jia48fa06d2016-12-20 15:30:49 -080092 mBufferingSettings = buffering;
93
Wei Jia48fa06d2016-12-20 15:30:49 -080094 if (mLiveSession != NULL) {
95 mLiveSession->setBufferingSettings(mBufferingSettings);
96 }
97
98 return OK;
99}
100
Andreas Huber9575c962013-02-05 13:59:56 -0800101void NuPlayer::HTTPLiveSource::prepareAsync() {
Chong Zhang1228d6b2014-08-12 21:25:48 -0700102 if (mLiveLooper == NULL) {
103 mLiveLooper = new ALooper;
104 mLiveLooper->setName("http live");
105 mLiveLooper->start();
106
107 mLiveLooper->registerHandler(this);
108 }
Andreas Huber5bc087c2010-12-23 10:27:40 -0800109
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800110 sp<AMessage> notify = new AMessage(kWhatSessionNotify, this);
Andreas Huber0df36ec2013-02-06 10:44:39 -0800111
Andreas Huber7314fa12011-02-24 14:42:48 -0800112 mLiveSession = new LiveSession(
Andreas Huber0df36ec2013-02-06 10:44:39 -0800113 notify,
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700114 (mFlags & kFlagIncognito) ? LiveSession::kFlagIncognito : 0,
Andreas Huber81e68442014-02-05 11:52:33 -0800115 mHTTPService);
Andreas Huber7314fa12011-02-24 14:42:48 -0800116
Andreas Huber5bc087c2010-12-23 10:27:40 -0800117 mLiveLooper->registerHandler(mLiveSession);
118
Wei Jia48fa06d2016-12-20 15:30:49 -0800119 mLiveSession->setBufferingSettings(mBufferingSettings);
Andreas Huber14f76722013-01-15 09:04:18 -0800120 mLiveSession->connectAsync(
Andreas Huberad0d9c92011-04-19 11:50:27 -0700121 mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
Andreas Huber9575c962013-02-05 13:59:56 -0800122}
123
124void NuPlayer::HTTPLiveSource::start() {
Andreas Huber5bc087c2010-12-23 10:27:40 -0800125}
126
Robert Shiha83eebb2016-10-13 15:10:42 -0700127sp<MetaData> NuPlayer::HTTPLiveSource::getFormatMeta(bool audio) {
128 sp<MetaData> meta;
Robert Shih7350b052015-10-01 15:50:14 -0700129 if (mLiveSession != NULL) {
Robert Shiha83eebb2016-10-13 15:10:42 -0700130 mLiveSession->getStreamFormatMeta(
Robert Shih7350b052015-10-01 15:50:14 -0700131 audio ? LiveSession::STREAMTYPE_AUDIO
132 : LiveSession::STREAMTYPE_VIDEO,
Robert Shiha83eebb2016-10-13 15:10:42 -0700133 &meta);
Robert Shih1098d872014-11-06 13:58:48 -0800134 }
135
Robert Shiha83eebb2016-10-13 15:10:42 -0700136 return meta;
137}
138
139sp<AMessage> NuPlayer::HTTPLiveSource::getFormat(bool audio) {
140 sp<MetaData> meta;
141 status_t err = -EWOULDBLOCK;
142 if (mLiveSession != NULL) {
143 err = mLiveSession->getStreamFormatMeta(
144 audio ? LiveSession::STREAMTYPE_AUDIO
145 : LiveSession::STREAMTYPE_VIDEO,
146 &meta);
147 }
148
149 sp<AMessage> format;
Robert Shih7350b052015-10-01 15:50:14 -0700150 if (err == -EWOULDBLOCK) {
151 format = new AMessage();
152 format->setInt32("err", err);
153 return format;
154 }
Andreas Huber5bc087c2010-12-23 10:27:40 -0800155
Robert Shiha83eebb2016-10-13 15:10:42 -0700156 if (err != OK || convertMetaDataToMessage(meta, &format) != OK) {
Andreas Huber5bc087c2010-12-23 10:27:40 -0800157 return NULL;
158 }
Andreas Huber14f76722013-01-15 09:04:18 -0800159 return format;
Andreas Huber5bc087c2010-12-23 10:27:40 -0800160}
161
Andreas Hubereac68ba2011-09-27 12:12:25 -0700162status_t NuPlayer::HTTPLiveSource::feedMoreTSData() {
Andreas Hubereac68ba2011-09-27 12:12:25 -0700163 return OK;
Andreas Huber5bc087c2010-12-23 10:27:40 -0800164}
165
166status_t NuPlayer::HTTPLiveSource::dequeueAccessUnit(
167 bool audio, sp<ABuffer> *accessUnit) {
Andreas Huber14f76722013-01-15 09:04:18 -0800168 return mLiveSession->dequeueAccessUnit(
169 audio ? LiveSession::STREAMTYPE_AUDIO
170 : LiveSession::STREAMTYPE_VIDEO,
171 accessUnit);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800172}
173
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800174status_t NuPlayer::HTTPLiveSource::getDuration(int64_t *durationUs) {
175 return mLiveSession->getDuration(durationUs);
176}
177
Chong Zhang404fced2014-06-11 14:45:31 -0700178size_t NuPlayer::HTTPLiveSource::getTrackCount() const {
179 return mLiveSession->getTrackCount();
180}
181
182sp<AMessage> NuPlayer::HTTPLiveSource::getTrackInfo(size_t trackIndex) const {
183 return mLiveSession->getTrackInfo(trackIndex);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700184}
185
Robert Shih89bf2522014-07-29 19:25:10 -0700186ssize_t NuPlayer::HTTPLiveSource::getSelectedTrack(media_track_type type) const {
187 if (mLiveSession == NULL) {
188 return -1;
Robert Shih08528432015-04-08 09:06:54 -0700189 } else if (type == MEDIA_TRACK_TYPE_METADATA) {
190 // MEDIA_TRACK_TYPE_METADATA is always last track
191 // mMetadataSelected can only be true when mHasMetadata is true
192 return mMetadataSelected ? (mLiveSession->getTrackCount() - 1) : -1;
Robert Shih89bf2522014-07-29 19:25:10 -0700193 } else {
194 return mLiveSession->getSelectedTrack(type);
195 }
196}
197
Robert Shih6ffb1fd2014-10-29 16:24:32 -0700198status_t NuPlayer::HTTPLiveSource::selectTrack(size_t trackIndex, bool select, int64_t /*timeUs*/) {
Robert Shih08528432015-04-08 09:06:54 -0700199 if (mLiveSession == NULL) {
200 return INVALID_OPERATION;
201 }
202
203 status_t err = INVALID_OPERATION;
204 bool postFetchMsg = false, isSub = false;
Robert Shih055404e2015-05-15 10:12:21 -0700205 if (!mHasMetadata || trackIndex != mLiveSession->getTrackCount() - 1) {
Robert Shih08528432015-04-08 09:06:54 -0700206 err = mLiveSession->selectTrack(trackIndex, select);
207 postFetchMsg = select;
208 isSub = true;
209 } else {
Robert Shih055404e2015-05-15 10:12:21 -0700210 // metadata track; i.e. (mHasMetadata && trackIndex == mLiveSession->getTrackCount() - 1)
211 if (mMetadataSelected && !select) {
212 err = OK;
213 } else if (!mMetadataSelected && select) {
214 postFetchMsg = true;
215 err = OK;
216 } else {
217 err = BAD_VALUE; // behave as LiveSession::selectTrack
Robert Shih08528432015-04-08 09:06:54 -0700218 }
Robert Shih055404e2015-05-15 10:12:21 -0700219
220 mMetadataSelected = select;
Robert Shih08528432015-04-08 09:06:54 -0700221 }
Chong Zhangdcb89b32013-08-06 09:44:47 -0700222
223 if (err == OK) {
Robert Shih08528432015-04-08 09:06:54 -0700224 int32_t &generation = isSub ? mFetchSubtitleDataGeneration : mFetchMetaDataGeneration;
225 generation++;
226 if (postFetchMsg) {
227 int32_t what = isSub ? kWhatFetchSubtitleData : kWhatFetchMetaData;
228 sp<AMessage> msg = new AMessage(what, this);
229 msg->setInt32("generation", generation);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700230 msg->post();
231 }
232 }
233
234 // LiveSession::selectTrack returns BAD_VALUE when selecting the currently
235 // selected track, or unselecting a non-selected track. In this case it's an
236 // no-op so we return OK.
Andreas Huber84333e02014-02-07 15:36:10 -0800237 return (err == OK || err == BAD_VALUE) ? (status_t)OK : err;
Chong Zhangdcb89b32013-08-06 09:44:47 -0700238}
239
Wei Jiac5de0912016-11-18 10:22:14 -0800240status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
Santhosh Behara8a750be2015-09-28 16:03:55 +0530241 if (mLiveSession->isSeekable()) {
242 return mLiveSession->seekTo(seekTimeUs, mode);
243 } else {
244 return INVALID_OPERATION;
245 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800246}
247
Robert Shih08528432015-04-08 09:06:54 -0700248void NuPlayer::HTTPLiveSource::pollForRawData(
249 const sp<AMessage> &msg, int32_t currentGeneration,
250 LiveSession::StreamType fetchType, int32_t pushWhat) {
251
252 int32_t generation;
253 CHECK(msg->findInt32("generation", &generation));
254
255 if (generation != currentGeneration) {
256 return;
257 }
258
259 sp<ABuffer> buffer;
260 while (mLiveSession->dequeueAccessUnit(fetchType, &buffer) == OK) {
261
262 sp<AMessage> notify = dupNotify();
263 notify->setInt32("what", pushWhat);
264 notify->setBuffer("buffer", buffer);
265
266 int64_t timeUs, baseUs, delayUs;
267 CHECK(buffer->meta()->findInt64("baseUs", &baseUs));
268 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
269 delayUs = baseUs + timeUs - ALooper::GetNowUs();
270
271 if (fetchType == LiveSession::STREAMTYPE_SUBTITLES) {
272 notify->post();
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800273 msg->post(delayUs > 0LL ? delayUs : 0LL);
Robert Shih08528432015-04-08 09:06:54 -0700274 return;
275 } else if (fetchType == LiveSession::STREAMTYPE_METADATA) {
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800276 if (delayUs < -1000000LL) { // 1 second
Robert Shih08528432015-04-08 09:06:54 -0700277 continue;
278 }
279 notify->post();
280 // push all currently available metadata buffers in each invocation of pollForRawData
281 // continue;
282 } else {
283 TRESPASS();
284 }
285 }
286
287 // try again in 1 second
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800288 msg->post(1000000LL);
Robert Shih08528432015-04-08 09:06:54 -0700289}
290
Andreas Huber0df36ec2013-02-06 10:44:39 -0800291void NuPlayer::HTTPLiveSource::onMessageReceived(const sp<AMessage> &msg) {
292 switch (msg->what()) {
293 case kWhatSessionNotify:
294 {
295 onSessionNotify(msg);
296 break;
297 }
298
Chong Zhangdcb89b32013-08-06 09:44:47 -0700299 case kWhatFetchSubtitleData:
300 {
Robert Shih08528432015-04-08 09:06:54 -0700301 pollForRawData(
302 msg, mFetchSubtitleDataGeneration,
303 /* fetch */ LiveSession::STREAMTYPE_SUBTITLES,
304 /* push */ kWhatSubtitleData);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700305
Robert Shih08528432015-04-08 09:06:54 -0700306 break;
307 }
308
309 case kWhatFetchMetaData:
310 {
311 if (!mMetadataSelected) {
Chong Zhangdcb89b32013-08-06 09:44:47 -0700312 break;
313 }
314
Robert Shih08528432015-04-08 09:06:54 -0700315 pollForRawData(
316 msg, mFetchMetaDataGeneration,
317 /* fetch */ LiveSession::STREAMTYPE_METADATA,
318 /* push */ kWhatTimedMetaData);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700319
320 break;
321 }
322
Andreas Huber0df36ec2013-02-06 10:44:39 -0800323 default:
324 Source::onMessageReceived(msg);
325 break;
326 }
327}
328
329void NuPlayer::HTTPLiveSource::onSessionNotify(const sp<AMessage> &msg) {
330 int32_t what;
331 CHECK(msg->findInt32("what", &what));
332
333 switch (what) {
334 case LiveSession::kWhatPrepared:
335 {
Marco Nelissen3e518fd2013-11-01 10:33:18 -0700336 // notify the current size here if we have it, otherwise report an initial size of (0,0)
337 sp<AMessage> format = getFormat(false /* audio */);
338 int32_t width;
339 int32_t height;
340 if (format != NULL &&
341 format->findInt32("width", &width) && format->findInt32("height", &height)) {
Chong Zhangced1c2f2014-08-08 15:22:35 -0700342 notifyVideoSizeChanged(format);
Marco Nelissen3e518fd2013-11-01 10:33:18 -0700343 } else {
Chong Zhangced1c2f2014-08-08 15:22:35 -0700344 notifyVideoSizeChanged();
Marco Nelissen3e518fd2013-11-01 10:33:18 -0700345 }
Andreas Huber0df36ec2013-02-06 10:44:39 -0800346
Roger1 Jonssonf9dee0c2013-10-11 08:43:35 +0200347 uint32_t flags = 0;
Andreas Huber0df36ec2013-02-06 10:44:39 -0800348 if (mLiveSession->isSeekable()) {
Roger1 Jonssonf9dee0c2013-10-11 08:43:35 +0200349 flags |= FLAG_CAN_PAUSE;
Andreas Huber0df36ec2013-02-06 10:44:39 -0800350 flags |= FLAG_CAN_SEEK;
351 flags |= FLAG_CAN_SEEK_BACKWARD;
352 flags |= FLAG_CAN_SEEK_FORWARD;
353 }
354
355 if (mLiveSession->hasDynamicDuration()) {
356 flags |= FLAG_DYNAMIC_DURATION;
357 }
358
359 notifyFlagsChanged(flags);
360
361 notifyPrepared();
362 break;
363 }
364
365 case LiveSession::kWhatPreparationFailed:
366 {
367 status_t err;
368 CHECK(msg->findInt32("err", &err));
369
370 notifyPrepared(err);
371 break;
372 }
373
Andreas Huber14f76722013-01-15 09:04:18 -0800374 case LiveSession::kWhatStreamsChanged:
375 {
376 uint32_t changedMask;
377 CHECK(msg->findInt32(
378 "changedMask", (int32_t *)&changedMask));
379
380 bool audio = changedMask & LiveSession::STREAMTYPE_AUDIO;
381 bool video = changedMask & LiveSession::STREAMTYPE_VIDEO;
382
383 sp<AMessage> reply;
384 CHECK(msg->findMessage("reply", &reply));
385
386 sp<AMessage> notify = dupNotify();
387 notify->setInt32("what", kWhatQueueDecoderShutdown);
388 notify->setInt32("audio", audio);
389 notify->setInt32("video", video);
390 notify->setMessage("reply", reply);
391 notify->post();
392 break;
393 }
394
Chong Zhang7c870802015-03-17 16:27:56 -0700395 case LiveSession::kWhatBufferingStart:
396 {
397 sp<AMessage> notify = dupNotify();
398 notify->setInt32("what", kWhatPauseOnBufferingStart);
399 notify->post();
400 break;
401 }
402
403 case LiveSession::kWhatBufferingEnd:
404 {
405 sp<AMessage> notify = dupNotify();
406 notify->setInt32("what", kWhatResumeOnBufferingEnd);
407 notify->post();
408 break;
409 }
410
411
412 case LiveSession::kWhatBufferingUpdate:
413 {
414 sp<AMessage> notify = dupNotify();
415 int32_t percentage;
416 CHECK(msg->findInt32("percentage", &percentage));
417 notify->setInt32("what", kWhatBufferingUpdate);
418 notify->setInt32("percentage", percentage);
419 notify->post();
420 break;
421 }
422
Robert Shih08528432015-04-08 09:06:54 -0700423 case LiveSession::kWhatMetadataDetected:
424 {
425 if (!mHasMetadata) {
426 mHasMetadata = true;
427
428 sp<AMessage> notify = dupNotify();
429 // notification without buffer triggers MEDIA_INFO_METADATA_UPDATE
430 notify->setInt32("what", kWhatTimedMetaData);
431 notify->post();
432 }
433 break;
434 }
435
Andreas Huber14f76722013-01-15 09:04:18 -0800436 case LiveSession::kWhatError:
437 {
438 break;
439 }
440
Andreas Huber0df36ec2013-02-06 10:44:39 -0800441 default:
442 TRESPASS();
443 }
444}
445
Andreas Huber5bc087c2010-12-23 10:27:40 -0800446} // namespace android
447