blob: 8b3d0dc5d663c83372867fc60f47d1eb0daac22f [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
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 Jia48fa06d2016-12-20 15:30:49 -080065 getDefaultBufferingSettings(&mBufferingSettings);
Andreas Huber2bfdd422011-10-11 15:24:07 -070066 if (headers) {
67 mExtraHeaders = *headers;
68
69 ssize_t index =
70 mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
71
72 if (index >= 0) {
73 mFlags |= kFlagIncognito;
74
75 mExtraHeaders.removeItemsAt(index);
76 }
77 }
78}
79
80NuPlayer::RTSPSource::~RTSPSource() {
Andreas Huber602f5bb2013-04-15 16:18:56 -070081 if (mLooper != NULL) {
Chong Zhang1228d6b2014-08-12 21:25:48 -070082 mLooper->unregisterHandler(id());
Andreas Huber602f5bb2013-04-15 16:18:56 -070083 mLooper->stop();
84 }
Andreas Huber2bfdd422011-10-11 15:24:07 -070085}
86
Wei Jia48fa06d2016-12-20 15:30:49 -080087status_t NuPlayer::RTSPSource::getDefaultBufferingSettings(
88 BufferingSettings* buffering /* nonnull */) {
89 buffering->mInitialBufferingMode = BUFFERING_MODE_TIME_ONLY;
90 buffering->mRebufferingMode = BUFFERING_MODE_TIME_ONLY;
91 buffering->mInitialWatermarkMs = kPrepareMarkMs;
92 buffering->mRebufferingWatermarkLowMs = kUnderflowMarkMs;
93 buffering->mRebufferingWatermarkHighMs = kOverflowMarkMs;
94
95 return OK;
96}
97
98status_t NuPlayer::RTSPSource::setBufferingSettings(const BufferingSettings& buffering) {
99 if (mLooper == NULL) {
100 mBufferingSettings = buffering;
101 return OK;
102 }
103
104 sp<AMessage> msg = new AMessage(kWhatSetBufferingSettings, this);
105 writeToAMessage(msg, buffering);
106 sp<AMessage> response;
107 status_t err = msg->postAndAwaitResponse(&response);
108 if (err == OK && response != NULL) {
109 CHECK(response->findInt32("err", &err));
110 }
111
112 return err;
113}
114
Andreas Huber57cea552013-02-05 13:59:56 -0800115void NuPlayer::RTSPSource::prepareAsync() {
Wei Jiace84b222016-01-14 14:39:42 -0800116 if (mIsSDP && mHTTPService == NULL) {
117 notifyPrepared(BAD_VALUE);
118 return;
119 }
120
Andreas Huber2bfdd422011-10-11 15:24:07 -0700121 if (mLooper == NULL) {
122 mLooper = new ALooper;
123 mLooper->setName("rtsp");
124 mLooper->start();
125
Chong Zhang1228d6b2014-08-12 21:25:48 -0700126 mLooper->registerHandler(this);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700127 }
128
129 CHECK(mHandler == NULL);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100130 CHECK(mSDPLoader == NULL);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700131
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800132 sp<AMessage> notify = new AMessage(kWhatNotify, this);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700133
Andreas Huber2bfdd422011-10-11 15:24:07 -0700134 CHECK_EQ(mState, (int)DISCONNECTED);
135 mState = CONNECTING;
136
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100137 if (mIsSDP) {
138 mSDPLoader = new SDPLoader(notify,
139 (mFlags & kFlagIncognito) ? SDPLoader::kFlagIncognito : 0,
Andreas Huber81e68442014-02-05 11:52:33 -0800140 mHTTPService);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100141
Andreas Huber57cea552013-02-05 13:59:56 -0800142 mSDPLoader->load(
143 mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100144 } else {
145 mHandler = new MyHandler(mURL.c_str(), notify, mUIDValid, mUID);
146 mLooper->registerHandler(mHandler);
147
148 mHandler->connect();
149 }
Roger Jönssoncfc30832013-01-21 16:26:41 +0100150
Chong Zhang180d1b92014-12-02 18:35:35 -0800151 startBufferingIfNecessary();
Andreas Huber57cea552013-02-05 13:59:56 -0800152}
153
154void NuPlayer::RTSPSource::start() {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700155}
156
157void NuPlayer::RTSPSource::stop() {
James Dong58341812012-11-16 14:31:15 -0800158 if (mLooper == NULL) {
159 return;
160 }
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800161 sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700162
163 sp<AMessage> dummy;
164 msg->postAndAwaitResponse(&dummy);
165}
166
167status_t NuPlayer::RTSPSource::feedMoreTSData() {
Chong Zhang180d1b92014-12-02 18:35:35 -0800168 Mutex::Autolock _l(mBufferingLock);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700169 return mFinalResult;
170}
171
Andreas Huber84066782011-08-16 09:34:26 -0700172sp<MetaData> NuPlayer::RTSPSource::getFormatMeta(bool audio) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700173 sp<AnotherPacketSource> source = getSource(audio);
174
175 if (source == NULL) {
176 return NULL;
177 }
178
179 return source->getFormat();
180}
181
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700182bool NuPlayer::RTSPSource::haveSufficientDataOnAllTracks() {
183 // We're going to buffer at least 2 secs worth data on all tracks before
184 // starting playback (both at startup and after a seek).
185
186 static const int64_t kMinDurationUs = 2000000ll;
187
Roger Jönssoncfc30832013-01-21 16:26:41 +0100188 int64_t mediaDurationUs = 0;
189 getDuration(&mediaDurationUs);
190 if ((mAudioTrack != NULL && mAudioTrack->isFinished(mediaDurationUs))
191 || (mVideoTrack != NULL && mVideoTrack->isFinished(mediaDurationUs))) {
192 return true;
193 }
194
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700195 status_t err;
196 int64_t durationUs;
197 if (mAudioTrack != NULL
198 && (durationUs = mAudioTrack->getBufferedDurationUs(&err))
199 < kMinDurationUs
200 && err == OK) {
201 ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
202 durationUs / 1E6);
203 return false;
204 }
205
206 if (mVideoTrack != NULL
207 && (durationUs = mVideoTrack->getBufferedDurationUs(&err))
208 < kMinDurationUs
209 && err == OK) {
210 ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
211 durationUs / 1E6);
212 return false;
213 }
214
215 return true;
216}
217
Andreas Huber2bfdd422011-10-11 15:24:07 -0700218status_t NuPlayer::RTSPSource::dequeueAccessUnit(
219 bool audio, sp<ABuffer> *accessUnit) {
Chong Zhang180d1b92014-12-02 18:35:35 -0800220 if (!stopBufferingIfNecessary()) {
221 return -EWOULDBLOCK;
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700222 }
223
Andreas Huber2bfdd422011-10-11 15:24:07 -0700224 sp<AnotherPacketSource> source = getSource(audio);
225
226 if (source == NULL) {
227 return -EWOULDBLOCK;
228 }
229
230 status_t finalResult;
231 if (!source->hasBufferAvailable(&finalResult)) {
Roger Jönssoncfc30832013-01-21 16:26:41 +0100232 if (finalResult == OK) {
Roger Jönssoncfc30832013-01-21 16:26:41 +0100233
Robert Shihf1d261f2016-07-29 16:44:39 -0700234 // If other source already signaled EOS, this source should also return EOS
235 if (sourceReachedEOS(!audio)) {
Roger Jönssoncfc30832013-01-21 16:26:41 +0100236 return ERROR_END_OF_STREAM;
237 }
238
239 // If this source has detected near end, give it some time to retrieve more
Robert Shihf1d261f2016-07-29 16:44:39 -0700240 // data before returning EOS
241 int64_t mediaDurationUs = 0;
242 getDuration(&mediaDurationUs);
Roger Jönssoncfc30832013-01-21 16:26:41 +0100243 if (source->isFinished(mediaDurationUs)) {
244 int64_t eosTimeout = audio ? mEOSTimeoutAudio : mEOSTimeoutVideo;
245 if (eosTimeout == 0) {
246 setEOSTimeout(audio, ALooper::GetNowUs());
247 } else if ((ALooper::GetNowUs() - eosTimeout) > kNearEOSTimeoutUs) {
248 setEOSTimeout(audio, 0);
Roger Jönssoncfc30832013-01-21 16:26:41 +0100249 return ERROR_END_OF_STREAM;
250 }
251 return -EWOULDBLOCK;
252 }
253
Robert Shihf1d261f2016-07-29 16:44:39 -0700254 if (!sourceNearEOS(!audio)) {
Roger Jönssoncfc30832013-01-21 16:26:41 +0100255 // We should not enter buffering mode
256 // if any of the sources already have detected EOS.
Chong Zhang180d1b92014-12-02 18:35:35 -0800257 startBufferingIfNecessary();
Roger Jönssoncfc30832013-01-21 16:26:41 +0100258 }
259
260 return -EWOULDBLOCK;
261 }
262 return finalResult;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700263 }
264
Roger Jönssoncfc30832013-01-21 16:26:41 +0100265 setEOSTimeout(audio, 0);
266
Andreas Huber2bfdd422011-10-11 15:24:07 -0700267 return source->dequeueAccessUnit(accessUnit);
268}
269
270sp<AnotherPacketSource> NuPlayer::RTSPSource::getSource(bool audio) {
Andreas Huber49694682012-08-31 10:27:46 -0700271 if (mTSParser != NULL) {
272 sp<MediaSource> source = mTSParser->getSource(
273 audio ? ATSParser::AUDIO : ATSParser::VIDEO);
274
275 return static_cast<AnotherPacketSource *>(source.get());
276 }
277
Andreas Huber2bfdd422011-10-11 15:24:07 -0700278 return audio ? mAudioTrack : mVideoTrack;
279}
280
Roger Jönssoncfc30832013-01-21 16:26:41 +0100281void NuPlayer::RTSPSource::setEOSTimeout(bool audio, int64_t timeout) {
282 if (audio) {
283 mEOSTimeoutAudio = timeout;
284 } else {
285 mEOSTimeoutVideo = timeout;
286 }
287}
288
Andreas Huber2bfdd422011-10-11 15:24:07 -0700289status_t NuPlayer::RTSPSource::getDuration(int64_t *durationUs) {
Robert Shih7e074a82016-10-13 15:13:00 -0700290 *durationUs = -1ll;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700291
292 int64_t audioDurationUs;
293 if (mAudioTrack != NULL
294 && mAudioTrack->getFormat()->findInt64(
295 kKeyDuration, &audioDurationUs)
296 && audioDurationUs > *durationUs) {
297 *durationUs = audioDurationUs;
298 }
299
300 int64_t videoDurationUs;
301 if (mVideoTrack != NULL
302 && mVideoTrack->getFormat()->findInt64(
303 kKeyDuration, &videoDurationUs)
304 && videoDurationUs > *durationUs) {
305 *durationUs = videoDurationUs;
306 }
307
308 return OK;
309}
310
Wei Jiac5de0912016-11-18 10:22:14 -0800311status_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800312 sp<AMessage> msg = new AMessage(kWhatPerformSeek, this);
Andreas Huberee736e92011-12-08 13:04:50 -0800313 msg->setInt32("generation", ++mSeekGeneration);
314 msg->setInt64("timeUs", seekTimeUs);
Wei Jiac5de0912016-11-18 10:22:14 -0800315 msg->setInt32("mode", mode);
Andreas Huberee736e92011-12-08 13:04:50 -0800316
Robert Shih8d237a52015-07-13 17:59:36 -0700317 sp<AMessage> response;
318 status_t err = msg->postAndAwaitResponse(&response);
319 if (err == OK && response != NULL) {
320 CHECK(response->findInt32("err", &err));
321 }
322
323 return err;
Andreas Huberee736e92011-12-08 13:04:50 -0800324}
325
326void NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700327 if (mState != CONNECTED) {
Robert Shih8d237a52015-07-13 17:59:36 -0700328 finishSeek(INVALID_OPERATION);
Andreas Huberee736e92011-12-08 13:04:50 -0800329 return;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700330 }
331
332 mState = SEEKING;
333 mHandler->seek(seekTimeUs);
Robert Shihf1d261f2016-07-29 16:44:39 -0700334 mEOSPending = false;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700335}
336
Robert Shih641e0c72016-02-22 11:37:20 -0800337void NuPlayer::RTSPSource::schedulePollBuffering() {
338 sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
339 msg->post(1000000ll); // 1 second intervals
340}
341
342void NuPlayer::RTSPSource::checkBuffering(
Robert Shihf1d261f2016-07-29 16:44:39 -0700343 bool *prepared, bool *underflow, bool *overflow, bool *startServer, bool *finished) {
Robert Shih641e0c72016-02-22 11:37:20 -0800344 size_t numTracks = mTracks.size();
Robert Shihf1d261f2016-07-29 16:44:39 -0700345 size_t preparedCount, underflowCount, overflowCount, startCount, finishedCount;
346 preparedCount = underflowCount = overflowCount = startCount = finishedCount = 0;
Takahiro Aizawac622c582016-06-20 09:53:47 +0900347
348 size_t count = numTracks;
349 for (size_t i = 0; i < count; ++i) {
Robert Shih641e0c72016-02-22 11:37:20 -0800350 status_t finalResult;
351 TrackInfo *info = &mTracks.editItemAt(i);
352 sp<AnotherPacketSource> src = info->mSource;
Takahiro Aizawac622c582016-06-20 09:53:47 +0900353 if (src == NULL) {
354 --numTracks;
355 continue;
356 }
Robert Shih641e0c72016-02-22 11:37:20 -0800357 int64_t bufferedDurationUs = src->getBufferedDurationUs(&finalResult);
358
359 // isFinished when duration is 0 checks for EOS result only
Wei Jia48fa06d2016-12-20 15:30:49 -0800360 if (bufferedDurationUs > mBufferingSettings.mInitialWatermarkMs * 1000
361 || src->isFinished(/* duration */ 0)) {
Robert Shih641e0c72016-02-22 11:37:20 -0800362 ++preparedCount;
363 }
364
365 if (src->isFinished(/* duration */ 0)) {
366 ++overflowCount;
Robert Shihf1d261f2016-07-29 16:44:39 -0700367 ++finishedCount;
Robert Shih641e0c72016-02-22 11:37:20 -0800368 } else {
Wei Jia48fa06d2016-12-20 15:30:49 -0800369 if (bufferedDurationUs < mBufferingSettings.mRebufferingWatermarkLowMs * 1000) {
Robert Shih641e0c72016-02-22 11:37:20 -0800370 ++underflowCount;
371 }
Wei Jia48fa06d2016-12-20 15:30:49 -0800372 if (bufferedDurationUs > mBufferingSettings.mRebufferingWatermarkHighMs * 1000) {
Robert Shih641e0c72016-02-22 11:37:20 -0800373 ++overflowCount;
374 }
Wei Jia48fa06d2016-12-20 15:30:49 -0800375 int64_t startServerMarkUs =
376 (mBufferingSettings.mRebufferingWatermarkLowMs
377 + mBufferingSettings.mRebufferingWatermarkHighMs) / 2 * 1000ll;
378 if (bufferedDurationUs < startServerMarkUs) {
Robert Shih641e0c72016-02-22 11:37:20 -0800379 ++startCount;
380 }
381 }
382 }
383
384 *prepared = (preparedCount == numTracks);
385 *underflow = (underflowCount > 0);
386 *overflow = (overflowCount == numTracks);
387 *startServer = (startCount > 0);
Robert Shihf1d261f2016-07-29 16:44:39 -0700388 *finished = (finishedCount > 0);
Robert Shih641e0c72016-02-22 11:37:20 -0800389}
390
391void NuPlayer::RTSPSource::onPollBuffering() {
Robert Shihf1d261f2016-07-29 16:44:39 -0700392 bool prepared, underflow, overflow, startServer, finished;
393 checkBuffering(&prepared, &underflow, &overflow, &startServer, &finished);
Robert Shih641e0c72016-02-22 11:37:20 -0800394
395 if (prepared && mInPreparationPhase) {
396 mInPreparationPhase = false;
397 notifyPrepared();
398 }
399
400 if (!mInPreparationPhase && underflow) {
401 startBufferingIfNecessary();
402 }
403
Robert Shih91ea5712016-08-01 16:26:58 -0700404 if (haveSufficientDataOnAllTracks()) {
Robert Shih641e0c72016-02-22 11:37:20 -0800405 stopBufferingIfNecessary();
Robert Shih91ea5712016-08-01 16:26:58 -0700406 }
407
408 if (overflow && mHandler != NULL) {
Robert Shih641e0c72016-02-22 11:37:20 -0800409 mHandler->pause();
410 }
411
412 if (startServer && mHandler != NULL) {
413 mHandler->resume();
414 }
415
Robert Shihf1d261f2016-07-29 16:44:39 -0700416 if (finished && mHandler != NULL) {
417 mHandler->cancelAccessUnitTimeoutCheck();
418 }
419
Robert Shih641e0c72016-02-22 11:37:20 -0800420 schedulePollBuffering();
421}
422
Robert Shihf1d261f2016-07-29 16:44:39 -0700423void NuPlayer::RTSPSource::signalSourceEOS(status_t result) {
424 const bool audio = true;
425 const bool video = false;
426
427 sp<AnotherPacketSource> source = getSource(audio);
428 if (source != NULL) {
429 source->signalEOS(result);
430 }
431
432 source = getSource(video);
433 if (source != NULL) {
434 source->signalEOS(result);
435 }
436}
437
438bool NuPlayer::RTSPSource::sourceReachedEOS(bool audio) {
439 sp<AnotherPacketSource> source = getSource(audio);
440 status_t finalResult;
441 return (source != NULL &&
442 !source->hasBufferAvailable(&finalResult) &&
443 finalResult == ERROR_END_OF_STREAM);
444}
445
446bool NuPlayer::RTSPSource::sourceNearEOS(bool audio) {
447 sp<AnotherPacketSource> source = getSource(audio);
448 int64_t mediaDurationUs = 0;
449 getDuration(&mediaDurationUs);
450 return (source != NULL && source->isFinished(mediaDurationUs));
451}
452
453void NuPlayer::RTSPSource::onSignalEOS(const sp<AMessage> &msg) {
454 int32_t generation;
455 CHECK(msg->findInt32("generation", &generation));
456
457 if (generation != mSeekGeneration) {
458 return;
459 }
460
461 if (mEOSPending) {
462 signalSourceEOS(ERROR_END_OF_STREAM);
463 mEOSPending = false;
464 }
465}
466
467void NuPlayer::RTSPSource::postSourceEOSIfNecessary() {
468 const bool audio = true;
469 const bool video = false;
470 // If a source has detected near end, give it some time to retrieve more
471 // data before signaling EOS
472 if (sourceNearEOS(audio) || sourceNearEOS(video)) {
473 if (!mEOSPending) {
474 sp<AMessage> msg = new AMessage(kWhatSignalEOS, this);
475 msg->setInt32("generation", mSeekGeneration);
476 msg->post(kNearEOSTimeoutUs);
477 mEOSPending = true;
478 }
479 }
480}
481
Andreas Huber2bfdd422011-10-11 15:24:07 -0700482void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
483 if (msg->what() == kWhatDisconnect) {
Lajos Molnar3f274362015-03-05 14:35:41 -0800484 sp<AReplyToken> replyID;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700485 CHECK(msg->senderAwaitsResponse(&replyID));
486
487 mDisconnectReplyID = replyID;
488 finishDisconnectIfPossible();
489 return;
Andreas Huberee736e92011-12-08 13:04:50 -0800490 } else if (msg->what() == kWhatPerformSeek) {
491 int32_t generation;
492 CHECK(msg->findInt32("generation", &generation));
Robert Shih8d237a52015-07-13 17:59:36 -0700493 CHECK(msg->senderAwaitsResponse(&mSeekReplyID));
Andreas Huberee736e92011-12-08 13:04:50 -0800494
495 if (generation != mSeekGeneration) {
496 // obsolete.
Robert Shih8d237a52015-07-13 17:59:36 -0700497 finishSeek(OK);
Andreas Huberee736e92011-12-08 13:04:50 -0800498 return;
499 }
500
501 int64_t seekTimeUs;
Wei Jiac5de0912016-11-18 10:22:14 -0800502 int32_t mode;
Andreas Huberee736e92011-12-08 13:04:50 -0800503 CHECK(msg->findInt64("timeUs", &seekTimeUs));
Wei Jiac5de0912016-11-18 10:22:14 -0800504 CHECK(msg->findInt32("mode", &mode));
Andreas Huberee736e92011-12-08 13:04:50 -0800505
Wei Jiac5de0912016-11-18 10:22:14 -0800506 // TODO: add "mode" to performSeek.
507 performSeek(seekTimeUs/*, (MediaPlayerSeekMode)mode */);
Andreas Huberee736e92011-12-08 13:04:50 -0800508 return;
Robert Shih641e0c72016-02-22 11:37:20 -0800509 } else if (msg->what() == kWhatPollBuffering) {
510 onPollBuffering();
511 return;
Robert Shihf1d261f2016-07-29 16:44:39 -0700512 } else if (msg->what() == kWhatSignalEOS) {
513 onSignalEOS(msg);
514 return;
Wei Jia48fa06d2016-12-20 15:30:49 -0800515 } else if (msg->what() == kWhatSetBufferingSettings) {
516 sp<AReplyToken> replyID;
517 CHECK(msg->senderAwaitsResponse(&replyID));
518
519 BufferingSettings buffering;
520 readFromAMessage(msg, &buffering);
521
522 status_t err = OK;
523 if (buffering.IsSizeBasedBufferingMode(buffering.mInitialBufferingMode)
524 || buffering.IsSizeBasedBufferingMode(buffering.mRebufferingMode)
525 || (buffering.mRebufferingWatermarkLowMs > buffering.mRebufferingWatermarkHighMs
526 && buffering.IsTimeBasedBufferingMode(buffering.mRebufferingMode))) {
527 err = BAD_VALUE;
528 } else {
529 if (buffering.mInitialBufferingMode == BUFFERING_MODE_NONE) {
530 buffering.mInitialWatermarkMs = BufferingSettings::kNoWatermark;
531 }
532 if (buffering.mRebufferingMode == BUFFERING_MODE_NONE) {
533 buffering.mRebufferingWatermarkLowMs = BufferingSettings::kNoWatermark;
534 buffering.mRebufferingWatermarkHighMs = INT32_MAX;
535 }
536
537 mBufferingSettings = buffering;
538 }
539
540 sp<AMessage> response = new AMessage;
541 response->setInt32("err", err);
542 response->postReply(replyID);
543
544 return;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700545 }
546
Colin Crossb8c35f92017-04-27 16:15:51 -0700547 CHECK_EQ(msg->what(), kWhatNotify);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700548
549 int32_t what;
550 CHECK(msg->findInt32("what", &what));
551
552 switch (what) {
553 case MyHandler::kWhatConnected:
Andreas Huber7f475c32013-02-05 14:47:13 -0800554 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700555 onConnected();
Andreas Huber7f475c32013-02-05 14:47:13 -0800556
Chong Zhangced1c2f2014-08-08 15:22:35 -0700557 notifyVideoSizeChanged();
Andreas Huber7f475c32013-02-05 14:47:13 -0800558
559 uint32_t flags = 0;
560
561 if (mHandler->isSeekable()) {
Chong Zhang4b7069d2013-09-11 12:52:43 -0700562 flags = FLAG_CAN_PAUSE
563 | FLAG_CAN_SEEK
564 | FLAG_CAN_SEEK_BACKWARD
565 | FLAG_CAN_SEEK_FORWARD;
Andreas Huber7f475c32013-02-05 14:47:13 -0800566 }
567
568 notifyFlagsChanged(flags);
Robert Shih641e0c72016-02-22 11:37:20 -0800569 schedulePollBuffering();
Andreas Huber2bfdd422011-10-11 15:24:07 -0700570 break;
Andreas Huber7f475c32013-02-05 14:47:13 -0800571 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700572
573 case MyHandler::kWhatDisconnected:
Andreas Huber7f475c32013-02-05 14:47:13 -0800574 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700575 onDisconnected(msg);
576 break;
Andreas Huber7f475c32013-02-05 14:47:13 -0800577 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700578
579 case MyHandler::kWhatSeekDone:
580 {
581 mState = CONNECTED;
Wei Jia4ad74b22016-02-05 17:11:20 -0800582 // Unblock seekTo here in case we attempted to seek in a live stream
583 finishSeek(OK);
Robert Shih8d237a52015-07-13 17:59:36 -0700584 break;
585 }
586
587 case MyHandler::kWhatSeekPaused:
588 {
589 sp<AnotherPacketSource> source = getSource(true /* audio */);
590 if (source != NULL) {
591 source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
592 /* extra */ NULL,
593 /* discard */ true);
594 }
595 source = getSource(false /* video */);
596 if (source != NULL) {
597 source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
598 /* extra */ NULL,
599 /* discard */ true);
600 };
601
602 status_t err = OK;
603 msg->findInt32("err", &err);
Robert Shih8d237a52015-07-13 17:59:36 -0700604
605 if (err == OK) {
606 int64_t timeUs;
607 CHECK(msg->findInt64("time", &timeUs));
608 mHandler->continueSeekAfterPause(timeUs);
Wei Jia4ad74b22016-02-05 17:11:20 -0800609 } else {
610 finishSeek(err);
Robert Shih8d237a52015-07-13 17:59:36 -0700611 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700612 break;
613 }
614
615 case MyHandler::kWhatAccessUnit:
616 {
617 size_t trackIndex;
618 CHECK(msg->findSize("trackIndex", &trackIndex));
Andreas Huber49694682012-08-31 10:27:46 -0700619
620 if (mTSParser == NULL) {
621 CHECK_LT(trackIndex, mTracks.size());
622 } else {
623 CHECK_EQ(trackIndex, 0u);
624 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700625
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800626 sp<ABuffer> accessUnit;
627 CHECK(msg->findBuffer("accessUnit", &accessUnit));
Andreas Huber2bfdd422011-10-11 15:24:07 -0700628
629 int32_t damaged;
630 if (accessUnit->meta()->findInt32("damaged", &damaged)
631 && damaged) {
Steve Blockdf64d152012-01-04 20:05:49 +0000632 ALOGI("dropping damaged access unit.");
Andreas Huber2bfdd422011-10-11 15:24:07 -0700633 break;
634 }
635
Andreas Huber49694682012-08-31 10:27:46 -0700636 if (mTSParser != NULL) {
637 size_t offset = 0;
638 status_t err = OK;
639 while (offset + 188 <= accessUnit->size()) {
640 err = mTSParser->feedTSPacket(
641 accessUnit->data() + offset, 188);
642 if (err != OK) {
643 break;
644 }
645
646 offset += 188;
647 }
648
649 if (offset < accessUnit->size()) {
650 err = ERROR_MALFORMED;
651 }
652
653 if (err != OK) {
Robert Shihf1d261f2016-07-29 16:44:39 -0700654 signalSourceEOS(err);
Andreas Huber49694682012-08-31 10:27:46 -0700655 }
Robert Shihf1d261f2016-07-29 16:44:39 -0700656
657 postSourceEOSIfNecessary();
Andreas Huber49694682012-08-31 10:27:46 -0700658 break;
659 }
660
Andreas Huber1906e5c2011-12-08 12:27:47 -0800661 TrackInfo *info = &mTracks.editItemAt(trackIndex);
662
663 sp<AnotherPacketSource> source = info->mSource;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700664 if (source != NULL) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700665 uint32_t rtpTime;
666 CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
667
Andreas Huber1906e5c2011-12-08 12:27:47 -0800668 if (!info->mNPTMappingValid) {
669 // This is a live stream, we didn't receive any normal
Andreas Huberc9d16962012-05-21 11:12:40 -0700670 // playtime mapping. We won't map to npt time.
671 source->queueAccessUnit(accessUnit);
672 break;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800673 }
674
Andreas Huber2bfdd422011-10-11 15:24:07 -0700675 int64_t nptUs =
Andreas Huber1906e5c2011-12-08 12:27:47 -0800676 ((double)rtpTime - (double)info->mRTPTime)
677 / info->mTimeScale
Andreas Huber2bfdd422011-10-11 15:24:07 -0700678 * 1000000ll
Andreas Huber1906e5c2011-12-08 12:27:47 -0800679 + info->mNormalPlaytimeUs;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700680
681 accessUnit->meta()->setInt64("timeUs", nptUs);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700682
683 source->queueAccessUnit(accessUnit);
684 }
Robert Shihf1d261f2016-07-29 16:44:39 -0700685 postSourceEOSIfNecessary();
Andreas Huber2bfdd422011-10-11 15:24:07 -0700686 break;
687 }
688
689 case MyHandler::kWhatEOS:
690 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700691 int32_t finalResult;
692 CHECK(msg->findInt32("finalResult", &finalResult));
693 CHECK_NE(finalResult, (status_t)OK);
694
Andreas Huber49694682012-08-31 10:27:46 -0700695 if (mTSParser != NULL) {
Robert Shihf1d261f2016-07-29 16:44:39 -0700696 signalSourceEOS(finalResult);
Andreas Huber49694682012-08-31 10:27:46 -0700697 }
698
699 size_t trackIndex;
700 CHECK(msg->findSize("trackIndex", &trackIndex));
701 CHECK_LT(trackIndex, mTracks.size());
702
Andreas Huber2bfdd422011-10-11 15:24:07 -0700703 TrackInfo *info = &mTracks.editItemAt(trackIndex);
704 sp<AnotherPacketSource> source = info->mSource;
705 if (source != NULL) {
706 source->signalEOS(finalResult);
707 }
708
709 break;
710 }
711
712 case MyHandler::kWhatSeekDiscontinuity:
713 {
714 size_t trackIndex;
715 CHECK(msg->findSize("trackIndex", &trackIndex));
716 CHECK_LT(trackIndex, mTracks.size());
717
718 TrackInfo *info = &mTracks.editItemAt(trackIndex);
719 sp<AnotherPacketSource> source = info->mSource;
720 if (source != NULL) {
Chong Zhang632740c2014-06-26 13:03:47 -0700721 source->queueDiscontinuity(
Wei Jiafef808d2014-10-31 17:57:05 -0700722 ATSParser::DISCONTINUITY_TIME,
Chong Zhang632740c2014-06-26 13:03:47 -0700723 NULL,
724 true /* discard */);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700725 }
726
727 break;
728 }
729
730 case MyHandler::kWhatNormalPlayTimeMapping:
731 {
732 size_t trackIndex;
733 CHECK(msg->findSize("trackIndex", &trackIndex));
734 CHECK_LT(trackIndex, mTracks.size());
735
736 uint32_t rtpTime;
737 CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime));
738
739 int64_t nptUs;
740 CHECK(msg->findInt64("nptUs", &nptUs));
741
742 TrackInfo *info = &mTracks.editItemAt(trackIndex);
743 info->mRTPTime = rtpTime;
744 info->mNormalPlaytimeUs = nptUs;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800745 info->mNPTMappingValid = true;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700746 break;
747 }
748
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100749 case SDPLoader::kWhatSDPLoaded:
750 {
751 onSDPLoaded(msg);
752 break;
753 }
754
Andreas Huber2bfdd422011-10-11 15:24:07 -0700755 default:
756 TRESPASS();
757 }
758}
759
760void NuPlayer::RTSPSource::onConnected() {
761 CHECK(mAudioTrack == NULL);
762 CHECK(mVideoTrack == NULL);
763
764 size_t numTracks = mHandler->countTracks();
765 for (size_t i = 0; i < numTracks; ++i) {
766 int32_t timeScale;
767 sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale);
768
769 const char *mime;
770 CHECK(format->findCString(kKeyMIMEType, &mime));
771
Andreas Huber49694682012-08-31 10:27:46 -0700772 if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
773 // Very special case for MPEG2 Transport Streams.
774 CHECK_EQ(numTracks, 1u);
775
776 mTSParser = new ATSParser;
777 return;
778 }
779
Andreas Huber2bfdd422011-10-11 15:24:07 -0700780 bool isAudio = !strncasecmp(mime, "audio/", 6);
781 bool isVideo = !strncasecmp(mime, "video/", 6);
782
783 TrackInfo info;
784 info.mTimeScale = timeScale;
785 info.mRTPTime = 0;
786 info.mNormalPlaytimeUs = 0ll;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800787 info.mNPTMappingValid = false;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700788
789 if ((isAudio && mAudioTrack == NULL)
790 || (isVideo && mVideoTrack == NULL)) {
791 sp<AnotherPacketSource> source = new AnotherPacketSource(format);
792
793 if (isAudio) {
794 mAudioTrack = source;
795 } else {
796 mVideoTrack = source;
797 }
798
799 info.mSource = source;
800 }
801
802 mTracks.push(info);
803 }
804
805 mState = CONNECTED;
806}
807
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100808void NuPlayer::RTSPSource::onSDPLoaded(const sp<AMessage> &msg) {
809 status_t err;
810 CHECK(msg->findInt32("result", &err));
811
812 mSDPLoader.clear();
813
814 if (mDisconnectReplyID != 0) {
815 err = UNKNOWN_ERROR;
816 }
817
818 if (err == OK) {
819 sp<ASessionDescription> desc;
820 sp<RefBase> obj;
821 CHECK(msg->findObject("description", &obj));
822 desc = static_cast<ASessionDescription *>(obj.get());
823
824 AString rtspUri;
825 if (!desc->findAttribute(0, "a=control", &rtspUri)) {
826 ALOGE("Unable to find url in SDP");
827 err = UNKNOWN_ERROR;
828 } else {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800829 sp<AMessage> notify = new AMessage(kWhatNotify, this);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100830
831 mHandler = new MyHandler(rtspUri.c_str(), notify, mUIDValid, mUID);
832 mLooper->registerHandler(mHandler);
833
834 mHandler->loadSDP(desc);
835 }
836 }
837
838 if (err != OK) {
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
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100845 mState = DISCONNECTED;
Chong Zhang180d1b92014-12-02 18:35:35 -0800846 setError(err);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100847
848 if (mDisconnectReplyID != 0) {
849 finishDisconnectIfPossible();
850 }
851 }
852}
853
Andreas Huber2bfdd422011-10-11 15:24:07 -0700854void NuPlayer::RTSPSource::onDisconnected(const sp<AMessage> &msg) {
Fredrik Rosin0ad03bc2013-03-06 13:42:53 +0100855 if (mState == DISCONNECTED) {
856 return;
857 }
858
Andreas Huber2bfdd422011-10-11 15:24:07 -0700859 status_t err;
860 CHECK(msg->findInt32("result", &err));
861 CHECK_NE(err, (status_t)OK);
862
863 mLooper->unregisterHandler(mHandler->id());
864 mHandler.clear();
865
Andreas Huber7f475c32013-02-05 14:47:13 -0800866 if (mState == CONNECTING) {
867 // We're still in the preparation phase, signal that it
868 // failed.
869 notifyPrepared(err);
870 }
871
Andreas Huber2bfdd422011-10-11 15:24:07 -0700872 mState = DISCONNECTED;
Chong Zhang180d1b92014-12-02 18:35:35 -0800873 setError(err);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700874
875 if (mDisconnectReplyID != 0) {
876 finishDisconnectIfPossible();
877 }
878}
879
880void NuPlayer::RTSPSource::finishDisconnectIfPossible() {
881 if (mState != DISCONNECTED) {
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100882 if (mHandler != NULL) {
883 mHandler->disconnect();
884 } else if (mSDPLoader != NULL) {
885 mSDPLoader->cancel();
886 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700887 return;
888 }
889
890 (new AMessage)->postReply(mDisconnectReplyID);
891 mDisconnectReplyID = 0;
892}
893
Chong Zhang180d1b92014-12-02 18:35:35 -0800894void NuPlayer::RTSPSource::setError(status_t err) {
895 Mutex::Autolock _l(mBufferingLock);
896 mFinalResult = err;
897}
898
899void NuPlayer::RTSPSource::startBufferingIfNecessary() {
900 Mutex::Autolock _l(mBufferingLock);
901
902 if (!mBuffering) {
903 mBuffering = true;
904
905 sp<AMessage> notify = dupNotify();
Wei Jiac9ff2002016-05-24 16:23:48 -0700906 notify->setInt32("what", kWhatPauseOnBufferingStart);
Chong Zhang180d1b92014-12-02 18:35:35 -0800907 notify->post();
908 }
909}
910
911bool NuPlayer::RTSPSource::stopBufferingIfNecessary() {
912 Mutex::Autolock _l(mBufferingLock);
913
914 if (mBuffering) {
915 if (!haveSufficientDataOnAllTracks()) {
916 return false;
917 }
918
919 mBuffering = false;
920
921 sp<AMessage> notify = dupNotify();
Wei Jiac9ff2002016-05-24 16:23:48 -0700922 notify->setInt32("what", kWhatResumeOnBufferingEnd);
Chong Zhang180d1b92014-12-02 18:35:35 -0800923 notify->post();
924 }
925
926 return true;
927}
928
Robert Shih8d237a52015-07-13 17:59:36 -0700929void NuPlayer::RTSPSource::finishSeek(status_t err) {
Wei Jia4ad74b22016-02-05 17:11:20 -0800930 if (mSeekReplyID == NULL) {
931 return;
932 }
Robert Shih8d237a52015-07-13 17:59:36 -0700933 sp<AMessage> seekReply = new AMessage;
934 seekReply->setInt32("err", err);
935 seekReply->postReply(mSeekReplyID);
936 mSeekReplyID = NULL;
937}
Chong Zhang180d1b92014-12-02 18:35:35 -0800938
Andreas Huber2bfdd422011-10-11 15:24:07 -0700939} // namespace android