blob: ba4087690b9f7c5871c9b1583076bc91a0ffe36d [file] [log] [blame]
Andreas Huber2bfdd422011-10-11 15:24:07 -07001/*
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 "RTSPSource"
19#include <utils/Log.h>
20
21#include "RTSPSource.h"
22
23#include "AnotherPacketSource.h"
24#include "MyHandler.h"
Oscar Rydhé81dd60e2012-02-20 10:15:48 +010025#include "SDPLoader.h"
Andreas Huber2bfdd422011-10-11 15:24:07 -070026
Andreas Huber1b86fe02014-01-29 11:13:26 -080027#include <media/IMediaHTTPService.h>
Andreas Huber49694682012-08-31 10:27:46 -070028#include <media/stagefright/MediaDefs.h>
Andreas Huber2bfdd422011-10-11 15:24:07 -070029#include <media/stagefright/MetaData.h>
30
31namespace android {
32
Roger Jönssoncfc30832013-01-21 16:26:41 +010033const int64_t kNearEOSTimeoutUs = 2000000ll; // 2 secs
34
Robert Shih641e0c72016-02-22 11:37:20 -080035// Buffer Underflow/Prepare/StartServer/Overflow Marks
36const int64_t NuPlayer::RTSPSource::kUnderflowMarkUs = 1000000ll;
37const int64_t NuPlayer::RTSPSource::kPrepareMarkUs = 3000000ll;
38const int64_t NuPlayer::RTSPSource::kStartServerMarkUs = 5000000ll;
39const int64_t NuPlayer::RTSPSource::kOverflowMarkUs = 10000000ll;
40
Andreas Huber2bfdd422011-10-11 15:24:07 -070041NuPlayer::RTSPSource::RTSPSource(
Andreas Huber5ab368a2013-02-05 10:14:26 -080042 const sp<AMessage> &notify,
Andreas Huber1b86fe02014-01-29 11:13:26 -080043 const sp<IMediaHTTPService> &httpService,
Andreas Huber2bfdd422011-10-11 15:24:07 -070044 const char *url,
45 const KeyedVector<String8, String8> *headers,
46 bool uidValid,
Oscar Rydhé81dd60e2012-02-20 10:15:48 +010047 uid_t uid,
48 bool isSDP)
Andreas Huber5ab368a2013-02-05 10:14:26 -080049 : Source(notify),
Andreas Huber1b86fe02014-01-29 11:13:26 -080050 mHTTPService(httpService),
Andreas Huber5ab368a2013-02-05 10:14:26 -080051 mURL(url),
Andreas Huber2bfdd422011-10-11 15:24:07 -070052 mUIDValid(uidValid),
53 mUID(uid),
54 mFlags(0),
Oscar Rydhé81dd60e2012-02-20 10:15:48 +010055 mIsSDP(isSDP),
Andreas Huber2bfdd422011-10-11 15:24:07 -070056 mState(DISCONNECTED),
57 mFinalResult(OK),
Andreas Huberee736e92011-12-08 13:04:50 -080058 mDisconnectReplyID(0),
Chong Zhang180d1b92014-12-02 18:35:35 -080059 mBuffering(false),
Robert Shih641e0c72016-02-22 11:37:20 -080060 mInPreparationPhase(true),
Roger Jönssoncfc30832013-01-21 16:26:41 +010061 mSeekGeneration(0),
62 mEOSTimeoutAudio(0),
63 mEOSTimeoutVideo(0) {
Andreas Huber2bfdd422011-10-11 15:24:07 -070064 if (headers) {
65 mExtraHeaders = *headers;
66
67 ssize_t index =
68 mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
69
70 if (index >= 0) {
71 mFlags |= kFlagIncognito;
72
73 mExtraHeaders.removeItemsAt(index);
74 }
75 }
76}
77
78NuPlayer::RTSPSource::~RTSPSource() {
Andreas Huber602f5bb2013-04-15 16:18:56 -070079 if (mLooper != NULL) {
Chong Zhang1228d6b2014-08-12 21:25:48 -070080 mLooper->unregisterHandler(id());
Andreas Huber602f5bb2013-04-15 16:18:56 -070081 mLooper->stop();
82 }
Andreas Huber2bfdd422011-10-11 15:24:07 -070083}
84
Andreas Huber57cea552013-02-05 13:59:56 -080085void NuPlayer::RTSPSource::prepareAsync() {
Wei Jiace84b222016-01-14 14:39:42 -080086 if (mIsSDP && mHTTPService == NULL) {
87 notifyPrepared(BAD_VALUE);
88 return;
89 }
90
Andreas Huber2bfdd422011-10-11 15:24:07 -070091 if (mLooper == NULL) {
92 mLooper = new ALooper;
93 mLooper->setName("rtsp");
94 mLooper->start();
95
Chong Zhang1228d6b2014-08-12 21:25:48 -070096 mLooper->registerHandler(this);
Andreas Huber2bfdd422011-10-11 15:24:07 -070097 }
98
99 CHECK(mHandler == NULL);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100100 CHECK(mSDPLoader == NULL);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700101
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800102 sp<AMessage> notify = new AMessage(kWhatNotify, this);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700103
Andreas Huber2bfdd422011-10-11 15:24:07 -0700104 CHECK_EQ(mState, (int)DISCONNECTED);
105 mState = CONNECTING;
106
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100107 if (mIsSDP) {
108 mSDPLoader = new SDPLoader(notify,
109 (mFlags & kFlagIncognito) ? SDPLoader::kFlagIncognito : 0,
Andreas Huber81e68442014-02-05 11:52:33 -0800110 mHTTPService);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100111
Andreas Huber57cea552013-02-05 13:59:56 -0800112 mSDPLoader->load(
113 mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100114 } else {
115 mHandler = new MyHandler(mURL.c_str(), notify, mUIDValid, mUID);
116 mLooper->registerHandler(mHandler);
117
118 mHandler->connect();
119 }
Roger Jönssoncfc30832013-01-21 16:26:41 +0100120
Chong Zhang180d1b92014-12-02 18:35:35 -0800121 startBufferingIfNecessary();
Andreas Huber57cea552013-02-05 13:59:56 -0800122}
123
124void NuPlayer::RTSPSource::start() {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700125}
126
127void NuPlayer::RTSPSource::stop() {
James Dong58341812012-11-16 14:31:15 -0800128 if (mLooper == NULL) {
129 return;
130 }
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800131 sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700132
133 sp<AMessage> dummy;
134 msg->postAndAwaitResponse(&dummy);
135}
136
137status_t NuPlayer::RTSPSource::feedMoreTSData() {
Chong Zhang180d1b92014-12-02 18:35:35 -0800138 Mutex::Autolock _l(mBufferingLock);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700139 return mFinalResult;
140}
141
Andreas Huber84066782011-08-16 09:34:26 -0700142sp<MetaData> NuPlayer::RTSPSource::getFormatMeta(bool audio) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700143 sp<AnotherPacketSource> source = getSource(audio);
144
145 if (source == NULL) {
146 return NULL;
147 }
148
149 return source->getFormat();
150}
151
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700152bool NuPlayer::RTSPSource::haveSufficientDataOnAllTracks() {
153 // We're going to buffer at least 2 secs worth data on all tracks before
154 // starting playback (both at startup and after a seek).
155
156 static const int64_t kMinDurationUs = 2000000ll;
157
Roger Jönssoncfc30832013-01-21 16:26:41 +0100158 int64_t mediaDurationUs = 0;
159 getDuration(&mediaDurationUs);
160 if ((mAudioTrack != NULL && mAudioTrack->isFinished(mediaDurationUs))
161 || (mVideoTrack != NULL && mVideoTrack->isFinished(mediaDurationUs))) {
162 return true;
163 }
164
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700165 status_t err;
166 int64_t durationUs;
167 if (mAudioTrack != NULL
168 && (durationUs = mAudioTrack->getBufferedDurationUs(&err))
169 < kMinDurationUs
170 && err == OK) {
171 ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
172 durationUs / 1E6);
173 return false;
174 }
175
176 if (mVideoTrack != NULL
177 && (durationUs = mVideoTrack->getBufferedDurationUs(&err))
178 < kMinDurationUs
179 && err == OK) {
180 ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
181 durationUs / 1E6);
182 return false;
183 }
184
185 return true;
186}
187
Andreas Huber2bfdd422011-10-11 15:24:07 -0700188status_t NuPlayer::RTSPSource::dequeueAccessUnit(
189 bool audio, sp<ABuffer> *accessUnit) {
Chong Zhang180d1b92014-12-02 18:35:35 -0800190 if (!stopBufferingIfNecessary()) {
191 return -EWOULDBLOCK;
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700192 }
193
Andreas Huber2bfdd422011-10-11 15:24:07 -0700194 sp<AnotherPacketSource> source = getSource(audio);
195
196 if (source == NULL) {
197 return -EWOULDBLOCK;
198 }
199
200 status_t finalResult;
201 if (!source->hasBufferAvailable(&finalResult)) {
Roger Jönssoncfc30832013-01-21 16:26:41 +0100202 if (finalResult == OK) {
203 int64_t mediaDurationUs = 0;
204 getDuration(&mediaDurationUs);
205 sp<AnotherPacketSource> otherSource = getSource(!audio);
206 status_t otherFinalResult;
207
208 // If other source already signaled EOS, this source should also signal EOS
209 if (otherSource != NULL &&
210 !otherSource->hasBufferAvailable(&otherFinalResult) &&
211 otherFinalResult == ERROR_END_OF_STREAM) {
212 source->signalEOS(ERROR_END_OF_STREAM);
213 return ERROR_END_OF_STREAM;
214 }
215
216 // If this source has detected near end, give it some time to retrieve more
217 // data before signaling EOS
218 if (source->isFinished(mediaDurationUs)) {
219 int64_t eosTimeout = audio ? mEOSTimeoutAudio : mEOSTimeoutVideo;
220 if (eosTimeout == 0) {
221 setEOSTimeout(audio, ALooper::GetNowUs());
222 } else if ((ALooper::GetNowUs() - eosTimeout) > kNearEOSTimeoutUs) {
223 setEOSTimeout(audio, 0);
224 source->signalEOS(ERROR_END_OF_STREAM);
225 return ERROR_END_OF_STREAM;
226 }
227 return -EWOULDBLOCK;
228 }
229
230 if (!(otherSource != NULL && otherSource->isFinished(mediaDurationUs))) {
231 // We should not enter buffering mode
232 // if any of the sources already have detected EOS.
Chong Zhang180d1b92014-12-02 18:35:35 -0800233 startBufferingIfNecessary();
Roger Jönssoncfc30832013-01-21 16:26:41 +0100234 }
235
236 return -EWOULDBLOCK;
237 }
238 return finalResult;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700239 }
240
Roger Jönssoncfc30832013-01-21 16:26:41 +0100241 setEOSTimeout(audio, 0);
242
Andreas Huber2bfdd422011-10-11 15:24:07 -0700243 return source->dequeueAccessUnit(accessUnit);
244}
245
246sp<AnotherPacketSource> NuPlayer::RTSPSource::getSource(bool audio) {
Andreas Huber49694682012-08-31 10:27:46 -0700247 if (mTSParser != NULL) {
248 sp<MediaSource> source = mTSParser->getSource(
249 audio ? ATSParser::AUDIO : ATSParser::VIDEO);
250
251 return static_cast<AnotherPacketSource *>(source.get());
252 }
253
Andreas Huber2bfdd422011-10-11 15:24:07 -0700254 return audio ? mAudioTrack : mVideoTrack;
255}
256
Roger Jönssoncfc30832013-01-21 16:26:41 +0100257void NuPlayer::RTSPSource::setEOSTimeout(bool audio, int64_t timeout) {
258 if (audio) {
259 mEOSTimeoutAudio = timeout;
260 } else {
261 mEOSTimeoutVideo = timeout;
262 }
263}
264
Andreas Huber2bfdd422011-10-11 15:24:07 -0700265status_t NuPlayer::RTSPSource::getDuration(int64_t *durationUs) {
266 *durationUs = 0ll;
267
268 int64_t audioDurationUs;
269 if (mAudioTrack != NULL
270 && mAudioTrack->getFormat()->findInt64(
271 kKeyDuration, &audioDurationUs)
272 && audioDurationUs > *durationUs) {
273 *durationUs = audioDurationUs;
274 }
275
276 int64_t videoDurationUs;
277 if (mVideoTrack != NULL
278 && mVideoTrack->getFormat()->findInt64(
279 kKeyDuration, &videoDurationUs)
280 && videoDurationUs > *durationUs) {
281 *durationUs = videoDurationUs;
282 }
283
284 return OK;
285}
286
287status_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800288 sp<AMessage> msg = new AMessage(kWhatPerformSeek, this);
Andreas Huberee736e92011-12-08 13:04:50 -0800289 msg->setInt32("generation", ++mSeekGeneration);
290 msg->setInt64("timeUs", seekTimeUs);
Andreas Huberee736e92011-12-08 13:04:50 -0800291
Robert Shih8d237a52015-07-13 17:59:36 -0700292 sp<AMessage> response;
293 status_t err = msg->postAndAwaitResponse(&response);
294 if (err == OK && response != NULL) {
295 CHECK(response->findInt32("err", &err));
296 }
297
298 return err;
Andreas Huberee736e92011-12-08 13:04:50 -0800299}
300
301void NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700302 if (mState != CONNECTED) {
Robert Shih8d237a52015-07-13 17:59:36 -0700303 finishSeek(INVALID_OPERATION);
Andreas Huberee736e92011-12-08 13:04:50 -0800304 return;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700305 }
306
307 mState = SEEKING;
308 mHandler->seek(seekTimeUs);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700309}
310
Robert Shih641e0c72016-02-22 11:37:20 -0800311void NuPlayer::RTSPSource::schedulePollBuffering() {
312 sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
313 msg->post(1000000ll); // 1 second intervals
314}
315
316void NuPlayer::RTSPSource::checkBuffering(
317 bool *prepared, bool *underflow, bool *overflow, bool *startServer) {
318 size_t numTracks = mTracks.size();
319 size_t preparedCount, underflowCount, overflowCount, startCount;
320 preparedCount = underflowCount = overflowCount = startCount = 0;
321 for (size_t i = 0; i < numTracks; ++i) {
322 status_t finalResult;
323 TrackInfo *info = &mTracks.editItemAt(i);
324 sp<AnotherPacketSource> src = info->mSource;
325 int64_t bufferedDurationUs = src->getBufferedDurationUs(&finalResult);
326
327 // isFinished when duration is 0 checks for EOS result only
328 if (bufferedDurationUs > kPrepareMarkUs || src->isFinished(/* duration */ 0)) {
329 ++preparedCount;
330 }
331
332 if (src->isFinished(/* duration */ 0)) {
333 ++overflowCount;
334 } else {
335 if (bufferedDurationUs < kUnderflowMarkUs) {
336 ++underflowCount;
337 }
338 if (bufferedDurationUs > kOverflowMarkUs) {
339 ++overflowCount;
340 }
341 if (bufferedDurationUs < kStartServerMarkUs) {
342 ++startCount;
343 }
344 }
345 }
346
347 *prepared = (preparedCount == numTracks);
348 *underflow = (underflowCount > 0);
349 *overflow = (overflowCount == numTracks);
350 *startServer = (startCount > 0);
351}
352
353void NuPlayer::RTSPSource::onPollBuffering() {
354 bool prepared, underflow, overflow, startServer;
355 checkBuffering(&prepared, &underflow, &overflow, &startServer);
356
357 if (prepared && mInPreparationPhase) {
358 mInPreparationPhase = false;
359 notifyPrepared();
360 }
361
362 if (!mInPreparationPhase && underflow) {
363 startBufferingIfNecessary();
364 }
365
366 if (overflow && mHandler != NULL) {
367 stopBufferingIfNecessary();
368 mHandler->pause();
369 }
370
371 if (startServer && mHandler != NULL) {
372 mHandler->resume();
373 }
374
375 schedulePollBuffering();
376}
377
Andreas Huber2bfdd422011-10-11 15:24:07 -0700378void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
379 if (msg->what() == kWhatDisconnect) {
Lajos Molnar3f274362015-03-05 14:35:41 -0800380 sp<AReplyToken> replyID;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700381 CHECK(msg->senderAwaitsResponse(&replyID));
382
383 mDisconnectReplyID = replyID;
384 finishDisconnectIfPossible();
385 return;
Andreas Huberee736e92011-12-08 13:04:50 -0800386 } else if (msg->what() == kWhatPerformSeek) {
387 int32_t generation;
388 CHECK(msg->findInt32("generation", &generation));
Robert Shih8d237a52015-07-13 17:59:36 -0700389 CHECK(msg->senderAwaitsResponse(&mSeekReplyID));
Andreas Huberee736e92011-12-08 13:04:50 -0800390
391 if (generation != mSeekGeneration) {
392 // obsolete.
Robert Shih8d237a52015-07-13 17:59:36 -0700393 finishSeek(OK);
Andreas Huberee736e92011-12-08 13:04:50 -0800394 return;
395 }
396
397 int64_t seekTimeUs;
398 CHECK(msg->findInt64("timeUs", &seekTimeUs));
399
400 performSeek(seekTimeUs);
401 return;
Robert Shih641e0c72016-02-22 11:37:20 -0800402 } else if (msg->what() == kWhatPollBuffering) {
403 onPollBuffering();
404 return;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700405 }
406
407 CHECK_EQ(msg->what(), (int)kWhatNotify);
408
409 int32_t what;
410 CHECK(msg->findInt32("what", &what));
411
412 switch (what) {
413 case MyHandler::kWhatConnected:
Andreas Huber7f475c32013-02-05 14:47:13 -0800414 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700415 onConnected();
Andreas Huber7f475c32013-02-05 14:47:13 -0800416
Chong Zhangced1c2f2014-08-08 15:22:35 -0700417 notifyVideoSizeChanged();
Andreas Huber7f475c32013-02-05 14:47:13 -0800418
419 uint32_t flags = 0;
420
421 if (mHandler->isSeekable()) {
Chong Zhang4b7069d2013-09-11 12:52:43 -0700422 flags = FLAG_CAN_PAUSE
423 | FLAG_CAN_SEEK
424 | FLAG_CAN_SEEK_BACKWARD
425 | FLAG_CAN_SEEK_FORWARD;
Andreas Huber7f475c32013-02-05 14:47:13 -0800426 }
427
428 notifyFlagsChanged(flags);
Robert Shih641e0c72016-02-22 11:37:20 -0800429 schedulePollBuffering();
Andreas Huber2bfdd422011-10-11 15:24:07 -0700430 break;
Andreas Huber7f475c32013-02-05 14:47:13 -0800431 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700432
433 case MyHandler::kWhatDisconnected:
Andreas Huber7f475c32013-02-05 14:47:13 -0800434 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700435 onDisconnected(msg);
436 break;
Andreas Huber7f475c32013-02-05 14:47:13 -0800437 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700438
439 case MyHandler::kWhatSeekDone:
440 {
441 mState = CONNECTED;
Wei Jia4ad74b22016-02-05 17:11:20 -0800442 // Unblock seekTo here in case we attempted to seek in a live stream
443 finishSeek(OK);
Robert Shih8d237a52015-07-13 17:59:36 -0700444 break;
445 }
446
447 case MyHandler::kWhatSeekPaused:
448 {
449 sp<AnotherPacketSource> source = getSource(true /* audio */);
450 if (source != NULL) {
451 source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
452 /* extra */ NULL,
453 /* discard */ true);
454 }
455 source = getSource(false /* video */);
456 if (source != NULL) {
457 source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
458 /* extra */ NULL,
459 /* discard */ true);
460 };
461
462 status_t err = OK;
463 msg->findInt32("err", &err);
Robert Shih8d237a52015-07-13 17:59:36 -0700464
465 if (err == OK) {
466 int64_t timeUs;
467 CHECK(msg->findInt64("time", &timeUs));
468 mHandler->continueSeekAfterPause(timeUs);
Wei Jia4ad74b22016-02-05 17:11:20 -0800469 } else {
470 finishSeek(err);
Robert Shih8d237a52015-07-13 17:59:36 -0700471 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700472 break;
473 }
474
475 case MyHandler::kWhatAccessUnit:
476 {
477 size_t trackIndex;
478 CHECK(msg->findSize("trackIndex", &trackIndex));
Andreas Huber49694682012-08-31 10:27:46 -0700479
480 if (mTSParser == NULL) {
481 CHECK_LT(trackIndex, mTracks.size());
482 } else {
483 CHECK_EQ(trackIndex, 0u);
484 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700485
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800486 sp<ABuffer> accessUnit;
487 CHECK(msg->findBuffer("accessUnit", &accessUnit));
Andreas Huber2bfdd422011-10-11 15:24:07 -0700488
489 int32_t damaged;
490 if (accessUnit->meta()->findInt32("damaged", &damaged)
491 && damaged) {
Steve Blockdf64d152012-01-04 20:05:49 +0000492 ALOGI("dropping damaged access unit.");
Andreas Huber2bfdd422011-10-11 15:24:07 -0700493 break;
494 }
495
Andreas Huber49694682012-08-31 10:27:46 -0700496 if (mTSParser != NULL) {
497 size_t offset = 0;
498 status_t err = OK;
499 while (offset + 188 <= accessUnit->size()) {
500 err = mTSParser->feedTSPacket(
501 accessUnit->data() + offset, 188);
502 if (err != OK) {
503 break;
504 }
505
506 offset += 188;
507 }
508
509 if (offset < accessUnit->size()) {
510 err = ERROR_MALFORMED;
511 }
512
513 if (err != OK) {
514 sp<AnotherPacketSource> source = getSource(false /* audio */);
515 if (source != NULL) {
516 source->signalEOS(err);
517 }
518
519 source = getSource(true /* audio */);
520 if (source != NULL) {
521 source->signalEOS(err);
522 }
523 }
524 break;
525 }
526
Andreas Huber1906e5c2011-12-08 12:27:47 -0800527 TrackInfo *info = &mTracks.editItemAt(trackIndex);
528
529 sp<AnotherPacketSource> source = info->mSource;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700530 if (source != NULL) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700531 uint32_t rtpTime;
532 CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
533
Andreas Huber1906e5c2011-12-08 12:27:47 -0800534 if (!info->mNPTMappingValid) {
535 // This is a live stream, we didn't receive any normal
Andreas Huberc9d16962012-05-21 11:12:40 -0700536 // playtime mapping. We won't map to npt time.
537 source->queueAccessUnit(accessUnit);
538 break;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800539 }
540
Andreas Huber2bfdd422011-10-11 15:24:07 -0700541 int64_t nptUs =
Andreas Huber1906e5c2011-12-08 12:27:47 -0800542 ((double)rtpTime - (double)info->mRTPTime)
543 / info->mTimeScale
Andreas Huber2bfdd422011-10-11 15:24:07 -0700544 * 1000000ll
Andreas Huber1906e5c2011-12-08 12:27:47 -0800545 + info->mNormalPlaytimeUs;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700546
547 accessUnit->meta()->setInt64("timeUs", nptUs);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700548
549 source->queueAccessUnit(accessUnit);
550 }
551 break;
552 }
553
554 case MyHandler::kWhatEOS:
555 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700556 int32_t finalResult;
557 CHECK(msg->findInt32("finalResult", &finalResult));
558 CHECK_NE(finalResult, (status_t)OK);
559
Andreas Huber49694682012-08-31 10:27:46 -0700560 if (mTSParser != NULL) {
561 sp<AnotherPacketSource> source = getSource(false /* audio */);
562 if (source != NULL) {
563 source->signalEOS(finalResult);
564 }
565
566 source = getSource(true /* audio */);
567 if (source != NULL) {
568 source->signalEOS(finalResult);
569 }
570
571 return;
572 }
573
574 size_t trackIndex;
575 CHECK(msg->findSize("trackIndex", &trackIndex));
576 CHECK_LT(trackIndex, mTracks.size());
577
Andreas Huber2bfdd422011-10-11 15:24:07 -0700578 TrackInfo *info = &mTracks.editItemAt(trackIndex);
579 sp<AnotherPacketSource> source = info->mSource;
580 if (source != NULL) {
581 source->signalEOS(finalResult);
582 }
583
584 break;
585 }
586
587 case MyHandler::kWhatSeekDiscontinuity:
588 {
589 size_t trackIndex;
590 CHECK(msg->findSize("trackIndex", &trackIndex));
591 CHECK_LT(trackIndex, mTracks.size());
592
593 TrackInfo *info = &mTracks.editItemAt(trackIndex);
594 sp<AnotherPacketSource> source = info->mSource;
595 if (source != NULL) {
Chong Zhang632740c2014-06-26 13:03:47 -0700596 source->queueDiscontinuity(
Wei Jiafef808d2014-10-31 17:57:05 -0700597 ATSParser::DISCONTINUITY_TIME,
Chong Zhang632740c2014-06-26 13:03:47 -0700598 NULL,
599 true /* discard */);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700600 }
601
602 break;
603 }
604
605 case MyHandler::kWhatNormalPlayTimeMapping:
606 {
607 size_t trackIndex;
608 CHECK(msg->findSize("trackIndex", &trackIndex));
609 CHECK_LT(trackIndex, mTracks.size());
610
611 uint32_t rtpTime;
612 CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime));
613
614 int64_t nptUs;
615 CHECK(msg->findInt64("nptUs", &nptUs));
616
617 TrackInfo *info = &mTracks.editItemAt(trackIndex);
618 info->mRTPTime = rtpTime;
619 info->mNormalPlaytimeUs = nptUs;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800620 info->mNPTMappingValid = true;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700621 break;
622 }
623
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100624 case SDPLoader::kWhatSDPLoaded:
625 {
626 onSDPLoaded(msg);
627 break;
628 }
629
Andreas Huber2bfdd422011-10-11 15:24:07 -0700630 default:
631 TRESPASS();
632 }
633}
634
635void NuPlayer::RTSPSource::onConnected() {
636 CHECK(mAudioTrack == NULL);
637 CHECK(mVideoTrack == NULL);
638
639 size_t numTracks = mHandler->countTracks();
640 for (size_t i = 0; i < numTracks; ++i) {
641 int32_t timeScale;
642 sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale);
643
644 const char *mime;
645 CHECK(format->findCString(kKeyMIMEType, &mime));
646
Andreas Huber49694682012-08-31 10:27:46 -0700647 if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
648 // Very special case for MPEG2 Transport Streams.
649 CHECK_EQ(numTracks, 1u);
650
651 mTSParser = new ATSParser;
652 return;
653 }
654
Andreas Huber2bfdd422011-10-11 15:24:07 -0700655 bool isAudio = !strncasecmp(mime, "audio/", 6);
656 bool isVideo = !strncasecmp(mime, "video/", 6);
657
658 TrackInfo info;
659 info.mTimeScale = timeScale;
660 info.mRTPTime = 0;
661 info.mNormalPlaytimeUs = 0ll;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800662 info.mNPTMappingValid = false;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700663
664 if ((isAudio && mAudioTrack == NULL)
665 || (isVideo && mVideoTrack == NULL)) {
666 sp<AnotherPacketSource> source = new AnotherPacketSource(format);
667
668 if (isAudio) {
669 mAudioTrack = source;
670 } else {
671 mVideoTrack = source;
672 }
673
674 info.mSource = source;
675 }
676
677 mTracks.push(info);
678 }
679
680 mState = CONNECTED;
681}
682
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100683void NuPlayer::RTSPSource::onSDPLoaded(const sp<AMessage> &msg) {
684 status_t err;
685 CHECK(msg->findInt32("result", &err));
686
687 mSDPLoader.clear();
688
689 if (mDisconnectReplyID != 0) {
690 err = UNKNOWN_ERROR;
691 }
692
693 if (err == OK) {
694 sp<ASessionDescription> desc;
695 sp<RefBase> obj;
696 CHECK(msg->findObject("description", &obj));
697 desc = static_cast<ASessionDescription *>(obj.get());
698
699 AString rtspUri;
700 if (!desc->findAttribute(0, "a=control", &rtspUri)) {
701 ALOGE("Unable to find url in SDP");
702 err = UNKNOWN_ERROR;
703 } else {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800704 sp<AMessage> notify = new AMessage(kWhatNotify, this);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100705
706 mHandler = new MyHandler(rtspUri.c_str(), notify, mUIDValid, mUID);
707 mLooper->registerHandler(mHandler);
708
709 mHandler->loadSDP(desc);
710 }
711 }
712
713 if (err != OK) {
Andreas Huber7f475c32013-02-05 14:47:13 -0800714 if (mState == CONNECTING) {
715 // We're still in the preparation phase, signal that it
716 // failed.
717 notifyPrepared(err);
718 }
719
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100720 mState = DISCONNECTED;
Chong Zhang180d1b92014-12-02 18:35:35 -0800721 setError(err);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100722
723 if (mDisconnectReplyID != 0) {
724 finishDisconnectIfPossible();
725 }
726 }
727}
728
Andreas Huber2bfdd422011-10-11 15:24:07 -0700729void NuPlayer::RTSPSource::onDisconnected(const sp<AMessage> &msg) {
Fredrik Rosin0ad03bc2013-03-06 13:42:53 +0100730 if (mState == DISCONNECTED) {
731 return;
732 }
733
Andreas Huber2bfdd422011-10-11 15:24:07 -0700734 status_t err;
735 CHECK(msg->findInt32("result", &err));
736 CHECK_NE(err, (status_t)OK);
737
738 mLooper->unregisterHandler(mHandler->id());
739 mHandler.clear();
740
Andreas Huber7f475c32013-02-05 14:47:13 -0800741 if (mState == CONNECTING) {
742 // We're still in the preparation phase, signal that it
743 // failed.
744 notifyPrepared(err);
745 }
746
Andreas Huber2bfdd422011-10-11 15:24:07 -0700747 mState = DISCONNECTED;
Chong Zhang180d1b92014-12-02 18:35:35 -0800748 setError(err);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700749
750 if (mDisconnectReplyID != 0) {
751 finishDisconnectIfPossible();
752 }
753}
754
755void NuPlayer::RTSPSource::finishDisconnectIfPossible() {
756 if (mState != DISCONNECTED) {
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100757 if (mHandler != NULL) {
758 mHandler->disconnect();
759 } else if (mSDPLoader != NULL) {
760 mSDPLoader->cancel();
761 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700762 return;
763 }
764
765 (new AMessage)->postReply(mDisconnectReplyID);
766 mDisconnectReplyID = 0;
767}
768
Chong Zhang180d1b92014-12-02 18:35:35 -0800769void NuPlayer::RTSPSource::setError(status_t err) {
770 Mutex::Autolock _l(mBufferingLock);
771 mFinalResult = err;
772}
773
774void NuPlayer::RTSPSource::startBufferingIfNecessary() {
775 Mutex::Autolock _l(mBufferingLock);
776
777 if (!mBuffering) {
778 mBuffering = true;
779
780 sp<AMessage> notify = dupNotify();
Wei Jiae67ba382016-02-03 01:41:49 +0000781 notify->setInt32("what", kWhatBufferingStart);
Chong Zhang180d1b92014-12-02 18:35:35 -0800782 notify->post();
783 }
784}
785
786bool NuPlayer::RTSPSource::stopBufferingIfNecessary() {
787 Mutex::Autolock _l(mBufferingLock);
788
789 if (mBuffering) {
790 if (!haveSufficientDataOnAllTracks()) {
791 return false;
792 }
793
794 mBuffering = false;
795
796 sp<AMessage> notify = dupNotify();
Wei Jiae67ba382016-02-03 01:41:49 +0000797 notify->setInt32("what", kWhatBufferingEnd);
Chong Zhang180d1b92014-12-02 18:35:35 -0800798 notify->post();
799 }
800
801 return true;
802}
803
Robert Shih8d237a52015-07-13 17:59:36 -0700804void NuPlayer::RTSPSource::finishSeek(status_t err) {
Wei Jia4ad74b22016-02-05 17:11:20 -0800805 if (mSeekReplyID == NULL) {
806 return;
807 }
Robert Shih8d237a52015-07-13 17:59:36 -0700808 sp<AMessage> seekReply = new AMessage;
809 seekReply->setInt32("err", err);
810 seekReply->postReply(mSeekReplyID);
811 mSeekReplyID = NULL;
812}
Chong Zhang180d1b92014-12-02 18:35:35 -0800813
Andreas Huber2bfdd422011-10-11 15:24:07 -0700814} // namespace android