blob: 8a305deb672464b6b1b30daf2b6eac5e49f7481c [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
372 if (overflow && mHandler != NULL) {
373 stopBufferingIfNecessary();
374 mHandler->pause();
375 }
376
377 if (startServer && mHandler != NULL) {
378 mHandler->resume();
379 }
380
381 schedulePollBuffering();
382}
383
Andreas Huber2bfdd422011-10-11 15:24:07 -0700384void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
385 if (msg->what() == kWhatDisconnect) {
Lajos Molnar3f274362015-03-05 14:35:41 -0800386 sp<AReplyToken> replyID;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700387 CHECK(msg->senderAwaitsResponse(&replyID));
388
389 mDisconnectReplyID = replyID;
390 finishDisconnectIfPossible();
391 return;
Andreas Huberee736e92011-12-08 13:04:50 -0800392 } else if (msg->what() == kWhatPerformSeek) {
393 int32_t generation;
394 CHECK(msg->findInt32("generation", &generation));
Robert Shih8d237a52015-07-13 17:59:36 -0700395 CHECK(msg->senderAwaitsResponse(&mSeekReplyID));
Andreas Huberee736e92011-12-08 13:04:50 -0800396
397 if (generation != mSeekGeneration) {
398 // obsolete.
Robert Shih8d237a52015-07-13 17:59:36 -0700399 finishSeek(OK);
Andreas Huberee736e92011-12-08 13:04:50 -0800400 return;
401 }
402
403 int64_t seekTimeUs;
404 CHECK(msg->findInt64("timeUs", &seekTimeUs));
405
406 performSeek(seekTimeUs);
407 return;
Robert Shih641e0c72016-02-22 11:37:20 -0800408 } else if (msg->what() == kWhatPollBuffering) {
409 onPollBuffering();
410 return;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700411 }
412
413 CHECK_EQ(msg->what(), (int)kWhatNotify);
414
415 int32_t what;
416 CHECK(msg->findInt32("what", &what));
417
418 switch (what) {
419 case MyHandler::kWhatConnected:
Andreas Huber7f475c32013-02-05 14:47:13 -0800420 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700421 onConnected();
Andreas Huber7f475c32013-02-05 14:47:13 -0800422
Chong Zhangced1c2f2014-08-08 15:22:35 -0700423 notifyVideoSizeChanged();
Andreas Huber7f475c32013-02-05 14:47:13 -0800424
425 uint32_t flags = 0;
426
427 if (mHandler->isSeekable()) {
Chong Zhang4b7069d2013-09-11 12:52:43 -0700428 flags = FLAG_CAN_PAUSE
429 | FLAG_CAN_SEEK
430 | FLAG_CAN_SEEK_BACKWARD
431 | FLAG_CAN_SEEK_FORWARD;
Andreas Huber7f475c32013-02-05 14:47:13 -0800432 }
433
434 notifyFlagsChanged(flags);
Robert Shih641e0c72016-02-22 11:37:20 -0800435 schedulePollBuffering();
Andreas Huber2bfdd422011-10-11 15:24:07 -0700436 break;
Andreas Huber7f475c32013-02-05 14:47:13 -0800437 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700438
439 case MyHandler::kWhatDisconnected:
Andreas Huber7f475c32013-02-05 14:47:13 -0800440 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700441 onDisconnected(msg);
442 break;
Andreas Huber7f475c32013-02-05 14:47:13 -0800443 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700444
445 case MyHandler::kWhatSeekDone:
446 {
447 mState = CONNECTED;
Wei Jia4ad74b22016-02-05 17:11:20 -0800448 // Unblock seekTo here in case we attempted to seek in a live stream
449 finishSeek(OK);
Robert Shih8d237a52015-07-13 17:59:36 -0700450 break;
451 }
452
453 case MyHandler::kWhatSeekPaused:
454 {
455 sp<AnotherPacketSource> source = getSource(true /* audio */);
456 if (source != NULL) {
457 source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
458 /* extra */ NULL,
459 /* discard */ true);
460 }
461 source = getSource(false /* video */);
462 if (source != NULL) {
463 source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
464 /* extra */ NULL,
465 /* discard */ true);
466 };
467
468 status_t err = OK;
469 msg->findInt32("err", &err);
Robert Shih8d237a52015-07-13 17:59:36 -0700470
471 if (err == OK) {
472 int64_t timeUs;
473 CHECK(msg->findInt64("time", &timeUs));
474 mHandler->continueSeekAfterPause(timeUs);
Wei Jia4ad74b22016-02-05 17:11:20 -0800475 } else {
476 finishSeek(err);
Robert Shih8d237a52015-07-13 17:59:36 -0700477 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700478 break;
479 }
480
481 case MyHandler::kWhatAccessUnit:
482 {
483 size_t trackIndex;
484 CHECK(msg->findSize("trackIndex", &trackIndex));
Andreas Huber49694682012-08-31 10:27:46 -0700485
486 if (mTSParser == NULL) {
487 CHECK_LT(trackIndex, mTracks.size());
488 } else {
489 CHECK_EQ(trackIndex, 0u);
490 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700491
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800492 sp<ABuffer> accessUnit;
493 CHECK(msg->findBuffer("accessUnit", &accessUnit));
Andreas Huber2bfdd422011-10-11 15:24:07 -0700494
495 int32_t damaged;
496 if (accessUnit->meta()->findInt32("damaged", &damaged)
497 && damaged) {
Steve Blockdf64d152012-01-04 20:05:49 +0000498 ALOGI("dropping damaged access unit.");
Andreas Huber2bfdd422011-10-11 15:24:07 -0700499 break;
500 }
501
Andreas Huber49694682012-08-31 10:27:46 -0700502 if (mTSParser != NULL) {
503 size_t offset = 0;
504 status_t err = OK;
505 while (offset + 188 <= accessUnit->size()) {
506 err = mTSParser->feedTSPacket(
507 accessUnit->data() + offset, 188);
508 if (err != OK) {
509 break;
510 }
511
512 offset += 188;
513 }
514
515 if (offset < accessUnit->size()) {
516 err = ERROR_MALFORMED;
517 }
518
519 if (err != OK) {
520 sp<AnotherPacketSource> source = getSource(false /* audio */);
521 if (source != NULL) {
522 source->signalEOS(err);
523 }
524
525 source = getSource(true /* audio */);
526 if (source != NULL) {
527 source->signalEOS(err);
528 }
529 }
530 break;
531 }
532
Andreas Huber1906e5c2011-12-08 12:27:47 -0800533 TrackInfo *info = &mTracks.editItemAt(trackIndex);
534
535 sp<AnotherPacketSource> source = info->mSource;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700536 if (source != NULL) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700537 uint32_t rtpTime;
538 CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
539
Andreas Huber1906e5c2011-12-08 12:27:47 -0800540 if (!info->mNPTMappingValid) {
541 // This is a live stream, we didn't receive any normal
Andreas Huberc9d16962012-05-21 11:12:40 -0700542 // playtime mapping. We won't map to npt time.
543 source->queueAccessUnit(accessUnit);
544 break;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800545 }
546
Andreas Huber2bfdd422011-10-11 15:24:07 -0700547 int64_t nptUs =
Andreas Huber1906e5c2011-12-08 12:27:47 -0800548 ((double)rtpTime - (double)info->mRTPTime)
549 / info->mTimeScale
Andreas Huber2bfdd422011-10-11 15:24:07 -0700550 * 1000000ll
Andreas Huber1906e5c2011-12-08 12:27:47 -0800551 + info->mNormalPlaytimeUs;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700552
553 accessUnit->meta()->setInt64("timeUs", nptUs);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700554
555 source->queueAccessUnit(accessUnit);
556 }
557 break;
558 }
559
560 case MyHandler::kWhatEOS:
561 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700562 int32_t finalResult;
563 CHECK(msg->findInt32("finalResult", &finalResult));
564 CHECK_NE(finalResult, (status_t)OK);
565
Andreas Huber49694682012-08-31 10:27:46 -0700566 if (mTSParser != NULL) {
567 sp<AnotherPacketSource> source = getSource(false /* audio */);
568 if (source != NULL) {
569 source->signalEOS(finalResult);
570 }
571
572 source = getSource(true /* audio */);
573 if (source != NULL) {
574 source->signalEOS(finalResult);
575 }
576
577 return;
578 }
579
580 size_t trackIndex;
581 CHECK(msg->findSize("trackIndex", &trackIndex));
582 CHECK_LT(trackIndex, mTracks.size());
583
Andreas Huber2bfdd422011-10-11 15:24:07 -0700584 TrackInfo *info = &mTracks.editItemAt(trackIndex);
585 sp<AnotherPacketSource> source = info->mSource;
586 if (source != NULL) {
587 source->signalEOS(finalResult);
588 }
589
590 break;
591 }
592
593 case MyHandler::kWhatSeekDiscontinuity:
594 {
595 size_t trackIndex;
596 CHECK(msg->findSize("trackIndex", &trackIndex));
597 CHECK_LT(trackIndex, mTracks.size());
598
599 TrackInfo *info = &mTracks.editItemAt(trackIndex);
600 sp<AnotherPacketSource> source = info->mSource;
601 if (source != NULL) {
Chong Zhang632740c2014-06-26 13:03:47 -0700602 source->queueDiscontinuity(
Wei Jiafef808d2014-10-31 17:57:05 -0700603 ATSParser::DISCONTINUITY_TIME,
Chong Zhang632740c2014-06-26 13:03:47 -0700604 NULL,
605 true /* discard */);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700606 }
607
608 break;
609 }
610
611 case MyHandler::kWhatNormalPlayTimeMapping:
612 {
613 size_t trackIndex;
614 CHECK(msg->findSize("trackIndex", &trackIndex));
615 CHECK_LT(trackIndex, mTracks.size());
616
617 uint32_t rtpTime;
618 CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime));
619
620 int64_t nptUs;
621 CHECK(msg->findInt64("nptUs", &nptUs));
622
623 TrackInfo *info = &mTracks.editItemAt(trackIndex);
624 info->mRTPTime = rtpTime;
625 info->mNormalPlaytimeUs = nptUs;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800626 info->mNPTMappingValid = true;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700627 break;
628 }
629
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100630 case SDPLoader::kWhatSDPLoaded:
631 {
632 onSDPLoaded(msg);
633 break;
634 }
635
Andreas Huber2bfdd422011-10-11 15:24:07 -0700636 default:
637 TRESPASS();
638 }
639}
640
641void NuPlayer::RTSPSource::onConnected() {
642 CHECK(mAudioTrack == NULL);
643 CHECK(mVideoTrack == NULL);
644
645 size_t numTracks = mHandler->countTracks();
646 for (size_t i = 0; i < numTracks; ++i) {
647 int32_t timeScale;
648 sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale);
649
650 const char *mime;
651 CHECK(format->findCString(kKeyMIMEType, &mime));
652
Andreas Huber49694682012-08-31 10:27:46 -0700653 if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
654 // Very special case for MPEG2 Transport Streams.
655 CHECK_EQ(numTracks, 1u);
656
657 mTSParser = new ATSParser;
658 return;
659 }
660
Andreas Huber2bfdd422011-10-11 15:24:07 -0700661 bool isAudio = !strncasecmp(mime, "audio/", 6);
662 bool isVideo = !strncasecmp(mime, "video/", 6);
663
664 TrackInfo info;
665 info.mTimeScale = timeScale;
666 info.mRTPTime = 0;
667 info.mNormalPlaytimeUs = 0ll;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800668 info.mNPTMappingValid = false;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700669
670 if ((isAudio && mAudioTrack == NULL)
671 || (isVideo && mVideoTrack == NULL)) {
672 sp<AnotherPacketSource> source = new AnotherPacketSource(format);
673
674 if (isAudio) {
675 mAudioTrack = source;
676 } else {
677 mVideoTrack = source;
678 }
679
680 info.mSource = source;
681 }
682
683 mTracks.push(info);
684 }
685
686 mState = CONNECTED;
687}
688
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100689void NuPlayer::RTSPSource::onSDPLoaded(const sp<AMessage> &msg) {
690 status_t err;
691 CHECK(msg->findInt32("result", &err));
692
693 mSDPLoader.clear();
694
695 if (mDisconnectReplyID != 0) {
696 err = UNKNOWN_ERROR;
697 }
698
699 if (err == OK) {
700 sp<ASessionDescription> desc;
701 sp<RefBase> obj;
702 CHECK(msg->findObject("description", &obj));
703 desc = static_cast<ASessionDescription *>(obj.get());
704
705 AString rtspUri;
706 if (!desc->findAttribute(0, "a=control", &rtspUri)) {
707 ALOGE("Unable to find url in SDP");
708 err = UNKNOWN_ERROR;
709 } else {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800710 sp<AMessage> notify = new AMessage(kWhatNotify, this);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100711
712 mHandler = new MyHandler(rtspUri.c_str(), notify, mUIDValid, mUID);
713 mLooper->registerHandler(mHandler);
714
715 mHandler->loadSDP(desc);
716 }
717 }
718
719 if (err != OK) {
Andreas Huber7f475c32013-02-05 14:47:13 -0800720 if (mState == CONNECTING) {
721 // We're still in the preparation phase, signal that it
722 // failed.
723 notifyPrepared(err);
724 }
725
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100726 mState = DISCONNECTED;
Chong Zhang180d1b92014-12-02 18:35:35 -0800727 setError(err);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100728
729 if (mDisconnectReplyID != 0) {
730 finishDisconnectIfPossible();
731 }
732 }
733}
734
Andreas Huber2bfdd422011-10-11 15:24:07 -0700735void NuPlayer::RTSPSource::onDisconnected(const sp<AMessage> &msg) {
Fredrik Rosin0ad03bc2013-03-06 13:42:53 +0100736 if (mState == DISCONNECTED) {
737 return;
738 }
739
Andreas Huber2bfdd422011-10-11 15:24:07 -0700740 status_t err;
741 CHECK(msg->findInt32("result", &err));
742 CHECK_NE(err, (status_t)OK);
743
744 mLooper->unregisterHandler(mHandler->id());
745 mHandler.clear();
746
Andreas Huber7f475c32013-02-05 14:47:13 -0800747 if (mState == CONNECTING) {
748 // We're still in the preparation phase, signal that it
749 // failed.
750 notifyPrepared(err);
751 }
752
Andreas Huber2bfdd422011-10-11 15:24:07 -0700753 mState = DISCONNECTED;
Chong Zhang180d1b92014-12-02 18:35:35 -0800754 setError(err);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700755
756 if (mDisconnectReplyID != 0) {
757 finishDisconnectIfPossible();
758 }
759}
760
761void NuPlayer::RTSPSource::finishDisconnectIfPossible() {
762 if (mState != DISCONNECTED) {
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100763 if (mHandler != NULL) {
764 mHandler->disconnect();
765 } else if (mSDPLoader != NULL) {
766 mSDPLoader->cancel();
767 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700768 return;
769 }
770
771 (new AMessage)->postReply(mDisconnectReplyID);
772 mDisconnectReplyID = 0;
773}
774
Chong Zhang180d1b92014-12-02 18:35:35 -0800775void NuPlayer::RTSPSource::setError(status_t err) {
776 Mutex::Autolock _l(mBufferingLock);
777 mFinalResult = err;
778}
779
780void NuPlayer::RTSPSource::startBufferingIfNecessary() {
781 Mutex::Autolock _l(mBufferingLock);
782
783 if (!mBuffering) {
784 mBuffering = true;
785
786 sp<AMessage> notify = dupNotify();
Wei Jiac9ff2002016-05-24 16:23:48 -0700787 notify->setInt32("what", kWhatPauseOnBufferingStart);
Chong Zhang180d1b92014-12-02 18:35:35 -0800788 notify->post();
789 }
790}
791
792bool NuPlayer::RTSPSource::stopBufferingIfNecessary() {
793 Mutex::Autolock _l(mBufferingLock);
794
795 if (mBuffering) {
796 if (!haveSufficientDataOnAllTracks()) {
797 return false;
798 }
799
800 mBuffering = false;
801
802 sp<AMessage> notify = dupNotify();
Wei Jiac9ff2002016-05-24 16:23:48 -0700803 notify->setInt32("what", kWhatResumeOnBufferingEnd);
Chong Zhang180d1b92014-12-02 18:35:35 -0800804 notify->post();
805 }
806
807 return true;
808}
809
Robert Shih8d237a52015-07-13 17:59:36 -0700810void NuPlayer::RTSPSource::finishSeek(status_t err) {
Wei Jia4ad74b22016-02-05 17:11:20 -0800811 if (mSeekReplyID == NULL) {
812 return;
813 }
Robert Shih8d237a52015-07-13 17:59:36 -0700814 sp<AMessage> seekReply = new AMessage;
815 seekReply->setInt32("err", err);
816 seekReply->postReply(mSeekReplyID);
817 mSeekReplyID = NULL;
818}
Chong Zhang180d1b92014-12-02 18:35:35 -0800819
Andreas Huber2bfdd422011-10-11 15:24:07 -0700820} // namespace android