RTSPSource.cpp revision cfaeeec0900014d97e15829e0fa52f865ee4c786
1ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe/*
2ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe * Copyright (C) 2010 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
4f29ed28c7b878ef28058bc730715d0d32445bc57John Reck * Licensed under the Apache License, Version 2.0 (the "License");
5e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy * you may not use this file except in compliance with the License.
61f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett * You may obtain a copy of the License at
71f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett *
8e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy *      http://www.apache.org/licenses/LICENSE-2.0
9e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy *
10e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135827cb5059ed0eec4c73adf1acbd7ee47b2c5c8fDerek Sollenberger * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
15dccca44ffda4836b56a21da95a046c9708ffd49csergeyv */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
171f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett//#define LOG_NDEBUG 0
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "RTSPSource"
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h>
203d528c403c8945cc326bb656ff0c2e11373401daRaph Levien
216ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod#include "RTSPSource.h"
22bad99183916ba2bac6659efc8a28273e344ba511sergeyv
233d528c403c8945cc326bb656ff0c2e11373401daRaph Levien#include "AnotherPacketSource.h"
243d528c403c8945cc326bb656ff0c2e11373401daRaph Levien#include "MyHandler.h"
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/stagefright/MediaDefs.h>
271abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik#include <media/stagefright/MetaData.h>
281abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik
291abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craiknamespace android {
301abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik
311abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris CraikNuPlayer::RTSPSource::RTSPSource(
321abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik        const char *url,
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const KeyedVector<String8, String8> *headers,
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bool uidValid,
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uid_t uid)
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    : mURL(url),
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      mUIDValid(uidValid),
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      mUID(uid),
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      mFlags(0),
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      mState(DISCONNECTED),
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      mFinalResult(OK),
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      mDisconnectReplyID(0),
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      mStartingUp(true),
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      mSeekGeneration(0) {
458451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes    if (headers) {
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mExtraHeaders = *headers;
478451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ssize_t index =
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
508451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (index >= 0) {
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFlags |= kFlagIncognito;
538451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
54c1b33d665c8caf5760f68c45c6ca0baa649b832aJohn Reck            mExtraHeaders.removeItemsAt(index);
55f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        }
56ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    }
57ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck}
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
598451b25a4422656bbd6657a5855e69c0f4d53c74Elliott HughesNuPlayer::RTSPSource::~RTSPSource() {
604c9355c35a0f62805739823a62ad41ca1cbc6502Mike Reed    if (mLooper != NULL) {
614c9355c35a0f62805739823a62ad41ca1cbc6502Mike Reed        mLooper->stop();
624c9355c35a0f62805739823a62ad41ca1cbc6502Mike Reed    }
634c9355c35a0f62805739823a62ad41ca1cbc6502Mike Reed}
641103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed
651103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reedvoid NuPlayer::RTSPSource::start() {
661103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    if (mLooper == NULL) {
671103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        mLooper = new ALooper;
681103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        mLooper->setName("rtsp");
691103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        mLooper->start();
701103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed
711103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed        mReflector = new AHandlerReflector<RTSPSource>(this);
7242a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed        mLooper->registerHandler(mReflector);
7342a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed    }
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7542a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed    CHECK(mHandler == NULL);
768451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
77f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    sp<AMessage> notify = new AMessage(kWhatNotify, mReflector->id());
78f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
79f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    mHandler = new MyHandler(mURL.c_str(), notify, mUIDValid, mUID);
80e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    mLooper->registerHandler(mHandler);
81f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
82f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    CHECK_EQ(mState, (int)DISCONNECTED);
83f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    mState = CONNECTING;
848451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
858790be6de3644e332ec6a17c855da89ffc13a9bfLeon Scroggins III    mHandler->connect();
868790be6de3644e332ec6a17c855da89ffc13a9bfLeon Scroggins III}
878790be6de3644e332ec6a17c855da89ffc13a9bfLeon Scroggins III
88f29ed28c7b878ef28058bc730715d0d32445bc57John Reckvoid NuPlayer::RTSPSource::stop() {
891abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik    sp<AMessage> msg = new AMessage(kWhatDisconnect, mReflector->id());
909f58361e98be7386a4eadd3aa254e9b7d09d0a3bChris Craik
919f58361e98be7386a4eadd3aa254e9b7d09d0a3bChris Craik    sp<AMessage> dummy;
929f58361e98be7386a4eadd3aa254e9b7d09d0a3bChris Craik    msg->postAndAwaitResponse(&dummy);
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
951f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarettstatus_t NuPlayer::RTSPSource::feedMoreTSData() {
96f1f48bc7f200f54c76b22d845d8ba8419879b375Joseph Wen    return mFinalResult;
97f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
981abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik
99e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroysp<MetaData> NuPlayer::RTSPSource::getFormatMeta(bool audio) {
10039d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    sp<AnotherPacketSource> source = getSource(audio);
10139d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews
10239d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    if (source == NULL) {
10339d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        return NULL;
104a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    }
10539d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews
1063d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger    return source->getFormat();
1073d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger}
1083d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger
1093d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenbergerbool NuPlayer::RTSPSource::haveSufficientDataOnAllTracks() {
1103d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger    // We're going to buffer at least 2 secs worth data on all tracks before
1113d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger    // starting playback (both at startup and after a seek).
1123d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger
1133d4eed7f1aa99401dabe2e45b82f98fb4fc2d754Derek Sollenberger    static const int64_t kMinDurationUs = 2000000ll;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t err;
11657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    int64_t durationUs;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mAudioTrack != NULL
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            && (durationUs = mAudioTrack->getBufferedDurationUs(&err))
1191abf5d62429e5a9329520b2f7c2b5a5e7a8e72ecChris Craik                    < kMinDurationUs
12057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            && err == OK) {
121e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy        ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
122e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy              durationUs / 1E6);
123e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy        return false;
124e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    }
125e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy
126e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    if (mVideoTrack != NULL
127e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy            && (durationUs = mVideoTrack->getBufferedDurationUs(&err))
1281f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett                    < kMinDurationUs
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            && err == OK) {
13012d81c49a015ed8d5ef7af2d854eee1e80472219Carl Shapiro        ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
131f29ed28c7b878ef28058bc730715d0d32445bc57John Reck              durationUs / 1E6);
1328451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes        return false;
133f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
134afde46ed008f150e45e1b0d7e1dc588fc047b74fPatrick Dubroy
135f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return true;
136f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
137afde46ed008f150e45e1b0d7e1dc588fc047b74fPatrick Dubroy
138f29ed28c7b878ef28058bc730715d0d32445bc57John Reckstatus_t NuPlayer::RTSPSource::dequeueAccessUnit(
139f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        bool audio, sp<ABuffer> *accessUnit) {
140f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (mStartingUp) {
141afde46ed008f150e45e1b0d7e1dc588fc047b74fPatrick Dubroy        if (!haveSufficientDataOnAllTracks()) {
142afde46ed008f150e45e1b0d7e1dc588fc047b74fPatrick Dubroy            return -EWOULDBLOCK;
143e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy        }
1441f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett
1451f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett        mStartingUp = false;
1461f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    }
1471f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett
1481f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    sp<AnotherPacketSource> source = getSource(audio);
1491f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (source == NULL) {
151f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return -EWOULDBLOCK;
152f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t finalResult;
1551f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    if (!source->hasBufferAvailable(&finalResult)) {
1561f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett        return finalResult == OK ? -EWOULDBLOCK : finalResult;
1571f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    }
1581f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett
1591f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    return source->dequeueAccessUnit(accessUnit);
1601f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett}
1611f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett
1621f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarettsp<AnotherPacketSource> NuPlayer::RTSPSource::getSource(bool audio) {
1631f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    if (mTSParser != NULL) {
1641f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett        sp<MediaSource> source = mTSParser->getSource(
1651f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett                audio ? ATSParser::AUDIO : ATSParser::VIDEO);
1661f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett
1671f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett        return static_cast<AnotherPacketSource *>(source.get());
1681f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    }
1691f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett
1701f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    return audio ? mAudioTrack : mVideoTrack;
1711f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett}
1721f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett
1731f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarettstatus_t NuPlayer::RTSPSource::getDuration(int64_t *durationUs) {
1741f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    *durationUs = 0ll;
1751f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett
1761f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    int64_t audioDurationUs;
1771f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    if (mAudioTrack != NULL
1781f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett            && mAudioTrack->getFormat()->findInt64(
1791f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett                kKeyDuration, &audioDurationUs)
1801f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett            && audioDurationUs > *durationUs) {
1811f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett        *durationUs = audioDurationUs;
1821f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    }
1831f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett
1841f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    int64_t videoDurationUs;
1851f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    if (mVideoTrack != NULL
1861f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett            && mVideoTrack->getFormat()->findInt64(
1871f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett                kKeyDuration, &videoDurationUs)
1881f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett            && videoDurationUs > *durationUs) {
1891f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett        *durationUs = videoDurationUs;
1901f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    }
1911f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett
1921f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    return OK;
1931f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett}
1941f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett
1951f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarettstatus_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs) {
1961f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    sp<AMessage> msg = new AMessage(kWhatPerformSeek, mReflector->id());
1971f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    msg->setInt32("generation", ++mSeekGeneration);
1981f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    msg->setInt64("timeUs", seekTimeUs);
1991f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    msg->post(200000ll);
2001f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett
2011f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    return OK;
2021f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett}
2031f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett
2041f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarettvoid NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) {
2051f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    if (mState != CONNECTED) {
2061f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett        return;
2071f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    }
2081f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett
2091f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    mState = SEEKING;
2101f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    mHandler->seek(seekTimeUs);
2111f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett}
2121f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett
2131f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarettbool NuPlayer::RTSPSource::isSeekable() {
2141f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett    return true;
2151f979639c168ebdf77ad8d7771786fc321ce8234Matt Sarett}
216721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews
217721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrewsvoid NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
218721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    if (msg->what() == kWhatDisconnect) {
219721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        uint32_t replyID;
220721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        CHECK(msg->senderAwaitsResponse(&replyID));
221721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews
222721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        mDisconnectReplyID = replyID;
223721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        finishDisconnectIfPossible();
224721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        return;
225721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    } else if (msg->what() == kWhatPerformSeek) {
226721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        int32_t generation;
227721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        CHECK(msg->findInt32("generation", &generation));
228721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews
229721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        if (generation != mSeekGeneration) {
230721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews            // obsolete.
231721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews            return;
232721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        }
233c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed
234c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed        int64_t seekTimeUs;
235c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed        CHECK(msg->findInt64("timeUs", &seekTimeUs));
236c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed
237c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed        performSeek(seekTimeUs);
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return;
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
240c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed
241c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed    CHECK_EQ(msg->what(), (int)kWhatNotify);
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2438451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes    int32_t what;
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    CHECK(msg->findInt32("what", &what));
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2468451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes    switch (what) {
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case MyHandler::kWhatConnected:
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            onConnected();
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case MyHandler::kWhatDisconnected:
252c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed            onDisconnected(msg);
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case MyHandler::kWhatSeekDone:
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mState = CONNECTED;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStartingUp = true;
2598451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes            break;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2628451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes        case MyHandler::kWhatAccessUnit:
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        {
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t trackIndex;
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            CHECK(msg->findSize("trackIndex", &trackIndex));
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mTSParser == NULL) {
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                CHECK_LT(trackIndex, mTracks.size());
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                CHECK_EQ(trackIndex, 0u);
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
272c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed
273c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed            sp<ABuffer> accessUnit;
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            CHECK(msg->findBuffer("accessUnit", &accessUnit));
2758451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int32_t damaged;
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (accessUnit->meta()->findInt32("damaged", &damaged)
2788451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes                    && damaged) {
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ALOGI("dropping damaged access unit.");
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mTSParser != NULL) {
284c04851fd0af87f44a7d7351e0c17442fa1d3fc28Mike Reed                size_t offset = 0;
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                status_t err = OK;
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while (offset + 188 <= accessUnit->size()) {
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    err = mTSParser->feedTSPacket(
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            accessUnit->data() + offset, 188);
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (err != OK) {
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
2918451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes                    }
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    offset += 188;
2948451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes                }
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (offset < accessUnit->size()) {
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    err = ERROR_MALFORMED;
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (err != OK) {
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    sp<AnotherPacketSource> source = getSource(false /* audio */);
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (source != NULL) {
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        source->signalEOS(err);
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    source = getSource(true /* audio */);
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (source != NULL) {
308f1f48bc7f200f54c76b22d845d8ba8419879b375Joseph Wen                        source->signalEOS(err);
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            TrackInfo *info = &mTracks.editItemAt(trackIndex);
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
316ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            sp<AnotherPacketSource> source = info->mSource;
317            if (source != NULL) {
318                uint32_t rtpTime;
319                CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
320
321                if (!info->mNPTMappingValid) {
322                    // This is a live stream, we didn't receive any normal
323                    // playtime mapping. We won't map to npt time.
324                    source->queueAccessUnit(accessUnit);
325                    break;
326                }
327
328                int64_t nptUs =
329                    ((double)rtpTime - (double)info->mRTPTime)
330                        / info->mTimeScale
331                        * 1000000ll
332                        + info->mNormalPlaytimeUs;
333
334                accessUnit->meta()->setInt64("timeUs", nptUs);
335
336                source->queueAccessUnit(accessUnit);
337            }
338            break;
339        }
340
341        case MyHandler::kWhatEOS:
342        {
343            int32_t finalResult;
344            CHECK(msg->findInt32("finalResult", &finalResult));
345            CHECK_NE(finalResult, (status_t)OK);
346
347            if (mTSParser != NULL) {
348                sp<AnotherPacketSource> source = getSource(false /* audio */);
349                if (source != NULL) {
350                    source->signalEOS(finalResult);
351                }
352
353                source = getSource(true /* audio */);
354                if (source != NULL) {
355                    source->signalEOS(finalResult);
356                }
357
358                return;
359            }
360
361            size_t trackIndex;
362            CHECK(msg->findSize("trackIndex", &trackIndex));
363            CHECK_LT(trackIndex, mTracks.size());
364
365            TrackInfo *info = &mTracks.editItemAt(trackIndex);
366            sp<AnotherPacketSource> source = info->mSource;
367            if (source != NULL) {
368                source->signalEOS(finalResult);
369            }
370
371            break;
372        }
373
374        case MyHandler::kWhatSeekDiscontinuity:
375        {
376            size_t trackIndex;
377            CHECK(msg->findSize("trackIndex", &trackIndex));
378            CHECK_LT(trackIndex, mTracks.size());
379
380            TrackInfo *info = &mTracks.editItemAt(trackIndex);
381            sp<AnotherPacketSource> source = info->mSource;
382            if (source != NULL) {
383                source->queueDiscontinuity(ATSParser::DISCONTINUITY_SEEK, NULL);
384            }
385
386            break;
387        }
388
389        case MyHandler::kWhatNormalPlayTimeMapping:
390        {
391            size_t trackIndex;
392            CHECK(msg->findSize("trackIndex", &trackIndex));
393            CHECK_LT(trackIndex, mTracks.size());
394
395            uint32_t rtpTime;
396            CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime));
397
398            int64_t nptUs;
399            CHECK(msg->findInt64("nptUs", &nptUs));
400
401            TrackInfo *info = &mTracks.editItemAt(trackIndex);
402            info->mRTPTime = rtpTime;
403            info->mNormalPlaytimeUs = nptUs;
404            info->mNPTMappingValid = true;
405            break;
406        }
407
408        default:
409            TRESPASS();
410    }
411}
412
413void NuPlayer::RTSPSource::onConnected() {
414    CHECK(mAudioTrack == NULL);
415    CHECK(mVideoTrack == NULL);
416
417    size_t numTracks = mHandler->countTracks();
418    for (size_t i = 0; i < numTracks; ++i) {
419        int32_t timeScale;
420        sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale);
421
422        const char *mime;
423        CHECK(format->findCString(kKeyMIMEType, &mime));
424
425        if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
426            // Very special case for MPEG2 Transport Streams.
427            CHECK_EQ(numTracks, 1u);
428
429            mTSParser = new ATSParser;
430            return;
431        }
432
433        bool isAudio = !strncasecmp(mime, "audio/", 6);
434        bool isVideo = !strncasecmp(mime, "video/", 6);
435
436        TrackInfo info;
437        info.mTimeScale = timeScale;
438        info.mRTPTime = 0;
439        info.mNormalPlaytimeUs = 0ll;
440        info.mNPTMappingValid = false;
441
442        if ((isAudio && mAudioTrack == NULL)
443                || (isVideo && mVideoTrack == NULL)) {
444            sp<AnotherPacketSource> source = new AnotherPacketSource(format);
445
446            if (isAudio) {
447                mAudioTrack = source;
448            } else {
449                mVideoTrack = source;
450            }
451
452            info.mSource = source;
453        }
454
455        mTracks.push(info);
456    }
457
458    mState = CONNECTED;
459}
460
461void NuPlayer::RTSPSource::onDisconnected(const sp<AMessage> &msg) {
462    status_t err;
463    CHECK(msg->findInt32("result", &err));
464    CHECK_NE(err, (status_t)OK);
465
466    mLooper->unregisterHandler(mHandler->id());
467    mHandler.clear();
468
469    mState = DISCONNECTED;
470    mFinalResult = err;
471
472    if (mDisconnectReplyID != 0) {
473        finishDisconnectIfPossible();
474    }
475}
476
477void NuPlayer::RTSPSource::finishDisconnectIfPossible() {
478    if (mState != DISCONNECTED) {
479        mHandler->disconnect();
480        return;
481    }
482
483    (new AMessage)->postReply(mDisconnectReplyID);
484    mDisconnectReplyID = 0;
485}
486
487}  // namespace android
488