blob: 77e7885f973843227f8e39aaaec2a2135fe5d00b [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
Wei Jia48fa06d2016-12-20 15:30:49 -080035// default buffer prepare/ready/underflow marks
36static const int kReadyMarkMs = 5000; // 5 seconds
37static const int kPrepareMarkMs = 1500; // 1.5 seconds
Wei Jia48fa06d2016-12-20 15:30:49 -080038
Andreas Huber5bc087c2010-12-23 10:27:40 -080039namespace android {
40
Andreas Huberad0d9c92011-04-19 11:50:27 -070041NuPlayer::HTTPLiveSource::HTTPLiveSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080042 const sp<AMessage> &notify,
Andreas Huber1b86fe02014-01-29 11:13:26 -080043 const sp<IMediaHTTPService> &httpService,
Andreas Huberad0d9c92011-04-19 11:50:27 -070044 const char *url,
Andreas Huber81e68442014-02-05 11:52:33 -080045 const KeyedVector<String8, String8> *headers)
Andreas Huberb5f25f02013-02-05 10:14:26 -080046 : Source(notify),
Andreas Huber1b86fe02014-01-29 11:13:26 -080047 mHTTPService(httpService),
Andreas Huberb5f25f02013-02-05 10:14:26 -080048 mURL(url),
Andreas Huberad0d9c92011-04-19 11:50:27 -070049 mFlags(0),
Andreas Hubereac68ba2011-09-27 12:12:25 -070050 mFinalResult(OK),
Chong Zhangdcb89b32013-08-06 09:44:47 -070051 mOffset(0),
Robert Shih08528432015-04-08 09:06:54 -070052 mFetchSubtitleDataGeneration(0),
53 mFetchMetaDataGeneration(0),
54 mHasMetadata(false),
55 mMetadataSelected(false) {
Wei Jia9bb38032017-03-23 18:00:38 -070056 mBufferingSettings.mInitialMarkMs = kPrepareMarkMs;
57 mBufferingSettings.mResumePlaybackMarkMs = kReadyMarkMs;
Andreas Huberad0d9c92011-04-19 11:50:27 -070058 if (headers) {
59 mExtraHeaders = *headers;
60
61 ssize_t index =
62 mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
63
64 if (index >= 0) {
65 mFlags |= kFlagIncognito;
66
67 mExtraHeaders.removeItemsAt(index);
68 }
69 }
Andreas Huber5bc087c2010-12-23 10:27:40 -080070}
71
72NuPlayer::HTTPLiveSource::~HTTPLiveSource() {
Andreas Huber2048d0c2011-07-15 16:25:41 -070073 if (mLiveSession != NULL) {
74 mLiveSession->disconnect();
Andreas Huber14f76722013-01-15 09:04:18 -080075
Chong Zhang1228d6b2014-08-12 21:25:48 -070076 mLiveLooper->unregisterHandler(mLiveSession->id());
77 mLiveLooper->unregisterHandler(id());
Andreas Huber2048d0c2011-07-15 16:25:41 -070078 mLiveLooper->stop();
Chong Zhang1228d6b2014-08-12 21:25:48 -070079
80 mLiveSession.clear();
Andreas Huber14f76722013-01-15 09:04:18 -080081 mLiveLooper.clear();
Andreas Huber2048d0c2011-07-15 16:25:41 -070082 }
Andreas Huber5bc087c2010-12-23 10:27:40 -080083}
84
Wei Jia9bb38032017-03-23 18:00:38 -070085status_t NuPlayer::HTTPLiveSource::getBufferingSettings(
Wei Jia48fa06d2016-12-20 15:30:49 -080086 BufferingSettings* buffering /* nonnull */) {
Wei Jia9bb38032017-03-23 18:00:38 -070087 *buffering = mBufferingSettings;
Wei Jia48fa06d2016-12-20 15:30:49 -080088
89 return OK;
90}
91
92status_t NuPlayer::HTTPLiveSource::setBufferingSettings(const BufferingSettings& buffering) {
Wei Jia48fa06d2016-12-20 15:30:49 -080093 mBufferingSettings = buffering;
94
Wei Jia48fa06d2016-12-20 15:30:49 -080095 if (mLiveSession != NULL) {
96 mLiveSession->setBufferingSettings(mBufferingSettings);
97 }
98
99 return OK;
100}
101
Andreas Huber9575c962013-02-05 13:59:56 -0800102void NuPlayer::HTTPLiveSource::prepareAsync() {
Chong Zhang1228d6b2014-08-12 21:25:48 -0700103 if (mLiveLooper == NULL) {
104 mLiveLooper = new ALooper;
105 mLiveLooper->setName("http live");
106 mLiveLooper->start();
107
108 mLiveLooper->registerHandler(this);
109 }
Andreas Huber5bc087c2010-12-23 10:27:40 -0800110
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800111 sp<AMessage> notify = new AMessage(kWhatSessionNotify, this);
Andreas Huber0df36ec2013-02-06 10:44:39 -0800112
Andreas Huber7314fa12011-02-24 14:42:48 -0800113 mLiveSession = new LiveSession(
Andreas Huber0df36ec2013-02-06 10:44:39 -0800114 notify,
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700115 (mFlags & kFlagIncognito) ? LiveSession::kFlagIncognito : 0,
Andreas Huber81e68442014-02-05 11:52:33 -0800116 mHTTPService);
Andreas Huber7314fa12011-02-24 14:42:48 -0800117
Andreas Huber5bc087c2010-12-23 10:27:40 -0800118 mLiveLooper->registerHandler(mLiveSession);
119
Wei Jia48fa06d2016-12-20 15:30:49 -0800120 mLiveSession->setBufferingSettings(mBufferingSettings);
Andreas Huber14f76722013-01-15 09:04:18 -0800121 mLiveSession->connectAsync(
Andreas Huberad0d9c92011-04-19 11:50:27 -0700122 mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
Andreas Huber9575c962013-02-05 13:59:56 -0800123}
124
125void NuPlayer::HTTPLiveSource::start() {
Andreas Huber5bc087c2010-12-23 10:27:40 -0800126}
127
Robert Shiha83eebb2016-10-13 15:10:42 -0700128sp<MetaData> NuPlayer::HTTPLiveSource::getFormatMeta(bool audio) {
129 sp<MetaData> meta;
Robert Shih7350b052015-10-01 15:50:14 -0700130 if (mLiveSession != NULL) {
Robert Shiha83eebb2016-10-13 15:10:42 -0700131 mLiveSession->getStreamFormatMeta(
Robert Shih7350b052015-10-01 15:50:14 -0700132 audio ? LiveSession::STREAMTYPE_AUDIO
133 : LiveSession::STREAMTYPE_VIDEO,
Robert Shiha83eebb2016-10-13 15:10:42 -0700134 &meta);
Robert Shih1098d872014-11-06 13:58:48 -0800135 }
136
Robert Shiha83eebb2016-10-13 15:10:42 -0700137 return meta;
138}
139
140sp<AMessage> NuPlayer::HTTPLiveSource::getFormat(bool audio) {
141 sp<MetaData> meta;
142 status_t err = -EWOULDBLOCK;
143 if (mLiveSession != NULL) {
144 err = mLiveSession->getStreamFormatMeta(
145 audio ? LiveSession::STREAMTYPE_AUDIO
146 : LiveSession::STREAMTYPE_VIDEO,
147 &meta);
148 }
149
150 sp<AMessage> format;
Robert Shih7350b052015-10-01 15:50:14 -0700151 if (err == -EWOULDBLOCK) {
152 format = new AMessage();
153 format->setInt32("err", err);
154 return format;
155 }
Andreas Huber5bc087c2010-12-23 10:27:40 -0800156
Robert Shiha83eebb2016-10-13 15:10:42 -0700157 if (err != OK || convertMetaDataToMessage(meta, &format) != OK) {
Andreas Huber5bc087c2010-12-23 10:27:40 -0800158 return NULL;
159 }
Andreas Huber14f76722013-01-15 09:04:18 -0800160 return format;
Andreas Huber5bc087c2010-12-23 10:27:40 -0800161}
162
Andreas Hubereac68ba2011-09-27 12:12:25 -0700163status_t NuPlayer::HTTPLiveSource::feedMoreTSData() {
Andreas Hubereac68ba2011-09-27 12:12:25 -0700164 return OK;
Andreas Huber5bc087c2010-12-23 10:27:40 -0800165}
166
167status_t NuPlayer::HTTPLiveSource::dequeueAccessUnit(
168 bool audio, sp<ABuffer> *accessUnit) {
Andreas Huber14f76722013-01-15 09:04:18 -0800169 return mLiveSession->dequeueAccessUnit(
170 audio ? LiveSession::STREAMTYPE_AUDIO
171 : LiveSession::STREAMTYPE_VIDEO,
172 accessUnit);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800173}
174
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800175status_t NuPlayer::HTTPLiveSource::getDuration(int64_t *durationUs) {
176 return mLiveSession->getDuration(durationUs);
177}
178
Chong Zhang404fced2014-06-11 14:45:31 -0700179size_t NuPlayer::HTTPLiveSource::getTrackCount() const {
180 return mLiveSession->getTrackCount();
181}
182
183sp<AMessage> NuPlayer::HTTPLiveSource::getTrackInfo(size_t trackIndex) const {
184 return mLiveSession->getTrackInfo(trackIndex);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700185}
186
Robert Shih89bf2522014-07-29 19:25:10 -0700187ssize_t NuPlayer::HTTPLiveSource::getSelectedTrack(media_track_type type) const {
188 if (mLiveSession == NULL) {
189 return -1;
Robert Shih08528432015-04-08 09:06:54 -0700190 } else if (type == MEDIA_TRACK_TYPE_METADATA) {
191 // MEDIA_TRACK_TYPE_METADATA is always last track
192 // mMetadataSelected can only be true when mHasMetadata is true
193 return mMetadataSelected ? (mLiveSession->getTrackCount() - 1) : -1;
Robert Shih89bf2522014-07-29 19:25:10 -0700194 } else {
195 return mLiveSession->getSelectedTrack(type);
196 }
197}
198
Robert Shih6ffb1fd2014-10-29 16:24:32 -0700199status_t NuPlayer::HTTPLiveSource::selectTrack(size_t trackIndex, bool select, int64_t /*timeUs*/) {
Robert Shih08528432015-04-08 09:06:54 -0700200 if (mLiveSession == NULL) {
201 return INVALID_OPERATION;
202 }
203
204 status_t err = INVALID_OPERATION;
205 bool postFetchMsg = false, isSub = false;
Robert Shih055404e2015-05-15 10:12:21 -0700206 if (!mHasMetadata || trackIndex != mLiveSession->getTrackCount() - 1) {
Robert Shih08528432015-04-08 09:06:54 -0700207 err = mLiveSession->selectTrack(trackIndex, select);
208 postFetchMsg = select;
209 isSub = true;
210 } else {
Robert Shih055404e2015-05-15 10:12:21 -0700211 // metadata track; i.e. (mHasMetadata && trackIndex == mLiveSession->getTrackCount() - 1)
212 if (mMetadataSelected && !select) {
213 err = OK;
214 } else if (!mMetadataSelected && select) {
215 postFetchMsg = true;
216 err = OK;
217 } else {
218 err = BAD_VALUE; // behave as LiveSession::selectTrack
Robert Shih08528432015-04-08 09:06:54 -0700219 }
Robert Shih055404e2015-05-15 10:12:21 -0700220
221 mMetadataSelected = select;
Robert Shih08528432015-04-08 09:06:54 -0700222 }
Chong Zhangdcb89b32013-08-06 09:44:47 -0700223
224 if (err == OK) {
Robert Shih08528432015-04-08 09:06:54 -0700225 int32_t &generation = isSub ? mFetchSubtitleDataGeneration : mFetchMetaDataGeneration;
226 generation++;
227 if (postFetchMsg) {
228 int32_t what = isSub ? kWhatFetchSubtitleData : kWhatFetchMetaData;
229 sp<AMessage> msg = new AMessage(what, this);
230 msg->setInt32("generation", generation);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700231 msg->post();
232 }
233 }
234
235 // LiveSession::selectTrack returns BAD_VALUE when selecting the currently
236 // selected track, or unselecting a non-selected track. In this case it's an
237 // no-op so we return OK.
Andreas Huber84333e02014-02-07 15:36:10 -0800238 return (err == OK || err == BAD_VALUE) ? (status_t)OK : err;
Chong Zhangdcb89b32013-08-06 09:44:47 -0700239}
240
Wei Jiac5de0912016-11-18 10:22:14 -0800241status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
Santhosh Behara8a750be2015-09-28 16:03:55 +0530242 if (mLiveSession->isSeekable()) {
243 return mLiveSession->seekTo(seekTimeUs, mode);
244 } else {
245 return INVALID_OPERATION;
246 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800247}
248
Robert Shih08528432015-04-08 09:06:54 -0700249void NuPlayer::HTTPLiveSource::pollForRawData(
250 const sp<AMessage> &msg, int32_t currentGeneration,
251 LiveSession::StreamType fetchType, int32_t pushWhat) {
252
253 int32_t generation;
254 CHECK(msg->findInt32("generation", &generation));
255
256 if (generation != currentGeneration) {
257 return;
258 }
259
260 sp<ABuffer> buffer;
261 while (mLiveSession->dequeueAccessUnit(fetchType, &buffer) == OK) {
262
263 sp<AMessage> notify = dupNotify();
264 notify->setInt32("what", pushWhat);
265 notify->setBuffer("buffer", buffer);
266
267 int64_t timeUs, baseUs, delayUs;
268 CHECK(buffer->meta()->findInt64("baseUs", &baseUs));
269 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
270 delayUs = baseUs + timeUs - ALooper::GetNowUs();
271
272 if (fetchType == LiveSession::STREAMTYPE_SUBTITLES) {
273 notify->post();
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800274 msg->post(delayUs > 0LL ? delayUs : 0LL);
Robert Shih08528432015-04-08 09:06:54 -0700275 return;
276 } else if (fetchType == LiveSession::STREAMTYPE_METADATA) {
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800277 if (delayUs < -1000000LL) { // 1 second
Robert Shih08528432015-04-08 09:06:54 -0700278 continue;
279 }
280 notify->post();
281 // push all currently available metadata buffers in each invocation of pollForRawData
282 // continue;
283 } else {
284 TRESPASS();
285 }
286 }
287
288 // try again in 1 second
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800289 msg->post(1000000LL);
Robert Shih08528432015-04-08 09:06:54 -0700290}
291
Andreas Huber0df36ec2013-02-06 10:44:39 -0800292void NuPlayer::HTTPLiveSource::onMessageReceived(const sp<AMessage> &msg) {
293 switch (msg->what()) {
294 case kWhatSessionNotify:
295 {
296 onSessionNotify(msg);
297 break;
298 }
299
Chong Zhangdcb89b32013-08-06 09:44:47 -0700300 case kWhatFetchSubtitleData:
301 {
Robert Shih08528432015-04-08 09:06:54 -0700302 pollForRawData(
303 msg, mFetchSubtitleDataGeneration,
304 /* fetch */ LiveSession::STREAMTYPE_SUBTITLES,
305 /* push */ kWhatSubtitleData);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700306
Robert Shih08528432015-04-08 09:06:54 -0700307 break;
308 }
309
310 case kWhatFetchMetaData:
311 {
312 if (!mMetadataSelected) {
Chong Zhangdcb89b32013-08-06 09:44:47 -0700313 break;
314 }
315
Robert Shih08528432015-04-08 09:06:54 -0700316 pollForRawData(
317 msg, mFetchMetaDataGeneration,
318 /* fetch */ LiveSession::STREAMTYPE_METADATA,
319 /* push */ kWhatTimedMetaData);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700320
321 break;
322 }
323
Andreas Huber0df36ec2013-02-06 10:44:39 -0800324 default:
325 Source::onMessageReceived(msg);
326 break;
327 }
328}
329
330void NuPlayer::HTTPLiveSource::onSessionNotify(const sp<AMessage> &msg) {
331 int32_t what;
332 CHECK(msg->findInt32("what", &what));
333
334 switch (what) {
335 case LiveSession::kWhatPrepared:
336 {
Marco Nelissen3e518fd2013-11-01 10:33:18 -0700337 // notify the current size here if we have it, otherwise report an initial size of (0,0)
338 sp<AMessage> format = getFormat(false /* audio */);
339 int32_t width;
340 int32_t height;
341 if (format != NULL &&
342 format->findInt32("width", &width) && format->findInt32("height", &height)) {
Chong Zhangced1c2f2014-08-08 15:22:35 -0700343 notifyVideoSizeChanged(format);
Marco Nelissen3e518fd2013-11-01 10:33:18 -0700344 } else {
Chong Zhangced1c2f2014-08-08 15:22:35 -0700345 notifyVideoSizeChanged();
Marco Nelissen3e518fd2013-11-01 10:33:18 -0700346 }
Andreas Huber0df36ec2013-02-06 10:44:39 -0800347
Roger1 Jonssonf9dee0c2013-10-11 08:43:35 +0200348 uint32_t flags = 0;
Andreas Huber0df36ec2013-02-06 10:44:39 -0800349 if (mLiveSession->isSeekable()) {
Roger1 Jonssonf9dee0c2013-10-11 08:43:35 +0200350 flags |= FLAG_CAN_PAUSE;
Andreas Huber0df36ec2013-02-06 10:44:39 -0800351 flags |= FLAG_CAN_SEEK;
352 flags |= FLAG_CAN_SEEK_BACKWARD;
353 flags |= FLAG_CAN_SEEK_FORWARD;
354 }
355
356 if (mLiveSession->hasDynamicDuration()) {
357 flags |= FLAG_DYNAMIC_DURATION;
358 }
359
360 notifyFlagsChanged(flags);
361
362 notifyPrepared();
363 break;
364 }
365
366 case LiveSession::kWhatPreparationFailed:
367 {
368 status_t err;
369 CHECK(msg->findInt32("err", &err));
370
371 notifyPrepared(err);
372 break;
373 }
374
Andreas Huber14f76722013-01-15 09:04:18 -0800375 case LiveSession::kWhatStreamsChanged:
376 {
377 uint32_t changedMask;
378 CHECK(msg->findInt32(
379 "changedMask", (int32_t *)&changedMask));
380
381 bool audio = changedMask & LiveSession::STREAMTYPE_AUDIO;
382 bool video = changedMask & LiveSession::STREAMTYPE_VIDEO;
383
384 sp<AMessage> reply;
385 CHECK(msg->findMessage("reply", &reply));
386
387 sp<AMessage> notify = dupNotify();
388 notify->setInt32("what", kWhatQueueDecoderShutdown);
389 notify->setInt32("audio", audio);
390 notify->setInt32("video", video);
391 notify->setMessage("reply", reply);
392 notify->post();
393 break;
394 }
395
Chong Zhang7c870802015-03-17 16:27:56 -0700396 case LiveSession::kWhatBufferingStart:
397 {
398 sp<AMessage> notify = dupNotify();
399 notify->setInt32("what", kWhatPauseOnBufferingStart);
400 notify->post();
401 break;
402 }
403
404 case LiveSession::kWhatBufferingEnd:
405 {
406 sp<AMessage> notify = dupNotify();
407 notify->setInt32("what", kWhatResumeOnBufferingEnd);
408 notify->post();
409 break;
410 }
411
412
413 case LiveSession::kWhatBufferingUpdate:
414 {
415 sp<AMessage> notify = dupNotify();
416 int32_t percentage;
417 CHECK(msg->findInt32("percentage", &percentage));
418 notify->setInt32("what", kWhatBufferingUpdate);
419 notify->setInt32("percentage", percentage);
420 notify->post();
421 break;
422 }
423
Robert Shih08528432015-04-08 09:06:54 -0700424 case LiveSession::kWhatMetadataDetected:
425 {
426 if (!mHasMetadata) {
427 mHasMetadata = true;
428
429 sp<AMessage> notify = dupNotify();
430 // notification without buffer triggers MEDIA_INFO_METADATA_UPDATE
431 notify->setInt32("what", kWhatTimedMetaData);
432 notify->post();
433 }
434 break;
435 }
436
Andreas Huber14f76722013-01-15 09:04:18 -0800437 case LiveSession::kWhatError:
438 {
439 break;
440 }
441
Andreas Huber0df36ec2013-02-06 10:44:39 -0800442 default:
443 TRESPASS();
444 }
445}
446
Andreas Huber5bc087c2010-12-23 10:27:40 -0800447} // namespace android
448