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