12bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber/* 22bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * Copyright (C) 2010 The Android Open Source Project 32bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * 42bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 52bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * you may not use this file except in compliance with the License. 62bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * You may obtain a copy of the License at 72bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * 82bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * http://www.apache.org/licenses/LICENSE-2.0 92bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * 102bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * Unless required by applicable law or agreed to in writing, software 112bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 122bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * See the License for the specific language governing permissions and 142bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * limitations under the License. 152bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber */ 162bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 172bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber//#define LOG_NDEBUG 0 182bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber#define LOG_TAG "RTSPSource" 192bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber#include <utils/Log.h> 202bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 212bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber#include "RTSPSource.h" 222bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 232bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber#include "AnotherPacketSource.h" 242bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber#include "MyHandler.h" 252bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 26cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber#include <media/stagefright/MediaDefs.h> 272bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber#include <media/stagefright/MetaData.h> 282bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 292bfdd428c56c7524d1a11979f200a1762866032dAndreas Hubernamespace android { 302bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 312bfdd428c56c7524d1a11979f200a1762866032dAndreas HuberNuPlayer::RTSPSource::RTSPSource( 322bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber const char *url, 332bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber const KeyedVector<String8, String8> *headers, 342bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber bool uidValid, 352bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber uid_t uid) 362bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber : mURL(url), 372bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mUIDValid(uidValid), 382bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mUID(uid), 392bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mFlags(0), 402bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mState(DISCONNECTED), 412bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mFinalResult(OK), 42ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber mDisconnectReplyID(0), 43bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber mStartingUp(true), 44ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber mSeekGeneration(0) { 452bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (headers) { 462bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mExtraHeaders = *headers; 472bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 482bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber ssize_t index = 492bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log")); 502bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 512bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (index >= 0) { 522bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mFlags |= kFlagIncognito; 532bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 542bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mExtraHeaders.removeItemsAt(index); 552bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 562bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 572bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber} 582bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 592bfdd428c56c7524d1a11979f200a1762866032dAndreas HuberNuPlayer::RTSPSource::~RTSPSource() { 602bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (mLooper != NULL) { 612bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mLooper->stop(); 622bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 632bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber} 642bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 652bfdd428c56c7524d1a11979f200a1762866032dAndreas Hubervoid NuPlayer::RTSPSource::start() { 662bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (mLooper == NULL) { 672bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mLooper = new ALooper; 682bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mLooper->setName("rtsp"); 692bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mLooper->start(); 702bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 712bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mReflector = new AHandlerReflector<RTSPSource>(this); 722bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mLooper->registerHandler(mReflector); 732bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 742bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 752bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK(mHandler == NULL); 762bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 772bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AMessage> notify = new AMessage(kWhatNotify, mReflector->id()); 782bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 792bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mHandler = new MyHandler(mURL.c_str(), notify, mUIDValid, mUID); 802bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mLooper->registerHandler(mHandler); 812bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 822bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK_EQ(mState, (int)DISCONNECTED); 832bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mState = CONNECTING; 842bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 852bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mHandler->connect(); 862bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber} 872bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 882bfdd428c56c7524d1a11979f200a1762866032dAndreas Hubervoid NuPlayer::RTSPSource::stop() { 892bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AMessage> msg = new AMessage(kWhatDisconnect, mReflector->id()); 902bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 912bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AMessage> dummy; 922bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->postAndAwaitResponse(&dummy); 932bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber} 942bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 952bfdd428c56c7524d1a11979f200a1762866032dAndreas Huberstatus_t NuPlayer::RTSPSource::feedMoreTSData() { 962bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber return mFinalResult; 972bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber} 982bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 99840667883fd09d44015716d79bc3ac4d60edc0f0Andreas Hubersp<MetaData> NuPlayer::RTSPSource::getFormatMeta(bool audio) { 1002bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AnotherPacketSource> source = getSource(audio); 1012bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 1022bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (source == NULL) { 1032bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber return NULL; 1042bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 1052bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 1062bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber return source->getFormat(); 1072bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber} 1082bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 109bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huberbool NuPlayer::RTSPSource::haveSufficientDataOnAllTracks() { 110bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber // We're going to buffer at least 2 secs worth data on all tracks before 111bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber // starting playback (both at startup and after a seek). 112bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber 113bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber static const int64_t kMinDurationUs = 2000000ll; 114bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber 115bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber status_t err; 116bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber int64_t durationUs; 117bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber if (mAudioTrack != NULL 118bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber && (durationUs = mAudioTrack->getBufferedDurationUs(&err)) 119bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber < kMinDurationUs 120bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber && err == OK) { 121bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)", 122bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber durationUs / 1E6); 123bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber return false; 124bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber } 125bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber 126bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber if (mVideoTrack != NULL 127bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber && (durationUs = mVideoTrack->getBufferedDurationUs(&err)) 128bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber < kMinDurationUs 129bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber && err == OK) { 130bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)", 131bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber durationUs / 1E6); 132bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber return false; 133bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber } 134bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber 135bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber return true; 136bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber} 137bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber 1382bfdd428c56c7524d1a11979f200a1762866032dAndreas Huberstatus_t NuPlayer::RTSPSource::dequeueAccessUnit( 1392bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber bool audio, sp<ABuffer> *accessUnit) { 140bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber if (mStartingUp) { 141bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber if (!haveSufficientDataOnAllTracks()) { 142bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber return -EWOULDBLOCK; 143bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber } 144bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber 145bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber mStartingUp = false; 146bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber } 147bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber 1482bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AnotherPacketSource> source = getSource(audio); 1492bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 1502bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (source == NULL) { 1512bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber return -EWOULDBLOCK; 1522bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 1532bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 1542bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber status_t finalResult; 1552bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (!source->hasBufferAvailable(&finalResult)) { 1562bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber return finalResult == OK ? -EWOULDBLOCK : finalResult; 1572bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 1582bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 1592bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber return source->dequeueAccessUnit(accessUnit); 1602bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber} 1612bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 1622bfdd428c56c7524d1a11979f200a1762866032dAndreas Hubersp<AnotherPacketSource> NuPlayer::RTSPSource::getSource(bool audio) { 163cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber if (mTSParser != NULL) { 164cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber sp<MediaSource> source = mTSParser->getSource( 165cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber audio ? ATSParser::AUDIO : ATSParser::VIDEO); 166cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber 167cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber return static_cast<AnotherPacketSource *>(source.get()); 168cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber } 169cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber 1702bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber return audio ? mAudioTrack : mVideoTrack; 1712bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber} 1722bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 1732bfdd428c56c7524d1a11979f200a1762866032dAndreas Huberstatus_t NuPlayer::RTSPSource::getDuration(int64_t *durationUs) { 1742bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber *durationUs = 0ll; 1752bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 1762bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber int64_t audioDurationUs; 1772bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (mAudioTrack != NULL 1782bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber && mAudioTrack->getFormat()->findInt64( 1792bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber kKeyDuration, &audioDurationUs) 1802bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber && audioDurationUs > *durationUs) { 1812bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber *durationUs = audioDurationUs; 1822bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 1832bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 1842bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber int64_t videoDurationUs; 1852bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (mVideoTrack != NULL 1862bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber && mVideoTrack->getFormat()->findInt64( 1872bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber kKeyDuration, &videoDurationUs) 1882bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber && videoDurationUs > *durationUs) { 1892bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber *durationUs = videoDurationUs; 1902bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 1912bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 1922bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber return OK; 1932bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber} 1942bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 1952bfdd428c56c7524d1a11979f200a1762866032dAndreas Huberstatus_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs) { 196ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber sp<AMessage> msg = new AMessage(kWhatPerformSeek, mReflector->id()); 197ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber msg->setInt32("generation", ++mSeekGeneration); 198ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber msg->setInt64("timeUs", seekTimeUs); 199ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber msg->post(200000ll); 200ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber 201ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber return OK; 202ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber} 203ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber 204ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Hubervoid NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) { 2052bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (mState != CONNECTED) { 206ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber return; 2072bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 2082bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 2092bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mState = SEEKING; 2102bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mHandler->seek(seekTimeUs); 2112bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber} 2122bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 213b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huberuint32_t NuPlayer::RTSPSource::flags() const { 214b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber return FLAG_SEEKABLE; 2152bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber} 2162bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 2172bfdd428c56c7524d1a11979f200a1762866032dAndreas Hubervoid NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) { 2182bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (msg->what() == kWhatDisconnect) { 2192bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber uint32_t replyID; 2202bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK(msg->senderAwaitsResponse(&replyID)); 2212bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 2222bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mDisconnectReplyID = replyID; 2232bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber finishDisconnectIfPossible(); 2242bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber return; 225ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber } else if (msg->what() == kWhatPerformSeek) { 226ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber int32_t generation; 227ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber CHECK(msg->findInt32("generation", &generation)); 228ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber 229ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber if (generation != mSeekGeneration) { 230ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber // obsolete. 231ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber return; 232ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber } 233ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber 234ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber int64_t seekTimeUs; 235ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber CHECK(msg->findInt64("timeUs", &seekTimeUs)); 236ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber 237ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber performSeek(seekTimeUs); 238ee736e9e74c5368db8d63214513c85cb74bb0183Andreas Huber return; 2392bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 2402bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 2412bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK_EQ(msg->what(), (int)kWhatNotify); 2422bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 2432bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber int32_t what; 2442bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK(msg->findInt32("what", &what)); 2452bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 2462bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber switch (what) { 2472bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber case MyHandler::kWhatConnected: 2482bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber onConnected(); 2492bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber break; 2502bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 2512bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber case MyHandler::kWhatDisconnected: 2522bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber onDisconnected(msg); 2532bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber break; 2542bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 2552bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber case MyHandler::kWhatSeekDone: 2562bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber { 2572bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mState = CONNECTED; 258bfd4d0d9fe0033abf3f55b94f30f6a58846a875eAndreas Huber mStartingUp = true; 2592bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber break; 2602bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 2612bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 2622bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber case MyHandler::kWhatAccessUnit: 2632bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber { 2642bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber size_t trackIndex; 2652bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK(msg->findSize("trackIndex", &trackIndex)); 266cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber 267cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber if (mTSParser == NULL) { 268cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber CHECK_LT(trackIndex, mTracks.size()); 269cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber } else { 270cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber CHECK_EQ(trackIndex, 0u); 271cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber } 2722bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 2732d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber sp<ABuffer> accessUnit; 2742d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber CHECK(msg->findBuffer("accessUnit", &accessUnit)); 2752bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 2762bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber int32_t damaged; 2772bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (accessUnit->meta()->findInt32("damaged", &damaged) 2782bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber && damaged) { 279df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("dropping damaged access unit."); 2802bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber break; 2812bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 2822bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 283cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber if (mTSParser != NULL) { 284cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber size_t offset = 0; 285cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber status_t err = OK; 286cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber while (offset + 188 <= accessUnit->size()) { 287cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber err = mTSParser->feedTSPacket( 288cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber accessUnit->data() + offset, 188); 289cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber if (err != OK) { 290cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber break; 291cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber } 292cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber 293cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber offset += 188; 294cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber } 295cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber 296cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber if (offset < accessUnit->size()) { 297cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber err = ERROR_MALFORMED; 298cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber } 299cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber 300cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber if (err != OK) { 301cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber sp<AnotherPacketSource> source = getSource(false /* audio */); 302cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber if (source != NULL) { 303cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber source->signalEOS(err); 304cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber } 305cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber 306cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber source = getSource(true /* audio */); 307cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber if (source != NULL) { 308cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber source->signalEOS(err); 309cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber } 310cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber } 311cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber break; 312cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber } 313cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber 3141906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber TrackInfo *info = &mTracks.editItemAt(trackIndex); 3151906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber 3161906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber sp<AnotherPacketSource> source = info->mSource; 3172bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (source != NULL) { 3182bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber uint32_t rtpTime; 3192bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime)); 3202bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 3211906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber if (!info->mNPTMappingValid) { 3221906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber // This is a live stream, we didn't receive any normal 323c9d1696d214d2175327067ccc1991bcb36976404Andreas Huber // playtime mapping. We won't map to npt time. 324c9d1696d214d2175327067ccc1991bcb36976404Andreas Huber source->queueAccessUnit(accessUnit); 325c9d1696d214d2175327067ccc1991bcb36976404Andreas Huber break; 3261906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber } 3271906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber 3282bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber int64_t nptUs = 3291906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber ((double)rtpTime - (double)info->mRTPTime) 3301906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber / info->mTimeScale 3312bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber * 1000000ll 3321906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber + info->mNormalPlaytimeUs; 3332bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 3342bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber accessUnit->meta()->setInt64("timeUs", nptUs); 3352bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 3362bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber source->queueAccessUnit(accessUnit); 3372bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 3382bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber break; 3392bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 3402bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 3412bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber case MyHandler::kWhatEOS: 3422bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber { 3432bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber int32_t finalResult; 3442bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK(msg->findInt32("finalResult", &finalResult)); 3452bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK_NE(finalResult, (status_t)OK); 3462bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 347cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber if (mTSParser != NULL) { 348cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber sp<AnotherPacketSource> source = getSource(false /* audio */); 349cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber if (source != NULL) { 350cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber source->signalEOS(finalResult); 351cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber } 352cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber 353cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber source = getSource(true /* audio */); 354cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber if (source != NULL) { 355cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber source->signalEOS(finalResult); 356cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber } 357cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber 358cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber return; 359cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber } 360cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber 361cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber size_t trackIndex; 362cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber CHECK(msg->findSize("trackIndex", &trackIndex)); 363cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber CHECK_LT(trackIndex, mTracks.size()); 364cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber 3652bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber TrackInfo *info = &mTracks.editItemAt(trackIndex); 3662bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AnotherPacketSource> source = info->mSource; 3672bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (source != NULL) { 3682bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber source->signalEOS(finalResult); 3692bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 3702bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 3712bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber break; 3722bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 3732bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 3742bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber case MyHandler::kWhatSeekDiscontinuity: 3752bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber { 3762bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber size_t trackIndex; 3772bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK(msg->findSize("trackIndex", &trackIndex)); 3782bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK_LT(trackIndex, mTracks.size()); 3792bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 3802bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber TrackInfo *info = &mTracks.editItemAt(trackIndex); 3812bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AnotherPacketSource> source = info->mSource; 3822bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (source != NULL) { 3832bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber source->queueDiscontinuity(ATSParser::DISCONTINUITY_SEEK, NULL); 3842bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 3852bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 3862bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber break; 3872bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 3882bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 3892bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber case MyHandler::kWhatNormalPlayTimeMapping: 3902bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber { 3912bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber size_t trackIndex; 3922bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK(msg->findSize("trackIndex", &trackIndex)); 3932bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK_LT(trackIndex, mTracks.size()); 3942bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 3952bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber uint32_t rtpTime; 3962bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime)); 3972bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 3982bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber int64_t nptUs; 3992bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK(msg->findInt64("nptUs", &nptUs)); 4002bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4012bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber TrackInfo *info = &mTracks.editItemAt(trackIndex); 4022bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber info->mRTPTime = rtpTime; 4032bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber info->mNormalPlaytimeUs = nptUs; 4041906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber info->mNPTMappingValid = true; 4052bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber break; 4062bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 4072bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4082bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber default: 4092bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber TRESPASS(); 4102bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 4112bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber} 4122bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4132bfdd428c56c7524d1a11979f200a1762866032dAndreas Hubervoid NuPlayer::RTSPSource::onConnected() { 4142bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK(mAudioTrack == NULL); 4152bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK(mVideoTrack == NULL); 4162bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4172bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber size_t numTracks = mHandler->countTracks(); 4182bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber for (size_t i = 0; i < numTracks; ++i) { 4192bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber int32_t timeScale; 4202bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale); 4212bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4222bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber const char *mime; 4232bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK(format->findCString(kKeyMIMEType, &mime)); 4242bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 425cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) { 426cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber // Very special case for MPEG2 Transport Streams. 427cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber CHECK_EQ(numTracks, 1u); 428cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber 429cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber mTSParser = new ATSParser; 430cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber return; 431cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber } 432cfaeeec0900014d97e15829e0fa52f865ee4c786Andreas Huber 4332bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber bool isAudio = !strncasecmp(mime, "audio/", 6); 4342bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber bool isVideo = !strncasecmp(mime, "video/", 6); 4352bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4362bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber TrackInfo info; 4372bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber info.mTimeScale = timeScale; 4382bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber info.mRTPTime = 0; 4392bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber info.mNormalPlaytimeUs = 0ll; 4401906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber info.mNPTMappingValid = false; 4412bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4422bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if ((isAudio && mAudioTrack == NULL) 4432bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber || (isVideo && mVideoTrack == NULL)) { 4442bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AnotherPacketSource> source = new AnotherPacketSource(format); 4452bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4462bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (isAudio) { 4472bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mAudioTrack = source; 4482bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } else { 4492bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mVideoTrack = source; 4502bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 4512bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4522bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber info.mSource = source; 4532bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 4542bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4552bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mTracks.push(info); 4562bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 4572bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4582bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mState = CONNECTED; 4592bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber} 4602bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4612bfdd428c56c7524d1a11979f200a1762866032dAndreas Hubervoid NuPlayer::RTSPSource::onDisconnected(const sp<AMessage> &msg) { 4622bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber status_t err; 4632bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK(msg->findInt32("result", &err)); 4642bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber CHECK_NE(err, (status_t)OK); 4652bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4662bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mLooper->unregisterHandler(mHandler->id()); 4672bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mHandler.clear(); 4682bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4692bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mState = DISCONNECTED; 4702bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mFinalResult = err; 4712bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4722bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (mDisconnectReplyID != 0) { 4732bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber finishDisconnectIfPossible(); 4742bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 4752bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber} 4762bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4772bfdd428c56c7524d1a11979f200a1762866032dAndreas Hubervoid NuPlayer::RTSPSource::finishDisconnectIfPossible() { 4782bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (mState != DISCONNECTED) { 4792bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mHandler->disconnect(); 4802bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber return; 4812bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 4822bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4832bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber (new AMessage)->postReply(mDisconnectReplyID); 4842bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber mDisconnectReplyID = 0; 4852bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber} 4862bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 4872bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber} // namespace android 488