blob: db24b3369c8f521558f0928af597bdee8ecf8516 [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>
Andreas Huber5bc087c2010-12-23 10:27:40 -080033
34namespace android {
35
Andreas Huberad0d9c92011-04-19 11:50:27 -070036NuPlayer::HTTPLiveSource::HTTPLiveSource(
Andreas Huberb5f25f02013-02-05 10:14:26 -080037 const sp<AMessage> &notify,
Andreas Huber1b86fe02014-01-29 11:13:26 -080038 const sp<IMediaHTTPService> &httpService,
Andreas Huberad0d9c92011-04-19 11:50:27 -070039 const char *url,
Andreas Huber81e68442014-02-05 11:52:33 -080040 const KeyedVector<String8, String8> *headers)
Andreas Huberb5f25f02013-02-05 10:14:26 -080041 : Source(notify),
Andreas Huber1b86fe02014-01-29 11:13:26 -080042 mHTTPService(httpService),
Andreas Huberb5f25f02013-02-05 10:14:26 -080043 mURL(url),
Andreas Huberad0d9c92011-04-19 11:50:27 -070044 mFlags(0),
Andreas Hubereac68ba2011-09-27 12:12:25 -070045 mFinalResult(OK),
Chong Zhangdcb89b32013-08-06 09:44:47 -070046 mOffset(0),
Robert Shih08528432015-04-08 09:06:54 -070047 mFetchSubtitleDataGeneration(0),
48 mFetchMetaDataGeneration(0),
49 mHasMetadata(false),
50 mMetadataSelected(false) {
Andreas Huberad0d9c92011-04-19 11:50:27 -070051 if (headers) {
52 mExtraHeaders = *headers;
53
54 ssize_t index =
55 mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
56
57 if (index >= 0) {
58 mFlags |= kFlagIncognito;
59
60 mExtraHeaders.removeItemsAt(index);
61 }
62 }
Andreas Huber5bc087c2010-12-23 10:27:40 -080063}
64
65NuPlayer::HTTPLiveSource::~HTTPLiveSource() {
Andreas Huber2048d0c2011-07-15 16:25:41 -070066 if (mLiveSession != NULL) {
67 mLiveSession->disconnect();
Andreas Huber14f76722013-01-15 09:04:18 -080068
Chong Zhang1228d6b2014-08-12 21:25:48 -070069 mLiveLooper->unregisterHandler(mLiveSession->id());
70 mLiveLooper->unregisterHandler(id());
Andreas Huber2048d0c2011-07-15 16:25:41 -070071 mLiveLooper->stop();
Chong Zhang1228d6b2014-08-12 21:25:48 -070072
73 mLiveSession.clear();
Andreas Huber14f76722013-01-15 09:04:18 -080074 mLiveLooper.clear();
Andreas Huber2048d0c2011-07-15 16:25:41 -070075 }
Andreas Huber5bc087c2010-12-23 10:27:40 -080076}
77
Andreas Huber9575c962013-02-05 13:59:56 -080078void NuPlayer::HTTPLiveSource::prepareAsync() {
Chong Zhang1228d6b2014-08-12 21:25:48 -070079 if (mLiveLooper == NULL) {
80 mLiveLooper = new ALooper;
81 mLiveLooper->setName("http live");
82 mLiveLooper->start();
83
84 mLiveLooper->registerHandler(this);
85 }
Andreas Huber5bc087c2010-12-23 10:27:40 -080086
Lajos Molnar1d15ab52015-03-04 16:46:34 -080087 sp<AMessage> notify = new AMessage(kWhatSessionNotify, this);
Andreas Huber0df36ec2013-02-06 10:44:39 -080088
Andreas Huber7314fa12011-02-24 14:42:48 -080089 mLiveSession = new LiveSession(
Andreas Huber0df36ec2013-02-06 10:44:39 -080090 notify,
Andreas Huber9b80c2b2011-06-30 15:47:02 -070091 (mFlags & kFlagIncognito) ? LiveSession::kFlagIncognito : 0,
Andreas Huber81e68442014-02-05 11:52:33 -080092 mHTTPService);
Andreas Huber7314fa12011-02-24 14:42:48 -080093
Andreas Huber5bc087c2010-12-23 10:27:40 -080094 mLiveLooper->registerHandler(mLiveSession);
95
Andreas Huber14f76722013-01-15 09:04:18 -080096 mLiveSession->connectAsync(
Andreas Huberad0d9c92011-04-19 11:50:27 -070097 mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
Andreas Huber9575c962013-02-05 13:59:56 -080098}
99
100void NuPlayer::HTTPLiveSource::start() {
Andreas Huber5bc087c2010-12-23 10:27:40 -0800101}
102
Andreas Huber14f76722013-01-15 09:04:18 -0800103sp<AMessage> NuPlayer::HTTPLiveSource::getFormat(bool audio) {
Robert Shih7350b052015-10-01 15:50:14 -0700104 sp<AMessage> format;
105 status_t err = -EWOULDBLOCK;
106 if (mLiveSession != NULL) {
107 err = mLiveSession->getStreamFormat(
108 audio ? LiveSession::STREAMTYPE_AUDIO
109 : LiveSession::STREAMTYPE_VIDEO,
110 &format);
Robert Shih1098d872014-11-06 13:58:48 -0800111 }
112
Robert Shih7350b052015-10-01 15:50:14 -0700113 if (err == -EWOULDBLOCK) {
114 format = new AMessage();
115 format->setInt32("err", err);
116 return format;
117 }
Andreas Huber5bc087c2010-12-23 10:27:40 -0800118
Andreas Huber14f76722013-01-15 09:04:18 -0800119 if (err != OK) {
Andreas Huber5bc087c2010-12-23 10:27:40 -0800120 return NULL;
121 }
122
Andreas Huber14f76722013-01-15 09:04:18 -0800123 return format;
Andreas Huber5bc087c2010-12-23 10:27:40 -0800124}
125
Andreas Hubereac68ba2011-09-27 12:12:25 -0700126status_t NuPlayer::HTTPLiveSource::feedMoreTSData() {
Andreas Hubereac68ba2011-09-27 12:12:25 -0700127 return OK;
Andreas Huber5bc087c2010-12-23 10:27:40 -0800128}
129
130status_t NuPlayer::HTTPLiveSource::dequeueAccessUnit(
131 bool audio, sp<ABuffer> *accessUnit) {
Andreas Huber14f76722013-01-15 09:04:18 -0800132 return mLiveSession->dequeueAccessUnit(
133 audio ? LiveSession::STREAMTYPE_AUDIO
134 : LiveSession::STREAMTYPE_VIDEO,
135 accessUnit);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800136}
137
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800138status_t NuPlayer::HTTPLiveSource::getDuration(int64_t *durationUs) {
139 return mLiveSession->getDuration(durationUs);
140}
141
Chong Zhang404fced2014-06-11 14:45:31 -0700142size_t NuPlayer::HTTPLiveSource::getTrackCount() const {
143 return mLiveSession->getTrackCount();
144}
145
146sp<AMessage> NuPlayer::HTTPLiveSource::getTrackInfo(size_t trackIndex) const {
147 return mLiveSession->getTrackInfo(trackIndex);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700148}
149
Robert Shih89bf2522014-07-29 19:25:10 -0700150ssize_t NuPlayer::HTTPLiveSource::getSelectedTrack(media_track_type type) const {
151 if (mLiveSession == NULL) {
152 return -1;
Robert Shih08528432015-04-08 09:06:54 -0700153 } else if (type == MEDIA_TRACK_TYPE_METADATA) {
154 // MEDIA_TRACK_TYPE_METADATA is always last track
155 // mMetadataSelected can only be true when mHasMetadata is true
156 return mMetadataSelected ? (mLiveSession->getTrackCount() - 1) : -1;
Robert Shih89bf2522014-07-29 19:25:10 -0700157 } else {
158 return mLiveSession->getSelectedTrack(type);
159 }
160}
161
Robert Shih6ffb1fd2014-10-29 16:24:32 -0700162status_t NuPlayer::HTTPLiveSource::selectTrack(size_t trackIndex, bool select, int64_t /*timeUs*/) {
Robert Shih08528432015-04-08 09:06:54 -0700163 if (mLiveSession == NULL) {
164 return INVALID_OPERATION;
165 }
166
167 status_t err = INVALID_OPERATION;
168 bool postFetchMsg = false, isSub = false;
Robert Shih055404e2015-05-15 10:12:21 -0700169 if (!mHasMetadata || trackIndex != mLiveSession->getTrackCount() - 1) {
Robert Shih08528432015-04-08 09:06:54 -0700170 err = mLiveSession->selectTrack(trackIndex, select);
171 postFetchMsg = select;
172 isSub = true;
173 } else {
Robert Shih055404e2015-05-15 10:12:21 -0700174 // metadata track; i.e. (mHasMetadata && trackIndex == mLiveSession->getTrackCount() - 1)
175 if (mMetadataSelected && !select) {
176 err = OK;
177 } else if (!mMetadataSelected && select) {
178 postFetchMsg = true;
179 err = OK;
180 } else {
181 err = BAD_VALUE; // behave as LiveSession::selectTrack
Robert Shih08528432015-04-08 09:06:54 -0700182 }
Robert Shih055404e2015-05-15 10:12:21 -0700183
184 mMetadataSelected = select;
Robert Shih08528432015-04-08 09:06:54 -0700185 }
Chong Zhangdcb89b32013-08-06 09:44:47 -0700186
187 if (err == OK) {
Robert Shih08528432015-04-08 09:06:54 -0700188 int32_t &generation = isSub ? mFetchSubtitleDataGeneration : mFetchMetaDataGeneration;
189 generation++;
190 if (postFetchMsg) {
191 int32_t what = isSub ? kWhatFetchSubtitleData : kWhatFetchMetaData;
192 sp<AMessage> msg = new AMessage(what, this);
193 msg->setInt32("generation", generation);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700194 msg->post();
195 }
196 }
197
198 // LiveSession::selectTrack returns BAD_VALUE when selecting the currently
199 // selected track, or unselecting a non-selected track. In this case it's an
200 // no-op so we return OK.
Andreas Huber84333e02014-02-07 15:36:10 -0800201 return (err == OK || err == BAD_VALUE) ? (status_t)OK : err;
Chong Zhangdcb89b32013-08-06 09:44:47 -0700202}
203
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800204status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) {
Andreas Huber14f76722013-01-15 09:04:18 -0800205 return mLiveSession->seekTo(seekTimeUs);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800206}
207
Robert Shih08528432015-04-08 09:06:54 -0700208void NuPlayer::HTTPLiveSource::pollForRawData(
209 const sp<AMessage> &msg, int32_t currentGeneration,
210 LiveSession::StreamType fetchType, int32_t pushWhat) {
211
212 int32_t generation;
213 CHECK(msg->findInt32("generation", &generation));
214
215 if (generation != currentGeneration) {
216 return;
217 }
218
219 sp<ABuffer> buffer;
220 while (mLiveSession->dequeueAccessUnit(fetchType, &buffer) == OK) {
221
222 sp<AMessage> notify = dupNotify();
223 notify->setInt32("what", pushWhat);
224 notify->setBuffer("buffer", buffer);
225
226 int64_t timeUs, baseUs, delayUs;
227 CHECK(buffer->meta()->findInt64("baseUs", &baseUs));
228 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
229 delayUs = baseUs + timeUs - ALooper::GetNowUs();
230
231 if (fetchType == LiveSession::STREAMTYPE_SUBTITLES) {
232 notify->post();
233 msg->post(delayUs > 0ll ? delayUs : 0ll);
234 return;
235 } else if (fetchType == LiveSession::STREAMTYPE_METADATA) {
236 if (delayUs < -1000000ll) { // 1 second
237 continue;
238 }
239 notify->post();
240 // push all currently available metadata buffers in each invocation of pollForRawData
241 // continue;
242 } else {
243 TRESPASS();
244 }
245 }
246
247 // try again in 1 second
248 msg->post(1000000ll);
249}
250
Andreas Huber0df36ec2013-02-06 10:44:39 -0800251void NuPlayer::HTTPLiveSource::onMessageReceived(const sp<AMessage> &msg) {
252 switch (msg->what()) {
253 case kWhatSessionNotify:
254 {
255 onSessionNotify(msg);
256 break;
257 }
258
Chong Zhangdcb89b32013-08-06 09:44:47 -0700259 case kWhatFetchSubtitleData:
260 {
Robert Shih08528432015-04-08 09:06:54 -0700261 pollForRawData(
262 msg, mFetchSubtitleDataGeneration,
263 /* fetch */ LiveSession::STREAMTYPE_SUBTITLES,
264 /* push */ kWhatSubtitleData);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700265
Robert Shih08528432015-04-08 09:06:54 -0700266 break;
267 }
268
269 case kWhatFetchMetaData:
270 {
271 if (!mMetadataSelected) {
Chong Zhangdcb89b32013-08-06 09:44:47 -0700272 break;
273 }
274
Robert Shih08528432015-04-08 09:06:54 -0700275 pollForRawData(
276 msg, mFetchMetaDataGeneration,
277 /* fetch */ LiveSession::STREAMTYPE_METADATA,
278 /* push */ kWhatTimedMetaData);
Chong Zhangdcb89b32013-08-06 09:44:47 -0700279
280 break;
281 }
282
Andreas Huber0df36ec2013-02-06 10:44:39 -0800283 default:
284 Source::onMessageReceived(msg);
285 break;
286 }
287}
288
289void NuPlayer::HTTPLiveSource::onSessionNotify(const sp<AMessage> &msg) {
290 int32_t what;
291 CHECK(msg->findInt32("what", &what));
292
293 switch (what) {
294 case LiveSession::kWhatPrepared:
295 {
Marco Nelissen3e518fd2013-11-01 10:33:18 -0700296 // notify the current size here if we have it, otherwise report an initial size of (0,0)
297 sp<AMessage> format = getFormat(false /* audio */);
298 int32_t width;
299 int32_t height;
300 if (format != NULL &&
301 format->findInt32("width", &width) && format->findInt32("height", &height)) {
Chong Zhangced1c2f2014-08-08 15:22:35 -0700302 notifyVideoSizeChanged(format);
Marco Nelissen3e518fd2013-11-01 10:33:18 -0700303 } else {
Chong Zhangced1c2f2014-08-08 15:22:35 -0700304 notifyVideoSizeChanged();
Marco Nelissen3e518fd2013-11-01 10:33:18 -0700305 }
Andreas Huber0df36ec2013-02-06 10:44:39 -0800306
Roger1 Jonssonf9dee0c2013-10-11 08:43:35 +0200307 uint32_t flags = 0;
Andreas Huber0df36ec2013-02-06 10:44:39 -0800308 if (mLiveSession->isSeekable()) {
Roger1 Jonssonf9dee0c2013-10-11 08:43:35 +0200309 flags |= FLAG_CAN_PAUSE;
Andreas Huber0df36ec2013-02-06 10:44:39 -0800310 flags |= FLAG_CAN_SEEK;
311 flags |= FLAG_CAN_SEEK_BACKWARD;
312 flags |= FLAG_CAN_SEEK_FORWARD;
313 }
314
315 if (mLiveSession->hasDynamicDuration()) {
316 flags |= FLAG_DYNAMIC_DURATION;
317 }
318
319 notifyFlagsChanged(flags);
320
321 notifyPrepared();
322 break;
323 }
324
325 case LiveSession::kWhatPreparationFailed:
326 {
327 status_t err;
328 CHECK(msg->findInt32("err", &err));
329
330 notifyPrepared(err);
331 break;
332 }
333
Andreas Huber14f76722013-01-15 09:04:18 -0800334 case LiveSession::kWhatStreamsChanged:
335 {
336 uint32_t changedMask;
337 CHECK(msg->findInt32(
338 "changedMask", (int32_t *)&changedMask));
339
340 bool audio = changedMask & LiveSession::STREAMTYPE_AUDIO;
341 bool video = changedMask & LiveSession::STREAMTYPE_VIDEO;
342
343 sp<AMessage> reply;
344 CHECK(msg->findMessage("reply", &reply));
345
346 sp<AMessage> notify = dupNotify();
347 notify->setInt32("what", kWhatQueueDecoderShutdown);
348 notify->setInt32("audio", audio);
349 notify->setInt32("video", video);
350 notify->setMessage("reply", reply);
351 notify->post();
352 break;
353 }
354
Chong Zhang7c870802015-03-17 16:27:56 -0700355 case LiveSession::kWhatBufferingStart:
356 {
357 sp<AMessage> notify = dupNotify();
358 notify->setInt32("what", kWhatPauseOnBufferingStart);
359 notify->post();
360 break;
361 }
362
363 case LiveSession::kWhatBufferingEnd:
364 {
365 sp<AMessage> notify = dupNotify();
366 notify->setInt32("what", kWhatResumeOnBufferingEnd);
367 notify->post();
368 break;
369 }
370
371
372 case LiveSession::kWhatBufferingUpdate:
373 {
374 sp<AMessage> notify = dupNotify();
375 int32_t percentage;
376 CHECK(msg->findInt32("percentage", &percentage));
377 notify->setInt32("what", kWhatBufferingUpdate);
378 notify->setInt32("percentage", percentage);
379 notify->post();
380 break;
381 }
382
Robert Shih08528432015-04-08 09:06:54 -0700383 case LiveSession::kWhatMetadataDetected:
384 {
385 if (!mHasMetadata) {
386 mHasMetadata = true;
387
388 sp<AMessage> notify = dupNotify();
389 // notification without buffer triggers MEDIA_INFO_METADATA_UPDATE
390 notify->setInt32("what", kWhatTimedMetaData);
391 notify->post();
392 }
393 break;
394 }
395
Andreas Huber14f76722013-01-15 09:04:18 -0800396 case LiveSession::kWhatError:
397 {
398 break;
399 }
400
Andreas Huber0df36ec2013-02-06 10:44:39 -0800401 default:
402 TRESPASS();
403 }
404}
405
Andreas Huber5bc087c2010-12-23 10:27:40 -0800406} // namespace android
407