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