blob: a5ff0ca2b3641479d09424b9e1964ed3d394f9bd [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é7a33b772012-02-20 10:15:48 +010025#include "SDPLoader.h"
Andreas Huber2bfdd422011-10-11 15:24:07 -070026
Andreas Hubercfaeeec2012-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önssonb50e83e2013-01-21 16:26:41 +010032const int64_t kNearEOSTimeoutUs = 2000000ll; // 2 secs
33
Andreas Huber2bfdd422011-10-11 15:24:07 -070034NuPlayer::RTSPSource::RTSPSource(
Andreas Huberb5f25f02013-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é7a33b772012-02-20 10:15:48 +010039 uid_t uid,
40 bool isSDP)
Andreas Huberb5f25f02013-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é7a33b772012-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önssonb50e83e2013-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 Dongf6f0f0e2012-11-16 14:31:15 -080069 mLooper->stop();
Andreas Huber2bfdd422011-10-11 15:24:07 -070070}
71
Andreas Huber9575c962013-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é7a33b772012-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é7a33b772012-02-20 10:15:48 +010090 if (mIsSDP) {
91 mSDPLoader = new SDPLoader(notify,
92 (mFlags & kFlagIncognito) ? SDPLoader::kFlagIncognito : 0,
93 mUIDValid, mUID);
94
Andreas Huber9575c962013-02-05 13:59:56 -080095 mSDPLoader->load(
96 mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
Oscar Rydhé7a33b772012-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önssonb50e83e2013-01-21 16:26:41 +0100103
104 sp<AMessage> notifyStart = dupNotify();
105 notifyStart->setInt32("what", kWhatBufferingStart);
106 notifyStart->post();
Andreas Huber9575c962013-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 Dongf6f0f0e2012-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
Roger Jönssonfba60da2013-01-21 17:15:45 +0100122void NuPlayer::RTSPSource::pause() {
123 int64_t mediaDurationUs = 0;
124 getDuration(&mediaDurationUs);
125 for (size_t index = 0; index < mTracks.size(); index++) {
126 TrackInfo *info = &mTracks.editItemAt(index);
127 sp<AnotherPacketSource> source = info->mSource;
128
129 // Check if EOS or ERROR is received
130 if (source != NULL && source->isFinished(mediaDurationUs)) {
131 return;
132 }
133 }
134 mHandler->pause();
135}
136
137void NuPlayer::RTSPSource::resume() {
138 mHandler->resume();
139}
140
Andreas Huber2bfdd422011-10-11 15:24:07 -0700141status_t NuPlayer::RTSPSource::feedMoreTSData() {
142 return mFinalResult;
143}
144
Andreas Huber84066782011-08-16 09:34:26 -0700145sp<MetaData> NuPlayer::RTSPSource::getFormatMeta(bool audio) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700146 sp<AnotherPacketSource> source = getSource(audio);
147
148 if (source == NULL) {
149 return NULL;
150 }
151
152 return source->getFormat();
153}
154
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700155bool NuPlayer::RTSPSource::haveSufficientDataOnAllTracks() {
156 // We're going to buffer at least 2 secs worth data on all tracks before
157 // starting playback (both at startup and after a seek).
158
159 static const int64_t kMinDurationUs = 2000000ll;
160
Roger Jönssonb50e83e2013-01-21 16:26:41 +0100161 int64_t mediaDurationUs = 0;
162 getDuration(&mediaDurationUs);
163 if ((mAudioTrack != NULL && mAudioTrack->isFinished(mediaDurationUs))
164 || (mVideoTrack != NULL && mVideoTrack->isFinished(mediaDurationUs))) {
165 return true;
166 }
167
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700168 status_t err;
169 int64_t durationUs;
170 if (mAudioTrack != NULL
171 && (durationUs = mAudioTrack->getBufferedDurationUs(&err))
172 < kMinDurationUs
173 && err == OK) {
174 ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
175 durationUs / 1E6);
176 return false;
177 }
178
179 if (mVideoTrack != NULL
180 && (durationUs = mVideoTrack->getBufferedDurationUs(&err))
181 < kMinDurationUs
182 && err == OK) {
183 ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
184 durationUs / 1E6);
185 return false;
186 }
187
188 return true;
189}
190
Andreas Huber2bfdd422011-10-11 15:24:07 -0700191status_t NuPlayer::RTSPSource::dequeueAccessUnit(
192 bool audio, sp<ABuffer> *accessUnit) {
Roger Jönssonb50e83e2013-01-21 16:26:41 +0100193 if (mBuffering) {
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700194 if (!haveSufficientDataOnAllTracks()) {
195 return -EWOULDBLOCK;
196 }
197
Roger Jönssonb50e83e2013-01-21 16:26:41 +0100198 mBuffering = false;
199
200 sp<AMessage> notify = dupNotify();
201 notify->setInt32("what", kWhatBufferingEnd);
202 notify->post();
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700203 }
204
Andreas Huber2bfdd422011-10-11 15:24:07 -0700205 sp<AnotherPacketSource> source = getSource(audio);
206
207 if (source == NULL) {
208 return -EWOULDBLOCK;
209 }
210
211 status_t finalResult;
212 if (!source->hasBufferAvailable(&finalResult)) {
Roger Jönssonb50e83e2013-01-21 16:26:41 +0100213 if (finalResult == OK) {
214 int64_t mediaDurationUs = 0;
215 getDuration(&mediaDurationUs);
216 sp<AnotherPacketSource> otherSource = getSource(!audio);
217 status_t otherFinalResult;
218
219 // If other source already signaled EOS, this source should also signal EOS
220 if (otherSource != NULL &&
221 !otherSource->hasBufferAvailable(&otherFinalResult) &&
222 otherFinalResult == ERROR_END_OF_STREAM) {
223 source->signalEOS(ERROR_END_OF_STREAM);
224 return ERROR_END_OF_STREAM;
225 }
226
227 // If this source has detected near end, give it some time to retrieve more
228 // data before signaling EOS
229 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);
235 source->signalEOS(ERROR_END_OF_STREAM);
236 return ERROR_END_OF_STREAM;
237 }
238 return -EWOULDBLOCK;
239 }
240
241 if (!(otherSource != NULL && otherSource->isFinished(mediaDurationUs))) {
242 // We should not enter buffering mode
243 // if any of the sources already have detected EOS.
244 mBuffering = true;
245
246 sp<AMessage> notify = dupNotify();
247 notify->setInt32("what", kWhatBufferingStart);
248 notify->post();
249 }
250
251 return -EWOULDBLOCK;
252 }
253 return finalResult;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700254 }
255
Roger Jönssonb50e83e2013-01-21 16:26:41 +0100256 setEOSTimeout(audio, 0);
257
Andreas Huber2bfdd422011-10-11 15:24:07 -0700258 return source->dequeueAccessUnit(accessUnit);
259}
260
261sp<AnotherPacketSource> NuPlayer::RTSPSource::getSource(bool audio) {
Andreas Hubercfaeeec2012-08-31 10:27:46 -0700262 if (mTSParser != NULL) {
263 sp<MediaSource> source = mTSParser->getSource(
264 audio ? ATSParser::AUDIO : ATSParser::VIDEO);
265
266 return static_cast<AnotherPacketSource *>(source.get());
267 }
268
Andreas Huber2bfdd422011-10-11 15:24:07 -0700269 return audio ? mAudioTrack : mVideoTrack;
270}
271
Roger Jönssonb50e83e2013-01-21 16:26:41 +0100272void NuPlayer::RTSPSource::setEOSTimeout(bool audio, int64_t timeout) {
273 if (audio) {
274 mEOSTimeoutAudio = timeout;
275 } else {
276 mEOSTimeoutVideo = timeout;
277 }
278}
279
Andreas Huber2bfdd422011-10-11 15:24:07 -0700280status_t NuPlayer::RTSPSource::getDuration(int64_t *durationUs) {
281 *durationUs = 0ll;
282
283 int64_t audioDurationUs;
284 if (mAudioTrack != NULL
285 && mAudioTrack->getFormat()->findInt64(
286 kKeyDuration, &audioDurationUs)
287 && audioDurationUs > *durationUs) {
288 *durationUs = audioDurationUs;
289 }
290
291 int64_t videoDurationUs;
292 if (mVideoTrack != NULL
293 && mVideoTrack->getFormat()->findInt64(
294 kKeyDuration, &videoDurationUs)
295 && videoDurationUs > *durationUs) {
296 *durationUs = videoDurationUs;
297 }
298
299 return OK;
300}
301
302status_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs) {
Andreas Huberee736e92011-12-08 13:04:50 -0800303 sp<AMessage> msg = new AMessage(kWhatPerformSeek, mReflector->id());
304 msg->setInt32("generation", ++mSeekGeneration);
305 msg->setInt64("timeUs", seekTimeUs);
306 msg->post(200000ll);
307
308 return OK;
309}
310
311void NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700312 if (mState != CONNECTED) {
Andreas Huberee736e92011-12-08 13:04:50 -0800313 return;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700314 }
315
316 mState = SEEKING;
317 mHandler->seek(seekTimeUs);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700318}
319
Andreas Huber2bfdd422011-10-11 15:24:07 -0700320void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
321 if (msg->what() == kWhatDisconnect) {
322 uint32_t replyID;
323 CHECK(msg->senderAwaitsResponse(&replyID));
324
325 mDisconnectReplyID = replyID;
326 finishDisconnectIfPossible();
327 return;
Andreas Huberee736e92011-12-08 13:04:50 -0800328 } else if (msg->what() == kWhatPerformSeek) {
329 int32_t generation;
330 CHECK(msg->findInt32("generation", &generation));
331
332 if (generation != mSeekGeneration) {
333 // obsolete.
334 return;
335 }
336
337 int64_t seekTimeUs;
338 CHECK(msg->findInt64("timeUs", &seekTimeUs));
339
340 performSeek(seekTimeUs);
341 return;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700342 }
343
344 CHECK_EQ(msg->what(), (int)kWhatNotify);
345
346 int32_t what;
347 CHECK(msg->findInt32("what", &what));
348
349 switch (what) {
350 case MyHandler::kWhatConnected:
Andreas Huberec0c5972013-02-05 14:47:13 -0800351 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700352 onConnected();
Andreas Huberec0c5972013-02-05 14:47:13 -0800353
354 notifyVideoSizeChanged(0, 0);
355
356 uint32_t flags = 0;
357
358 if (mHandler->isSeekable()) {
359 flags = FLAG_CAN_PAUSE | FLAG_CAN_SEEK;
360
361 // Seeking 10secs forward or backward is a very expensive
362 // operation for rtsp, so let's not enable that.
363 // The user can always use the seek bar.
364 }
365
366 notifyFlagsChanged(flags);
367 notifyPrepared();
Andreas Huber2bfdd422011-10-11 15:24:07 -0700368 break;
Andreas Huberec0c5972013-02-05 14:47:13 -0800369 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700370
371 case MyHandler::kWhatDisconnected:
Andreas Huberec0c5972013-02-05 14:47:13 -0800372 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700373 onDisconnected(msg);
374 break;
Andreas Huberec0c5972013-02-05 14:47:13 -0800375 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700376
377 case MyHandler::kWhatSeekDone:
378 {
379 mState = CONNECTED;
380 break;
381 }
382
383 case MyHandler::kWhatAccessUnit:
384 {
385 size_t trackIndex;
386 CHECK(msg->findSize("trackIndex", &trackIndex));
Andreas Hubercfaeeec2012-08-31 10:27:46 -0700387
388 if (mTSParser == NULL) {
389 CHECK_LT(trackIndex, mTracks.size());
390 } else {
391 CHECK_EQ(trackIndex, 0u);
392 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700393
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800394 sp<ABuffer> accessUnit;
395 CHECK(msg->findBuffer("accessUnit", &accessUnit));
Andreas Huber2bfdd422011-10-11 15:24:07 -0700396
397 int32_t damaged;
398 if (accessUnit->meta()->findInt32("damaged", &damaged)
399 && damaged) {
Steve Blockdf64d152012-01-04 20:05:49 +0000400 ALOGI("dropping damaged access unit.");
Andreas Huber2bfdd422011-10-11 15:24:07 -0700401 break;
402 }
403
Andreas Hubercfaeeec2012-08-31 10:27:46 -0700404 if (mTSParser != NULL) {
405 size_t offset = 0;
406 status_t err = OK;
407 while (offset + 188 <= accessUnit->size()) {
408 err = mTSParser->feedTSPacket(
409 accessUnit->data() + offset, 188);
410 if (err != OK) {
411 break;
412 }
413
414 offset += 188;
415 }
416
417 if (offset < accessUnit->size()) {
418 err = ERROR_MALFORMED;
419 }
420
421 if (err != OK) {
422 sp<AnotherPacketSource> source = getSource(false /* audio */);
423 if (source != NULL) {
424 source->signalEOS(err);
425 }
426
427 source = getSource(true /* audio */);
428 if (source != NULL) {
429 source->signalEOS(err);
430 }
431 }
432 break;
433 }
434
Andreas Huber1906e5c2011-12-08 12:27:47 -0800435 TrackInfo *info = &mTracks.editItemAt(trackIndex);
436
437 sp<AnotherPacketSource> source = info->mSource;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700438 if (source != NULL) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700439 uint32_t rtpTime;
440 CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
441
Andreas Huber1906e5c2011-12-08 12:27:47 -0800442 if (!info->mNPTMappingValid) {
443 // This is a live stream, we didn't receive any normal
Andreas Huberc9d16962012-05-21 11:12:40 -0700444 // playtime mapping. We won't map to npt time.
445 source->queueAccessUnit(accessUnit);
446 break;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800447 }
448
Andreas Huber2bfdd422011-10-11 15:24:07 -0700449 int64_t nptUs =
Andreas Huber1906e5c2011-12-08 12:27:47 -0800450 ((double)rtpTime - (double)info->mRTPTime)
451 / info->mTimeScale
Andreas Huber2bfdd422011-10-11 15:24:07 -0700452 * 1000000ll
Andreas Huber1906e5c2011-12-08 12:27:47 -0800453 + info->mNormalPlaytimeUs;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700454
455 accessUnit->meta()->setInt64("timeUs", nptUs);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700456
457 source->queueAccessUnit(accessUnit);
458 }
459 break;
460 }
461
462 case MyHandler::kWhatEOS:
463 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700464 int32_t finalResult;
465 CHECK(msg->findInt32("finalResult", &finalResult));
466 CHECK_NE(finalResult, (status_t)OK);
467
Andreas Hubercfaeeec2012-08-31 10:27:46 -0700468 if (mTSParser != NULL) {
469 sp<AnotherPacketSource> source = getSource(false /* audio */);
470 if (source != NULL) {
471 source->signalEOS(finalResult);
472 }
473
474 source = getSource(true /* audio */);
475 if (source != NULL) {
476 source->signalEOS(finalResult);
477 }
478
479 return;
480 }
481
482 size_t trackIndex;
483 CHECK(msg->findSize("trackIndex", &trackIndex));
484 CHECK_LT(trackIndex, mTracks.size());
485
Andreas Huber2bfdd422011-10-11 15:24:07 -0700486 TrackInfo *info = &mTracks.editItemAt(trackIndex);
487 sp<AnotherPacketSource> source = info->mSource;
488 if (source != NULL) {
489 source->signalEOS(finalResult);
490 }
491
492 break;
493 }
494
495 case MyHandler::kWhatSeekDiscontinuity:
496 {
497 size_t trackIndex;
498 CHECK(msg->findSize("trackIndex", &trackIndex));
499 CHECK_LT(trackIndex, mTracks.size());
500
501 TrackInfo *info = &mTracks.editItemAt(trackIndex);
502 sp<AnotherPacketSource> source = info->mSource;
503 if (source != NULL) {
504 source->queueDiscontinuity(ATSParser::DISCONTINUITY_SEEK, NULL);
505 }
506
507 break;
508 }
509
510 case MyHandler::kWhatNormalPlayTimeMapping:
511 {
512 size_t trackIndex;
513 CHECK(msg->findSize("trackIndex", &trackIndex));
514 CHECK_LT(trackIndex, mTracks.size());
515
516 uint32_t rtpTime;
517 CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime));
518
519 int64_t nptUs;
520 CHECK(msg->findInt64("nptUs", &nptUs));
521
522 TrackInfo *info = &mTracks.editItemAt(trackIndex);
523 info->mRTPTime = rtpTime;
524 info->mNormalPlaytimeUs = nptUs;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800525 info->mNPTMappingValid = true;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700526 break;
527 }
528
Oscar Rydhé7a33b772012-02-20 10:15:48 +0100529 case SDPLoader::kWhatSDPLoaded:
530 {
531 onSDPLoaded(msg);
532 break;
533 }
534
Andreas Huber2bfdd422011-10-11 15:24:07 -0700535 default:
536 TRESPASS();
537 }
538}
539
540void NuPlayer::RTSPSource::onConnected() {
541 CHECK(mAudioTrack == NULL);
542 CHECK(mVideoTrack == NULL);
543
544 size_t numTracks = mHandler->countTracks();
545 for (size_t i = 0; i < numTracks; ++i) {
546 int32_t timeScale;
547 sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale);
548
549 const char *mime;
550 CHECK(format->findCString(kKeyMIMEType, &mime));
551
Andreas Hubercfaeeec2012-08-31 10:27:46 -0700552 if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
553 // Very special case for MPEG2 Transport Streams.
554 CHECK_EQ(numTracks, 1u);
555
556 mTSParser = new ATSParser;
557 return;
558 }
559
Andreas Huber2bfdd422011-10-11 15:24:07 -0700560 bool isAudio = !strncasecmp(mime, "audio/", 6);
561 bool isVideo = !strncasecmp(mime, "video/", 6);
562
563 TrackInfo info;
564 info.mTimeScale = timeScale;
565 info.mRTPTime = 0;
566 info.mNormalPlaytimeUs = 0ll;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800567 info.mNPTMappingValid = false;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700568
569 if ((isAudio && mAudioTrack == NULL)
570 || (isVideo && mVideoTrack == NULL)) {
571 sp<AnotherPacketSource> source = new AnotherPacketSource(format);
572
573 if (isAudio) {
574 mAudioTrack = source;
575 } else {
576 mVideoTrack = source;
577 }
578
579 info.mSource = source;
580 }
581
582 mTracks.push(info);
583 }
584
585 mState = CONNECTED;
586}
587
Oscar Rydhé7a33b772012-02-20 10:15:48 +0100588void NuPlayer::RTSPSource::onSDPLoaded(const sp<AMessage> &msg) {
589 status_t err;
590 CHECK(msg->findInt32("result", &err));
591
592 mSDPLoader.clear();
593
594 if (mDisconnectReplyID != 0) {
595 err = UNKNOWN_ERROR;
596 }
597
598 if (err == OK) {
599 sp<ASessionDescription> desc;
600 sp<RefBase> obj;
601 CHECK(msg->findObject("description", &obj));
602 desc = static_cast<ASessionDescription *>(obj.get());
603
604 AString rtspUri;
605 if (!desc->findAttribute(0, "a=control", &rtspUri)) {
606 ALOGE("Unable to find url in SDP");
607 err = UNKNOWN_ERROR;
608 } else {
609 sp<AMessage> notify = new AMessage(kWhatNotify, mReflector->id());
610
611 mHandler = new MyHandler(rtspUri.c_str(), notify, mUIDValid, mUID);
612 mLooper->registerHandler(mHandler);
613
614 mHandler->loadSDP(desc);
615 }
616 }
617
618 if (err != OK) {
Andreas Huberec0c5972013-02-05 14:47:13 -0800619 if (mState == CONNECTING) {
620 // We're still in the preparation phase, signal that it
621 // failed.
622 notifyPrepared(err);
623 }
624
Oscar Rydhé7a33b772012-02-20 10:15:48 +0100625 mState = DISCONNECTED;
626 mFinalResult = err;
627
628 if (mDisconnectReplyID != 0) {
629 finishDisconnectIfPossible();
630 }
631 }
632}
633
Andreas Huber2bfdd422011-10-11 15:24:07 -0700634void NuPlayer::RTSPSource::onDisconnected(const sp<AMessage> &msg) {
635 status_t err;
636 CHECK(msg->findInt32("result", &err));
637 CHECK_NE(err, (status_t)OK);
638
639 mLooper->unregisterHandler(mHandler->id());
640 mHandler.clear();
641
Andreas Huberec0c5972013-02-05 14:47:13 -0800642 if (mState == CONNECTING) {
643 // We're still in the preparation phase, signal that it
644 // failed.
645 notifyPrepared(err);
646 }
647
Andreas Huber2bfdd422011-10-11 15:24:07 -0700648 mState = DISCONNECTED;
649 mFinalResult = err;
650
651 if (mDisconnectReplyID != 0) {
652 finishDisconnectIfPossible();
653 }
654}
655
656void NuPlayer::RTSPSource::finishDisconnectIfPossible() {
657 if (mState != DISCONNECTED) {
Oscar Rydhé7a33b772012-02-20 10:15:48 +0100658 if (mHandler != NULL) {
659 mHandler->disconnect();
660 } else if (mSDPLoader != NULL) {
661 mSDPLoader->cancel();
662 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700663 return;
664 }
665
666 (new AMessage)->postReply(mDisconnectReplyID);
667 mDisconnectReplyID = 0;
668}
669
670} // namespace android