blob: 901f6364bfcfa91f90245dac616dec088ac57298 [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;
Takahiro Aizawac622c582016-06-20 09:53:47 +0900321
322 size_t count = numTracks;
323 for (size_t i = 0; i < count; ++i) {
Robert Shih641e0c72016-02-22 11:37:20 -0800324 status_t finalResult;
325 TrackInfo *info = &mTracks.editItemAt(i);
326 sp<AnotherPacketSource> src = info->mSource;
Takahiro Aizawac622c582016-06-20 09:53:47 +0900327 if (src == NULL) {
328 --numTracks;
329 continue;
330 }
Robert Shih641e0c72016-02-22 11:37:20 -0800331 int64_t bufferedDurationUs = src->getBufferedDurationUs(&finalResult);
332
333 // isFinished when duration is 0 checks for EOS result only
334 if (bufferedDurationUs > kPrepareMarkUs || src->isFinished(/* duration */ 0)) {
335 ++preparedCount;
336 }
337
338 if (src->isFinished(/* duration */ 0)) {
339 ++overflowCount;
340 } else {
341 if (bufferedDurationUs < kUnderflowMarkUs) {
342 ++underflowCount;
343 }
344 if (bufferedDurationUs > kOverflowMarkUs) {
345 ++overflowCount;
346 }
347 if (bufferedDurationUs < kStartServerMarkUs) {
348 ++startCount;
349 }
350 }
351 }
352
353 *prepared = (preparedCount == numTracks);
354 *underflow = (underflowCount > 0);
355 *overflow = (overflowCount == numTracks);
356 *startServer = (startCount > 0);
357}
358
359void NuPlayer::RTSPSource::onPollBuffering() {
360 bool prepared, underflow, overflow, startServer;
361 checkBuffering(&prepared, &underflow, &overflow, &startServer);
362
363 if (prepared && mInPreparationPhase) {
364 mInPreparationPhase = false;
365 notifyPrepared();
366 }
367
368 if (!mInPreparationPhase && underflow) {
369 startBufferingIfNecessary();
370 }
371
Robert Shih91ea5712016-08-01 16:26:58 -0700372 if (haveSufficientDataOnAllTracks()) {
Robert Shih641e0c72016-02-22 11:37:20 -0800373 stopBufferingIfNecessary();
Robert Shih91ea5712016-08-01 16:26:58 -0700374 }
375
376 if (overflow && mHandler != NULL) {
Robert Shih641e0c72016-02-22 11:37:20 -0800377 mHandler->pause();
378 }
379
380 if (startServer && mHandler != NULL) {
381 mHandler->resume();
382 }
383
384 schedulePollBuffering();
385}
386
Andreas Huber2bfdd422011-10-11 15:24:07 -0700387void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
388 if (msg->what() == kWhatDisconnect) {
Lajos Molnar3f274362015-03-05 14:35:41 -0800389 sp<AReplyToken> replyID;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700390 CHECK(msg->senderAwaitsResponse(&replyID));
391
392 mDisconnectReplyID = replyID;
393 finishDisconnectIfPossible();
394 return;
Andreas Huberee736e92011-12-08 13:04:50 -0800395 } else if (msg->what() == kWhatPerformSeek) {
396 int32_t generation;
397 CHECK(msg->findInt32("generation", &generation));
Robert Shih8d237a52015-07-13 17:59:36 -0700398 CHECK(msg->senderAwaitsResponse(&mSeekReplyID));
Andreas Huberee736e92011-12-08 13:04:50 -0800399
400 if (generation != mSeekGeneration) {
401 // obsolete.
Robert Shih8d237a52015-07-13 17:59:36 -0700402 finishSeek(OK);
Andreas Huberee736e92011-12-08 13:04:50 -0800403 return;
404 }
405
406 int64_t seekTimeUs;
407 CHECK(msg->findInt64("timeUs", &seekTimeUs));
408
409 performSeek(seekTimeUs);
410 return;
Robert Shih641e0c72016-02-22 11:37:20 -0800411 } else if (msg->what() == kWhatPollBuffering) {
412 onPollBuffering();
413 return;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700414 }
415
416 CHECK_EQ(msg->what(), (int)kWhatNotify);
417
418 int32_t what;
419 CHECK(msg->findInt32("what", &what));
420
421 switch (what) {
422 case MyHandler::kWhatConnected:
Andreas Huber7f475c32013-02-05 14:47:13 -0800423 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700424 onConnected();
Andreas Huber7f475c32013-02-05 14:47:13 -0800425
Chong Zhangced1c2f2014-08-08 15:22:35 -0700426 notifyVideoSizeChanged();
Andreas Huber7f475c32013-02-05 14:47:13 -0800427
428 uint32_t flags = 0;
429
430 if (mHandler->isSeekable()) {
Chong Zhang4b7069d2013-09-11 12:52:43 -0700431 flags = FLAG_CAN_PAUSE
432 | FLAG_CAN_SEEK
433 | FLAG_CAN_SEEK_BACKWARD
434 | FLAG_CAN_SEEK_FORWARD;
Andreas Huber7f475c32013-02-05 14:47:13 -0800435 }
436
437 notifyFlagsChanged(flags);
Robert Shih641e0c72016-02-22 11:37:20 -0800438 schedulePollBuffering();
Andreas Huber2bfdd422011-10-11 15:24:07 -0700439 break;
Andreas Huber7f475c32013-02-05 14:47:13 -0800440 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700441
442 case MyHandler::kWhatDisconnected:
Andreas Huber7f475c32013-02-05 14:47:13 -0800443 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700444 onDisconnected(msg);
445 break;
Andreas Huber7f475c32013-02-05 14:47:13 -0800446 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700447
448 case MyHandler::kWhatSeekDone:
449 {
450 mState = CONNECTED;
Wei Jia4ad74b22016-02-05 17:11:20 -0800451 // Unblock seekTo here in case we attempted to seek in a live stream
452 finishSeek(OK);
Robert Shih8d237a52015-07-13 17:59:36 -0700453 break;
454 }
455
456 case MyHandler::kWhatSeekPaused:
457 {
458 sp<AnotherPacketSource> source = getSource(true /* audio */);
459 if (source != NULL) {
460 source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
461 /* extra */ NULL,
462 /* discard */ true);
463 }
464 source = getSource(false /* video */);
465 if (source != NULL) {
466 source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
467 /* extra */ NULL,
468 /* discard */ true);
469 };
470
471 status_t err = OK;
472 msg->findInt32("err", &err);
Robert Shih8d237a52015-07-13 17:59:36 -0700473
474 if (err == OK) {
475 int64_t timeUs;
476 CHECK(msg->findInt64("time", &timeUs));
477 mHandler->continueSeekAfterPause(timeUs);
Wei Jia4ad74b22016-02-05 17:11:20 -0800478 } else {
479 finishSeek(err);
Robert Shih8d237a52015-07-13 17:59:36 -0700480 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700481 break;
482 }
483
484 case MyHandler::kWhatAccessUnit:
485 {
486 size_t trackIndex;
487 CHECK(msg->findSize("trackIndex", &trackIndex));
Andreas Huber49694682012-08-31 10:27:46 -0700488
489 if (mTSParser == NULL) {
490 CHECK_LT(trackIndex, mTracks.size());
491 } else {
492 CHECK_EQ(trackIndex, 0u);
493 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700494
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800495 sp<ABuffer> accessUnit;
496 CHECK(msg->findBuffer("accessUnit", &accessUnit));
Andreas Huber2bfdd422011-10-11 15:24:07 -0700497
498 int32_t damaged;
499 if (accessUnit->meta()->findInt32("damaged", &damaged)
500 && damaged) {
Steve Blockdf64d152012-01-04 20:05:49 +0000501 ALOGI("dropping damaged access unit.");
Andreas Huber2bfdd422011-10-11 15:24:07 -0700502 break;
503 }
504
Andreas Huber49694682012-08-31 10:27:46 -0700505 if (mTSParser != NULL) {
506 size_t offset = 0;
507 status_t err = OK;
508 while (offset + 188 <= accessUnit->size()) {
509 err = mTSParser->feedTSPacket(
510 accessUnit->data() + offset, 188);
511 if (err != OK) {
512 break;
513 }
514
515 offset += 188;
516 }
517
518 if (offset < accessUnit->size()) {
519 err = ERROR_MALFORMED;
520 }
521
522 if (err != OK) {
523 sp<AnotherPacketSource> source = getSource(false /* audio */);
524 if (source != NULL) {
525 source->signalEOS(err);
526 }
527
528 source = getSource(true /* audio */);
529 if (source != NULL) {
530 source->signalEOS(err);
531 }
532 }
533 break;
534 }
535
Andreas Huber1906e5c2011-12-08 12:27:47 -0800536 TrackInfo *info = &mTracks.editItemAt(trackIndex);
537
538 sp<AnotherPacketSource> source = info->mSource;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700539 if (source != NULL) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700540 uint32_t rtpTime;
541 CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
542
Andreas Huber1906e5c2011-12-08 12:27:47 -0800543 if (!info->mNPTMappingValid) {
544 // This is a live stream, we didn't receive any normal
Andreas Huberc9d16962012-05-21 11:12:40 -0700545 // playtime mapping. We won't map to npt time.
546 source->queueAccessUnit(accessUnit);
547 break;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800548 }
549
Andreas Huber2bfdd422011-10-11 15:24:07 -0700550 int64_t nptUs =
Andreas Huber1906e5c2011-12-08 12:27:47 -0800551 ((double)rtpTime - (double)info->mRTPTime)
552 / info->mTimeScale
Andreas Huber2bfdd422011-10-11 15:24:07 -0700553 * 1000000ll
Andreas Huber1906e5c2011-12-08 12:27:47 -0800554 + info->mNormalPlaytimeUs;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700555
556 accessUnit->meta()->setInt64("timeUs", nptUs);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700557
558 source->queueAccessUnit(accessUnit);
559 }
560 break;
561 }
562
563 case MyHandler::kWhatEOS:
564 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700565 int32_t finalResult;
566 CHECK(msg->findInt32("finalResult", &finalResult));
567 CHECK_NE(finalResult, (status_t)OK);
568
Andreas Huber49694682012-08-31 10:27:46 -0700569 if (mTSParser != NULL) {
570 sp<AnotherPacketSource> source = getSource(false /* audio */);
571 if (source != NULL) {
572 source->signalEOS(finalResult);
573 }
574
575 source = getSource(true /* audio */);
576 if (source != NULL) {
577 source->signalEOS(finalResult);
578 }
579
580 return;
581 }
582
583 size_t trackIndex;
584 CHECK(msg->findSize("trackIndex", &trackIndex));
585 CHECK_LT(trackIndex, mTracks.size());
586
Andreas Huber2bfdd422011-10-11 15:24:07 -0700587 TrackInfo *info = &mTracks.editItemAt(trackIndex);
588 sp<AnotherPacketSource> source = info->mSource;
589 if (source != NULL) {
590 source->signalEOS(finalResult);
591 }
592
593 break;
594 }
595
596 case MyHandler::kWhatSeekDiscontinuity:
597 {
598 size_t trackIndex;
599 CHECK(msg->findSize("trackIndex", &trackIndex));
600 CHECK_LT(trackIndex, mTracks.size());
601
602 TrackInfo *info = &mTracks.editItemAt(trackIndex);
603 sp<AnotherPacketSource> source = info->mSource;
604 if (source != NULL) {
Chong Zhang632740c2014-06-26 13:03:47 -0700605 source->queueDiscontinuity(
Wei Jiafef808d2014-10-31 17:57:05 -0700606 ATSParser::DISCONTINUITY_TIME,
Chong Zhang632740c2014-06-26 13:03:47 -0700607 NULL,
608 true /* discard */);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700609 }
610
611 break;
612 }
613
614 case MyHandler::kWhatNormalPlayTimeMapping:
615 {
616 size_t trackIndex;
617 CHECK(msg->findSize("trackIndex", &trackIndex));
618 CHECK_LT(trackIndex, mTracks.size());
619
620 uint32_t rtpTime;
621 CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime));
622
623 int64_t nptUs;
624 CHECK(msg->findInt64("nptUs", &nptUs));
625
626 TrackInfo *info = &mTracks.editItemAt(trackIndex);
627 info->mRTPTime = rtpTime;
628 info->mNormalPlaytimeUs = nptUs;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800629 info->mNPTMappingValid = true;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700630 break;
631 }
632
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100633 case SDPLoader::kWhatSDPLoaded:
634 {
635 onSDPLoaded(msg);
636 break;
637 }
638
Andreas Huber2bfdd422011-10-11 15:24:07 -0700639 default:
640 TRESPASS();
641 }
642}
643
644void NuPlayer::RTSPSource::onConnected() {
645 CHECK(mAudioTrack == NULL);
646 CHECK(mVideoTrack == NULL);
647
648 size_t numTracks = mHandler->countTracks();
649 for (size_t i = 0; i < numTracks; ++i) {
650 int32_t timeScale;
651 sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale);
652
653 const char *mime;
654 CHECK(format->findCString(kKeyMIMEType, &mime));
655
Andreas Huber49694682012-08-31 10:27:46 -0700656 if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
657 // Very special case for MPEG2 Transport Streams.
658 CHECK_EQ(numTracks, 1u);
659
660 mTSParser = new ATSParser;
661 return;
662 }
663
Andreas Huber2bfdd422011-10-11 15:24:07 -0700664 bool isAudio = !strncasecmp(mime, "audio/", 6);
665 bool isVideo = !strncasecmp(mime, "video/", 6);
666
667 TrackInfo info;
668 info.mTimeScale = timeScale;
669 info.mRTPTime = 0;
670 info.mNormalPlaytimeUs = 0ll;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800671 info.mNPTMappingValid = false;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700672
673 if ((isAudio && mAudioTrack == NULL)
674 || (isVideo && mVideoTrack == NULL)) {
675 sp<AnotherPacketSource> source = new AnotherPacketSource(format);
676
677 if (isAudio) {
678 mAudioTrack = source;
679 } else {
680 mVideoTrack = source;
681 }
682
683 info.mSource = source;
684 }
685
686 mTracks.push(info);
687 }
688
689 mState = CONNECTED;
690}
691
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100692void NuPlayer::RTSPSource::onSDPLoaded(const sp<AMessage> &msg) {
693 status_t err;
694 CHECK(msg->findInt32("result", &err));
695
696 mSDPLoader.clear();
697
698 if (mDisconnectReplyID != 0) {
699 err = UNKNOWN_ERROR;
700 }
701
702 if (err == OK) {
703 sp<ASessionDescription> desc;
704 sp<RefBase> obj;
705 CHECK(msg->findObject("description", &obj));
706 desc = static_cast<ASessionDescription *>(obj.get());
707
708 AString rtspUri;
709 if (!desc->findAttribute(0, "a=control", &rtspUri)) {
710 ALOGE("Unable to find url in SDP");
711 err = UNKNOWN_ERROR;
712 } else {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800713 sp<AMessage> notify = new AMessage(kWhatNotify, this);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100714
715 mHandler = new MyHandler(rtspUri.c_str(), notify, mUIDValid, mUID);
716 mLooper->registerHandler(mHandler);
717
718 mHandler->loadSDP(desc);
719 }
720 }
721
722 if (err != OK) {
Andreas Huber7f475c32013-02-05 14:47:13 -0800723 if (mState == CONNECTING) {
724 // We're still in the preparation phase, signal that it
725 // failed.
726 notifyPrepared(err);
727 }
728
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100729 mState = DISCONNECTED;
Chong Zhang180d1b92014-12-02 18:35:35 -0800730 setError(err);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100731
732 if (mDisconnectReplyID != 0) {
733 finishDisconnectIfPossible();
734 }
735 }
736}
737
Andreas Huber2bfdd422011-10-11 15:24:07 -0700738void NuPlayer::RTSPSource::onDisconnected(const sp<AMessage> &msg) {
Fredrik Rosin0ad03bc2013-03-06 13:42:53 +0100739 if (mState == DISCONNECTED) {
740 return;
741 }
742
Andreas Huber2bfdd422011-10-11 15:24:07 -0700743 status_t err;
744 CHECK(msg->findInt32("result", &err));
745 CHECK_NE(err, (status_t)OK);
746
747 mLooper->unregisterHandler(mHandler->id());
748 mHandler.clear();
749
Andreas Huber7f475c32013-02-05 14:47:13 -0800750 if (mState == CONNECTING) {
751 // We're still in the preparation phase, signal that it
752 // failed.
753 notifyPrepared(err);
754 }
755
Andreas Huber2bfdd422011-10-11 15:24:07 -0700756 mState = DISCONNECTED;
Chong Zhang180d1b92014-12-02 18:35:35 -0800757 setError(err);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700758
759 if (mDisconnectReplyID != 0) {
760 finishDisconnectIfPossible();
761 }
762}
763
764void NuPlayer::RTSPSource::finishDisconnectIfPossible() {
765 if (mState != DISCONNECTED) {
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100766 if (mHandler != NULL) {
767 mHandler->disconnect();
768 } else if (mSDPLoader != NULL) {
769 mSDPLoader->cancel();
770 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700771 return;
772 }
773
774 (new AMessage)->postReply(mDisconnectReplyID);
775 mDisconnectReplyID = 0;
776}
777
Chong Zhang180d1b92014-12-02 18:35:35 -0800778void NuPlayer::RTSPSource::setError(status_t err) {
779 Mutex::Autolock _l(mBufferingLock);
780 mFinalResult = err;
781}
782
783void NuPlayer::RTSPSource::startBufferingIfNecessary() {
784 Mutex::Autolock _l(mBufferingLock);
785
786 if (!mBuffering) {
787 mBuffering = true;
788
789 sp<AMessage> notify = dupNotify();
Wei Jiac9ff2002016-05-24 16:23:48 -0700790 notify->setInt32("what", kWhatPauseOnBufferingStart);
Chong Zhang180d1b92014-12-02 18:35:35 -0800791 notify->post();
792 }
793}
794
795bool NuPlayer::RTSPSource::stopBufferingIfNecessary() {
796 Mutex::Autolock _l(mBufferingLock);
797
798 if (mBuffering) {
799 if (!haveSufficientDataOnAllTracks()) {
800 return false;
801 }
802
803 mBuffering = false;
804
805 sp<AMessage> notify = dupNotify();
Wei Jiac9ff2002016-05-24 16:23:48 -0700806 notify->setInt32("what", kWhatResumeOnBufferingEnd);
Chong Zhang180d1b92014-12-02 18:35:35 -0800807 notify->post();
808 }
809
810 return true;
811}
812
Robert Shih8d237a52015-07-13 17:59:36 -0700813void NuPlayer::RTSPSource::finishSeek(status_t err) {
Wei Jia4ad74b22016-02-05 17:11:20 -0800814 if (mSeekReplyID == NULL) {
815 return;
816 }
Robert Shih8d237a52015-07-13 17:59:36 -0700817 sp<AMessage> seekReply = new AMessage;
818 seekReply->setInt32("err", err);
819 seekReply->postReply(mSeekReplyID);
820 mSeekReplyID = NULL;
821}
Chong Zhang180d1b92014-12-02 18:35:35 -0800822
Andreas Huber2bfdd422011-10-11 15:24:07 -0700823} // namespace android