blob: 8e05de854c3095c1f8b373793383a6ea1ac29361 [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 }
Dichen Zhangfd3bbcb2019-08-08 17:15:01 -0700147
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800148 sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700149
150 sp<AMessage> dummy;
151 msg->postAndAwaitResponse(&dummy);
Byeongjo Park6a45b8b2021-07-08 21:27:22 +0900152
153 // Close socket after posting message to RTSPSource message handler.
154 if (mHandler != NULL && mHandler->getARTSPConnection()->getSocket() >= 0) {
155 ALOGD("closing rtsp socket if not closed yet.");
156 close(mHandler->getARTSPConnection()->getSocket());
157 }
158
Andreas Huber2bfdd422011-10-11 15:24:07 -0700159}
160
161status_t NuPlayer::RTSPSource::feedMoreTSData() {
Chong Zhang180d1b92014-12-02 18:35:35 -0800162 Mutex::Autolock _l(mBufferingLock);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700163 return mFinalResult;
164}
165
Andreas Huber84066782011-08-16 09:34:26 -0700166sp<MetaData> NuPlayer::RTSPSource::getFormatMeta(bool audio) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700167 sp<AnotherPacketSource> source = getSource(audio);
168
169 if (source == NULL) {
170 return NULL;
171 }
172
173 return source->getFormat();
174}
175
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700176bool NuPlayer::RTSPSource::haveSufficientDataOnAllTracks() {
177 // We're going to buffer at least 2 secs worth data on all tracks before
178 // starting playback (both at startup and after a seek).
179
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800180 static const int64_t kMinDurationUs = 2000000LL;
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700181
Roger Jönssoncfc30832013-01-21 16:26:41 +0100182 int64_t mediaDurationUs = 0;
183 getDuration(&mediaDurationUs);
184 if ((mAudioTrack != NULL && mAudioTrack->isFinished(mediaDurationUs))
185 || (mVideoTrack != NULL && mVideoTrack->isFinished(mediaDurationUs))) {
186 return true;
187 }
188
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700189 status_t err;
190 int64_t durationUs;
191 if (mAudioTrack != NULL
192 && (durationUs = mAudioTrack->getBufferedDurationUs(&err))
193 < kMinDurationUs
194 && err == OK) {
195 ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
196 durationUs / 1E6);
197 return false;
198 }
199
200 if (mVideoTrack != NULL
201 && (durationUs = mVideoTrack->getBufferedDurationUs(&err))
202 < kMinDurationUs
203 && err == OK) {
204 ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
205 durationUs / 1E6);
206 return false;
207 }
208
209 return true;
210}
211
Andreas Huber2bfdd422011-10-11 15:24:07 -0700212status_t NuPlayer::RTSPSource::dequeueAccessUnit(
213 bool audio, sp<ABuffer> *accessUnit) {
Chong Zhang180d1b92014-12-02 18:35:35 -0800214 if (!stopBufferingIfNecessary()) {
215 return -EWOULDBLOCK;
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700216 }
217
Andreas Huber2bfdd422011-10-11 15:24:07 -0700218 sp<AnotherPacketSource> source = getSource(audio);
219
220 if (source == NULL) {
221 return -EWOULDBLOCK;
222 }
223
224 status_t finalResult;
225 if (!source->hasBufferAvailable(&finalResult)) {
Roger Jönssoncfc30832013-01-21 16:26:41 +0100226 if (finalResult == OK) {
Roger Jönssoncfc30832013-01-21 16:26:41 +0100227
Robert Shihf1d261f2016-07-29 16:44:39 -0700228 // If other source already signaled EOS, this source should also return EOS
229 if (sourceReachedEOS(!audio)) {
Roger Jönssoncfc30832013-01-21 16:26:41 +0100230 return ERROR_END_OF_STREAM;
231 }
232
233 // If this source has detected near end, give it some time to retrieve more
Robert Shihf1d261f2016-07-29 16:44:39 -0700234 // data before returning EOS
235 int64_t mediaDurationUs = 0;
236 getDuration(&mediaDurationUs);
Roger Jönssoncfc30832013-01-21 16:26:41 +0100237 if (source->isFinished(mediaDurationUs)) {
238 int64_t eosTimeout = audio ? mEOSTimeoutAudio : mEOSTimeoutVideo;
239 if (eosTimeout == 0) {
240 setEOSTimeout(audio, ALooper::GetNowUs());
241 } else if ((ALooper::GetNowUs() - eosTimeout) > kNearEOSTimeoutUs) {
242 setEOSTimeout(audio, 0);
Roger Jönssoncfc30832013-01-21 16:26:41 +0100243 return ERROR_END_OF_STREAM;
244 }
245 return -EWOULDBLOCK;
246 }
247
Robert Shihf1d261f2016-07-29 16:44:39 -0700248 if (!sourceNearEOS(!audio)) {
Roger Jönssoncfc30832013-01-21 16:26:41 +0100249 // We should not enter buffering mode
250 // if any of the sources already have detected EOS.
Chong Zhang180d1b92014-12-02 18:35:35 -0800251 startBufferingIfNecessary();
Roger Jönssoncfc30832013-01-21 16:26:41 +0100252 }
253
254 return -EWOULDBLOCK;
255 }
256 return finalResult;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700257 }
258
Roger Jönssoncfc30832013-01-21 16:26:41 +0100259 setEOSTimeout(audio, 0);
260
Andreas Huber2bfdd422011-10-11 15:24:07 -0700261 return source->dequeueAccessUnit(accessUnit);
262}
263
264sp<AnotherPacketSource> NuPlayer::RTSPSource::getSource(bool audio) {
Andreas Huber49694682012-08-31 10:27:46 -0700265 if (mTSParser != NULL) {
266 sp<MediaSource> source = mTSParser->getSource(
267 audio ? ATSParser::AUDIO : ATSParser::VIDEO);
268
269 return static_cast<AnotherPacketSource *>(source.get());
270 }
271
Andreas Huber2bfdd422011-10-11 15:24:07 -0700272 return audio ? mAudioTrack : mVideoTrack;
273}
274
Roger Jönssoncfc30832013-01-21 16:26:41 +0100275void NuPlayer::RTSPSource::setEOSTimeout(bool audio, int64_t timeout) {
276 if (audio) {
277 mEOSTimeoutAudio = timeout;
278 } else {
279 mEOSTimeoutVideo = timeout;
280 }
281}
282
Andreas Huber2bfdd422011-10-11 15:24:07 -0700283status_t NuPlayer::RTSPSource::getDuration(int64_t *durationUs) {
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800284 *durationUs = -1LL;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700285
286 int64_t audioDurationUs;
287 if (mAudioTrack != NULL
288 && mAudioTrack->getFormat()->findInt64(
289 kKeyDuration, &audioDurationUs)
290 && audioDurationUs > *durationUs) {
291 *durationUs = audioDurationUs;
292 }
293
294 int64_t videoDurationUs;
295 if (mVideoTrack != NULL
296 && mVideoTrack->getFormat()->findInt64(
297 kKeyDuration, &videoDurationUs)
298 && videoDurationUs > *durationUs) {
299 *durationUs = videoDurationUs;
300 }
301
302 return OK;
303}
304
Wei Jiac5de0912016-11-18 10:22:14 -0800305status_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800306 sp<AMessage> msg = new AMessage(kWhatPerformSeek, this);
Andreas Huberee736e92011-12-08 13:04:50 -0800307 msg->setInt32("generation", ++mSeekGeneration);
308 msg->setInt64("timeUs", seekTimeUs);
Wei Jiac5de0912016-11-18 10:22:14 -0800309 msg->setInt32("mode", mode);
Andreas Huberee736e92011-12-08 13:04:50 -0800310
Robert Shih8d237a52015-07-13 17:59:36 -0700311 sp<AMessage> response;
312 status_t err = msg->postAndAwaitResponse(&response);
313 if (err == OK && response != NULL) {
314 CHECK(response->findInt32("err", &err));
315 }
316
317 return err;
Andreas Huberee736e92011-12-08 13:04:50 -0800318}
319
320void NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700321 if (mState != CONNECTED) {
Robert Shih8d237a52015-07-13 17:59:36 -0700322 finishSeek(INVALID_OPERATION);
Andreas Huberee736e92011-12-08 13:04:50 -0800323 return;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700324 }
325
326 mState = SEEKING;
327 mHandler->seek(seekTimeUs);
Robert Shihf1d261f2016-07-29 16:44:39 -0700328 mEOSPending = false;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700329}
330
Robert Shih641e0c72016-02-22 11:37:20 -0800331void NuPlayer::RTSPSource::schedulePollBuffering() {
332 sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800333 msg->post(1000000LL); // 1 second intervals
Robert Shih641e0c72016-02-22 11:37:20 -0800334}
335
336void NuPlayer::RTSPSource::checkBuffering(
Robert Shihf1d261f2016-07-29 16:44:39 -0700337 bool *prepared, bool *underflow, bool *overflow, bool *startServer, bool *finished) {
Robert Shih641e0c72016-02-22 11:37:20 -0800338 size_t numTracks = mTracks.size();
Robert Shihf1d261f2016-07-29 16:44:39 -0700339 size_t preparedCount, underflowCount, overflowCount, startCount, finishedCount;
340 preparedCount = underflowCount = overflowCount = startCount = finishedCount = 0;
Takahiro Aizawac622c582016-06-20 09:53:47 +0900341
342 size_t count = numTracks;
343 for (size_t i = 0; i < count; ++i) {
Robert Shih641e0c72016-02-22 11:37:20 -0800344 status_t finalResult;
345 TrackInfo *info = &mTracks.editItemAt(i);
346 sp<AnotherPacketSource> src = info->mSource;
Takahiro Aizawac622c582016-06-20 09:53:47 +0900347 if (src == NULL) {
348 --numTracks;
349 continue;
350 }
Robert Shih641e0c72016-02-22 11:37:20 -0800351 int64_t bufferedDurationUs = src->getBufferedDurationUs(&finalResult);
352
Wei Jia9bb38032017-03-23 18:00:38 -0700353 int64_t initialMarkUs;
354 int64_t maxRebufferingMarkUs;
355 {
356 Mutex::Autolock _l(mBufferingSettingsLock);
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800357 initialMarkUs = mBufferingSettings.mInitialMarkMs * 1000LL;
Wei Jia9bb38032017-03-23 18:00:38 -0700358 // TODO: maxRebufferingMarkUs could be larger than
359 // mBufferingSettings.mResumePlaybackMarkMs * 1000ll.
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800360 maxRebufferingMarkUs = mBufferingSettings.mResumePlaybackMarkMs * 1000LL;
Wei Jia9bb38032017-03-23 18:00:38 -0700361 }
Robert Shih641e0c72016-02-22 11:37:20 -0800362 // isFinished when duration is 0 checks for EOS result only
Wei Jia9bb38032017-03-23 18:00:38 -0700363 if (bufferedDurationUs > initialMarkUs
Wei Jia48fa06d2016-12-20 15:30:49 -0800364 || src->isFinished(/* duration */ 0)) {
Robert Shih641e0c72016-02-22 11:37:20 -0800365 ++preparedCount;
366 }
367
368 if (src->isFinished(/* duration */ 0)) {
369 ++overflowCount;
Robert Shihf1d261f2016-07-29 16:44:39 -0700370 ++finishedCount;
Robert Shih641e0c72016-02-22 11:37:20 -0800371 } else {
Wei Jia9bb38032017-03-23 18:00:38 -0700372 // TODO: redefine kUnderflowMarkMs to a fair value,
373 if (bufferedDurationUs < kUnderflowMarkMs * 1000) {
Robert Shih641e0c72016-02-22 11:37:20 -0800374 ++underflowCount;
375 }
Wei Jia9bb38032017-03-23 18:00:38 -0700376 if (bufferedDurationUs > maxRebufferingMarkUs) {
Robert Shih641e0c72016-02-22 11:37:20 -0800377 ++overflowCount;
378 }
Wei Jia48fa06d2016-12-20 15:30:49 -0800379 int64_t startServerMarkUs =
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800380 (kUnderflowMarkMs * 1000LL + maxRebufferingMarkUs) / 2;
Wei Jia48fa06d2016-12-20 15:30:49 -0800381 if (bufferedDurationUs < startServerMarkUs) {
Robert Shih641e0c72016-02-22 11:37:20 -0800382 ++startCount;
383 }
384 }
385 }
386
387 *prepared = (preparedCount == numTracks);
388 *underflow = (underflowCount > 0);
389 *overflow = (overflowCount == numTracks);
390 *startServer = (startCount > 0);
Robert Shihf1d261f2016-07-29 16:44:39 -0700391 *finished = (finishedCount > 0);
Robert Shih641e0c72016-02-22 11:37:20 -0800392}
393
394void NuPlayer::RTSPSource::onPollBuffering() {
Robert Shihf1d261f2016-07-29 16:44:39 -0700395 bool prepared, underflow, overflow, startServer, finished;
396 checkBuffering(&prepared, &underflow, &overflow, &startServer, &finished);
Robert Shih641e0c72016-02-22 11:37:20 -0800397
398 if (prepared && mInPreparationPhase) {
399 mInPreparationPhase = false;
400 notifyPrepared();
401 }
402
403 if (!mInPreparationPhase && underflow) {
404 startBufferingIfNecessary();
405 }
406
Robert Shih91ea5712016-08-01 16:26:58 -0700407 if (haveSufficientDataOnAllTracks()) {
Robert Shih641e0c72016-02-22 11:37:20 -0800408 stopBufferingIfNecessary();
Robert Shih91ea5712016-08-01 16:26:58 -0700409 }
410
411 if (overflow && mHandler != NULL) {
Robert Shih641e0c72016-02-22 11:37:20 -0800412 mHandler->pause();
413 }
414
415 if (startServer && mHandler != NULL) {
416 mHandler->resume();
417 }
418
Robert Shihf1d261f2016-07-29 16:44:39 -0700419 if (finished && mHandler != NULL) {
420 mHandler->cancelAccessUnitTimeoutCheck();
421 }
422
Robert Shih641e0c72016-02-22 11:37:20 -0800423 schedulePollBuffering();
424}
425
Robert Shihf1d261f2016-07-29 16:44:39 -0700426void NuPlayer::RTSPSource::signalSourceEOS(status_t result) {
427 const bool audio = true;
428 const bool video = false;
429
430 sp<AnotherPacketSource> source = getSource(audio);
431 if (source != NULL) {
432 source->signalEOS(result);
433 }
434
435 source = getSource(video);
436 if (source != NULL) {
437 source->signalEOS(result);
438 }
439}
440
441bool NuPlayer::RTSPSource::sourceReachedEOS(bool audio) {
442 sp<AnotherPacketSource> source = getSource(audio);
443 status_t finalResult;
444 return (source != NULL &&
445 !source->hasBufferAvailable(&finalResult) &&
446 finalResult == ERROR_END_OF_STREAM);
447}
448
449bool NuPlayer::RTSPSource::sourceNearEOS(bool audio) {
450 sp<AnotherPacketSource> source = getSource(audio);
451 int64_t mediaDurationUs = 0;
452 getDuration(&mediaDurationUs);
453 return (source != NULL && source->isFinished(mediaDurationUs));
454}
455
456void NuPlayer::RTSPSource::onSignalEOS(const sp<AMessage> &msg) {
457 int32_t generation;
458 CHECK(msg->findInt32("generation", &generation));
459
460 if (generation != mSeekGeneration) {
461 return;
462 }
463
464 if (mEOSPending) {
465 signalSourceEOS(ERROR_END_OF_STREAM);
466 mEOSPending = false;
467 }
468}
469
470void NuPlayer::RTSPSource::postSourceEOSIfNecessary() {
471 const bool audio = true;
472 const bool video = false;
473 // If a source has detected near end, give it some time to retrieve more
474 // data before signaling EOS
475 if (sourceNearEOS(audio) || sourceNearEOS(video)) {
476 if (!mEOSPending) {
477 sp<AMessage> msg = new AMessage(kWhatSignalEOS, this);
478 msg->setInt32("generation", mSeekGeneration);
479 msg->post(kNearEOSTimeoutUs);
480 mEOSPending = true;
481 }
482 }
483}
484
Andreas Huber2bfdd422011-10-11 15:24:07 -0700485void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
486 if (msg->what() == kWhatDisconnect) {
Lajos Molnar3f274362015-03-05 14:35:41 -0800487 sp<AReplyToken> replyID;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700488 CHECK(msg->senderAwaitsResponse(&replyID));
489
490 mDisconnectReplyID = replyID;
491 finishDisconnectIfPossible();
492 return;
Andreas Huberee736e92011-12-08 13:04:50 -0800493 } else if (msg->what() == kWhatPerformSeek) {
494 int32_t generation;
495 CHECK(msg->findInt32("generation", &generation));
Robert Shih8d237a52015-07-13 17:59:36 -0700496 CHECK(msg->senderAwaitsResponse(&mSeekReplyID));
Andreas Huberee736e92011-12-08 13:04:50 -0800497
498 if (generation != mSeekGeneration) {
499 // obsolete.
Robert Shih8d237a52015-07-13 17:59:36 -0700500 finishSeek(OK);
Andreas Huberee736e92011-12-08 13:04:50 -0800501 return;
502 }
503
504 int64_t seekTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -0800505 int32_t mode;
Andreas Huberee736e92011-12-08 13:04:50 -0800506 CHECK(msg->findInt64("timeUs", &seekTimeUs));
Wei Jiac5de0912016-11-18 10:22:14 -0800507 CHECK(msg->findInt32("mode", &mode));
Andreas Huberee736e92011-12-08 13:04:50 -0800508
Wei Jiac5de0912016-11-18 10:22:14 -0800509 // TODO: add "mode" to performSeek.
510 performSeek(seekTimeUs/*, (MediaPlayerSeekMode)mode */);
Andreas Huberee736e92011-12-08 13:04:50 -0800511 return;
Robert Shih641e0c72016-02-22 11:37:20 -0800512 } else if (msg->what() == kWhatPollBuffering) {
513 onPollBuffering();
514 return;
Robert Shihf1d261f2016-07-29 16:44:39 -0700515 } else if (msg->what() == kWhatSignalEOS) {
516 onSignalEOS(msg);
517 return;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700518 }
519
Colin Crossb8c35f92017-04-27 16:15:51 -0700520 CHECK_EQ(msg->what(), kWhatNotify);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700521
522 int32_t what;
523 CHECK(msg->findInt32("what", &what));
524
525 switch (what) {
526 case MyHandler::kWhatConnected:
Andreas Huber7f475c32013-02-05 14:47:13 -0800527 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700528 onConnected();
Andreas Huber7f475c32013-02-05 14:47:13 -0800529
Chong Zhangced1c2f2014-08-08 15:22:35 -0700530 notifyVideoSizeChanged();
Andreas Huber7f475c32013-02-05 14:47:13 -0800531
532 uint32_t flags = 0;
533
534 if (mHandler->isSeekable()) {
Chong Zhang4b7069d2013-09-11 12:52:43 -0700535 flags = FLAG_CAN_PAUSE
536 | FLAG_CAN_SEEK
537 | FLAG_CAN_SEEK_BACKWARD
538 | FLAG_CAN_SEEK_FORWARD;
Andreas Huber7f475c32013-02-05 14:47:13 -0800539 }
540
541 notifyFlagsChanged(flags);
Robert Shih641e0c72016-02-22 11:37:20 -0800542 schedulePollBuffering();
Andreas Huber2bfdd422011-10-11 15:24:07 -0700543 break;
Andreas Huber7f475c32013-02-05 14:47:13 -0800544 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700545
546 case MyHandler::kWhatDisconnected:
Andreas Huber7f475c32013-02-05 14:47:13 -0800547 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700548 onDisconnected(msg);
549 break;
Andreas Huber7f475c32013-02-05 14:47:13 -0800550 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700551
552 case MyHandler::kWhatSeekDone:
553 {
554 mState = CONNECTED;
Wei Jia4ad74b22016-02-05 17:11:20 -0800555 // Unblock seekTo here in case we attempted to seek in a live stream
556 finishSeek(OK);
Robert Shih8d237a52015-07-13 17:59:36 -0700557 break;
558 }
559
560 case MyHandler::kWhatSeekPaused:
561 {
562 sp<AnotherPacketSource> source = getSource(true /* audio */);
563 if (source != NULL) {
564 source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
565 /* extra */ NULL,
566 /* discard */ true);
567 }
568 source = getSource(false /* video */);
569 if (source != NULL) {
570 source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
571 /* extra */ NULL,
572 /* discard */ true);
573 };
574
575 status_t err = OK;
576 msg->findInt32("err", &err);
Robert Shih8d237a52015-07-13 17:59:36 -0700577
578 if (err == OK) {
579 int64_t timeUs;
580 CHECK(msg->findInt64("time", &timeUs));
581 mHandler->continueSeekAfterPause(timeUs);
Wei Jia4ad74b22016-02-05 17:11:20 -0800582 } else {
583 finishSeek(err);
Robert Shih8d237a52015-07-13 17:59:36 -0700584 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700585 break;
586 }
587
588 case MyHandler::kWhatAccessUnit:
589 {
590 size_t trackIndex;
591 CHECK(msg->findSize("trackIndex", &trackIndex));
Andreas Huber49694682012-08-31 10:27:46 -0700592
593 if (mTSParser == NULL) {
594 CHECK_LT(trackIndex, mTracks.size());
595 } else {
596 CHECK_EQ(trackIndex, 0u);
597 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700598
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800599 sp<ABuffer> accessUnit;
600 CHECK(msg->findBuffer("accessUnit", &accessUnit));
Andreas Huber2bfdd422011-10-11 15:24:07 -0700601
602 int32_t damaged;
603 if (accessUnit->meta()->findInt32("damaged", &damaged)
604 && damaged) {
Steve Blockdf64d152012-01-04 20:05:49 +0000605 ALOGI("dropping damaged access unit.");
Andreas Huber2bfdd422011-10-11 15:24:07 -0700606 break;
607 }
608
Andreas Huber49694682012-08-31 10:27:46 -0700609 if (mTSParser != NULL) {
610 size_t offset = 0;
611 status_t err = OK;
612 while (offset + 188 <= accessUnit->size()) {
613 err = mTSParser->feedTSPacket(
614 accessUnit->data() + offset, 188);
615 if (err != OK) {
616 break;
617 }
618
619 offset += 188;
620 }
621
622 if (offset < accessUnit->size()) {
623 err = ERROR_MALFORMED;
624 }
625
626 if (err != OK) {
Robert Shihf1d261f2016-07-29 16:44:39 -0700627 signalSourceEOS(err);
Andreas Huber49694682012-08-31 10:27:46 -0700628 }
Robert Shihf1d261f2016-07-29 16:44:39 -0700629
630 postSourceEOSIfNecessary();
Andreas Huber49694682012-08-31 10:27:46 -0700631 break;
632 }
633
Andreas Huber1906e5c2011-12-08 12:27:47 -0800634 TrackInfo *info = &mTracks.editItemAt(trackIndex);
635
636 sp<AnotherPacketSource> source = info->mSource;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700637 if (source != NULL) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700638 uint32_t rtpTime;
639 CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
640
Andreas Huber1906e5c2011-12-08 12:27:47 -0800641 if (!info->mNPTMappingValid) {
642 // This is a live stream, we didn't receive any normal
Andreas Huberc9d16962012-05-21 11:12:40 -0700643 // playtime mapping. We won't map to npt time.
644 source->queueAccessUnit(accessUnit);
645 break;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800646 }
647
Andreas Huber2bfdd422011-10-11 15:24:07 -0700648 int64_t nptUs =
Andreas Huber1906e5c2011-12-08 12:27:47 -0800649 ((double)rtpTime - (double)info->mRTPTime)
650 / info->mTimeScale
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800651 * 1000000LL
Andreas Huber1906e5c2011-12-08 12:27:47 -0800652 + info->mNormalPlaytimeUs;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700653
654 accessUnit->meta()->setInt64("timeUs", nptUs);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700655
656 source->queueAccessUnit(accessUnit);
657 }
Robert Shihf1d261f2016-07-29 16:44:39 -0700658 postSourceEOSIfNecessary();
Andreas Huber2bfdd422011-10-11 15:24:07 -0700659 break;
660 }
661
662 case MyHandler::kWhatEOS:
663 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700664 int32_t finalResult;
665 CHECK(msg->findInt32("finalResult", &finalResult));
666 CHECK_NE(finalResult, (status_t)OK);
667
Andreas Huber49694682012-08-31 10:27:46 -0700668 if (mTSParser != NULL) {
Robert Shihf1d261f2016-07-29 16:44:39 -0700669 signalSourceEOS(finalResult);
Andreas Huber49694682012-08-31 10:27:46 -0700670 }
671
672 size_t trackIndex;
673 CHECK(msg->findSize("trackIndex", &trackIndex));
674 CHECK_LT(trackIndex, mTracks.size());
675
Andreas Huber2bfdd422011-10-11 15:24:07 -0700676 TrackInfo *info = &mTracks.editItemAt(trackIndex);
677 sp<AnotherPacketSource> source = info->mSource;
678 if (source != NULL) {
679 source->signalEOS(finalResult);
680 }
681
682 break;
683 }
684
685 case MyHandler::kWhatSeekDiscontinuity:
686 {
687 size_t trackIndex;
688 CHECK(msg->findSize("trackIndex", &trackIndex));
689 CHECK_LT(trackIndex, mTracks.size());
690
691 TrackInfo *info = &mTracks.editItemAt(trackIndex);
692 sp<AnotherPacketSource> source = info->mSource;
693 if (source != NULL) {
Chong Zhang632740c2014-06-26 13:03:47 -0700694 source->queueDiscontinuity(
Wei Jiafef808d2014-10-31 17:57:05 -0700695 ATSParser::DISCONTINUITY_TIME,
Chong Zhang632740c2014-06-26 13:03:47 -0700696 NULL,
697 true /* discard */);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700698 }
699
700 break;
701 }
702
703 case MyHandler::kWhatNormalPlayTimeMapping:
704 {
705 size_t trackIndex;
706 CHECK(msg->findSize("trackIndex", &trackIndex));
707 CHECK_LT(trackIndex, mTracks.size());
708
709 uint32_t rtpTime;
710 CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime));
711
712 int64_t nptUs;
713 CHECK(msg->findInt64("nptUs", &nptUs));
714
715 TrackInfo *info = &mTracks.editItemAt(trackIndex);
716 info->mRTPTime = rtpTime;
717 info->mNormalPlaytimeUs = nptUs;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800718 info->mNPTMappingValid = true;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700719 break;
720 }
721
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100722 case SDPLoader::kWhatSDPLoaded:
723 {
724 onSDPLoaded(msg);
725 break;
726 }
727
Andreas Huber2bfdd422011-10-11 15:24:07 -0700728 default:
729 TRESPASS();
730 }
731}
732
733void NuPlayer::RTSPSource::onConnected() {
734 CHECK(mAudioTrack == NULL);
735 CHECK(mVideoTrack == NULL);
736
737 size_t numTracks = mHandler->countTracks();
738 for (size_t i = 0; i < numTracks; ++i) {
739 int32_t timeScale;
740 sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale);
741
742 const char *mime;
743 CHECK(format->findCString(kKeyMIMEType, &mime));
744
Andreas Huber49694682012-08-31 10:27:46 -0700745 if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
746 // Very special case for MPEG2 Transport Streams.
747 CHECK_EQ(numTracks, 1u);
748
749 mTSParser = new ATSParser;
750 return;
751 }
752
Andreas Huber2bfdd422011-10-11 15:24:07 -0700753 bool isAudio = !strncasecmp(mime, "audio/", 6);
754 bool isVideo = !strncasecmp(mime, "video/", 6);
755
756 TrackInfo info;
757 info.mTimeScale = timeScale;
758 info.mRTPTime = 0;
Chih-Hung Hsieh62309d52018-12-11 13:54:02 -0800759 info.mNormalPlaytimeUs = 0LL;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800760 info.mNPTMappingValid = false;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700761
762 if ((isAudio && mAudioTrack == NULL)
763 || (isVideo && mVideoTrack == NULL)) {
764 sp<AnotherPacketSource> source = new AnotherPacketSource(format);
765
766 if (isAudio) {
767 mAudioTrack = source;
768 } else {
769 mVideoTrack = source;
770 }
771
772 info.mSource = source;
773 }
774
775 mTracks.push(info);
776 }
777
778 mState = CONNECTED;
779}
780
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100781void NuPlayer::RTSPSource::onSDPLoaded(const sp<AMessage> &msg) {
782 status_t err;
783 CHECK(msg->findInt32("result", &err));
784
785 mSDPLoader.clear();
786
787 if (mDisconnectReplyID != 0) {
788 err = UNKNOWN_ERROR;
789 }
790
791 if (err == OK) {
792 sp<ASessionDescription> desc;
793 sp<RefBase> obj;
794 CHECK(msg->findObject("description", &obj));
795 desc = static_cast<ASessionDescription *>(obj.get());
796
797 AString rtspUri;
798 if (!desc->findAttribute(0, "a=control", &rtspUri)) {
799 ALOGE("Unable to find url in SDP");
800 err = UNKNOWN_ERROR;
801 } else {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800802 sp<AMessage> notify = new AMessage(kWhatNotify, this);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100803
804 mHandler = new MyHandler(rtspUri.c_str(), notify, mUIDValid, mUID);
805 mLooper->registerHandler(mHandler);
806
807 mHandler->loadSDP(desc);
808 }
809 }
810
811 if (err != OK) {
Andreas Huber7f475c32013-02-05 14:47:13 -0800812 if (mState == CONNECTING) {
813 // We're still in the preparation phase, signal that it
814 // failed.
815 notifyPrepared(err);
816 }
817
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100818 mState = DISCONNECTED;
Chong Zhang180d1b92014-12-02 18:35:35 -0800819 setError(err);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100820
821 if (mDisconnectReplyID != 0) {
822 finishDisconnectIfPossible();
823 }
824 }
825}
826
Andreas Huber2bfdd422011-10-11 15:24:07 -0700827void NuPlayer::RTSPSource::onDisconnected(const sp<AMessage> &msg) {
Fredrik Rosin0ad03bc2013-03-06 13:42:53 +0100828 if (mState == DISCONNECTED) {
829 return;
830 }
831
Andreas Huber2bfdd422011-10-11 15:24:07 -0700832 status_t err;
833 CHECK(msg->findInt32("result", &err));
834 CHECK_NE(err, (status_t)OK);
835
836 mLooper->unregisterHandler(mHandler->id());
837 mHandler.clear();
838
Andreas Huber7f475c32013-02-05 14:47:13 -0800839 if (mState == CONNECTING) {
840 // We're still in the preparation phase, signal that it
841 // failed.
842 notifyPrepared(err);
843 }
844
Andreas Huber2bfdd422011-10-11 15:24:07 -0700845 mState = DISCONNECTED;
Chong Zhang180d1b92014-12-02 18:35:35 -0800846 setError(err);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700847
848 if (mDisconnectReplyID != 0) {
849 finishDisconnectIfPossible();
850 }
851}
852
853void NuPlayer::RTSPSource::finishDisconnectIfPossible() {
854 if (mState != DISCONNECTED) {
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100855 if (mHandler != NULL) {
856 mHandler->disconnect();
857 } else if (mSDPLoader != NULL) {
858 mSDPLoader->cancel();
859 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700860 return;
861 }
862
863 (new AMessage)->postReply(mDisconnectReplyID);
864 mDisconnectReplyID = 0;
865}
866
Chong Zhang180d1b92014-12-02 18:35:35 -0800867void NuPlayer::RTSPSource::setError(status_t err) {
868 Mutex::Autolock _l(mBufferingLock);
869 mFinalResult = err;
870}
871
872void NuPlayer::RTSPSource::startBufferingIfNecessary() {
873 Mutex::Autolock _l(mBufferingLock);
874
875 if (!mBuffering) {
876 mBuffering = true;
877
878 sp<AMessage> notify = dupNotify();
Wei Jiac9ff2002016-05-24 16:23:48 -0700879 notify->setInt32("what", kWhatPauseOnBufferingStart);
Chong Zhang180d1b92014-12-02 18:35:35 -0800880 notify->post();
881 }
882}
883
884bool NuPlayer::RTSPSource::stopBufferingIfNecessary() {
885 Mutex::Autolock _l(mBufferingLock);
886
887 if (mBuffering) {
888 if (!haveSufficientDataOnAllTracks()) {
889 return false;
890 }
891
892 mBuffering = false;
893
894 sp<AMessage> notify = dupNotify();
Wei Jiac9ff2002016-05-24 16:23:48 -0700895 notify->setInt32("what", kWhatResumeOnBufferingEnd);
Chong Zhang180d1b92014-12-02 18:35:35 -0800896 notify->post();
897 }
898
899 return true;
900}
901
Robert Shih8d237a52015-07-13 17:59:36 -0700902void NuPlayer::RTSPSource::finishSeek(status_t err) {
Wei Jia4ad74b22016-02-05 17:11:20 -0800903 if (mSeekReplyID == NULL) {
904 return;
905 }
Robert Shih8d237a52015-07-13 17:59:36 -0700906 sp<AMessage> seekReply = new AMessage;
907 seekReply->setInt32("err", err);
908 seekReply->postReply(mSeekReplyID);
909 mSeekReplyID = NULL;
910}
Chong Zhang180d1b92014-12-02 18:35:35 -0800911
Andreas Huber2bfdd422011-10-11 15:24:07 -0700912} // namespace android