blob: 0282a9fbc8cd4a0da45fba28cef26863bcf1f0a6 [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
Andreas Huber2bfdd422011-10-11 15:24:07 -070035NuPlayer::RTSPSource::RTSPSource(
Andreas Huber5ab368a2013-02-05 10:14:26 -080036 const sp<AMessage> &notify,
Andreas Huber1b86fe02014-01-29 11:13:26 -080037 const sp<IMediaHTTPService> &httpService,
Andreas Huber2bfdd422011-10-11 15:24:07 -070038 const char *url,
39 const KeyedVector<String8, String8> *headers,
40 bool uidValid,
Oscar Rydhé81dd60e2012-02-20 10:15:48 +010041 uid_t uid,
42 bool isSDP)
Andreas Huber5ab368a2013-02-05 10:14:26 -080043 : Source(notify),
Andreas Huber1b86fe02014-01-29 11:13:26 -080044 mHTTPService(httpService),
Andreas Huber5ab368a2013-02-05 10:14:26 -080045 mURL(url),
Andreas Huber2bfdd422011-10-11 15:24:07 -070046 mUIDValid(uidValid),
47 mUID(uid),
48 mFlags(0),
Oscar Rydhé81dd60e2012-02-20 10:15:48 +010049 mIsSDP(isSDP),
Andreas Huber2bfdd422011-10-11 15:24:07 -070050 mState(DISCONNECTED),
51 mFinalResult(OK),
Andreas Huberee736e92011-12-08 13:04:50 -080052 mDisconnectReplyID(0),
Chong Zhang180d1b92014-12-02 18:35:35 -080053 mBuffering(false),
Roger Jönssoncfc30832013-01-21 16:26:41 +010054 mSeekGeneration(0),
55 mEOSTimeoutAudio(0),
56 mEOSTimeoutVideo(0) {
Andreas Huber2bfdd422011-10-11 15:24:07 -070057 if (headers) {
58 mExtraHeaders = *headers;
59
60 ssize_t index =
61 mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
62
63 if (index >= 0) {
64 mFlags |= kFlagIncognito;
65
66 mExtraHeaders.removeItemsAt(index);
67 }
68 }
69}
70
71NuPlayer::RTSPSource::~RTSPSource() {
Andreas Huber602f5bb2013-04-15 16:18:56 -070072 if (mLooper != NULL) {
Chong Zhang1228d6b2014-08-12 21:25:48 -070073 mLooper->unregisterHandler(id());
Andreas Huber602f5bb2013-04-15 16:18:56 -070074 mLooper->stop();
75 }
Andreas Huber2bfdd422011-10-11 15:24:07 -070076}
77
Andreas Huber57cea552013-02-05 13:59:56 -080078void NuPlayer::RTSPSource::prepareAsync() {
Andreas Huber2bfdd422011-10-11 15:24:07 -070079 if (mLooper == NULL) {
80 mLooper = new ALooper;
81 mLooper->setName("rtsp");
82 mLooper->start();
83
Chong Zhang1228d6b2014-08-12 21:25:48 -070084 mLooper->registerHandler(this);
Andreas Huber2bfdd422011-10-11 15:24:07 -070085 }
86
87 CHECK(mHandler == NULL);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +010088 CHECK(mSDPLoader == NULL);
Andreas Huber2bfdd422011-10-11 15:24:07 -070089
Chong Zhang1228d6b2014-08-12 21:25:48 -070090 sp<AMessage> notify = new AMessage(kWhatNotify, id());
Andreas Huber2bfdd422011-10-11 15:24:07 -070091
Andreas Huber2bfdd422011-10-11 15:24:07 -070092 CHECK_EQ(mState, (int)DISCONNECTED);
93 mState = CONNECTING;
94
Oscar Rydhé81dd60e2012-02-20 10:15:48 +010095 if (mIsSDP) {
96 mSDPLoader = new SDPLoader(notify,
97 (mFlags & kFlagIncognito) ? SDPLoader::kFlagIncognito : 0,
Andreas Huber81e68442014-02-05 11:52:33 -080098 mHTTPService);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +010099
Andreas Huber57cea552013-02-05 13:59:56 -0800100 mSDPLoader->load(
101 mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100102 } else {
103 mHandler = new MyHandler(mURL.c_str(), notify, mUIDValid, mUID);
104 mLooper->registerHandler(mHandler);
105
106 mHandler->connect();
107 }
Roger Jönssoncfc30832013-01-21 16:26:41 +0100108
Chong Zhang180d1b92014-12-02 18:35:35 -0800109 startBufferingIfNecessary();
Andreas Huber57cea552013-02-05 13:59:56 -0800110}
111
112void NuPlayer::RTSPSource::start() {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700113}
114
115void NuPlayer::RTSPSource::stop() {
James Dong58341812012-11-16 14:31:15 -0800116 if (mLooper == NULL) {
117 return;
118 }
Chong Zhang1228d6b2014-08-12 21:25:48 -0700119 sp<AMessage> msg = new AMessage(kWhatDisconnect, id());
Andreas Huber2bfdd422011-10-11 15:24:07 -0700120
121 sp<AMessage> dummy;
122 msg->postAndAwaitResponse(&dummy);
123}
124
Roger Jönsson46d13e32013-01-21 17:15:45 +0100125void NuPlayer::RTSPSource::pause() {
126 int64_t mediaDurationUs = 0;
127 getDuration(&mediaDurationUs);
128 for (size_t index = 0; index < mTracks.size(); index++) {
129 TrackInfo *info = &mTracks.editItemAt(index);
130 sp<AnotherPacketSource> source = info->mSource;
131
132 // Check if EOS or ERROR is received
133 if (source != NULL && source->isFinished(mediaDurationUs)) {
134 return;
135 }
136 }
137 mHandler->pause();
138}
139
140void NuPlayer::RTSPSource::resume() {
141 mHandler->resume();
142}
143
Andreas Huber2bfdd422011-10-11 15:24:07 -0700144status_t NuPlayer::RTSPSource::feedMoreTSData() {
Chong Zhang180d1b92014-12-02 18:35:35 -0800145 Mutex::Autolock _l(mBufferingLock);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700146 return mFinalResult;
147}
148
Andreas Huber84066782011-08-16 09:34:26 -0700149sp<MetaData> NuPlayer::RTSPSource::getFormatMeta(bool audio) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700150 sp<AnotherPacketSource> source = getSource(audio);
151
152 if (source == NULL) {
153 return NULL;
154 }
155
156 return source->getFormat();
157}
158
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700159bool NuPlayer::RTSPSource::haveSufficientDataOnAllTracks() {
160 // We're going to buffer at least 2 secs worth data on all tracks before
161 // starting playback (both at startup and after a seek).
162
163 static const int64_t kMinDurationUs = 2000000ll;
164
Roger Jönssoncfc30832013-01-21 16:26:41 +0100165 int64_t mediaDurationUs = 0;
166 getDuration(&mediaDurationUs);
167 if ((mAudioTrack != NULL && mAudioTrack->isFinished(mediaDurationUs))
168 || (mVideoTrack != NULL && mVideoTrack->isFinished(mediaDurationUs))) {
169 return true;
170 }
171
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700172 status_t err;
173 int64_t durationUs;
174 if (mAudioTrack != NULL
175 && (durationUs = mAudioTrack->getBufferedDurationUs(&err))
176 < kMinDurationUs
177 && err == OK) {
178 ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
179 durationUs / 1E6);
180 return false;
181 }
182
183 if (mVideoTrack != NULL
184 && (durationUs = mVideoTrack->getBufferedDurationUs(&err))
185 < kMinDurationUs
186 && err == OK) {
187 ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
188 durationUs / 1E6);
189 return false;
190 }
191
192 return true;
193}
194
Andreas Huber2bfdd422011-10-11 15:24:07 -0700195status_t NuPlayer::RTSPSource::dequeueAccessUnit(
196 bool audio, sp<ABuffer> *accessUnit) {
Chong Zhang180d1b92014-12-02 18:35:35 -0800197 if (!stopBufferingIfNecessary()) {
198 return -EWOULDBLOCK;
Andreas Huberbfd4d0d2012-05-17 14:18:50 -0700199 }
200
Andreas Huber2bfdd422011-10-11 15:24:07 -0700201 sp<AnotherPacketSource> source = getSource(audio);
202
203 if (source == NULL) {
204 return -EWOULDBLOCK;
205 }
206
207 status_t finalResult;
208 if (!source->hasBufferAvailable(&finalResult)) {
Roger Jönssoncfc30832013-01-21 16:26:41 +0100209 if (finalResult == OK) {
210 int64_t mediaDurationUs = 0;
211 getDuration(&mediaDurationUs);
212 sp<AnotherPacketSource> otherSource = getSource(!audio);
213 status_t otherFinalResult;
214
215 // If other source already signaled EOS, this source should also signal EOS
216 if (otherSource != NULL &&
217 !otherSource->hasBufferAvailable(&otherFinalResult) &&
218 otherFinalResult == ERROR_END_OF_STREAM) {
219 source->signalEOS(ERROR_END_OF_STREAM);
220 return ERROR_END_OF_STREAM;
221 }
222
223 // If this source has detected near end, give it some time to retrieve more
224 // data before signaling EOS
225 if (source->isFinished(mediaDurationUs)) {
226 int64_t eosTimeout = audio ? mEOSTimeoutAudio : mEOSTimeoutVideo;
227 if (eosTimeout == 0) {
228 setEOSTimeout(audio, ALooper::GetNowUs());
229 } else if ((ALooper::GetNowUs() - eosTimeout) > kNearEOSTimeoutUs) {
230 setEOSTimeout(audio, 0);
231 source->signalEOS(ERROR_END_OF_STREAM);
232 return ERROR_END_OF_STREAM;
233 }
234 return -EWOULDBLOCK;
235 }
236
237 if (!(otherSource != NULL && otherSource->isFinished(mediaDurationUs))) {
238 // We should not enter buffering mode
239 // if any of the sources already have detected EOS.
Chong Zhang180d1b92014-12-02 18:35:35 -0800240 startBufferingIfNecessary();
Roger Jönssoncfc30832013-01-21 16:26:41 +0100241 }
242
243 return -EWOULDBLOCK;
244 }
245 return finalResult;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700246 }
247
Roger Jönssoncfc30832013-01-21 16:26:41 +0100248 setEOSTimeout(audio, 0);
249
Andreas Huber2bfdd422011-10-11 15:24:07 -0700250 return source->dequeueAccessUnit(accessUnit);
251}
252
253sp<AnotherPacketSource> NuPlayer::RTSPSource::getSource(bool audio) {
Andreas Huber49694682012-08-31 10:27:46 -0700254 if (mTSParser != NULL) {
255 sp<MediaSource> source = mTSParser->getSource(
256 audio ? ATSParser::AUDIO : ATSParser::VIDEO);
257
258 return static_cast<AnotherPacketSource *>(source.get());
259 }
260
Andreas Huber2bfdd422011-10-11 15:24:07 -0700261 return audio ? mAudioTrack : mVideoTrack;
262}
263
Roger Jönssoncfc30832013-01-21 16:26:41 +0100264void NuPlayer::RTSPSource::setEOSTimeout(bool audio, int64_t timeout) {
265 if (audio) {
266 mEOSTimeoutAudio = timeout;
267 } else {
268 mEOSTimeoutVideo = timeout;
269 }
270}
271
Andreas Huber2bfdd422011-10-11 15:24:07 -0700272status_t NuPlayer::RTSPSource::getDuration(int64_t *durationUs) {
273 *durationUs = 0ll;
274
275 int64_t audioDurationUs;
276 if (mAudioTrack != NULL
277 && mAudioTrack->getFormat()->findInt64(
278 kKeyDuration, &audioDurationUs)
279 && audioDurationUs > *durationUs) {
280 *durationUs = audioDurationUs;
281 }
282
283 int64_t videoDurationUs;
284 if (mVideoTrack != NULL
285 && mVideoTrack->getFormat()->findInt64(
286 kKeyDuration, &videoDurationUs)
287 && videoDurationUs > *durationUs) {
288 *durationUs = videoDurationUs;
289 }
290
291 return OK;
292}
293
294status_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs) {
Chong Zhang1228d6b2014-08-12 21:25:48 -0700295 sp<AMessage> msg = new AMessage(kWhatPerformSeek, id());
Andreas Huberee736e92011-12-08 13:04:50 -0800296 msg->setInt32("generation", ++mSeekGeneration);
297 msg->setInt64("timeUs", seekTimeUs);
298 msg->post(200000ll);
299
300 return OK;
301}
302
303void NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700304 if (mState != CONNECTED) {
Andreas Huberee736e92011-12-08 13:04:50 -0800305 return;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700306 }
307
308 mState = SEEKING;
309 mHandler->seek(seekTimeUs);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700310}
311
Andreas Huber2bfdd422011-10-11 15:24:07 -0700312void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
313 if (msg->what() == kWhatDisconnect) {
314 uint32_t replyID;
315 CHECK(msg->senderAwaitsResponse(&replyID));
316
317 mDisconnectReplyID = replyID;
318 finishDisconnectIfPossible();
319 return;
Andreas Huberee736e92011-12-08 13:04:50 -0800320 } else if (msg->what() == kWhatPerformSeek) {
321 int32_t generation;
322 CHECK(msg->findInt32("generation", &generation));
323
324 if (generation != mSeekGeneration) {
325 // obsolete.
326 return;
327 }
328
329 int64_t seekTimeUs;
330 CHECK(msg->findInt64("timeUs", &seekTimeUs));
331
332 performSeek(seekTimeUs);
333 return;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700334 }
335
336 CHECK_EQ(msg->what(), (int)kWhatNotify);
337
338 int32_t what;
339 CHECK(msg->findInt32("what", &what));
340
341 switch (what) {
342 case MyHandler::kWhatConnected:
Andreas Huber7f475c32013-02-05 14:47:13 -0800343 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700344 onConnected();
Andreas Huber7f475c32013-02-05 14:47:13 -0800345
Chong Zhangced1c2f2014-08-08 15:22:35 -0700346 notifyVideoSizeChanged();
Andreas Huber7f475c32013-02-05 14:47:13 -0800347
348 uint32_t flags = 0;
349
350 if (mHandler->isSeekable()) {
Chong Zhang4b7069d2013-09-11 12:52:43 -0700351 flags = FLAG_CAN_PAUSE
352 | FLAG_CAN_SEEK
353 | FLAG_CAN_SEEK_BACKWARD
354 | FLAG_CAN_SEEK_FORWARD;
Andreas Huber7f475c32013-02-05 14:47:13 -0800355 }
356
357 notifyFlagsChanged(flags);
358 notifyPrepared();
Andreas Huber2bfdd422011-10-11 15:24:07 -0700359 break;
Andreas Huber7f475c32013-02-05 14:47:13 -0800360 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700361
362 case MyHandler::kWhatDisconnected:
Andreas Huber7f475c32013-02-05 14:47:13 -0800363 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700364 onDisconnected(msg);
365 break;
Andreas Huber7f475c32013-02-05 14:47:13 -0800366 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700367
368 case MyHandler::kWhatSeekDone:
369 {
370 mState = CONNECTED;
371 break;
372 }
373
374 case MyHandler::kWhatAccessUnit:
375 {
376 size_t trackIndex;
377 CHECK(msg->findSize("trackIndex", &trackIndex));
Andreas Huber49694682012-08-31 10:27:46 -0700378
379 if (mTSParser == NULL) {
380 CHECK_LT(trackIndex, mTracks.size());
381 } else {
382 CHECK_EQ(trackIndex, 0u);
383 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700384
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800385 sp<ABuffer> accessUnit;
386 CHECK(msg->findBuffer("accessUnit", &accessUnit));
Andreas Huber2bfdd422011-10-11 15:24:07 -0700387
388 int32_t damaged;
389 if (accessUnit->meta()->findInt32("damaged", &damaged)
390 && damaged) {
Steve Blockdf64d152012-01-04 20:05:49 +0000391 ALOGI("dropping damaged access unit.");
Andreas Huber2bfdd422011-10-11 15:24:07 -0700392 break;
393 }
394
Andreas Huber49694682012-08-31 10:27:46 -0700395 if (mTSParser != NULL) {
396 size_t offset = 0;
397 status_t err = OK;
398 while (offset + 188 <= accessUnit->size()) {
399 err = mTSParser->feedTSPacket(
400 accessUnit->data() + offset, 188);
401 if (err != OK) {
402 break;
403 }
404
405 offset += 188;
406 }
407
408 if (offset < accessUnit->size()) {
409 err = ERROR_MALFORMED;
410 }
411
412 if (err != OK) {
413 sp<AnotherPacketSource> source = getSource(false /* audio */);
414 if (source != NULL) {
415 source->signalEOS(err);
416 }
417
418 source = getSource(true /* audio */);
419 if (source != NULL) {
420 source->signalEOS(err);
421 }
422 }
423 break;
424 }
425
Andreas Huber1906e5c2011-12-08 12:27:47 -0800426 TrackInfo *info = &mTracks.editItemAt(trackIndex);
427
428 sp<AnotherPacketSource> source = info->mSource;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700429 if (source != NULL) {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700430 uint32_t rtpTime;
431 CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
432
Andreas Huber1906e5c2011-12-08 12:27:47 -0800433 if (!info->mNPTMappingValid) {
434 // This is a live stream, we didn't receive any normal
Andreas Huberc9d16962012-05-21 11:12:40 -0700435 // playtime mapping. We won't map to npt time.
436 source->queueAccessUnit(accessUnit);
437 break;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800438 }
439
Andreas Huber2bfdd422011-10-11 15:24:07 -0700440 int64_t nptUs =
Andreas Huber1906e5c2011-12-08 12:27:47 -0800441 ((double)rtpTime - (double)info->mRTPTime)
442 / info->mTimeScale
Andreas Huber2bfdd422011-10-11 15:24:07 -0700443 * 1000000ll
Andreas Huber1906e5c2011-12-08 12:27:47 -0800444 + info->mNormalPlaytimeUs;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700445
446 accessUnit->meta()->setInt64("timeUs", nptUs);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700447
448 source->queueAccessUnit(accessUnit);
449 }
450 break;
451 }
452
453 case MyHandler::kWhatEOS:
454 {
Andreas Huber2bfdd422011-10-11 15:24:07 -0700455 int32_t finalResult;
456 CHECK(msg->findInt32("finalResult", &finalResult));
457 CHECK_NE(finalResult, (status_t)OK);
458
Andreas Huber49694682012-08-31 10:27:46 -0700459 if (mTSParser != NULL) {
460 sp<AnotherPacketSource> source = getSource(false /* audio */);
461 if (source != NULL) {
462 source->signalEOS(finalResult);
463 }
464
465 source = getSource(true /* audio */);
466 if (source != NULL) {
467 source->signalEOS(finalResult);
468 }
469
470 return;
471 }
472
473 size_t trackIndex;
474 CHECK(msg->findSize("trackIndex", &trackIndex));
475 CHECK_LT(trackIndex, mTracks.size());
476
Andreas Huber2bfdd422011-10-11 15:24:07 -0700477 TrackInfo *info = &mTracks.editItemAt(trackIndex);
478 sp<AnotherPacketSource> source = info->mSource;
479 if (source != NULL) {
480 source->signalEOS(finalResult);
481 }
482
483 break;
484 }
485
486 case MyHandler::kWhatSeekDiscontinuity:
487 {
488 size_t trackIndex;
489 CHECK(msg->findSize("trackIndex", &trackIndex));
490 CHECK_LT(trackIndex, mTracks.size());
491
492 TrackInfo *info = &mTracks.editItemAt(trackIndex);
493 sp<AnotherPacketSource> source = info->mSource;
494 if (source != NULL) {
Chong Zhang632740c2014-06-26 13:03:47 -0700495 source->queueDiscontinuity(
Wei Jiafef808d2014-10-31 17:57:05 -0700496 ATSParser::DISCONTINUITY_TIME,
Chong Zhang632740c2014-06-26 13:03:47 -0700497 NULL,
498 true /* discard */);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700499 }
500
501 break;
502 }
503
504 case MyHandler::kWhatNormalPlayTimeMapping:
505 {
506 size_t trackIndex;
507 CHECK(msg->findSize("trackIndex", &trackIndex));
508 CHECK_LT(trackIndex, mTracks.size());
509
510 uint32_t rtpTime;
511 CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime));
512
513 int64_t nptUs;
514 CHECK(msg->findInt64("nptUs", &nptUs));
515
516 TrackInfo *info = &mTracks.editItemAt(trackIndex);
517 info->mRTPTime = rtpTime;
518 info->mNormalPlaytimeUs = nptUs;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800519 info->mNPTMappingValid = true;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700520 break;
521 }
522
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100523 case SDPLoader::kWhatSDPLoaded:
524 {
525 onSDPLoaded(msg);
526 break;
527 }
528
Andreas Huber2bfdd422011-10-11 15:24:07 -0700529 default:
530 TRESPASS();
531 }
532}
533
534void NuPlayer::RTSPSource::onConnected() {
535 CHECK(mAudioTrack == NULL);
536 CHECK(mVideoTrack == NULL);
537
538 size_t numTracks = mHandler->countTracks();
539 for (size_t i = 0; i < numTracks; ++i) {
540 int32_t timeScale;
541 sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale);
542
543 const char *mime;
544 CHECK(format->findCString(kKeyMIMEType, &mime));
545
Andreas Huber49694682012-08-31 10:27:46 -0700546 if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
547 // Very special case for MPEG2 Transport Streams.
548 CHECK_EQ(numTracks, 1u);
549
550 mTSParser = new ATSParser;
551 return;
552 }
553
Andreas Huber2bfdd422011-10-11 15:24:07 -0700554 bool isAudio = !strncasecmp(mime, "audio/", 6);
555 bool isVideo = !strncasecmp(mime, "video/", 6);
556
557 TrackInfo info;
558 info.mTimeScale = timeScale;
559 info.mRTPTime = 0;
560 info.mNormalPlaytimeUs = 0ll;
Andreas Huber1906e5c2011-12-08 12:27:47 -0800561 info.mNPTMappingValid = false;
Andreas Huber2bfdd422011-10-11 15:24:07 -0700562
563 if ((isAudio && mAudioTrack == NULL)
564 || (isVideo && mVideoTrack == NULL)) {
565 sp<AnotherPacketSource> source = new AnotherPacketSource(format);
566
567 if (isAudio) {
568 mAudioTrack = source;
569 } else {
570 mVideoTrack = source;
571 }
572
573 info.mSource = source;
574 }
575
576 mTracks.push(info);
577 }
578
579 mState = CONNECTED;
580}
581
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100582void NuPlayer::RTSPSource::onSDPLoaded(const sp<AMessage> &msg) {
583 status_t err;
584 CHECK(msg->findInt32("result", &err));
585
586 mSDPLoader.clear();
587
588 if (mDisconnectReplyID != 0) {
589 err = UNKNOWN_ERROR;
590 }
591
592 if (err == OK) {
593 sp<ASessionDescription> desc;
594 sp<RefBase> obj;
595 CHECK(msg->findObject("description", &obj));
596 desc = static_cast<ASessionDescription *>(obj.get());
597
598 AString rtspUri;
599 if (!desc->findAttribute(0, "a=control", &rtspUri)) {
600 ALOGE("Unable to find url in SDP");
601 err = UNKNOWN_ERROR;
602 } else {
Chong Zhang1228d6b2014-08-12 21:25:48 -0700603 sp<AMessage> notify = new AMessage(kWhatNotify, id());
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100604
605 mHandler = new MyHandler(rtspUri.c_str(), notify, mUIDValid, mUID);
606 mLooper->registerHandler(mHandler);
607
608 mHandler->loadSDP(desc);
609 }
610 }
611
612 if (err != OK) {
Andreas Huber7f475c32013-02-05 14:47:13 -0800613 if (mState == CONNECTING) {
614 // We're still in the preparation phase, signal that it
615 // failed.
616 notifyPrepared(err);
617 }
618
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100619 mState = DISCONNECTED;
Chong Zhang180d1b92014-12-02 18:35:35 -0800620 setError(err);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100621
622 if (mDisconnectReplyID != 0) {
623 finishDisconnectIfPossible();
624 }
625 }
626}
627
Andreas Huber2bfdd422011-10-11 15:24:07 -0700628void NuPlayer::RTSPSource::onDisconnected(const sp<AMessage> &msg) {
Fredrik Rosin0ad03bc2013-03-06 13:42:53 +0100629 if (mState == DISCONNECTED) {
630 return;
631 }
632
Andreas Huber2bfdd422011-10-11 15:24:07 -0700633 status_t err;
634 CHECK(msg->findInt32("result", &err));
635 CHECK_NE(err, (status_t)OK);
636
637 mLooper->unregisterHandler(mHandler->id());
638 mHandler.clear();
639
Andreas Huber7f475c32013-02-05 14:47:13 -0800640 if (mState == CONNECTING) {
641 // We're still in the preparation phase, signal that it
642 // failed.
643 notifyPrepared(err);
644 }
645
Andreas Huber2bfdd422011-10-11 15:24:07 -0700646 mState = DISCONNECTED;
Chong Zhang180d1b92014-12-02 18:35:35 -0800647 setError(err);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700648
649 if (mDisconnectReplyID != 0) {
650 finishDisconnectIfPossible();
651 }
652}
653
654void NuPlayer::RTSPSource::finishDisconnectIfPossible() {
655 if (mState != DISCONNECTED) {
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100656 if (mHandler != NULL) {
657 mHandler->disconnect();
658 } else if (mSDPLoader != NULL) {
659 mSDPLoader->cancel();
660 }
Andreas Huber2bfdd422011-10-11 15:24:07 -0700661 return;
662 }
663
664 (new AMessage)->postReply(mDisconnectReplyID);
665 mDisconnectReplyID = 0;
666}
667
Chong Zhang180d1b92014-12-02 18:35:35 -0800668void NuPlayer::RTSPSource::setError(status_t err) {
669 Mutex::Autolock _l(mBufferingLock);
670 mFinalResult = err;
671}
672
673void NuPlayer::RTSPSource::startBufferingIfNecessary() {
674 Mutex::Autolock _l(mBufferingLock);
675
676 if (!mBuffering) {
677 mBuffering = true;
678
679 sp<AMessage> notify = dupNotify();
680 notify->setInt32("what", kWhatBufferingStart);
681 notify->post();
682 }
683}
684
685bool NuPlayer::RTSPSource::stopBufferingIfNecessary() {
686 Mutex::Autolock _l(mBufferingLock);
687
688 if (mBuffering) {
689 if (!haveSufficientDataOnAllTracks()) {
690 return false;
691 }
692
693 mBuffering = false;
694
695 sp<AMessage> notify = dupNotify();
696 notify->setInt32("what", kWhatBufferingEnd);
697 notify->post();
698 }
699
700 return true;
701}
702
703
Andreas Huber2bfdd422011-10-11 15:24:07 -0700704} // namespace android