blob: b70d5503f0ae01f917b5134e332e2ec546c3d327 [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 Huber49694682012-08-31 10:27:46 -070027#include <media/stagefright/MediaDefs.h>
Andreas Huber2bfdd422011-10-11 15:24:07 -070028#include <media/stagefright/MetaData.h>
29
30namespace android {
31
Roger Jönssoncfc30832013-01-21 16:26:41 +010032const int64_t kNearEOSTimeoutUs = 2000000ll; // 2 secs
33
Andreas Huber2bfdd422011-10-11 15:24:07 -070034NuPlayer::RTSPSource::RTSPSource(
Andreas Huber5ab368a2013-02-05 10:14:26 -080035 const sp<AMessage> &notify,
Andreas Huber2bfdd422011-10-11 15:24:07 -070036 const char *url,
37 const KeyedVector<String8, String8> *headers,
38 bool uidValid,
Oscar Rydhé81dd60e2012-02-20 10:15:48 +010039 uid_t uid,
40 bool isSDP)
Andreas Huber5ab368a2013-02-05 10:14:26 -080041 : Source(notify),
42 mURL(url),
Andreas Huber2bfdd422011-10-11 15:24:07 -070043 mUIDValid(uidValid),
44 mUID(uid),
45 mFlags(0),
Oscar Rydhé81dd60e2012-02-20 10:15:48 +010046 mIsSDP(isSDP),
Andreas Huber2bfdd422011-10-11 15:24:07 -070047 mState(DISCONNECTED),
48 mFinalResult(OK),
Andreas Huberee736e92011-12-08 13:04:50 -080049 mDisconnectReplyID(0),
Roger Jönssoncfc30832013-01-21 16:26:41 +010050 mBuffering(true),
51 mSeekGeneration(0),
52 mEOSTimeoutAudio(0),
53 mEOSTimeoutVideo(0) {
Andreas Huber2bfdd422011-10-11 15:24:07 -070054 if (headers) {
55 mExtraHeaders = *headers;
56
57 ssize_t index =
58 mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
59
60 if (index >= 0) {
61 mFlags |= kFlagIncognito;
62
63 mExtraHeaders.removeItemsAt(index);
64 }
65 }
66}
67
68NuPlayer::RTSPSource::~RTSPSource() {
James Dong58341812012-11-16 14:31:15 -080069 mLooper->stop();
Andreas Huber2bfdd422011-10-11 15:24:07 -070070}
71
Andreas Huber57cea552013-02-05 13:59:56 -080072void NuPlayer::RTSPSource::prepareAsync() {
Andreas Huber2bfdd422011-10-11 15:24:07 -070073 if (mLooper == NULL) {
74 mLooper = new ALooper;
75 mLooper->setName("rtsp");
76 mLooper->start();
77
78 mReflector = new AHandlerReflector<RTSPSource>(this);
79 mLooper->registerHandler(mReflector);
80 }
81
82 CHECK(mHandler == NULL);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +010083 CHECK(mSDPLoader == NULL);
Andreas Huber2bfdd422011-10-11 15:24:07 -070084
85 sp<AMessage> notify = new AMessage(kWhatNotify, mReflector->id());
86
Andreas Huber2bfdd422011-10-11 15:24:07 -070087 CHECK_EQ(mState, (int)DISCONNECTED);
88 mState = CONNECTING;
89
Oscar Rydhé81dd60e2012-02-20 10:15:48 +010090 if (mIsSDP) {
91 mSDPLoader = new SDPLoader(notify,
92 (mFlags & kFlagIncognito) ? SDPLoader::kFlagIncognito : 0,
93 mUIDValid, mUID);
94
Andreas Huber57cea552013-02-05 13:59:56 -080095 mSDPLoader->load(
96 mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +010097 } else {
98 mHandler = new MyHandler(mURL.c_str(), notify, mUIDValid, mUID);
99 mLooper->registerHandler(mHandler);
100
101 mHandler->connect();
102 }
Roger Jönssoncfc30832013-01-21 16:26:41 +0100103
104 sp<AMessage> notifyStart = dupNotify();
105 notifyStart->setInt32("what", kWhatBufferingStart);
106 notifyStart->post();
Andreas Huber57cea552013-02-05 13:59:56 -0800107}
108
109void NuPlayer::RTSPSource::start() {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700110}
111
112void NuPlayer::RTSPSource::stop() {
James Dong58341812012-11-16 14:31:15 -0800113 if (mLooper == NULL) {
114 return;
115 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700116 sp<AMessage> msg = new AMessage(kWhatDisconnect, mReflector->id());
117
118 sp<AMessage> dummy;
119 msg->postAndAwaitResponse(&dummy);
120}
121
122status_t NuPlayer::RTSPSource::feedMoreTSData() {
123 return mFinalResult;
124}
125
Andreas Huber84066782011-08-16 09:34:26 -0700126sp<MetaData> NuPlayer::RTSPSource::getFormatMeta(bool audio) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700127 sp<AnotherPacketSource> source = getSource(audio);
128
129 if (source == NULL) {
130 return NULL;
131 }
132
133 return source->getFormat();
134}
135
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700136bool NuPlayer::RTSPSource::haveSufficientDataOnAllTracks() {
137 // We're going to buffer at least 2 secs worth data on all tracks before
138 // starting playback (both at startup and after a seek).
139
140 static const int64_t kMinDurationUs = 2000000ll;
141
Roger Jönssoncfc30832013-01-21 16:26:41 +0100142 int64_t mediaDurationUs = 0;
143 getDuration(&mediaDurationUs);
144 if ((mAudioTrack != NULL && mAudioTrack->isFinished(mediaDurationUs))
145 || (mVideoTrack != NULL && mVideoTrack->isFinished(mediaDurationUs))) {
146 return true;
147 }
148
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700149 status_t err;
150 int64_t durationUs;
151 if (mAudioTrack != NULL
152 && (durationUs = mAudioTrack->getBufferedDurationUs(&err))
153 < kMinDurationUs
154 && err == OK) {
155 ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
156 durationUs / 1E6);
157 return false;
158 }
159
160 if (mVideoTrack != NULL
161 && (durationUs = mVideoTrack->getBufferedDurationUs(&err))
162 < kMinDurationUs
163 && err == OK) {
164 ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
165 durationUs / 1E6);
166 return false;
167 }
168
169 return true;
170}
171
Andreas Huber2bfdd422011-10-11 15:24:07 -0700172status_t NuPlayer::RTSPSource::dequeueAccessUnit(
173 bool audio, sp<ABuffer> *accessUnit) {
Roger Jönssoncfc30832013-01-21 16:26:41 +0100174 if (mBuffering) {
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700175 if (!haveSufficientDataOnAllTracks()) {
176 return -EWOULDBLOCK;
177 }
178
Roger Jönssoncfc30832013-01-21 16:26:41 +0100179 mBuffering = false;
180
181 sp<AMessage> notify = dupNotify();
182 notify->setInt32("what", kWhatBufferingEnd);
183 notify->post();
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700184 }
185
Andreas Huber2bfdd422011-10-11 15:24:07 -0700186 sp<AnotherPacketSource> source = getSource(audio);
187
188 if (source == NULL) {
189 return -EWOULDBLOCK;
190 }
191
192 status_t finalResult;
193 if (!source->hasBufferAvailable(&finalResult)) {
Roger Jönssoncfc30832013-01-21 16:26:41 +0100194 if (finalResult == OK) {
195 int64_t mediaDurationUs = 0;
196 getDuration(&mediaDurationUs);
197 sp<AnotherPacketSource> otherSource = getSource(!audio);
198 status_t otherFinalResult;
199
200 // If other source already signaled EOS, this source should also signal EOS
201 if (otherSource != NULL &&
202 !otherSource->hasBufferAvailable(&otherFinalResult) &&
203 otherFinalResult == ERROR_END_OF_STREAM) {
204 source->signalEOS(ERROR_END_OF_STREAM);
205 return ERROR_END_OF_STREAM;
206 }
207
208 // If this source has detected near end, give it some time to retrieve more
209 // data before signaling EOS
210 if (source->isFinished(mediaDurationUs)) {
211 int64_t eosTimeout = audio ? mEOSTimeoutAudio : mEOSTimeoutVideo;
212 if (eosTimeout == 0) {
213 setEOSTimeout(audio, ALooper::GetNowUs());
214 } else if ((ALooper::GetNowUs() - eosTimeout) > kNearEOSTimeoutUs) {
215 setEOSTimeout(audio, 0);
216 source->signalEOS(ERROR_END_OF_STREAM);
217 return ERROR_END_OF_STREAM;
218 }
219 return -EWOULDBLOCK;
220 }
221
222 if (!(otherSource != NULL && otherSource->isFinished(mediaDurationUs))) {
223 // We should not enter buffering mode
224 // if any of the sources already have detected EOS.
225 mBuffering = true;
226
227 sp<AMessage> notify = dupNotify();
228 notify->setInt32("what", kWhatBufferingStart);
229 notify->post();
230 }
231
232 return -EWOULDBLOCK;
233 }
234 return finalResult;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700235 }
236
Roger Jönssoncfc30832013-01-21 16:26:41 +0100237 setEOSTimeout(audio, 0);
238
Andreas Huber2bfdd422011-10-11 15:24:07 -0700239 return source->dequeueAccessUnit(accessUnit);
240}
241
242sp<AnotherPacketSource> NuPlayer::RTSPSource::getSource(bool audio) {
Andreas Huber49694682012-08-31 10:27:46 -0700243 if (mTSParser != NULL) {
244 sp<MediaSource> source = mTSParser->getSource(
245 audio ? ATSParser::AUDIO : ATSParser::VIDEO);
246
247 return static_cast<AnotherPacketSource *>(source.get());
248 }
249
Andreas Huber2bfdd422011-10-11 15:24:07 -0700250 return audio ? mAudioTrack : mVideoTrack;
251}
252
Roger Jönssoncfc30832013-01-21 16:26:41 +0100253void NuPlayer::RTSPSource::setEOSTimeout(bool audio, int64_t timeout) {
254 if (audio) {
255 mEOSTimeoutAudio = timeout;
256 } else {
257 mEOSTimeoutVideo = timeout;
258 }
259}
260
Andreas Huber2bfdd422011-10-11 15:24:07 -0700261status_t NuPlayer::RTSPSource::getDuration(int64_t *durationUs) {
262 *durationUs = 0ll;
263
264 int64_t audioDurationUs;
265 if (mAudioTrack != NULL
266 && mAudioTrack->getFormat()->findInt64(
267 kKeyDuration, &audioDurationUs)
268 && audioDurationUs > *durationUs) {
269 *durationUs = audioDurationUs;
270 }
271
272 int64_t videoDurationUs;
273 if (mVideoTrack != NULL
274 && mVideoTrack->getFormat()->findInt64(
275 kKeyDuration, &videoDurationUs)
276 && videoDurationUs > *durationUs) {
277 *durationUs = videoDurationUs;
278 }
279
280 return OK;
281}
282
283status_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs) {
Andreas Huberee736e92011-12-08 13:04:50 -0800284 sp<AMessage> msg = new AMessage(kWhatPerformSeek, mReflector->id());
285 msg->setInt32("generation", ++mSeekGeneration);
286 msg->setInt64("timeUs", seekTimeUs);
287 msg->post(200000ll);
288
289 return OK;
290}
291
292void NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700293 if (mState != CONNECTED) {
Andreas Huberee736e92011-12-08 13:04:50 -0800294 return;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700295 }
296
297 mState = SEEKING;
298 mHandler->seek(seekTimeUs);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700299}
300
Andreas Huber2bfdd422011-10-11 15:24:07 -0700301void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
302 if (msg->what() == kWhatDisconnect) {
303 uint32_t replyID;
304 CHECK(msg->senderAwaitsResponse(&replyID));
305
306 mDisconnectReplyID = replyID;
307 finishDisconnectIfPossible();
308 return;
Andreas Huberee736e92011-12-08 13:04:50 -0800309 } else if (msg->what() == kWhatPerformSeek) {
310 int32_t generation;
311 CHECK(msg->findInt32("generation", &generation));
312
313 if (generation != mSeekGeneration) {
314 // obsolete.
315 return;
316 }
317
318 int64_t seekTimeUs;
319 CHECK(msg->findInt64("timeUs", &seekTimeUs));
320
321 performSeek(seekTimeUs);
322 return;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700323 }
324
325 CHECK_EQ(msg->what(), (int)kWhatNotify);
326
327 int32_t what;
328 CHECK(msg->findInt32("what", &what));
329
330 switch (what) {
331 case MyHandler::kWhatConnected:
Andreas Huber7f475c32013-02-05 14:47:13 -0800332 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700333 onConnected();
Andreas Huber7f475c32013-02-05 14:47:13 -0800334
335 notifyVideoSizeChanged(0, 0);
336
337 uint32_t flags = 0;
338
339 if (mHandler->isSeekable()) {
340 flags = FLAG_CAN_PAUSE | FLAG_CAN_SEEK;
341
342 // Seeking 10secs forward or backward is a very expensive
343 // operation for rtsp, so let's not enable that.
344 // The user can always use the seek bar.
345 }
346
347 notifyFlagsChanged(flags);
348 notifyPrepared();
Andreas Huber2bfdd422011-10-11 15:24:07 -0700349 break;
Andreas Huber7f475c32013-02-05 14:47:13 -0800350 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700351
352 case MyHandler::kWhatDisconnected:
Andreas Huber7f475c32013-02-05 14:47:13 -0800353 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700354 onDisconnected(msg);
355 break;
Andreas Huber7f475c32013-02-05 14:47:13 -0800356 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700357
358 case MyHandler::kWhatSeekDone:
359 {
360 mState = CONNECTED;
361 break;
362 }
363
364 case MyHandler::kWhatAccessUnit:
365 {
366 size_t trackIndex;
367 CHECK(msg->findSize("trackIndex", &trackIndex));
Andreas Huber49694682012-08-31 10:27:46 -0700368
369 if (mTSParser == NULL) {
370 CHECK_LT(trackIndex, mTracks.size());
371 } else {
372 CHECK_EQ(trackIndex, 0u);
373 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700374
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800375 sp<ABuffer> accessUnit;
376 CHECK(msg->findBuffer("accessUnit", &accessUnit));
Andreas Huber2bfdd422011-10-11 15:24:07 -0700377
378 int32_t damaged;
379 if (accessUnit->meta()->findInt32("damaged", &damaged)
380 && damaged) {
Steve Blockdf64d152012-01-04 20:05:49 +0000381 ALOGI("dropping damaged access unit.");
Andreas Huber2bfdd422011-10-11 15:24:07 -0700382 break;
383 }
384
Andreas Huber49694682012-08-31 10:27:46 -0700385 if (mTSParser != NULL) {
386 size_t offset = 0;
387 status_t err = OK;
388 while (offset + 188 <= accessUnit->size()) {
389 err = mTSParser->feedTSPacket(
390 accessUnit->data() + offset, 188);
391 if (err != OK) {
392 break;
393 }
394
395 offset += 188;
396 }
397
398 if (offset < accessUnit->size()) {
399 err = ERROR_MALFORMED;
400 }
401
402 if (err != OK) {
403 sp<AnotherPacketSource> source = getSource(false /* audio */);
404 if (source != NULL) {
405 source->signalEOS(err);
406 }
407
408 source = getSource(true /* audio */);
409 if (source != NULL) {
410 source->signalEOS(err);
411 }
412 }
413 break;
414 }
415
Andreas Huber1906e5c2011-12-08 12:27:47 -0800416 TrackInfo *info = &mTracks.editItemAt(trackIndex);
417
418 sp<AnotherPacketSource> source = info->mSource;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700419 if (source != NULL) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700420 uint32_t rtpTime;
421 CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
422
Andreas Huber1906e5c2011-12-08 12:27:47 -0800423 if (!info->mNPTMappingValid) {
424 // This is a live stream, we didn't receive any normal
Andreas Huberc9d16962012-05-21 11:12:40 -0700425 // playtime mapping. We won't map to npt time.
426 source->queueAccessUnit(accessUnit);
427 break;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800428 }
429
Andreas Huber2bfdd422011-10-11 15:24:07 -0700430 int64_t nptUs =
Andreas Huber1906e5c2011-12-08 12:27:47 -0800431 ((double)rtpTime - (double)info->mRTPTime)
432 / info->mTimeScale
Andreas Huber2bfdd422011-10-11 15:24:07 -0700433 * 1000000ll
Andreas Huber1906e5c2011-12-08 12:27:47 -0800434 + info->mNormalPlaytimeUs;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700435
436 accessUnit->meta()->setInt64("timeUs", nptUs);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700437
438 source->queueAccessUnit(accessUnit);
439 }
440 break;
441 }
442
443 case MyHandler::kWhatEOS:
444 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700445 int32_t finalResult;
446 CHECK(msg->findInt32("finalResult", &finalResult));
447 CHECK_NE(finalResult, (status_t)OK);
448
Andreas Huber49694682012-08-31 10:27:46 -0700449 if (mTSParser != NULL) {
450 sp<AnotherPacketSource> source = getSource(false /* audio */);
451 if (source != NULL) {
452 source->signalEOS(finalResult);
453 }
454
455 source = getSource(true /* audio */);
456 if (source != NULL) {
457 source->signalEOS(finalResult);
458 }
459
460 return;
461 }
462
463 size_t trackIndex;
464 CHECK(msg->findSize("trackIndex", &trackIndex));
465 CHECK_LT(trackIndex, mTracks.size());
466
Andreas Huber2bfdd422011-10-11 15:24:07 -0700467 TrackInfo *info = &mTracks.editItemAt(trackIndex);
468 sp<AnotherPacketSource> source = info->mSource;
469 if (source != NULL) {
470 source->signalEOS(finalResult);
471 }
472
473 break;
474 }
475
476 case MyHandler::kWhatSeekDiscontinuity:
477 {
478 size_t trackIndex;
479 CHECK(msg->findSize("trackIndex", &trackIndex));
480 CHECK_LT(trackIndex, mTracks.size());
481
482 TrackInfo *info = &mTracks.editItemAt(trackIndex);
483 sp<AnotherPacketSource> source = info->mSource;
484 if (source != NULL) {
485 source->queueDiscontinuity(ATSParser::DISCONTINUITY_SEEK, NULL);
486 }
487
488 break;
489 }
490
491 case MyHandler::kWhatNormalPlayTimeMapping:
492 {
493 size_t trackIndex;
494 CHECK(msg->findSize("trackIndex", &trackIndex));
495 CHECK_LT(trackIndex, mTracks.size());
496
497 uint32_t rtpTime;
498 CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime));
499
500 int64_t nptUs;
501 CHECK(msg->findInt64("nptUs", &nptUs));
502
503 TrackInfo *info = &mTracks.editItemAt(trackIndex);
504 info->mRTPTime = rtpTime;
505 info->mNormalPlaytimeUs = nptUs;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800506 info->mNPTMappingValid = true;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700507 break;
508 }
509
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100510 case SDPLoader::kWhatSDPLoaded:
511 {
512 onSDPLoaded(msg);
513 break;
514 }
515
Andreas Huber2bfdd422011-10-11 15:24:07 -0700516 default:
517 TRESPASS();
518 }
519}
520
521void NuPlayer::RTSPSource::onConnected() {
522 CHECK(mAudioTrack == NULL);
523 CHECK(mVideoTrack == NULL);
524
525 size_t numTracks = mHandler->countTracks();
526 for (size_t i = 0; i < numTracks; ++i) {
527 int32_t timeScale;
528 sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale);
529
530 const char *mime;
531 CHECK(format->findCString(kKeyMIMEType, &mime));
532
Andreas Huber49694682012-08-31 10:27:46 -0700533 if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
534 // Very special case for MPEG2 Transport Streams.
535 CHECK_EQ(numTracks, 1u);
536
537 mTSParser = new ATSParser;
538 return;
539 }
540
Andreas Huber2bfdd422011-10-11 15:24:07 -0700541 bool isAudio = !strncasecmp(mime, "audio/", 6);
542 bool isVideo = !strncasecmp(mime, "video/", 6);
543
544 TrackInfo info;
545 info.mTimeScale = timeScale;
546 info.mRTPTime = 0;
547 info.mNormalPlaytimeUs = 0ll;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800548 info.mNPTMappingValid = false;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700549
550 if ((isAudio && mAudioTrack == NULL)
551 || (isVideo && mVideoTrack == NULL)) {
552 sp<AnotherPacketSource> source = new AnotherPacketSource(format);
553
554 if (isAudio) {
555 mAudioTrack = source;
556 } else {
557 mVideoTrack = source;
558 }
559
560 info.mSource = source;
561 }
562
563 mTracks.push(info);
564 }
565
566 mState = CONNECTED;
567}
568
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100569void NuPlayer::RTSPSource::onSDPLoaded(const sp<AMessage> &msg) {
570 status_t err;
571 CHECK(msg->findInt32("result", &err));
572
573 mSDPLoader.clear();
574
575 if (mDisconnectReplyID != 0) {
576 err = UNKNOWN_ERROR;
577 }
578
579 if (err == OK) {
580 sp<ASessionDescription> desc;
581 sp<RefBase> obj;
582 CHECK(msg->findObject("description", &obj));
583 desc = static_cast<ASessionDescription *>(obj.get());
584
585 AString rtspUri;
586 if (!desc->findAttribute(0, "a=control", &rtspUri)) {
587 ALOGE("Unable to find url in SDP");
588 err = UNKNOWN_ERROR;
589 } else {
590 sp<AMessage> notify = new AMessage(kWhatNotify, mReflector->id());
591
592 mHandler = new MyHandler(rtspUri.c_str(), notify, mUIDValid, mUID);
593 mLooper->registerHandler(mHandler);
594
595 mHandler->loadSDP(desc);
596 }
597 }
598
599 if (err != OK) {
Andreas Huber7f475c32013-02-05 14:47:13 -0800600 if (mState == CONNECTING) {
601 // We're still in the preparation phase, signal that it
602 // failed.
603 notifyPrepared(err);
604 }
605
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100606 mState = DISCONNECTED;
607 mFinalResult = err;
608
609 if (mDisconnectReplyID != 0) {
610 finishDisconnectIfPossible();
611 }
612 }
613}
614
Andreas Huber2bfdd422011-10-11 15:24:07 -0700615void NuPlayer::RTSPSource::onDisconnected(const sp<AMessage> &msg) {
616 status_t err;
617 CHECK(msg->findInt32("result", &err));
618 CHECK_NE(err, (status_t)OK);
619
620 mLooper->unregisterHandler(mHandler->id());
621 mHandler.clear();
622
Andreas Huber7f475c32013-02-05 14:47:13 -0800623 if (mState == CONNECTING) {
624 // We're still in the preparation phase, signal that it
625 // failed.
626 notifyPrepared(err);
627 }
628
Andreas Huber2bfdd422011-10-11 15:24:07 -0700629 mState = DISCONNECTED;
630 mFinalResult = err;
631
632 if (mDisconnectReplyID != 0) {
633 finishDisconnectIfPossible();
634 }
635}
636
637void NuPlayer::RTSPSource::finishDisconnectIfPossible() {
638 if (mState != DISCONNECTED) {
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100639 if (mHandler != NULL) {
640 mHandler->disconnect();
641 } else if (mSDPLoader != NULL) {
642 mSDPLoader->cancel();
643 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700644 return;
645 }
646
647 (new AMessage)->postReply(mDisconnectReplyID);
648 mDisconnectReplyID = 0;
649}
650
651} // namespace android