blob: bf14ec2ef925a132e4fc21cd3f0c9660aeb67ab8 [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
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -080033const int64_t kNearEOSTimeoutUs = 2000000LL; // 2 secs
Roger Jönssoncfc30832013-01-21 16:26:41 +010034
Wei Jia48fa06d2016-12-20 15:30:49 -080035// Default Buffer Underflow/Prepare/StartServer/Overflow Marks
36static const int kUnderflowMarkMs = 1000; // 1 second
37static const int kPrepareMarkMs = 3000; // 3 seconds
38//static const int kStartServerMarkMs = 5000;
39static const int kOverflowMarkMs = 10000; // 10 seconds
Robert Shih641e0c72016-02-22 11:37:20 -080040
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),
Robert Shihf1d261f2016-07-29 16:44:39 -070061 mEOSPending(false),
Roger Jönssoncfc30832013-01-21 16:26:41 +010062 mSeekGeneration(0),
63 mEOSTimeoutAudio(0),
64 mEOSTimeoutVideo(0) {
Wei Jia9bb38032017-03-23 18:00:38 -070065 mBufferingSettings.mInitialMarkMs = kPrepareMarkMs;
66 mBufferingSettings.mResumePlaybackMarkMs = kOverflowMarkMs;
Andreas Huber2bfdd422011-10-11 15:24:07 -070067 if (headers) {
68 mExtraHeaders = *headers;
69
70 ssize_t index =
71 mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
72
73 if (index >= 0) {
74 mFlags |= kFlagIncognito;
75
76 mExtraHeaders.removeItemsAt(index);
77 }
78 }
79}
80
81NuPlayer::RTSPSource::~RTSPSource() {
Andreas Huber602f5bb2013-04-15 16:18:56 -070082 if (mLooper != NULL) {
Chong Zhang1228d6b2014-08-12 21:25:48 -070083 mLooper->unregisterHandler(id());
Andreas Huber602f5bb2013-04-15 16:18:56 -070084 mLooper->stop();
85 }
Andreas Huber2bfdd422011-10-11 15:24:07 -070086}
87
Wei Jia9bb38032017-03-23 18:00:38 -070088status_t NuPlayer::RTSPSource::getBufferingSettings(
Wei Jia48fa06d2016-12-20 15:30:49 -080089 BufferingSettings* buffering /* nonnull */) {
Wei Jia9bb38032017-03-23 18:00:38 -070090 Mutex::Autolock _l(mBufferingSettingsLock);
91 *buffering = mBufferingSettings;
Wei Jia48fa06d2016-12-20 15:30:49 -080092 return OK;
93}
94
95status_t NuPlayer::RTSPSource::setBufferingSettings(const BufferingSettings& buffering) {
Wei Jia9bb38032017-03-23 18:00:38 -070096 Mutex::Autolock _l(mBufferingSettingsLock);
97 mBufferingSettings = buffering;
98 return OK;
Wei Jia48fa06d2016-12-20 15:30:49 -080099}
100
Andreas Huber57cea552013-02-05 13:59:56 -0800101void NuPlayer::RTSPSource::prepareAsync() {
Wei Jiace84b222016-01-14 14:39:42 -0800102 if (mIsSDP && mHTTPService == NULL) {
103 notifyPrepared(BAD_VALUE);
104 return;
105 }
106
Andreas Huber2bfdd422011-10-11 15:24:07 -0700107 if (mLooper == NULL) {
108 mLooper = new ALooper;
109 mLooper->setName("rtsp");
110 mLooper->start();
111
Chong Zhang1228d6b2014-08-12 21:25:48 -0700112 mLooper->registerHandler(this);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700113 }
114
115 CHECK(mHandler == NULL);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100116 CHECK(mSDPLoader == NULL);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700117
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800118 sp<AMessage> notify = new AMessage(kWhatNotify, this);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700119
Andreas Huber2bfdd422011-10-11 15:24:07 -0700120 CHECK_EQ(mState, (int)DISCONNECTED);
121 mState = CONNECTING;
122
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100123 if (mIsSDP) {
124 mSDPLoader = new SDPLoader(notify,
125 (mFlags & kFlagIncognito) ? SDPLoader::kFlagIncognito : 0,
Andreas Huber81e68442014-02-05 11:52:33 -0800126 mHTTPService);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100127
Andreas Huber57cea552013-02-05 13:59:56 -0800128 mSDPLoader->load(
129 mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100130 } else {
131 mHandler = new MyHandler(mURL.c_str(), notify, mUIDValid, mUID);
132 mLooper->registerHandler(mHandler);
133
134 mHandler->connect();
135 }
Roger Jönssoncfc30832013-01-21 16:26:41 +0100136
Chong Zhang180d1b92014-12-02 18:35:35 -0800137 startBufferingIfNecessary();
Andreas Huber57cea552013-02-05 13:59:56 -0800138}
139
140void NuPlayer::RTSPSource::start() {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700141}
142
143void NuPlayer::RTSPSource::stop() {
James Dong58341812012-11-16 14:31:15 -0800144 if (mLooper == NULL) {
145 return;
146 }
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800147 sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700148
149 sp<AMessage> dummy;
150 msg->postAndAwaitResponse(&dummy);
151}
152
153status_t NuPlayer::RTSPSource::feedMoreTSData() {
Chong Zhang180d1b92014-12-02 18:35:35 -0800154 Mutex::Autolock _l(mBufferingLock);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700155 return mFinalResult;
156}
157
Andreas Huber84066782011-08-16 09:34:26 -0700158sp<MetaData> NuPlayer::RTSPSource::getFormatMeta(bool audio) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700159 sp<AnotherPacketSource> source = getSource(audio);
160
161 if (source == NULL) {
162 return NULL;
163 }
164
165 return source->getFormat();
166}
167
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700168bool NuPlayer::RTSPSource::haveSufficientDataOnAllTracks() {
169 // We're going to buffer at least 2 secs worth data on all tracks before
170 // starting playback (both at startup and after a seek).
171
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800172 static const int64_t kMinDurationUs = 2000000LL;
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700173
Roger Jönssoncfc30832013-01-21 16:26:41 +0100174 int64_t mediaDurationUs = 0;
175 getDuration(&mediaDurationUs);
176 if ((mAudioTrack != NULL && mAudioTrack->isFinished(mediaDurationUs))
177 || (mVideoTrack != NULL && mVideoTrack->isFinished(mediaDurationUs))) {
178 return true;
179 }
180
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700181 status_t err;
182 int64_t durationUs;
183 if (mAudioTrack != NULL
184 && (durationUs = mAudioTrack->getBufferedDurationUs(&err))
185 < kMinDurationUs
186 && err == OK) {
187 ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
188 durationUs / 1E6);
189 return false;
190 }
191
192 if (mVideoTrack != NULL
193 && (durationUs = mVideoTrack->getBufferedDurationUs(&err))
194 < kMinDurationUs
195 && err == OK) {
196 ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
197 durationUs / 1E6);
198 return false;
199 }
200
201 return true;
202}
203
Andreas Huber2bfdd422011-10-11 15:24:07 -0700204status_t NuPlayer::RTSPSource::dequeueAccessUnit(
205 bool audio, sp<ABuffer> *accessUnit) {
Chong Zhang180d1b92014-12-02 18:35:35 -0800206 if (!stopBufferingIfNecessary()) {
207 return -EWOULDBLOCK;
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700208 }
209
Andreas Huber2bfdd422011-10-11 15:24:07 -0700210 sp<AnotherPacketSource> source = getSource(audio);
211
212 if (source == NULL) {
213 return -EWOULDBLOCK;
214 }
215
216 status_t finalResult;
217 if (!source->hasBufferAvailable(&finalResult)) {
Roger Jönssoncfc30832013-01-21 16:26:41 +0100218 if (finalResult == OK) {
Roger Jönssoncfc30832013-01-21 16:26:41 +0100219
Robert Shihf1d261f2016-07-29 16:44:39 -0700220 // If other source already signaled EOS, this source should also return EOS
221 if (sourceReachedEOS(!audio)) {
Roger Jönssoncfc30832013-01-21 16:26:41 +0100222 return ERROR_END_OF_STREAM;
223 }
224
225 // If this source has detected near end, give it some time to retrieve more
Robert Shihf1d261f2016-07-29 16:44:39 -0700226 // data before returning EOS
227 int64_t mediaDurationUs = 0;
228 getDuration(&mediaDurationUs);
Roger Jönssoncfc30832013-01-21 16:26:41 +0100229 if (source->isFinished(mediaDurationUs)) {
230 int64_t eosTimeout = audio ? mEOSTimeoutAudio : mEOSTimeoutVideo;
231 if (eosTimeout == 0) {
232 setEOSTimeout(audio, ALooper::GetNowUs());
233 } else if ((ALooper::GetNowUs() - eosTimeout) > kNearEOSTimeoutUs) {
234 setEOSTimeout(audio, 0);
Roger Jönssoncfc30832013-01-21 16:26:41 +0100235 return ERROR_END_OF_STREAM;
236 }
237 return -EWOULDBLOCK;
238 }
239
Robert Shihf1d261f2016-07-29 16:44:39 -0700240 if (!sourceNearEOS(!audio)) {
Roger Jönssoncfc30832013-01-21 16:26:41 +0100241 // We should not enter buffering mode
242 // if any of the sources already have detected EOS.
Chong Zhang180d1b92014-12-02 18:35:35 -0800243 startBufferingIfNecessary();
Roger Jönssoncfc30832013-01-21 16:26:41 +0100244 }
245
246 return -EWOULDBLOCK;
247 }
248 return finalResult;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700249 }
250
Roger Jönssoncfc30832013-01-21 16:26:41 +0100251 setEOSTimeout(audio, 0);
252
Andreas Huber2bfdd422011-10-11 15:24:07 -0700253 return source->dequeueAccessUnit(accessUnit);
254}
255
256sp<AnotherPacketSource> NuPlayer::RTSPSource::getSource(bool audio) {
Andreas Huber49694682012-08-31 10:27:46 -0700257 if (mTSParser != NULL) {
258 sp<MediaSource> source = mTSParser->getSource(
259 audio ? ATSParser::AUDIO : ATSParser::VIDEO);
260
261 return static_cast<AnotherPacketSource *>(source.get());
262 }
263
Andreas Huber2bfdd422011-10-11 15:24:07 -0700264 return audio ? mAudioTrack : mVideoTrack;
265}
266
Roger Jönssoncfc30832013-01-21 16:26:41 +0100267void NuPlayer::RTSPSource::setEOSTimeout(bool audio, int64_t timeout) {
268 if (audio) {
269 mEOSTimeoutAudio = timeout;
270 } else {
271 mEOSTimeoutVideo = timeout;
272 }
273}
274
Andreas Huber2bfdd422011-10-11 15:24:07 -0700275status_t NuPlayer::RTSPSource::getDuration(int64_t *durationUs) {
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800276 *durationUs = -1LL;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700277
278 int64_t audioDurationUs;
279 if (mAudioTrack != NULL
280 && mAudioTrack->getFormat()->findInt64(
281 kKeyDuration, &audioDurationUs)
282 && audioDurationUs > *durationUs) {
283 *durationUs = audioDurationUs;
284 }
285
286 int64_t videoDurationUs;
287 if (mVideoTrack != NULL
288 && mVideoTrack->getFormat()->findInt64(
289 kKeyDuration, &videoDurationUs)
290 && videoDurationUs > *durationUs) {
291 *durationUs = videoDurationUs;
292 }
293
294 return OK;
295}
296
Wei Jiac5de0912016-11-18 10:22:14 -0800297status_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800298 sp<AMessage> msg = new AMessage(kWhatPerformSeek, this);
Andreas Huberee736e92011-12-08 13:04:50 -0800299 msg->setInt32("generation", ++mSeekGeneration);
300 msg->setInt64("timeUs", seekTimeUs);
Wei Jiac5de0912016-11-18 10:22:14 -0800301 msg->setInt32("mode", mode);
Andreas Huberee736e92011-12-08 13:04:50 -0800302
Robert Shih8d237a52015-07-13 17:59:36 -0700303 sp<AMessage> response;
304 status_t err = msg->postAndAwaitResponse(&response);
305 if (err == OK && response != NULL) {
306 CHECK(response->findInt32("err", &err));
307 }
308
309 return err;
Andreas Huberee736e92011-12-08 13:04:50 -0800310}
311
312void NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700313 if (mState != CONNECTED) {
Robert Shih8d237a52015-07-13 17:59:36 -0700314 finishSeek(INVALID_OPERATION);
Andreas Huberee736e92011-12-08 13:04:50 -0800315 return;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700316 }
317
318 mState = SEEKING;
319 mHandler->seek(seekTimeUs);
Robert Shihf1d261f2016-07-29 16:44:39 -0700320 mEOSPending = false;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700321}
322
Robert Shih641e0c72016-02-22 11:37:20 -0800323void NuPlayer::RTSPSource::schedulePollBuffering() {
324 sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800325 msg->post(1000000LL); // 1 second intervals
Robert Shih641e0c72016-02-22 11:37:20 -0800326}
327
328void NuPlayer::RTSPSource::checkBuffering(
Robert Shihf1d261f2016-07-29 16:44:39 -0700329 bool *prepared, bool *underflow, bool *overflow, bool *startServer, bool *finished) {
Robert Shih641e0c72016-02-22 11:37:20 -0800330 size_t numTracks = mTracks.size();
Robert Shihf1d261f2016-07-29 16:44:39 -0700331 size_t preparedCount, underflowCount, overflowCount, startCount, finishedCount;
332 preparedCount = underflowCount = overflowCount = startCount = finishedCount = 0;
Takahiro Aizawac622c582016-06-20 09:53:47 +0900333
334 size_t count = numTracks;
335 for (size_t i = 0; i < count; ++i) {
Robert Shih641e0c72016-02-22 11:37:20 -0800336 status_t finalResult;
337 TrackInfo *info = &mTracks.editItemAt(i);
338 sp<AnotherPacketSource> src = info->mSource;
Takahiro Aizawac622c582016-06-20 09:53:47 +0900339 if (src == NULL) {
340 --numTracks;
341 continue;
342 }
Robert Shih641e0c72016-02-22 11:37:20 -0800343 int64_t bufferedDurationUs = src->getBufferedDurationUs(&finalResult);
344
Wei Jia9bb38032017-03-23 18:00:38 -0700345 int64_t initialMarkUs;
346 int64_t maxRebufferingMarkUs;
347 {
348 Mutex::Autolock _l(mBufferingSettingsLock);
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800349 initialMarkUs = mBufferingSettings.mInitialMarkMs * 1000LL;
Wei Jia9bb38032017-03-23 18:00:38 -0700350 // TODO: maxRebufferingMarkUs could be larger than
351 // mBufferingSettings.mResumePlaybackMarkMs * 1000ll.
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800352 maxRebufferingMarkUs = mBufferingSettings.mResumePlaybackMarkMs * 1000LL;
Wei Jia9bb38032017-03-23 18:00:38 -0700353 }
Robert Shih641e0c72016-02-22 11:37:20 -0800354 // isFinished when duration is 0 checks for EOS result only
Wei Jia9bb38032017-03-23 18:00:38 -0700355 if (bufferedDurationUs > initialMarkUs
Wei Jia48fa06d2016-12-20 15:30:49 -0800356 || src->isFinished(/* duration */ 0)) {
Robert Shih641e0c72016-02-22 11:37:20 -0800357 ++preparedCount;
358 }
359
360 if (src->isFinished(/* duration */ 0)) {
361 ++overflowCount;
Robert Shihf1d261f2016-07-29 16:44:39 -0700362 ++finishedCount;
Robert Shih641e0c72016-02-22 11:37:20 -0800363 } else {
Wei Jia9bb38032017-03-23 18:00:38 -0700364 // TODO: redefine kUnderflowMarkMs to a fair value,
365 if (bufferedDurationUs < kUnderflowMarkMs * 1000) {
Robert Shih641e0c72016-02-22 11:37:20 -0800366 ++underflowCount;
367 }
Wei Jia9bb38032017-03-23 18:00:38 -0700368 if (bufferedDurationUs > maxRebufferingMarkUs) {
Robert Shih641e0c72016-02-22 11:37:20 -0800369 ++overflowCount;
370 }
Wei Jia48fa06d2016-12-20 15:30:49 -0800371 int64_t startServerMarkUs =
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800372 (kUnderflowMarkMs * 1000LL + maxRebufferingMarkUs) / 2;
Wei Jia48fa06d2016-12-20 15:30:49 -0800373 if (bufferedDurationUs < startServerMarkUs) {
Robert Shih641e0c72016-02-22 11:37:20 -0800374 ++startCount;
375 }
376 }
377 }
378
379 *prepared = (preparedCount == numTracks);
380 *underflow = (underflowCount > 0);
381 *overflow = (overflowCount == numTracks);
382 *startServer = (startCount > 0);
Robert Shihf1d261f2016-07-29 16:44:39 -0700383 *finished = (finishedCount > 0);
Robert Shih641e0c72016-02-22 11:37:20 -0800384}
385
386void NuPlayer::RTSPSource::onPollBuffering() {
Robert Shihf1d261f2016-07-29 16:44:39 -0700387 bool prepared, underflow, overflow, startServer, finished;
388 checkBuffering(&prepared, &underflow, &overflow, &startServer, &finished);
Robert Shih641e0c72016-02-22 11:37:20 -0800389
390 if (prepared && mInPreparationPhase) {
391 mInPreparationPhase = false;
392 notifyPrepared();
393 }
394
395 if (!mInPreparationPhase && underflow) {
396 startBufferingIfNecessary();
397 }
398
Robert Shih91ea5712016-08-01 16:26:58 -0700399 if (haveSufficientDataOnAllTracks()) {
Robert Shih641e0c72016-02-22 11:37:20 -0800400 stopBufferingIfNecessary();
Robert Shih91ea5712016-08-01 16:26:58 -0700401 }
402
403 if (overflow && mHandler != NULL) {
Robert Shih641e0c72016-02-22 11:37:20 -0800404 mHandler->pause();
405 }
406
407 if (startServer && mHandler != NULL) {
408 mHandler->resume();
409 }
410
Robert Shihf1d261f2016-07-29 16:44:39 -0700411 if (finished && mHandler != NULL) {
412 mHandler->cancelAccessUnitTimeoutCheck();
413 }
414
Robert Shih641e0c72016-02-22 11:37:20 -0800415 schedulePollBuffering();
416}
417
Robert Shihf1d261f2016-07-29 16:44:39 -0700418void NuPlayer::RTSPSource::signalSourceEOS(status_t result) {
419 const bool audio = true;
420 const bool video = false;
421
422 sp<AnotherPacketSource> source = getSource(audio);
423 if (source != NULL) {
424 source->signalEOS(result);
425 }
426
427 source = getSource(video);
428 if (source != NULL) {
429 source->signalEOS(result);
430 }
431}
432
433bool NuPlayer::RTSPSource::sourceReachedEOS(bool audio) {
434 sp<AnotherPacketSource> source = getSource(audio);
435 status_t finalResult;
436 return (source != NULL &&
437 !source->hasBufferAvailable(&finalResult) &&
438 finalResult == ERROR_END_OF_STREAM);
439}
440
441bool NuPlayer::RTSPSource::sourceNearEOS(bool audio) {
442 sp<AnotherPacketSource> source = getSource(audio);
443 int64_t mediaDurationUs = 0;
444 getDuration(&mediaDurationUs);
445 return (source != NULL && source->isFinished(mediaDurationUs));
446}
447
448void NuPlayer::RTSPSource::onSignalEOS(const sp<AMessage> &msg) {
449 int32_t generation;
450 CHECK(msg->findInt32("generation", &generation));
451
452 if (generation != mSeekGeneration) {
453 return;
454 }
455
456 if (mEOSPending) {
457 signalSourceEOS(ERROR_END_OF_STREAM);
458 mEOSPending = false;
459 }
460}
461
462void NuPlayer::RTSPSource::postSourceEOSIfNecessary() {
463 const bool audio = true;
464 const bool video = false;
465 // If a source has detected near end, give it some time to retrieve more
466 // data before signaling EOS
467 if (sourceNearEOS(audio) || sourceNearEOS(video)) {
468 if (!mEOSPending) {
469 sp<AMessage> msg = new AMessage(kWhatSignalEOS, this);
470 msg->setInt32("generation", mSeekGeneration);
471 msg->post(kNearEOSTimeoutUs);
472 mEOSPending = true;
473 }
474 }
475}
476
Andreas Huber2bfdd422011-10-11 15:24:07 -0700477void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
478 if (msg->what() == kWhatDisconnect) {
Lajos Molnar3f274362015-03-05 14:35:41 -0800479 sp<AReplyToken> replyID;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700480 CHECK(msg->senderAwaitsResponse(&replyID));
481
482 mDisconnectReplyID = replyID;
483 finishDisconnectIfPossible();
484 return;
Andreas Huberee736e92011-12-08 13:04:50 -0800485 } else if (msg->what() == kWhatPerformSeek) {
486 int32_t generation;
487 CHECK(msg->findInt32("generation", &generation));
Robert Shih8d237a52015-07-13 17:59:36 -0700488 CHECK(msg->senderAwaitsResponse(&mSeekReplyID));
Andreas Huberee736e92011-12-08 13:04:50 -0800489
490 if (generation != mSeekGeneration) {
491 // obsolete.
Robert Shih8d237a52015-07-13 17:59:36 -0700492 finishSeek(OK);
Andreas Huberee736e92011-12-08 13:04:50 -0800493 return;
494 }
495
496 int64_t seekTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -0800497 int32_t mode;
Andreas Huberee736e92011-12-08 13:04:50 -0800498 CHECK(msg->findInt64("timeUs", &seekTimeUs));
Wei Jiac5de0912016-11-18 10:22:14 -0800499 CHECK(msg->findInt32("mode", &mode));
Andreas Huberee736e92011-12-08 13:04:50 -0800500
Wei Jiac5de0912016-11-18 10:22:14 -0800501 // TODO: add "mode" to performSeek.
502 performSeek(seekTimeUs/*, (MediaPlayerSeekMode)mode */);
Andreas Huberee736e92011-12-08 13:04:50 -0800503 return;
Robert Shih641e0c72016-02-22 11:37:20 -0800504 } else if (msg->what() == kWhatPollBuffering) {
505 onPollBuffering();
506 return;
Robert Shihf1d261f2016-07-29 16:44:39 -0700507 } else if (msg->what() == kWhatSignalEOS) {
508 onSignalEOS(msg);
509 return;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700510 }
511
Colin Crossb8c35f92017-04-27 16:15:51 -0700512 CHECK_EQ(msg->what(), kWhatNotify);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700513
514 int32_t what;
515 CHECK(msg->findInt32("what", &what));
516
517 switch (what) {
518 case MyHandler::kWhatConnected:
Andreas Huber7f475c32013-02-05 14:47:13 -0800519 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700520 onConnected();
Andreas Huber7f475c32013-02-05 14:47:13 -0800521
Chong Zhangced1c2f2014-08-08 15:22:35 -0700522 notifyVideoSizeChanged();
Andreas Huber7f475c32013-02-05 14:47:13 -0800523
524 uint32_t flags = 0;
525
526 if (mHandler->isSeekable()) {
Chong Zhang4b7069d2013-09-11 12:52:43 -0700527 flags = FLAG_CAN_PAUSE
528 | FLAG_CAN_SEEK
529 | FLAG_CAN_SEEK_BACKWARD
530 | FLAG_CAN_SEEK_FORWARD;
Andreas Huber7f475c32013-02-05 14:47:13 -0800531 }
532
533 notifyFlagsChanged(flags);
Robert Shih641e0c72016-02-22 11:37:20 -0800534 schedulePollBuffering();
Andreas Huber2bfdd422011-10-11 15:24:07 -0700535 break;
Andreas Huber7f475c32013-02-05 14:47:13 -0800536 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700537
538 case MyHandler::kWhatDisconnected:
Andreas Huber7f475c32013-02-05 14:47:13 -0800539 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700540 onDisconnected(msg);
541 break;
Andreas Huber7f475c32013-02-05 14:47:13 -0800542 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700543
544 case MyHandler::kWhatSeekDone:
545 {
546 mState = CONNECTED;
Wei Jia4ad74b22016-02-05 17:11:20 -0800547 // Unblock seekTo here in case we attempted to seek in a live stream
548 finishSeek(OK);
Robert Shih8d237a52015-07-13 17:59:36 -0700549 break;
550 }
551
552 case MyHandler::kWhatSeekPaused:
553 {
554 sp<AnotherPacketSource> source = getSource(true /* audio */);
555 if (source != NULL) {
556 source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
557 /* extra */ NULL,
558 /* discard */ true);
559 }
560 source = getSource(false /* video */);
561 if (source != NULL) {
562 source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
563 /* extra */ NULL,
564 /* discard */ true);
565 };
566
567 status_t err = OK;
568 msg->findInt32("err", &err);
Robert Shih8d237a52015-07-13 17:59:36 -0700569
570 if (err == OK) {
571 int64_t timeUs;
572 CHECK(msg->findInt64("time", &timeUs));
573 mHandler->continueSeekAfterPause(timeUs);
Wei Jia4ad74b22016-02-05 17:11:20 -0800574 } else {
575 finishSeek(err);
Robert Shih8d237a52015-07-13 17:59:36 -0700576 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700577 break;
578 }
579
580 case MyHandler::kWhatAccessUnit:
581 {
582 size_t trackIndex;
583 CHECK(msg->findSize("trackIndex", &trackIndex));
Andreas Huber49694682012-08-31 10:27:46 -0700584
585 if (mTSParser == NULL) {
586 CHECK_LT(trackIndex, mTracks.size());
587 } else {
588 CHECK_EQ(trackIndex, 0u);
589 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700590
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800591 sp<ABuffer> accessUnit;
592 CHECK(msg->findBuffer("accessUnit", &accessUnit));
Andreas Huber2bfdd422011-10-11 15:24:07 -0700593
594 int32_t damaged;
595 if (accessUnit->meta()->findInt32("damaged", &damaged)
596 && damaged) {
Steve Blockdf64d152012-01-04 20:05:49 +0000597 ALOGI("dropping damaged access unit.");
Andreas Huber2bfdd422011-10-11 15:24:07 -0700598 break;
599 }
600
Andreas Huber49694682012-08-31 10:27:46 -0700601 if (mTSParser != NULL) {
602 size_t offset = 0;
603 status_t err = OK;
604 while (offset + 188 <= accessUnit->size()) {
605 err = mTSParser->feedTSPacket(
606 accessUnit->data() + offset, 188);
607 if (err != OK) {
608 break;
609 }
610
611 offset += 188;
612 }
613
614 if (offset < accessUnit->size()) {
615 err = ERROR_MALFORMED;
616 }
617
618 if (err != OK) {
Robert Shihf1d261f2016-07-29 16:44:39 -0700619 signalSourceEOS(err);
Andreas Huber49694682012-08-31 10:27:46 -0700620 }
Robert Shihf1d261f2016-07-29 16:44:39 -0700621
622 postSourceEOSIfNecessary();
Andreas Huber49694682012-08-31 10:27:46 -0700623 break;
624 }
625
Andreas Huber1906e5c2011-12-08 12:27:47 -0800626 TrackInfo *info = &mTracks.editItemAt(trackIndex);
627
628 sp<AnotherPacketSource> source = info->mSource;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700629 if (source != NULL) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700630 uint32_t rtpTime;
631 CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
632
Andreas Huber1906e5c2011-12-08 12:27:47 -0800633 if (!info->mNPTMappingValid) {
634 // This is a live stream, we didn't receive any normal
Andreas Huberc9d16962012-05-21 11:12:40 -0700635 // playtime mapping. We won't map to npt time.
636 source->queueAccessUnit(accessUnit);
637 break;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800638 }
639
Andreas Huber2bfdd422011-10-11 15:24:07 -0700640 int64_t nptUs =
Andreas Huber1906e5c2011-12-08 12:27:47 -0800641 ((double)rtpTime - (double)info->mRTPTime)
642 / info->mTimeScale
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800643 * 1000000LL
Andreas Huber1906e5c2011-12-08 12:27:47 -0800644 + info->mNormalPlaytimeUs;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700645
646 accessUnit->meta()->setInt64("timeUs", nptUs);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700647
648 source->queueAccessUnit(accessUnit);
649 }
Robert Shihf1d261f2016-07-29 16:44:39 -0700650 postSourceEOSIfNecessary();
Andreas Huber2bfdd422011-10-11 15:24:07 -0700651 break;
652 }
653
654 case MyHandler::kWhatEOS:
655 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700656 int32_t finalResult;
657 CHECK(msg->findInt32("finalResult", &finalResult));
658 CHECK_NE(finalResult, (status_t)OK);
659
Andreas Huber49694682012-08-31 10:27:46 -0700660 if (mTSParser != NULL) {
Robert Shihf1d261f2016-07-29 16:44:39 -0700661 signalSourceEOS(finalResult);
Andreas Huber49694682012-08-31 10:27:46 -0700662 }
663
664 size_t trackIndex;
665 CHECK(msg->findSize("trackIndex", &trackIndex));
666 CHECK_LT(trackIndex, mTracks.size());
667
Andreas Huber2bfdd422011-10-11 15:24:07 -0700668 TrackInfo *info = &mTracks.editItemAt(trackIndex);
669 sp<AnotherPacketSource> source = info->mSource;
670 if (source != NULL) {
671 source->signalEOS(finalResult);
672 }
673
674 break;
675 }
676
677 case MyHandler::kWhatSeekDiscontinuity:
678 {
679 size_t trackIndex;
680 CHECK(msg->findSize("trackIndex", &trackIndex));
681 CHECK_LT(trackIndex, mTracks.size());
682
683 TrackInfo *info = &mTracks.editItemAt(trackIndex);
684 sp<AnotherPacketSource> source = info->mSource;
685 if (source != NULL) {
Chong Zhang632740c2014-06-26 13:03:47 -0700686 source->queueDiscontinuity(
Wei Jiafef808d2014-10-31 17:57:05 -0700687 ATSParser::DISCONTINUITY_TIME,
Chong Zhang632740c2014-06-26 13:03:47 -0700688 NULL,
689 true /* discard */);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700690 }
691
692 break;
693 }
694
695 case MyHandler::kWhatNormalPlayTimeMapping:
696 {
697 size_t trackIndex;
698 CHECK(msg->findSize("trackIndex", &trackIndex));
699 CHECK_LT(trackIndex, mTracks.size());
700
701 uint32_t rtpTime;
702 CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime));
703
704 int64_t nptUs;
705 CHECK(msg->findInt64("nptUs", &nptUs));
706
707 TrackInfo *info = &mTracks.editItemAt(trackIndex);
708 info->mRTPTime = rtpTime;
709 info->mNormalPlaytimeUs = nptUs;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800710 info->mNPTMappingValid = true;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700711 break;
712 }
713
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100714 case SDPLoader::kWhatSDPLoaded:
715 {
716 onSDPLoaded(msg);
717 break;
718 }
719
Andreas Huber2bfdd422011-10-11 15:24:07 -0700720 default:
721 TRESPASS();
722 }
723}
724
725void NuPlayer::RTSPSource::onConnected() {
726 CHECK(mAudioTrack == NULL);
727 CHECK(mVideoTrack == NULL);
728
729 size_t numTracks = mHandler->countTracks();
730 for (size_t i = 0; i < numTracks; ++i) {
731 int32_t timeScale;
732 sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale);
733
734 const char *mime;
735 CHECK(format->findCString(kKeyMIMEType, &mime));
736
Andreas Huber49694682012-08-31 10:27:46 -0700737 if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
738 // Very special case for MPEG2 Transport Streams.
739 CHECK_EQ(numTracks, 1u);
740
741 mTSParser = new ATSParser;
742 return;
743 }
744
Andreas Huber2bfdd422011-10-11 15:24:07 -0700745 bool isAudio = !strncasecmp(mime, "audio/", 6);
746 bool isVideo = !strncasecmp(mime, "video/", 6);
747
748 TrackInfo info;
749 info.mTimeScale = timeScale;
750 info.mRTPTime = 0;
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800751 info.mNormalPlaytimeUs = 0LL;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800752 info.mNPTMappingValid = false;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700753
754 if ((isAudio && mAudioTrack == NULL)
755 || (isVideo && mVideoTrack == NULL)) {
756 sp<AnotherPacketSource> source = new AnotherPacketSource(format);
757
758 if (isAudio) {
759 mAudioTrack = source;
760 } else {
761 mVideoTrack = source;
762 }
763
764 info.mSource = source;
765 }
766
767 mTracks.push(info);
768 }
769
770 mState = CONNECTED;
771}
772
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100773void NuPlayer::RTSPSource::onSDPLoaded(const sp<AMessage> &msg) {
774 status_t err;
775 CHECK(msg->findInt32("result", &err));
776
777 mSDPLoader.clear();
778
779 if (mDisconnectReplyID != 0) {
780 err = UNKNOWN_ERROR;
781 }
782
783 if (err == OK) {
784 sp<ASessionDescription> desc;
785 sp<RefBase> obj;
786 CHECK(msg->findObject("description", &obj));
787 desc = static_cast<ASessionDescription *>(obj.get());
788
789 AString rtspUri;
790 if (!desc->findAttribute(0, "a=control", &rtspUri)) {
791 ALOGE("Unable to find url in SDP");
792 err = UNKNOWN_ERROR;
793 } else {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800794 sp<AMessage> notify = new AMessage(kWhatNotify, this);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100795
796 mHandler = new MyHandler(rtspUri.c_str(), notify, mUIDValid, mUID);
797 mLooper->registerHandler(mHandler);
798
799 mHandler->loadSDP(desc);
800 }
801 }
802
803 if (err != OK) {
Andreas Huber7f475c32013-02-05 14:47:13 -0800804 if (mState == CONNECTING) {
805 // We're still in the preparation phase, signal that it
806 // failed.
807 notifyPrepared(err);
808 }
809
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100810 mState = DISCONNECTED;
Chong Zhang180d1b92014-12-02 18:35:35 -0800811 setError(err);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100812
813 if (mDisconnectReplyID != 0) {
814 finishDisconnectIfPossible();
815 }
816 }
817}
818
Andreas Huber2bfdd422011-10-11 15:24:07 -0700819void NuPlayer::RTSPSource::onDisconnected(const sp<AMessage> &msg) {
Fredrik Rosin0ad03bc2013-03-06 13:42:53 +0100820 if (mState == DISCONNECTED) {
821 return;
822 }
823
Andreas Huber2bfdd422011-10-11 15:24:07 -0700824 status_t err;
825 CHECK(msg->findInt32("result", &err));
826 CHECK_NE(err, (status_t)OK);
827
828 mLooper->unregisterHandler(mHandler->id());
829 mHandler.clear();
830
Andreas Huber7f475c32013-02-05 14:47:13 -0800831 if (mState == CONNECTING) {
832 // We're still in the preparation phase, signal that it
833 // failed.
834 notifyPrepared(err);
835 }
836
Andreas Huber2bfdd422011-10-11 15:24:07 -0700837 mState = DISCONNECTED;
Chong Zhang180d1b92014-12-02 18:35:35 -0800838 setError(err);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700839
840 if (mDisconnectReplyID != 0) {
841 finishDisconnectIfPossible();
842 }
843}
844
845void NuPlayer::RTSPSource::finishDisconnectIfPossible() {
846 if (mState != DISCONNECTED) {
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100847 if (mHandler != NULL) {
848 mHandler->disconnect();
849 } else if (mSDPLoader != NULL) {
850 mSDPLoader->cancel();
851 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700852 return;
853 }
854
855 (new AMessage)->postReply(mDisconnectReplyID);
856 mDisconnectReplyID = 0;
857}
858
Chong Zhang180d1b92014-12-02 18:35:35 -0800859void NuPlayer::RTSPSource::setError(status_t err) {
860 Mutex::Autolock _l(mBufferingLock);
861 mFinalResult = err;
862}
863
864void NuPlayer::RTSPSource::startBufferingIfNecessary() {
865 Mutex::Autolock _l(mBufferingLock);
866
867 if (!mBuffering) {
868 mBuffering = true;
869
870 sp<AMessage> notify = dupNotify();
Wei Jiac9ff2002016-05-24 16:23:48 -0700871 notify->setInt32("what", kWhatPauseOnBufferingStart);
Chong Zhang180d1b92014-12-02 18:35:35 -0800872 notify->post();
873 }
874}
875
876bool NuPlayer::RTSPSource::stopBufferingIfNecessary() {
877 Mutex::Autolock _l(mBufferingLock);
878
879 if (mBuffering) {
880 if (!haveSufficientDataOnAllTracks()) {
881 return false;
882 }
883
884 mBuffering = false;
885
886 sp<AMessage> notify = dupNotify();
Wei Jiac9ff2002016-05-24 16:23:48 -0700887 notify->setInt32("what", kWhatResumeOnBufferingEnd);
Chong Zhang180d1b92014-12-02 18:35:35 -0800888 notify->post();
889 }
890
891 return true;
892}
893
Robert Shih8d237a52015-07-13 17:59:36 -0700894void NuPlayer::RTSPSource::finishSeek(status_t err) {
Wei Jia4ad74b22016-02-05 17:11:20 -0800895 if (mSeekReplyID == NULL) {
896 return;
897 }
Robert Shih8d237a52015-07-13 17:59:36 -0700898 sp<AMessage> seekReply = new AMessage;
899 seekReply->setInt32("err", err);
900 seekReply->postReply(mSeekReplyID);
901 mSeekReplyID = NULL;
902}
Chong Zhang180d1b92014-12-02 18:35:35 -0800903
Andreas Huber2bfdd422011-10-11 15:24:07 -0700904} // namespace android