1 /*
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"
25 #include "SDPLoader.h"
26 
27 #include <media/IMediaHTTPService.h>
28 #include <media/stagefright/MediaDefs.h>
29 #include <media/stagefright/MetaData.h>
30 
31 namespace android {
32 
33 const int64_t kNearEOSTimeoutUs = 2000000LL; // 2 secs
34 
35 // Default Buffer Underflow/Prepare/StartServer/Overflow Marks
36 static const int kUnderflowMarkMs   =  1000;  // 1 second
37 static const int kPrepareMarkMs     =  3000;  // 3 seconds
38 //static const int kStartServerMarkMs =  5000;
39 static const int kOverflowMarkMs    = 10000;  // 10 seconds
40 
RTSPSource(const sp<AMessage> & notify,const sp<IMediaHTTPService> & httpService,const char * url,const KeyedVector<String8,String8> * headers,bool uidValid,uid_t uid,bool isSDP)41 NuPlayer::RTSPSource::RTSPSource(
42         const sp<AMessage> &notify,
43         const sp<IMediaHTTPService> &httpService,
44         const char *url,
45         const KeyedVector<String8, String8> *headers,
46         bool uidValid,
47         uid_t uid,
48         bool isSDP)
49     : Source(notify),
50       mHTTPService(httpService),
51       mURL(url),
52       mUIDValid(uidValid),
53       mUID(uid),
54       mFlags(0),
55       mIsSDP(isSDP),
56       mState(DISCONNECTED),
57       mFinalResult(OK),
58       mDisconnectReplyID(0),
59       mBuffering(false),
60       mInPreparationPhase(true),
61       mEOSPending(false),
62       mSeekGeneration(0),
63       mEOSTimeoutAudio(0),
64       mEOSTimeoutVideo(0) {
65     mBufferingSettings.mInitialMarkMs = kPrepareMarkMs;
66     mBufferingSettings.mResumePlaybackMarkMs = kOverflowMarkMs;
67     if (headers) {
68         mExtraHeaders = *headers;
69 
70         ssize_t index =
71             mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
72 
73         if (index >= 0) {
74             mFlags |= kFlagIncognito;
75 
76             mExtraHeaders.removeItemsAt(index);
77         }
78     }
79 }
80 
~RTSPSource()81 NuPlayer::RTSPSource::~RTSPSource() {
82     if (mLooper != NULL) {
83         mLooper->unregisterHandler(id());
84         mLooper->stop();
85     }
86 }
87 
getBufferingSettings(BufferingSettings * buffering)88 status_t NuPlayer::RTSPSource::getBufferingSettings(
89             BufferingSettings* buffering /* nonnull */) {
90     Mutex::Autolock _l(mBufferingSettingsLock);
91     *buffering = mBufferingSettings;
92     return OK;
93 }
94 
setBufferingSettings(const BufferingSettings & buffering)95 status_t NuPlayer::RTSPSource::setBufferingSettings(const BufferingSettings& buffering) {
96     Mutex::Autolock _l(mBufferingSettingsLock);
97     mBufferingSettings = buffering;
98     return OK;
99 }
100 
prepareAsync()101 void NuPlayer::RTSPSource::prepareAsync() {
102     if (mIsSDP && mHTTPService == NULL) {
103         notifyPrepared(BAD_VALUE);
104         return;
105     }
106 
107     if (mLooper == NULL) {
108         mLooper = new ALooper;
109         mLooper->setName("rtsp");
110         mLooper->start();
111 
112         mLooper->registerHandler(this);
113     }
114 
115     CHECK(mHandler == NULL);
116     CHECK(mSDPLoader == NULL);
117 
118     sp<AMessage> notify = new AMessage(kWhatNotify, this);
119 
120     CHECK_EQ(mState, (int)DISCONNECTED);
121     mState = CONNECTING;
122 
123     if (mIsSDP) {
124         mSDPLoader = new SDPLoader(notify,
125                 (mFlags & kFlagIncognito) ? SDPLoader::kFlagIncognito : 0,
126                 mHTTPService);
127 
128         mSDPLoader->load(
129                 mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
130     } else {
131         mHandler = new MyHandler(mURL.c_str(), notify, mUIDValid, mUID);
132         mLooper->registerHandler(mHandler);
133 
134         mHandler->connect();
135     }
136 
137     startBufferingIfNecessary();
138 }
139 
start()140 void NuPlayer::RTSPSource::start() {
141 }
142 
stop()143 void NuPlayer::RTSPSource::stop() {
144     if (mLooper == NULL) {
145         return;
146     }
147 
148     // Close socket before posting message to RTSPSource message handler.
149     close(mHandler->getARTSPConnection()->getSocket());
150 
151     sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
152 
153     sp<AMessage> dummy;
154     msg->postAndAwaitResponse(&dummy);
155 }
156 
feedMoreTSData()157 status_t NuPlayer::RTSPSource::feedMoreTSData() {
158     Mutex::Autolock _l(mBufferingLock);
159     return mFinalResult;
160 }
161 
getFormatMeta(bool audio)162 sp<MetaData> NuPlayer::RTSPSource::getFormatMeta(bool audio) {
163     sp<AnotherPacketSource> source = getSource(audio);
164 
165     if (source == NULL) {
166         return NULL;
167     }
168 
169     return source->getFormat();
170 }
171 
haveSufficientDataOnAllTracks()172 bool NuPlayer::RTSPSource::haveSufficientDataOnAllTracks() {
173     // We're going to buffer at least 2 secs worth data on all tracks before
174     // starting playback (both at startup and after a seek).
175 
176     static const int64_t kMinDurationUs = 2000000LL;
177 
178     int64_t mediaDurationUs = 0;
179     getDuration(&mediaDurationUs);
180     if ((mAudioTrack != NULL && mAudioTrack->isFinished(mediaDurationUs))
181             || (mVideoTrack != NULL && mVideoTrack->isFinished(mediaDurationUs))) {
182         return true;
183     }
184 
185     status_t err;
186     int64_t durationUs;
187     if (mAudioTrack != NULL
188             && (durationUs = mAudioTrack->getBufferedDurationUs(&err))
189                     < kMinDurationUs
190             && err == OK) {
191         ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
192               durationUs / 1E6);
193         return false;
194     }
195 
196     if (mVideoTrack != NULL
197             && (durationUs = mVideoTrack->getBufferedDurationUs(&err))
198                     < kMinDurationUs
199             && err == OK) {
200         ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
201               durationUs / 1E6);
202         return false;
203     }
204 
205     return true;
206 }
207 
dequeueAccessUnit(bool audio,sp<ABuffer> * accessUnit)208 status_t NuPlayer::RTSPSource::dequeueAccessUnit(
209         bool audio, sp<ABuffer> *accessUnit) {
210     if (!stopBufferingIfNecessary()) {
211         return -EWOULDBLOCK;
212     }
213 
214     sp<AnotherPacketSource> source = getSource(audio);
215 
216     if (source == NULL) {
217         return -EWOULDBLOCK;
218     }
219 
220     status_t finalResult;
221     if (!source->hasBufferAvailable(&finalResult)) {
222         if (finalResult == OK) {
223 
224             // If other source already signaled EOS, this source should also return EOS
225             if (sourceReachedEOS(!audio)) {
226                 return ERROR_END_OF_STREAM;
227             }
228 
229             // If this source has detected near end, give it some time to retrieve more
230             // data before returning EOS
231             int64_t mediaDurationUs = 0;
232             getDuration(&mediaDurationUs);
233             if (source->isFinished(mediaDurationUs)) {
234                 int64_t eosTimeout = audio ? mEOSTimeoutAudio : mEOSTimeoutVideo;
235                 if (eosTimeout == 0) {
236                     setEOSTimeout(audio, ALooper::GetNowUs());
237                 } else if ((ALooper::GetNowUs() - eosTimeout) > kNearEOSTimeoutUs) {
238                     setEOSTimeout(audio, 0);
239                     return ERROR_END_OF_STREAM;
240                 }
241                 return -EWOULDBLOCK;
242             }
243 
244             if (!sourceNearEOS(!audio)) {
245                 // We should not enter buffering mode
246                 // if any of the sources already have detected EOS.
247                 startBufferingIfNecessary();
248             }
249 
250             return -EWOULDBLOCK;
251         }
252         return finalResult;
253     }
254 
255     setEOSTimeout(audio, 0);
256 
257     return source->dequeueAccessUnit(accessUnit);
258 }
259 
getSource(bool audio)260 sp<AnotherPacketSource> NuPlayer::RTSPSource::getSource(bool audio) {
261     if (mTSParser != NULL) {
262         sp<MediaSource> source = mTSParser->getSource(
263                 audio ? ATSParser::AUDIO : ATSParser::VIDEO);
264 
265         return static_cast<AnotherPacketSource *>(source.get());
266     }
267 
268     return audio ? mAudioTrack : mVideoTrack;
269 }
270 
setEOSTimeout(bool audio,int64_t timeout)271 void NuPlayer::RTSPSource::setEOSTimeout(bool audio, int64_t timeout) {
272     if (audio) {
273         mEOSTimeoutAudio = timeout;
274     } else {
275         mEOSTimeoutVideo = timeout;
276     }
277 }
278 
getDuration(int64_t * durationUs)279 status_t NuPlayer::RTSPSource::getDuration(int64_t *durationUs) {
280     *durationUs = -1LL;
281 
282     int64_t audioDurationUs;
283     if (mAudioTrack != NULL
284             && mAudioTrack->getFormat()->findInt64(
285                 kKeyDuration, &audioDurationUs)
286             && audioDurationUs > *durationUs) {
287         *durationUs = audioDurationUs;
288     }
289 
290     int64_t videoDurationUs;
291     if (mVideoTrack != NULL
292             && mVideoTrack->getFormat()->findInt64(
293                 kKeyDuration, &videoDurationUs)
294             && videoDurationUs > *durationUs) {
295         *durationUs = videoDurationUs;
296     }
297 
298     return OK;
299 }
300 
seekTo(int64_t seekTimeUs,MediaPlayerSeekMode mode)301 status_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
302     sp<AMessage> msg = new AMessage(kWhatPerformSeek, this);
303     msg->setInt32("generation", ++mSeekGeneration);
304     msg->setInt64("timeUs", seekTimeUs);
305     msg->setInt32("mode", mode);
306 
307     sp<AMessage> response;
308     status_t err = msg->postAndAwaitResponse(&response);
309     if (err == OK && response != NULL) {
310         CHECK(response->findInt32("err", &err));
311     }
312 
313     return err;
314 }
315 
performSeek(int64_t seekTimeUs)316 void NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) {
317     if (mState != CONNECTED) {
318         finishSeek(INVALID_OPERATION);
319         return;
320     }
321 
322     mState = SEEKING;
323     mHandler->seek(seekTimeUs);
324     mEOSPending = false;
325 }
326 
schedulePollBuffering()327 void NuPlayer::RTSPSource::schedulePollBuffering() {
328     sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
329     msg->post(1000000LL); // 1 second intervals
330 }
331 
checkBuffering(bool * prepared,bool * underflow,bool * overflow,bool * startServer,bool * finished)332 void NuPlayer::RTSPSource::checkBuffering(
333         bool *prepared, bool *underflow, bool *overflow, bool *startServer, bool *finished) {
334     size_t numTracks = mTracks.size();
335     size_t preparedCount, underflowCount, overflowCount, startCount, finishedCount;
336     preparedCount = underflowCount = overflowCount = startCount = finishedCount = 0;
337 
338     size_t count = numTracks;
339     for (size_t i = 0; i < count; ++i) {
340         status_t finalResult;
341         TrackInfo *info = &mTracks.editItemAt(i);
342         sp<AnotherPacketSource> src = info->mSource;
343         if (src == NULL) {
344             --numTracks;
345             continue;
346         }
347         int64_t bufferedDurationUs = src->getBufferedDurationUs(&finalResult);
348 
349         int64_t initialMarkUs;
350         int64_t maxRebufferingMarkUs;
351         {
352             Mutex::Autolock _l(mBufferingSettingsLock);
353             initialMarkUs = mBufferingSettings.mInitialMarkMs * 1000LL;
354             // TODO: maxRebufferingMarkUs could be larger than
355             // mBufferingSettings.mResumePlaybackMarkMs * 1000ll.
356             maxRebufferingMarkUs = mBufferingSettings.mResumePlaybackMarkMs * 1000LL;
357         }
358         // isFinished when duration is 0 checks for EOS result only
359         if (bufferedDurationUs > initialMarkUs
360                 || src->isFinished(/* duration */ 0)) {
361             ++preparedCount;
362         }
363 
364         if (src->isFinished(/* duration */ 0)) {
365             ++overflowCount;
366             ++finishedCount;
367         } else {
368             // TODO: redefine kUnderflowMarkMs to a fair value,
369             if (bufferedDurationUs < kUnderflowMarkMs * 1000) {
370                 ++underflowCount;
371             }
372             if (bufferedDurationUs > maxRebufferingMarkUs) {
373                 ++overflowCount;
374             }
375             int64_t startServerMarkUs =
376                     (kUnderflowMarkMs * 1000LL + maxRebufferingMarkUs) / 2;
377             if (bufferedDurationUs < startServerMarkUs) {
378                 ++startCount;
379             }
380         }
381     }
382 
383     *prepared    = (preparedCount == numTracks);
384     *underflow   = (underflowCount > 0);
385     *overflow    = (overflowCount == numTracks);
386     *startServer = (startCount > 0);
387     *finished    = (finishedCount > 0);
388 }
389 
onPollBuffering()390 void NuPlayer::RTSPSource::onPollBuffering() {
391     bool prepared, underflow, overflow, startServer, finished;
392     checkBuffering(&prepared, &underflow, &overflow, &startServer, &finished);
393 
394     if (prepared && mInPreparationPhase) {
395         mInPreparationPhase = false;
396         notifyPrepared();
397     }
398 
399     if (!mInPreparationPhase && underflow) {
400         startBufferingIfNecessary();
401     }
402 
403     if (haveSufficientDataOnAllTracks()) {
404         stopBufferingIfNecessary();
405     }
406 
407     if (overflow && mHandler != NULL) {
408         mHandler->pause();
409     }
410 
411     if (startServer && mHandler != NULL) {
412         mHandler->resume();
413     }
414 
415     if (finished && mHandler != NULL) {
416         mHandler->cancelAccessUnitTimeoutCheck();
417     }
418 
419     schedulePollBuffering();
420 }
421 
signalSourceEOS(status_t result)422 void NuPlayer::RTSPSource::signalSourceEOS(status_t result) {
423     const bool audio = true;
424     const bool video = false;
425 
426     sp<AnotherPacketSource> source = getSource(audio);
427     if (source != NULL) {
428         source->signalEOS(result);
429     }
430 
431     source = getSource(video);
432     if (source != NULL) {
433         source->signalEOS(result);
434     }
435 }
436 
sourceReachedEOS(bool audio)437 bool NuPlayer::RTSPSource::sourceReachedEOS(bool audio) {
438     sp<AnotherPacketSource> source = getSource(audio);
439     status_t finalResult;
440     return (source != NULL &&
441             !source->hasBufferAvailable(&finalResult) &&
442             finalResult == ERROR_END_OF_STREAM);
443 }
444 
sourceNearEOS(bool audio)445 bool NuPlayer::RTSPSource::sourceNearEOS(bool audio) {
446     sp<AnotherPacketSource> source = getSource(audio);
447     int64_t mediaDurationUs = 0;
448     getDuration(&mediaDurationUs);
449     return (source != NULL && source->isFinished(mediaDurationUs));
450 }
451 
onSignalEOS(const sp<AMessage> & msg)452 void NuPlayer::RTSPSource::onSignalEOS(const sp<AMessage> &msg) {
453     int32_t generation;
454     CHECK(msg->findInt32("generation", &generation));
455 
456     if (generation != mSeekGeneration) {
457         return;
458     }
459 
460     if (mEOSPending) {
461         signalSourceEOS(ERROR_END_OF_STREAM);
462         mEOSPending = false;
463     }
464 }
465 
postSourceEOSIfNecessary()466 void NuPlayer::RTSPSource::postSourceEOSIfNecessary() {
467     const bool audio = true;
468     const bool video = false;
469     // If a source has detected near end, give it some time to retrieve more
470     // data before signaling EOS
471     if (sourceNearEOS(audio) || sourceNearEOS(video)) {
472         if (!mEOSPending) {
473             sp<AMessage> msg = new AMessage(kWhatSignalEOS, this);
474             msg->setInt32("generation", mSeekGeneration);
475             msg->post(kNearEOSTimeoutUs);
476             mEOSPending = true;
477         }
478     }
479 }
480 
onMessageReceived(const sp<AMessage> & msg)481 void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
482     if (msg->what() == kWhatDisconnect) {
483         sp<AReplyToken> replyID;
484         CHECK(msg->senderAwaitsResponse(&replyID));
485 
486         mDisconnectReplyID = replyID;
487         finishDisconnectIfPossible();
488         return;
489     } else if (msg->what() == kWhatPerformSeek) {
490         int32_t generation;
491         CHECK(msg->findInt32("generation", &generation));
492         CHECK(msg->senderAwaitsResponse(&mSeekReplyID));
493 
494         if (generation != mSeekGeneration) {
495             // obsolete.
496             finishSeek(OK);
497             return;
498         }
499 
500         int64_t seekTimeUs;
501         int32_t mode;
502         CHECK(msg->findInt64("timeUs", &seekTimeUs));
503         CHECK(msg->findInt32("mode", &mode));
504 
505         // TODO: add "mode" to performSeek.
506         performSeek(seekTimeUs/*, (MediaPlayerSeekMode)mode */);
507         return;
508     } else if (msg->what() == kWhatPollBuffering) {
509         onPollBuffering();
510         return;
511     } else if (msg->what() == kWhatSignalEOS) {
512         onSignalEOS(msg);
513         return;
514     }
515 
516     CHECK_EQ(msg->what(), kWhatNotify);
517 
518     int32_t what;
519     CHECK(msg->findInt32("what", &what));
520 
521     switch (what) {
522         case MyHandler::kWhatConnected:
523         {
524             onConnected();
525 
526             notifyVideoSizeChanged();
527 
528             uint32_t flags = 0;
529 
530             if (mHandler->isSeekable()) {
531                 flags = FLAG_CAN_PAUSE
532                         | FLAG_CAN_SEEK
533                         | FLAG_CAN_SEEK_BACKWARD
534                         | FLAG_CAN_SEEK_FORWARD;
535             }
536 
537             notifyFlagsChanged(flags);
538             schedulePollBuffering();
539             break;
540         }
541 
542         case MyHandler::kWhatDisconnected:
543         {
544             onDisconnected(msg);
545             break;
546         }
547 
548         case MyHandler::kWhatSeekDone:
549         {
550             mState = CONNECTED;
551             // Unblock seekTo here in case we attempted to seek in a live stream
552             finishSeek(OK);
553             break;
554         }
555 
556         case MyHandler::kWhatSeekPaused:
557         {
558             sp<AnotherPacketSource> source = getSource(true /* audio */);
559             if (source != NULL) {
560                 source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
561                         /* extra */ NULL,
562                         /* discard */ true);
563             }
564             source = getSource(false /* video */);
565             if (source != NULL) {
566                 source->queueDiscontinuity(ATSParser::DISCONTINUITY_NONE,
567                         /* extra */ NULL,
568                         /* discard */ true);
569             };
570 
571             status_t err = OK;
572             msg->findInt32("err", &err);
573 
574             if (err == OK) {
575                 int64_t timeUs;
576                 CHECK(msg->findInt64("time", &timeUs));
577                 mHandler->continueSeekAfterPause(timeUs);
578             } else {
579                 finishSeek(err);
580             }
581             break;
582         }
583 
584         case MyHandler::kWhatAccessUnit:
585         {
586             size_t trackIndex;
587             CHECK(msg->findSize("trackIndex", &trackIndex));
588 
589             if (mTSParser == NULL) {
590                 CHECK_LT(trackIndex, mTracks.size());
591             } else {
592                 CHECK_EQ(trackIndex, 0u);
593             }
594 
595             sp<ABuffer> accessUnit;
596             CHECK(msg->findBuffer("accessUnit", &accessUnit));
597 
598             int32_t damaged;
599             if (accessUnit->meta()->findInt32("damaged", &damaged)
600                     && damaged) {
601                 ALOGI("dropping damaged access unit.");
602                 break;
603             }
604 
605             if (mTSParser != NULL) {
606                 size_t offset = 0;
607                 status_t err = OK;
608                 while (offset + 188 <= accessUnit->size()) {
609                     err = mTSParser->feedTSPacket(
610                             accessUnit->data() + offset, 188);
611                     if (err != OK) {
612                         break;
613                     }
614 
615                     offset += 188;
616                 }
617 
618                 if (offset < accessUnit->size()) {
619                     err = ERROR_MALFORMED;
620                 }
621 
622                 if (err != OK) {
623                     signalSourceEOS(err);
624                 }
625 
626                 postSourceEOSIfNecessary();
627                 break;
628             }
629 
630             TrackInfo *info = &mTracks.editItemAt(trackIndex);
631 
632             sp<AnotherPacketSource> source = info->mSource;
633             if (source != NULL) {
634                 uint32_t rtpTime;
635                 CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
636 
637                 if (!info->mNPTMappingValid) {
638                     // This is a live stream, we didn't receive any normal
639                     // playtime mapping. We won't map to npt time.
640                     source->queueAccessUnit(accessUnit);
641                     break;
642                 }
643 
644                 int64_t nptUs =
645                     ((double)rtpTime - (double)info->mRTPTime)
646                         / info->mTimeScale
647                         * 1000000LL
648                         + info->mNormalPlaytimeUs;
649 
650                 accessUnit->meta()->setInt64("timeUs", nptUs);
651 
652                 source->queueAccessUnit(accessUnit);
653             }
654             postSourceEOSIfNecessary();
655             break;
656         }
657 
658         case MyHandler::kWhatEOS:
659         {
660             int32_t finalResult;
661             CHECK(msg->findInt32("finalResult", &finalResult));
662             CHECK_NE(finalResult, (status_t)OK);
663 
664             if (mTSParser != NULL) {
665                 signalSourceEOS(finalResult);
666             }
667 
668             size_t trackIndex;
669             CHECK(msg->findSize("trackIndex", &trackIndex));
670             CHECK_LT(trackIndex, mTracks.size());
671 
672             TrackInfo *info = &mTracks.editItemAt(trackIndex);
673             sp<AnotherPacketSource> source = info->mSource;
674             if (source != NULL) {
675                 source->signalEOS(finalResult);
676             }
677 
678             break;
679         }
680 
681         case MyHandler::kWhatSeekDiscontinuity:
682         {
683             size_t trackIndex;
684             CHECK(msg->findSize("trackIndex", &trackIndex));
685             CHECK_LT(trackIndex, mTracks.size());
686 
687             TrackInfo *info = &mTracks.editItemAt(trackIndex);
688             sp<AnotherPacketSource> source = info->mSource;
689             if (source != NULL) {
690                 source->queueDiscontinuity(
691                         ATSParser::DISCONTINUITY_TIME,
692                         NULL,
693                         true /* discard */);
694             }
695 
696             break;
697         }
698 
699         case MyHandler::kWhatNormalPlayTimeMapping:
700         {
701             size_t trackIndex;
702             CHECK(msg->findSize("trackIndex", &trackIndex));
703             CHECK_LT(trackIndex, mTracks.size());
704 
705             uint32_t rtpTime;
706             CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime));
707 
708             int64_t nptUs;
709             CHECK(msg->findInt64("nptUs", &nptUs));
710 
711             TrackInfo *info = &mTracks.editItemAt(trackIndex);
712             info->mRTPTime = rtpTime;
713             info->mNormalPlaytimeUs = nptUs;
714             info->mNPTMappingValid = true;
715             break;
716         }
717 
718         case SDPLoader::kWhatSDPLoaded:
719         {
720             onSDPLoaded(msg);
721             break;
722         }
723 
724         default:
725             TRESPASS();
726     }
727 }
728 
onConnected()729 void NuPlayer::RTSPSource::onConnected() {
730     CHECK(mAudioTrack == NULL);
731     CHECK(mVideoTrack == NULL);
732 
733     size_t numTracks = mHandler->countTracks();
734     for (size_t i = 0; i < numTracks; ++i) {
735         int32_t timeScale;
736         sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale);
737 
738         const char *mime;
739         CHECK(format->findCString(kKeyMIMEType, &mime));
740 
741         if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
742             // Very special case for MPEG2 Transport Streams.
743             CHECK_EQ(numTracks, 1u);
744 
745             mTSParser = new ATSParser;
746             return;
747         }
748 
749         bool isAudio = !strncasecmp(mime, "audio/", 6);
750         bool isVideo = !strncasecmp(mime, "video/", 6);
751 
752         TrackInfo info;
753         info.mTimeScale = timeScale;
754         info.mRTPTime = 0;
755         info.mNormalPlaytimeUs = 0LL;
756         info.mNPTMappingValid = false;
757 
758         if ((isAudio && mAudioTrack == NULL)
759                 || (isVideo && mVideoTrack == NULL)) {
760             sp<AnotherPacketSource> source = new AnotherPacketSource(format);
761 
762             if (isAudio) {
763                 mAudioTrack = source;
764             } else {
765                 mVideoTrack = source;
766             }
767 
768             info.mSource = source;
769         }
770 
771         mTracks.push(info);
772     }
773 
774     mState = CONNECTED;
775 }
776 
onSDPLoaded(const sp<AMessage> & msg)777 void NuPlayer::RTSPSource::onSDPLoaded(const sp<AMessage> &msg) {
778     status_t err;
779     CHECK(msg->findInt32("result", &err));
780 
781     mSDPLoader.clear();
782 
783     if (mDisconnectReplyID != 0) {
784         err = UNKNOWN_ERROR;
785     }
786 
787     if (err == OK) {
788         sp<ASessionDescription> desc;
789         sp<RefBase> obj;
790         CHECK(msg->findObject("description", &obj));
791         desc = static_cast<ASessionDescription *>(obj.get());
792 
793         AString rtspUri;
794         if (!desc->findAttribute(0, "a=control", &rtspUri)) {
795             ALOGE("Unable to find url in SDP");
796             err = UNKNOWN_ERROR;
797         } else {
798             sp<AMessage> notify = new AMessage(kWhatNotify, this);
799 
800             mHandler = new MyHandler(rtspUri.c_str(), notify, mUIDValid, mUID);
801             mLooper->registerHandler(mHandler);
802 
803             mHandler->loadSDP(desc);
804         }
805     }
806 
807     if (err != OK) {
808         if (mState == CONNECTING) {
809             // We're still in the preparation phase, signal that it
810             // failed.
811             notifyPrepared(err);
812         }
813 
814         mState = DISCONNECTED;
815         setError(err);
816 
817         if (mDisconnectReplyID != 0) {
818             finishDisconnectIfPossible();
819         }
820     }
821 }
822 
onDisconnected(const sp<AMessage> & msg)823 void NuPlayer::RTSPSource::onDisconnected(const sp<AMessage> &msg) {
824     if (mState == DISCONNECTED) {
825         return;
826     }
827 
828     status_t err;
829     CHECK(msg->findInt32("result", &err));
830     CHECK_NE(err, (status_t)OK);
831 
832     mLooper->unregisterHandler(mHandler->id());
833     mHandler.clear();
834 
835     if (mState == CONNECTING) {
836         // We're still in the preparation phase, signal that it
837         // failed.
838         notifyPrepared(err);
839     }
840 
841     mState = DISCONNECTED;
842     setError(err);
843 
844     if (mDisconnectReplyID != 0) {
845         finishDisconnectIfPossible();
846     }
847 }
848 
finishDisconnectIfPossible()849 void NuPlayer::RTSPSource::finishDisconnectIfPossible() {
850     if (mState != DISCONNECTED) {
851         if (mHandler != NULL) {
852             mHandler->disconnect();
853         } else if (mSDPLoader != NULL) {
854             mSDPLoader->cancel();
855         }
856         return;
857     }
858 
859     (new AMessage)->postReply(mDisconnectReplyID);
860     mDisconnectReplyID = 0;
861 }
862 
setError(status_t err)863 void NuPlayer::RTSPSource::setError(status_t err) {
864     Mutex::Autolock _l(mBufferingLock);
865     mFinalResult = err;
866 }
867 
startBufferingIfNecessary()868 void NuPlayer::RTSPSource::startBufferingIfNecessary() {
869     Mutex::Autolock _l(mBufferingLock);
870 
871     if (!mBuffering) {
872         mBuffering = true;
873 
874         sp<AMessage> notify = dupNotify();
875         notify->setInt32("what", kWhatPauseOnBufferingStart);
876         notify->post();
877     }
878 }
879 
stopBufferingIfNecessary()880 bool NuPlayer::RTSPSource::stopBufferingIfNecessary() {
881     Mutex::Autolock _l(mBufferingLock);
882 
883     if (mBuffering) {
884         if (!haveSufficientDataOnAllTracks()) {
885             return false;
886         }
887 
888         mBuffering = false;
889 
890         sp<AMessage> notify = dupNotify();
891         notify->setInt32("what", kWhatResumeOnBufferingEnd);
892         notify->post();
893     }
894 
895     return true;
896 }
897 
finishSeek(status_t err)898 void NuPlayer::RTSPSource::finishSeek(status_t err) {
899     if (mSeekReplyID == NULL) {
900         return;
901     }
902     sp<AMessage> seekReply = new AMessage;
903     seekReply->setInt32("err", err);
904     seekReply->postReply(mSeekReplyID);
905     mSeekReplyID = NULL;
906 }
907 
908 }  // namespace android
909