1cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber/*
2cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Copyright (C) 2010 The Android Open Source Project
3cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber *
4cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * you may not use this file except in compliance with the License.
6cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * You may obtain a copy of the License at
7cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber *
8cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber *
10cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Unless required by applicable law or agreed to in writing, software
11cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * See the License for the specific language governing permissions and
14cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * limitations under the License.
15cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber */
16cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
17cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#ifndef MY_HANDLER_H_
18cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
19cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#define MY_HANDLER_H_
20cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
216e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber//#define LOG_NDEBUG 0
2284333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber
2384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#ifndef LOG_TAG
246e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber#define LOG_TAG "MyHandler"
2584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#endif
2684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber
276e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber#include <utils/Log.h>
286e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber
29cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "APacketSource.h"
30cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ARTPConnection.h"
31cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ARTSPConnection.h"
32cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ASessionDescription.h"
33cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
348d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber#include <ctype.h>
358d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
36cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
37cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ADebug.h>
38cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ALooper.h>
39cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/AMessage.h>
40cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/MediaErrors.h>
41190cdbab6ba24519d6b5e8bec6c2c74e6650e284Andreas Huber#include <media/stagefright/Utils.h>
42cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
432bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber#include <arpa/inet.h>
442bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber#include <sys/socket.h>
45de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber#include <netdb.h>
462bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
47dab718bba3945332dc75e268e1e7f0fe2eb91c4aAndreas Huber#include "HTTPBase.h"
489b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
4984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#if LOG_NDEBUG
5084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#define UNUSED_UNLESS_VERBOSE(x) (void)(x)
5184333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#else
5284333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#define UNUSED_UNLESS_VERBOSE(x)
5384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#endif
5484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber
55100a4408968b90e314526185d572c72ea4cc784aAndreas Huber// If no access units are received within 5 secs, assume that the rtp
56e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// stream has ended and signal end of stream.
57908dbdee96856693decc04fa143c2ba525495d43Andreas Huberstatic int64_t kAccessUnitTimeoutUs = 10000000ll;
58e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber
59e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// If no access units arrive for the first 10 secs after starting the
60e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// stream, assume none ever will and signal EOS or switch transports.
61e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huberstatic int64_t kStartupTimeoutUs = 10000000ll;
62e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber
63908dbdee96856693decc04fa143c2ba525495d43Andreas Huberstatic int64_t kDefaultKeepAliveTimeoutUs = 60000000ll;
64908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
650955986e6c1c27ba752e293246086ea79c49d39cRoger Jönssonstatic int64_t kPauseDelayUs = 3000000ll;
660955986e6c1c27ba752e293246086ea79c49d39cRoger Jönsson
67cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubernamespace android {
68cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
698d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huberstatic bool GetAttribute(const char *s, const char *key, AString *value) {
708d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    value->clear();
718d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
728d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    size_t keyLen = strlen(key);
738d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
748d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    for (;;) {
758d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        while (isspace(*s)) {
768d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            ++s;
778d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        }
788d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
798d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        const char *colonPos = strchr(s, ';');
808d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
818d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        size_t len =
828d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            (colonPos == NULL) ? strlen(s) : colonPos - s;
838d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
848d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) {
858d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            value->setTo(&s[keyLen + 1], len - keyLen - 1);
868d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            return true;
878d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        }
888d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
898d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        if (colonPos == NULL) {
908d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            return false;
918d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        }
928d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
938d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        s = colonPos + 1;
948d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    }
958d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber}
968d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
97cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstruct MyHandler : public AHandler {
982bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    enum {
992bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        kWhatConnected                  = 'conn',
1002bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        kWhatDisconnected               = 'disc',
1018d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih        kWhatSeekPaused                 = 'spau',
1022bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        kWhatSeekDone                   = 'sdon',
1032bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
1042bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        kWhatAccessUnit                 = 'accU',
1052bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        kWhatEOS                        = 'eos!',
1062bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        kWhatSeekDiscontinuity          = 'seeD',
1072bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        kWhatNormalPlayTimeMapping      = 'nptM',
1082bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    };
1092bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
1109b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber    MyHandler(
1112bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            const char *url,
1122bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            const sp<AMessage> &notify,
1139b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber            bool uidValid = false, uid_t uid = 0)
1142bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        : mNotify(notify),
1152bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber          mUIDValid(uidValid),
1169b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber          mUID(uid),
117348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber          mNetLooper(new ALooper),
1189b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber          mConn(new ARTSPConnection(mUIDValid, mUID)),
119cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber          mRTPConn(new ARTPConnection),
1204579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber          mOriginalSessionURL(url),
121cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber          mSessionURL(url),
122cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber          mSetupTracksSuccessful(false),
123cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber          mSeekPending(false),
124cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber          mFirstAccessUnit(true),
1257e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber          mAllTracksHaveTime(false),
126100a4408968b90e314526185d572c72ea4cc784aAndreas Huber          mNTPAnchorUs(-1),
127100a4408968b90e314526185d572c72ea4cc784aAndreas Huber          mMediaAnchorUs(-1),
128100a4408968b90e314526185d572c72ea4cc784aAndreas Huber          mLastMediaTimeUs(0),
1298d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber          mNumAccessUnitsReceived(0),
1307aef03379179c109c2547c33c410bfc93c8db576Andreas Huber          mCheckPending(false),
131a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber          mCheckGeneration(0),
1321a37ee3c877165c812734b405f922f6e0d747052joakim johansson          mCheckTimeoutGeneration(0),
133e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber          mTryTCPInterleaving(false),
134f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber          mTryFakeRTCP(false),
1350dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber          mReceivedFirstRTCPPacket(false),
136f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber          mReceivedFirstRTPPacket(false),
137ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson          mSeekable(true),
138908dbdee96856693decc04fa143c2ba525495d43Andreas Huber          mKeepAliveTimeoutUs(kDefaultKeepAliveTimeoutUs),
13946d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson          mKeepAliveGeneration(0),
1400955986e6c1c27ba752e293246086ea79c49d39cRoger Jönsson          mPausing(false),
141c582fde93ded7219107157333a9e46d780adcf9cJean-Baptiste Queru          mPauseGeneration(0),
142bbbf9c4552402ab18b255f4058e9e6e506f3f106Yajun Zeng          mPlayResponseParsed(false) {
143a814c1fdc2acf0ed2ee3b175110f6039be7c4873Andreas Huber        mNetLooper->setName("rtsp net");
144348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber        mNetLooper->start(false /* runOnCallingThread */,
145348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                          false /* canCallJava */,
146348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber                          PRIORITY_HIGHEST);
1474579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
1484579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        // Strip any authentication info from the session url, we don't
1494579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        // want to transmit user/pass in cleartext.
1504579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        AString host, path, user, pass;
1514579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        unsigned port;
152de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber        CHECK(ARTSPConnection::ParseURL(
153de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber                    mSessionURL.c_str(), &host, &port, &path, &user, &pass));
154de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber
155de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber        if (user.size() > 0) {
1564579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            mSessionURL.clear();
1574579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            mSessionURL.append("rtsp://");
1584579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            mSessionURL.append(host);
1594579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            mSessionURL.append(":");
160a1e8944a21e5833b7aadc451776f11797f5f9273Elliott Hughes            mSessionURL.append(AStringPrintf("%u", port));
1614579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            mSessionURL.append(path);
1624579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
163a8b8488f703bb6bda039d7d98f87e4f9d845664dDavid Williams            ALOGV("rewritten session url: '%s'", mSessionURL.c_str());
1644579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        }
165de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber
166de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber        mSessionHost = host;
167348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber    }
168348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber
1692bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    void connect() {
1702bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        looper()->registerHandler(mConn);
1712bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        (1 ? mNetLooper : looper())->registerHandler(mRTPConn);
172348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber
1731d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> notify = new AMessage('biny', this);
1740792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        mConn->observeBinaryData(notify);
1750792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
1761d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> reply = new AMessage('conn', this);
1774579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        mConn->connect(mOriginalSessionURL.c_str(), reply);
178cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
179cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
18081dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé    void loadSDP(const sp<ASessionDescription>& desc) {
18181dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        looper()->registerHandler(mConn);
18281dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        (1 ? mNetLooper : looper())->registerHandler(mRTPConn);
18381dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
1841d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> notify = new AMessage('biny', this);
18581dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        mConn->observeBinaryData(notify);
18681dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
1871d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> reply = new AMessage('sdpl', this);
18881dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        reply->setObject("description", desc);
18981dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé        mConn->connect(mOriginalSessionURL.c_str(), reply);
19081dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé    }
19181dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
19284333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber    AString getControlURL() {
193b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher        AString sessionLevelControlURL;
194b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher        if (mSessionDesc->findAttribute(
195b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher                0,
196b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher                "a=control",
197b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher                &sessionLevelControlURL)) {
198b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher            if (sessionLevelControlURL.compare("*") == 0) {
199b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher                return mBaseURL;
200b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher            } else {
201b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher                AString controlURL;
202b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher                CHECK(MakeURL(
203b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher                        mBaseURL.c_str(),
204b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher                        sessionLevelControlURL.c_str(),
205b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher                        &controlURL));
206b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher                return controlURL;
207b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher            }
208b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher        } else {
209b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher            return mSessionURL;
210b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher        }
211b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher    }
212b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher
2132bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    void disconnect() {
2141d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        (new AMessage('abor', this))->post();
215348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber    }
216348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber
2172bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    void seek(int64_t timeUs) {
2181d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> msg = new AMessage('seek', this);
219cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber        msg->setInt64("time", timeUs);
2200955986e6c1c27ba752e293246086ea79c49d39cRoger Jönsson        mPauseGeneration++;
221cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber        msg->post();
222cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber    }
223cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
2248d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih    void continueSeekAfterPause(int64_t timeUs) {
2258d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih        sp<AMessage> msg = new AMessage('see1', this);
2268d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih        msg->setInt64("time", timeUs);
2278d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih        msg->post();
2288d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih    }
2298d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih
2307f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber    bool isSeekable() const {
2317f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber        return mSeekable;
2327f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber    }
2337f475c34ffc8e35345f2cceee2ef56a50bb5fea6Andreas Huber
23446d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson    void pause() {
2351d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> msg = new AMessage('paus', this);
2360955986e6c1c27ba752e293246086ea79c49d39cRoger Jönsson        mPauseGeneration++;
2370955986e6c1c27ba752e293246086ea79c49d39cRoger Jönsson        msg->setInt32("pausecheck", mPauseGeneration);
2380955986e6c1c27ba752e293246086ea79c49d39cRoger Jönsson        msg->post(kPauseDelayUs);
23946d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson    }
24046d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
24146d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson    void resume() {
2421d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> msg = new AMessage('resu', this);
2430955986e6c1c27ba752e293246086ea79c49d39cRoger Jönsson        mPauseGeneration++;
24446d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson        msg->post();
24546d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson    }
24646d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
2472bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber    static void addRR(const sp<ABuffer> &buf) {
2482bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        uint8_t *ptr = buf->data() + buf->size();
2492bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        ptr[0] = 0x80 | 0;
2502bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        ptr[1] = 201;  // RR
2512bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        ptr[2] = 0;
2522bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        ptr[3] = 1;
2532bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        ptr[4] = 0xde;  // SSRC
2542bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        ptr[5] = 0xad;
2552bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        ptr[6] = 0xbe;
2562bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        ptr[7] = 0xef;
2572bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
2582bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        buf->setRange(0, buf->size() + 8);
2592bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber    }
2602bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
2612bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber    static void addSDES(int s, const sp<ABuffer> &buffer) {
2622bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        struct sockaddr_in addr;
2632bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        socklen_t addrSize = sizeof(addr);
264820c4893fdec784321826fd903da34fe3d609b93Wei Jia        if (getsockname(s, (sockaddr *)&addr, &addrSize) != 0) {
265820c4893fdec784321826fd903da34fe3d609b93Wei Jia            inet_aton("0.0.0.0", &(addr.sin_addr));
266820c4893fdec784321826fd903da34fe3d609b93Wei Jia        }
2672bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
2682bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        uint8_t *data = buffer->data() + buffer->size();
2692bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        data[0] = 0x80 | 1;
2702bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        data[1] = 202;  // SDES
2712bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        data[4] = 0xde;  // SSRC
2722bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        data[5] = 0xad;
2732bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        data[6] = 0xbe;
2742bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        data[7] = 0xef;
2752bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
2762bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        size_t offset = 8;
2772bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
2782bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        data[offset++] = 1;  // CNAME
2792bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
2802bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        AString cname = "stagefright@";
2812bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        cname.append(inet_ntoa(addr.sin_addr));
2822bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        data[offset++] = cname.size();
2832bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
2842bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        memcpy(&data[offset], cname.c_str(), cname.size());
2852bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        offset += cname.size();
2862bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
2872bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        data[offset++] = 6;  // TOOL
2882bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
289190cdbab6ba24519d6b5e8bec6c2c74e6650e284Andreas Huber        AString tool = MakeUserAgent();
2902bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
2912bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        data[offset++] = tool.size();
2922bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
2932bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        memcpy(&data[offset], tool.c_str(), tool.size());
2942bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        offset += tool.size();
2952bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
2962bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        data[offset++] = 0;
2972bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
2982bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        if ((offset % 4) > 0) {
2992bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber            size_t count = 4 - (offset % 4);
3002bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber            switch (count) {
3012bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                case 3:
3022bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                    data[offset++] = 0;
3032bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                case 2:
3042bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                    data[offset++] = 0;
3052bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                case 1:
3062bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                    data[offset++] = 0;
3072bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber            }
3082bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        }
3092bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
3102bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        size_t numWords = (offset / 4) - 1;
3112bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        data[2] = numWords >> 8;
3122bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        data[3] = numWords & 0xff;
3132bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
3142bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        buffer->setRange(buffer->offset(), buffer->size() + offset);
3152bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber    }
3162bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
3172bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber    // In case we're behind NAT, fire off two UDP packets to the remote
3182bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber    // rtp/rtcp ports to poke a hole into the firewall for future incoming
3192bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber    // packets. We're going to send an RR/SDES RTCP packet to both of them.
320dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber    bool pokeAHole(int rtpSocket, int rtcpSocket, const AString &transport) {
321de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber        struct sockaddr_in addr;
322de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber        memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
323de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber        addr.sin_family = AF_INET;
324de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber
3252bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        AString source;
3262bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        AString server_port;
3272bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        if (!GetAttribute(transport.c_str(),
3282bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                          "source",
329de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber                          &source)) {
3305ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("Missing 'source' field in Transport response. Using "
331de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber                 "RTSP endpoint address.");
332de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber
333de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber            struct hostent *ent = gethostbyname(mSessionHost.c_str());
334de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber            if (ent == NULL) {
33529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Failed to look up address of session host '%s'",
336de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber                     mSessionHost.c_str());
337de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber
338de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber                return false;
339de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber            }
340de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber
341de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber            addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
342de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber        } else {
343de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber            addr.sin_addr.s_addr = inet_addr(source.c_str());
344de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber        }
345de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber
346de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber        if (!GetAttribute(transport.c_str(),
3472bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                                 "server_port",
3482bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                                 &server_port)) {
349df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("Missing 'server_port' field in Transport response.");
350dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber            return false;
3512bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        }
3522bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
3532bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        int rtpPort, rtcpPort;
3542bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        if (sscanf(server_port.c_str(), "%d-%d", &rtpPort, &rtcpPort) != 2
3552bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                || rtpPort <= 0 || rtpPort > 65535
3562bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                || rtcpPort <=0 || rtcpPort > 65535
357dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                || rtcpPort != rtpPort + 1) {
35829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Server picked invalid RTP/RTCP port pair %s,"
359dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                 " RTP port must be even, RTCP port must be one higher.",
360dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                 server_port.c_str());
361dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber
362dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber            return false;
363dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber        }
364dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber
365dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber        if (rtpPort & 1) {
3665ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("Server picked an odd RTP port, it should've picked an "
367dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                 "even one, we'll let it pass for now, but this may break "
368dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                 "in the future.");
3692bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        }
3702bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
3712bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        if (addr.sin_addr.s_addr == INADDR_NONE) {
372dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber            return true;
373dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber        }
374dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber
375dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber        if (IN_LOOPBACK(ntohl(addr.sin_addr.s_addr))) {
376dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber            // No firewalls to traverse on the loopback interface.
377dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber            return true;
3782bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        }
3792bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
3802bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        // Make up an RR/SDES RTCP packet.
3812bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        sp<ABuffer> buf = new ABuffer(65536);
3822bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        buf->setRange(0, 0);
3832bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        addRR(buf);
3842bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        addSDES(rtpSocket, buf);
3852bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
3862bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        addr.sin_port = htons(rtpPort);
3872bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
3882bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        ssize_t n = sendto(
3892bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                rtpSocket, buf->data(), buf->size(), 0,
3902bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                (const sockaddr *)&addr, sizeof(addr));
391dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber
392dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber        if (n < (ssize_t)buf->size()) {
39329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("failed to poke a hole for RTP packets");
394dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber            return false;
395dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber        }
3962bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
3972bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        addr.sin_port = htons(rtcpPort);
3982bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
3992bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber        n = sendto(
4002bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                rtcpSocket, buf->data(), buf->size(), 0,
4012bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                (const sockaddr *)&addr, sizeof(addr));
402dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber
403dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber        if (n < (ssize_t)buf->size()) {
40429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("failed to poke a hole for RTCP packets");
405dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber            return false;
406dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber        }
4072bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
4083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("successfully poked holes.");
409dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber
410dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber        return true;
4112bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber    }
4122bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
413ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson    static bool isLiveStream(const sp<ASessionDescription> &desc) {
414ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson        AString attrLiveStream;
415ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson        if (desc->findAttribute(0, "a=LiveStream", &attrLiveStream)) {
416ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson            ssize_t semicolonPos = attrLiveStream.find(";", 2);
417ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson
418ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson            const char* liveStreamValue;
419ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson            if (semicolonPos < 0) {
420ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson                liveStreamValue = attrLiveStream.c_str();
421ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson            } else {
422ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson                AString valString;
423ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson                valString.setTo(attrLiveStream,
424ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson                        semicolonPos + 1,
425ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson                        attrLiveStream.size() - semicolonPos - 1);
426ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson                liveStreamValue = valString.c_str();
427ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson            }
428ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson
429ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson            uint32_t value = strtoul(liveStreamValue, NULL, 10);
430ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson            if (value == 1) {
431ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson                ALOGV("found live stream");
432ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson                return true;
433ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson            }
434ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson        } else {
435ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson            // It is a live stream if no duration is returned
436ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson            int64_t durationUs;
437ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson            if (!desc->getDurationUs(&durationUs)) {
438ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson                ALOGV("No duration found, assume live stream");
439ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson                return true;
440ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson            }
441ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson        }
442ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson
443ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson        return false;
444ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson    }
445ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson
446cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    virtual void onMessageReceived(const sp<AMessage> &msg) {
447cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        switch (msg->what()) {
448cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'conn':
449cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
450cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                int32_t result;
451cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                CHECK(msg->findInt32("result", &result));
452cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
453df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block                ALOGI("connection request completed with result %d (%s)",
4546e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber                     result, strerror(-result));
455cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
456cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                if (result == OK) {
457cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    AString request;
458cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request = "DESCRIBE ";
459cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append(mSessionURL);
460cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append(" RTSP/1.0\r\n");
461cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append("Accept: application/sdp\r\n");
462cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append("\r\n");
463cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
4641d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                    sp<AMessage> reply = new AMessage('desc', this);
465cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    mConn->sendRequest(request.c_str(), reply);
4660792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                } else {
4671d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                    (new AMessage('disc', this))->post();
468cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                }
469cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
470cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
471cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
472cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'disc':
473cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
474908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                ++mKeepAliveGeneration;
475908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
4767aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                int32_t reconnect;
4777aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                if (msg->findInt32("reconnect", &reconnect) && reconnect) {
4781d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                    sp<AMessage> reply = new AMessage('conn', this);
4794579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber                    mConn->connect(mOriginalSessionURL.c_str(), reply);
4807aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                } else {
4811d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                    (new AMessage('quit', this))->post();
4827aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                }
483cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
484cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
485cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
486cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'desc':
487cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
488cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                int32_t result;
489cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                CHECK(msg->findInt32("result", &result));
490cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
491df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block                ALOGI("DESCRIBE completed with result %d (%s)",
4926e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber                     result, strerror(-result));
493cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
494cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                if (result == OK) {
495cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<RefBase> obj;
496cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    CHECK(msg->findObject("response", &obj));
497cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<ARTSPResponse> response =
498cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        static_cast<ARTSPResponse *>(obj.get());
499cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
5004bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                    if (response->mStatusCode == 301 || response->mStatusCode == 302) {
501cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        ssize_t i = response->mHeaders.indexOfKey("location");
502cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        CHECK_GE(i, 0);
503cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
5044bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                        mOriginalSessionURL = response->mHeaders.valueAt(i);
5054bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                        mSessionURL = mOriginalSessionURL;
5064bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams
5074bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                        // Strip any authentication info from the session url, we don't
5084bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                        // want to transmit user/pass in cleartext.
5094bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                        AString host, path, user, pass;
5104bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                        unsigned port;
5114bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                        if (ARTSPConnection::ParseURL(
5124bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                                    mSessionURL.c_str(), &host, &port, &path, &user, &pass)
5134bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                                && user.size() > 0) {
5144bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                            mSessionURL.clear();
5154bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                            mSessionURL.append("rtsp://");
5164bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                            mSessionURL.append(host);
5174bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                            mSessionURL.append(":");
518a1e8944a21e5833b7aadc451776f11797f5f9273Elliott Hughes                            mSessionURL.append(AStringPrintf("%u", port));
5194bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                            mSessionURL.append(path);
5204bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams
5214bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                            ALOGI("rewritten session url: '%s'", mSessionURL.c_str());
5224bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                        }
5234bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams
5241d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                        sp<AMessage> reply = new AMessage('conn', this);
5254bb026ba585d5b37795bd9765459f0607b7aa60aDavid Williams                        mConn->connect(mOriginalSessionURL.c_str(), reply);
526cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        break;
527cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    }
528cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
529e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                    if (response->mStatusCode != 200) {
530e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                        result = UNKNOWN_ERROR;
531d32b7b479fad359d7fe779a9c5b4c090cdc14b56Xuefei Chen                    } else if (response->mContent == NULL) {
532d32b7b479fad359d7fe779a9c5b4c090cdc14b56Xuefei Chen                        result = ERROR_MALFORMED;
533d32b7b479fad359d7fe779a9c5b4c090cdc14b56Xuefei Chen                        ALOGE("The response has no content.");
534e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                    } else {
535e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                        mSessionDesc = new ASessionDescription;
536cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
537e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                        mSessionDesc->setTo(
538e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                                response->mContent->data(),
539e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                                response->mContent->size());
540cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
5416f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                        if (!mSessionDesc->isValid()) {
54229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                            ALOGE("Failed to parse session description.");
5436f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                            result = ERROR_MALFORMED;
544cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        } else {
5456f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                            ssize_t i = response->mHeaders.indexOfKey("content-base");
546e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                            if (i >= 0) {
547e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                                mBaseURL = response->mHeaders.valueAt(i);
548e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                            } else {
5496f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                                i = response->mHeaders.indexOfKey("content-location");
5506f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                                if (i >= 0) {
5516f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                                    mBaseURL = response->mHeaders.valueAt(i);
5526f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                                } else {
5536f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                                    mBaseURL = mSessionURL;
5546f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                                }
555e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                            }
556e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber
557ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson                            mSeekable = !isLiveStream(mSessionDesc);
558ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson
559dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                            if (!mBaseURL.startsWith("rtsp://")) {
560dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                                // Some misbehaving servers specify a relative
561dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                                // URL in one of the locations above, combine
562dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                                // it with the absolute session URL to get
563dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                                // something usable...
564dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber
5655ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block                                ALOGW("Server specified a non-absolute base URL"
566dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                                     ", combining it with the session URL to "
567dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                                     "get something usable...");
568dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber
569dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                                AString tmp;
570dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                                CHECK(MakeURL(
571dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                                            mSessionURL.c_str(),
572dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                                            mBaseURL.c_str(),
573dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                                            &tmp));
574dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber
575dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                                mBaseURL = tmp;
576dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                            }
577dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber
57884333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber                            mControlURL = getControlURL();
579b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher
580f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber                            if (mSessionDesc->countTracks() < 2) {
581f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber                                // There's no actual tracks in this session.
582f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber                                // The first "track" is merely session meta
583f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber                                // data.
584f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber
5855ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block                                ALOGW("Session doesn't contain any playable "
586f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber                                     "tracks. Aborting.");
587f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber                                result = ERROR_UNSUPPORTED;
588f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber                            } else {
589f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber                                setupTrack(1);
590f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber                            }
5916f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                        }
592cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    }
593e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                }
594cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
595e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                if (result != OK) {
5961d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                    sp<AMessage> reply = new AMessage('disc', this);
597cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    mConn->disconnect(reply);
598cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                }
599cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
600cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
601cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
60281dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé            case 'sdpl':
60381dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé            {
60481dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                int32_t result;
60581dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                CHECK(msg->findInt32("result", &result));
60681dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
60781dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                ALOGI("SDP connection request completed with result %d (%s)",
60881dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                     result, strerror(-result));
60981dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
61081dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                if (result == OK) {
61181dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                    sp<RefBase> obj;
61281dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                    CHECK(msg->findObject("description", &obj));
61381dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                    mSessionDesc =
61481dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                        static_cast<ASessionDescription *>(obj.get());
61581dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
61681dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                    if (!mSessionDesc->isValid()) {
61781dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                        ALOGE("Failed to parse session description.");
61881dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                        result = ERROR_MALFORMED;
61981dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                    } else {
62081dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                        mBaseURL = mSessionURL;
62181dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
622ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson                        mSeekable = !isLiveStream(mSessionDesc);
623ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson
62484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber                        mControlURL = getControlURL();
625b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher
62681dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                        if (mSessionDesc->countTracks() < 2) {
62781dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                            // There's no actual tracks in this session.
62881dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                            // The first "track" is merely session meta
62981dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                            // data.
63081dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
63181dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                            ALOGW("Session doesn't contain any playable "
63281dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                                 "tracks. Aborting.");
63381dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                            result = ERROR_UNSUPPORTED;
63481dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                        } else {
63581dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                            setupTrack(1);
63681dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                        }
63781dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                    }
63881dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                }
63981dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
64081dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                if (result != OK) {
6411d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                    sp<AMessage> reply = new AMessage('disc', this);
64281dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                    mConn->disconnect(reply);
64381dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                }
64481dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé                break;
64581dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé            }
64681dd60e0340ddcf7f1d5fb80b6c30906fabf201aOscar Rydhé
647cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'setu':
648cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
649cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                size_t index;
650cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                CHECK(msg->findSize("index", &index));
651cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
65239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                TrackInfo *track = NULL;
653cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                size_t trackIndex;
65439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                if (msg->findSize("track-index", &trackIndex)) {
65539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                    track = &mTracks.editItemAt(trackIndex);
65639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                }
657cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
658cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                int32_t result;
659cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                CHECK(msg->findInt32("result", &result));
660cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
6616d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar                ALOGI("SETUP(%zu) completed with result %d (%s)",
6626e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber                     index, result, strerror(-result));
663cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
664e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                if (result == OK) {
66539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                    CHECK(track != NULL);
666cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
667cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<RefBase> obj;
668cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    CHECK(msg->findObject("response", &obj));
669cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<ARTSPResponse> response =
670cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        static_cast<ARTSPResponse *>(obj.get());
671cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
672e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                    if (response->mStatusCode != 200) {
673e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                        result = UNKNOWN_ERROR;
674e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                    } else {
675e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                        ssize_t i = response->mHeaders.indexOfKey("session");
676e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                        CHECK_GE(i, 0);
677cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
678cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        mSessionID = response->mHeaders.valueAt(i);
679908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
680908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                        mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs;
681908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                        AString timeoutStr;
682908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                        if (GetAttribute(
683908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                                    mSessionID.c_str(), "timeout", &timeoutStr)) {
684908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                            char *end;
685908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                            unsigned long timeoutSecs =
686908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                                strtoul(timeoutStr.c_str(), &end, 10);
687908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
688908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                            if (end == timeoutStr.c_str() || *end != '\0') {
6895ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block                                ALOGW("server specified malformed timeout '%s'",
690908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                                     timeoutStr.c_str());
691908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
692908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                                mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs;
693908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                            } else if (timeoutSecs < 15) {
6945ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block                                ALOGW("server specified too short a timeout "
695908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                                     "(%lu secs), using default.",
696908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                                     timeoutSecs);
697908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
698908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                                mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs;
699908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                            } else {
700908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                                mKeepAliveTimeoutUs = timeoutSecs * 1000000ll;
701908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
702df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block                                ALOGI("server specified timeout of %lu secs.",
703908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                                     timeoutSecs);
704908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                            }
705908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                        }
706908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
707cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        i = mSessionID.find(";");
708cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        if (i >= 0) {
709cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                            // Remove options, i.e. ";timeout=90"
710cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                            mSessionID.erase(i, mSessionID.size() - i);
711cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        }
712cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
7131d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                        sp<AMessage> notify = new AMessage('accu', this);
714e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                        notify->setSize("track-index", trackIndex);
715cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
7162bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                        i = response->mHeaders.indexOfKey("transport");
7172bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber                        CHECK_GE(i, 0);
7182bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
719b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                        if (track->mRTPSocket != -1 && track->mRTCPSocket != -1) {
720b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                            if (!track->mUsingInterleavedTCP) {
721b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                                AString transport = response->mHeaders.valueAt(i);
722b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund
723b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                                // We are going to continue even if we were
724b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                                // unable to poke a hole into the firewall...
725b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                                pokeAHole(
726b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                                        track->mRTPSocket,
727b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                                        track->mRTCPSocket,
728b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                                        transport);
729b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                            }
7302bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber
731b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                            mRTPConn->addStream(
732b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                                    track->mRTPSocket, track->mRTCPSocket,
733b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                                    mSessionDesc, index,
734b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                                    notify, track->mUsingInterleavedTCP);
735cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
736b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                            mSetupTracksSuccessful = true;
737b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                        } else {
738b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                            result = BAD_VALUE;
739b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                        }
740e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                    }
741e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                }
742e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber
743e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                if (result != OK) {
744e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                    if (track) {
745e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                        if (!track->mUsingInterleavedTCP) {
746a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma                            // Clear the tag
747a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma                            if (mUIDValid) {
748a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma                                HTTPBase::UnRegisterSocketUserTag(track->mRTPSocket);
7495908f88a7e45380a9b0d71a3b1ea535d76c420b3Chad Brubaker                                HTTPBase::UnRegisterSocketUserMark(track->mRTPSocket);
750a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma                                HTTPBase::UnRegisterSocketUserTag(track->mRTCPSocket);
7515908f88a7e45380a9b0d71a3b1ea535d76c420b3Chad Brubaker                                HTTPBase::UnRegisterSocketUserMark(track->mRTCPSocket);
752a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma                            }
753a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma
754e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                            close(track->mRTPSocket);
755e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                            close(track->mRTCPSocket);
756e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                        }
757e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber
758e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                        mTracks.removeItemsAt(trackIndex);
759e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                    }
760cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                }
761cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
76239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                ++index;
763b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund                if (result == OK && index < mSessionDesc->countTracks()) {
76439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                    setupTrack(index);
76539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                } else if (mSetupTracksSuccessful) {
766908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                    ++mKeepAliveGeneration;
767908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                    postKeepAlive();
768908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
769cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    AString request = "PLAY ";
770b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher                    request.append(mControlURL);
771cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append(" RTSP/1.0\r\n");
772cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
773cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append("Session: ");
774cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append(mSessionID);
775cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append("\r\n");
776cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
777cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    request.append("\r\n");
778cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
7791d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                    sp<AMessage> reply = new AMessage('play', this);
780cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    mConn->sendRequest(request.c_str(), reply);
781cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                } else {
7821d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                    sp<AMessage> reply = new AMessage('disc', this);
783cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    mConn->disconnect(reply);
784cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                }
785cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
786cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
787cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
788cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'play':
789cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
790cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                int32_t result;
791cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                CHECK(msg->findInt32("result", &result));
792cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
793df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block                ALOGI("PLAY completed with result %d (%s)",
7946e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber                     result, strerror(-result));
795cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
796cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                if (result == OK) {
797cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<RefBase> obj;
798cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    CHECK(msg->findObject("response", &obj));
799cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    sp<ARTSPResponse> response =
800cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                        static_cast<ARTSPResponse *>(obj.get());
801cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
8026f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                    if (response->mStatusCode != 200) {
8036f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                        result = UNKNOWN_ERROR;
8046f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                    } else {
8056f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                        parsePlayResponse(response);
806cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
8071d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                        sp<AMessage> timeout = new AMessage('tiou', this);
8081a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        mCheckTimeoutGeneration++;
8091a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        timeout->setInt32("tioucheck", mCheckTimeoutGeneration);
8106f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                        timeout->post(kStartupTimeoutUs);
8116f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                    }
8126f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                }
8138d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
8146f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                if (result != OK) {
8151d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                    sp<AMessage> reply = new AMessage('disc', this);
816cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                    mConn->disconnect(reply);
817cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                }
818cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
819cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
820cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
821cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
822908dbdee96856693decc04fa143c2ba525495d43Andreas Huber            case 'aliv':
823908dbdee96856693decc04fa143c2ba525495d43Andreas Huber            {
824908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                int32_t generation;
825908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                CHECK(msg->findInt32("generation", &generation));
826908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
827908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                if (generation != mKeepAliveGeneration) {
828908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                    // obsolete event.
829908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                    break;
830908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                }
831908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
832908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                AString request;
833908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                request.append("OPTIONS ");
834908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                request.append(mSessionURL);
835908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                request.append(" RTSP/1.0\r\n");
836908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                request.append("Session: ");
837908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                request.append(mSessionID);
838908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                request.append("\r\n");
839908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                request.append("\r\n");
840908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
8411d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                sp<AMessage> reply = new AMessage('opts', this);
842908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                reply->setInt32("generation", mKeepAliveGeneration);
843908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                mConn->sendRequest(request.c_str(), reply);
844908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                break;
845908dbdee96856693decc04fa143c2ba525495d43Andreas Huber            }
846908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
847908dbdee96856693decc04fa143c2ba525495d43Andreas Huber            case 'opts':
848908dbdee96856693decc04fa143c2ba525495d43Andreas Huber            {
849908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                int32_t result;
850908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                CHECK(msg->findInt32("result", &result));
851908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
852df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block                ALOGI("OPTIONS completed with result %d (%s)",
853908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                     result, strerror(-result));
854908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
855908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                int32_t generation;
856908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                CHECK(msg->findInt32("generation", &generation));
857908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
858908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                if (generation != mKeepAliveGeneration) {
859908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                    // obsolete event.
860908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                    break;
861908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                }
862908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
863908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                postKeepAlive();
864908dbdee96856693decc04fa143c2ba525495d43Andreas Huber                break;
865908dbdee96856693decc04fa143c2ba525495d43Andreas Huber            }
866908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
867cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'abor':
868cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
869cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                for (size_t i = 0; i < mTracks.size(); ++i) {
8707aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                    TrackInfo *info = &mTracks.editItemAt(i);
8717aef03379179c109c2547c33c410bfc93c8db576Andreas Huber
8722bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                    if (!mFirstAccessUnit) {
8732bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                        postQueueEOS(i, ERROR_END_OF_STREAM);
8742bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                    }
8757aef03379179c109c2547c33c410bfc93c8db576Andreas Huber
8767aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                    if (!info->mUsingInterleavedTCP) {
8777aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                        mRTPConn->removeStream(info->mRTPSocket, info->mRTCPSocket);
8787aef03379179c109c2547c33c410bfc93c8db576Andreas Huber
879a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma                        // Clear the tag
880a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma                        if (mUIDValid) {
881a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma                            HTTPBase::UnRegisterSocketUserTag(info->mRTPSocket);
8825908f88a7e45380a9b0d71a3b1ea535d76c420b3Chad Brubaker                            HTTPBase::UnRegisterSocketUserMark(info->mRTPSocket);
883a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma                            HTTPBase::UnRegisterSocketUserTag(info->mRTCPSocket);
88459d3f809024ae5b5a7ea35dcfdd056f1c7ca42b2Chad Brubaker                            HTTPBase::UnRegisterSocketUserMark(info->mRTCPSocket);
885a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma                        }
886a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma
8877aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                        close(info->mRTPSocket);
8887aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                        close(info->mRTCPSocket);
8897aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                    }
890cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                }
8917aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                mTracks.clear();
892e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                mSetupTracksSuccessful = false;
893e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                mSeekPending = false;
894e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                mFirstAccessUnit = true;
8957e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber                mAllTracksHaveTime = false;
896100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                mNTPAnchorUs = -1;
897100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                mMediaAnchorUs = -1;
898e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                mNumAccessUnitsReceived = 0;
899e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                mReceivedFirstRTCPPacket = false;
900f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber                mReceivedFirstRTPPacket = false;
90146d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                mPausing = false;
902ec29a2bfb5364a5968b77559fd13821b827d173aRoger Jönsson                mSeekable = true;
903cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
9041d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                sp<AMessage> reply = new AMessage('tear', this);
905cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
9067aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                int32_t reconnect;
9077aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                if (msg->findInt32("reconnect", &reconnect) && reconnect) {
9087aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                    reply->setInt32("reconnect", true);
9097aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                }
9107aef03379179c109c2547c33c410bfc93c8db576Andreas Huber
911cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                AString request;
912cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                request = "TEARDOWN ";
913cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
914cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                // XXX should use aggregate url from SDP here...
915cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                request.append(mSessionURL);
916cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                request.append(" RTSP/1.0\r\n");
917cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
918cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                request.append("Session: ");
919cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                request.append(mSessionID);
920cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                request.append("\r\n");
921cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
922cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                request.append("\r\n");
923cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
924cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                mConn->sendRequest(request.c_str(), reply);
925cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
926cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
927cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
928cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'tear':
929cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
930cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                int32_t result;
931cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                CHECK(msg->findInt32("result", &result));
932cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
933df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block                ALOGI("TEARDOWN completed with result %d (%s)",
9346e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber                     result, strerror(-result));
935cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
9361d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                sp<AMessage> reply = new AMessage('disc', this);
9377aef03379179c109c2547c33c410bfc93c8db576Andreas Huber
9387aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                int32_t reconnect;
9397aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                if (msg->findInt32("reconnect", &reconnect) && reconnect) {
9407aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                    reply->setInt32("reconnect", true);
9417aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                }
9427aef03379179c109c2547c33c410bfc93c8db576Andreas Huber
943cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                mConn->disconnect(reply);
944cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
945cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
946cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
947cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'quit':
948cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
9492bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                sp<AMessage> msg = mNotify->dup();
9502bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                msg->setInt32("what", kWhatDisconnected);
9512bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                msg->setInt32("result", UNKNOWN_ERROR);
9522bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                msg->post();
953cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
954cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
955cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
9568d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            case 'chek':
9578d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            {
958a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber                int32_t generation;
959a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber                CHECK(msg->findInt32("generation", &generation));
960a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber                if (generation != mCheckGeneration) {
961a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber                    // This is an outdated message. Ignore.
962a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber                    break;
963a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber                }
964a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber
9658d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                if (mNumAccessUnitsReceived == 0) {
96691f230461288a2a5091182ef9e17079aabf8ebaaAndreas Huber#if 1
967df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block                    ALOGI("stream ended? aborting.");
9681d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                    (new AMessage('abor', this))->post();
9698d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    break;
970f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber#else
971df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block                    ALOGI("haven't seen an AU in a looong time.");
972f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber#endif
9738d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                }
9748d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
9758d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                mNumAccessUnitsReceived = 0;
976e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber                msg->post(kAccessUnitTimeoutUs);
9778d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                break;
9788d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            }
9798d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
980cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 'accu':
981cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
982100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                int32_t timeUpdate;
983100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                if (msg->findInt32("time-update", &timeUpdate) && timeUpdate) {
984100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                    size_t trackIndex;
985100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                    CHECK(msg->findSize("track-index", &trackIndex));
986100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
987100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                    uint32_t rtpTime;
988100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                    uint64_t ntpTime;
989100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                    CHECK(msg->findInt32("rtp-time", (int32_t *)&rtpTime));
990100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                    CHECK(msg->findInt64("ntp-time", (int64_t *)&ntpTime));
991100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
992100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                    onTimeUpdate(trackIndex, rtpTime, ntpTime);
993100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                    break;
994100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                }
995100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
996f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber                int32_t first;
997f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber                if (msg->findInt32("first-rtcp", &first)) {
998e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                    mReceivedFirstRTCPPacket = true;
999e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                    break;
1000e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                }
1001e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber
1002f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber                if (msg->findInt32("first-rtp", &first)) {
1003f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber                    mReceivedFirstRTPPacket = true;
1004f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber                    break;
1005f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber                }
1006f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber
10078d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                ++mNumAccessUnitsReceived;
1008a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber                postAccessUnitTimeoutCheck();
10098d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
1010cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                size_t trackIndex;
1011cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                CHECK(msg->findSize("track-index", &trackIndex));
1012cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
10137aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                if (trackIndex >= mTracks.size()) {
10143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                    ALOGV("late packets ignored.");
10157aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                    break;
10167aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                }
10177aef03379179c109c2547c33c410bfc93c8db576Andreas Huber
10188d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                TrackInfo *track = &mTracks.editItemAt(trackIndex);
10198d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
1020ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber                int32_t eos;
1021ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber                if (msg->findInt32("eos", &eos)) {
10226d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar                    ALOGI("received BYE on track index %zu", trackIndex);
10231a37ee3c877165c812734b405f922f6e0d747052joakim johansson                    if (!mAllTracksHaveTime && dataReceivedOnAllChannels()) {
10241a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        ALOGI("No time established => fake existing data");
10251a37ee3c877165c812734b405f922f6e0d747052joakim johansson
10261a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        track->mEOSReceived = true;
10271a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        mTryFakeRTCP = true;
10281a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        mReceivedFirstRTCPPacket = true;
10291a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        fakeTimestamps();
10301a37ee3c877165c812734b405f922f6e0d747052joakim johansson                    } else {
10311a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        postQueueEOS(trackIndex, ERROR_END_OF_STREAM);
10321a37ee3c877165c812734b405f922f6e0d747052joakim johansson                    }
1033ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber                    return;
1034ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber                }
1035ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber
10362d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber                sp<ABuffer> accessUnit;
10372d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber                CHECK(msg->findBuffer("access-unit", &accessUnit));
1038cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
10398d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                uint32_t seqNum = (uint32_t)accessUnit->int32Data();
10408d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
10416f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                if (mSeekPending) {
10423856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                    ALOGV("we're seeking, dropping stale packet.");
10436f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                    break;
10446f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                }
10456f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
10468d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                if (seqNum < track->mFirstSeqNumInSegment) {
10473856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                    ALOGV("dropping stale access-unit (%d < %d)",
10486e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber                         seqNum, track->mFirstSeqNumInSegment);
10498d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    break;
10508d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                }
10518d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
10528d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                if (track->mNewSegment) {
10538d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    track->mNewSegment = false;
10548d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                }
10558d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
1056100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                onAccessUnitComplete(trackIndex, accessUnit);
1057cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
1058cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
1059cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
106046d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson            case 'paus':
106146d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson            {
10620955986e6c1c27ba752e293246086ea79c49d39cRoger Jönsson                int32_t generation;
10630955986e6c1c27ba752e293246086ea79c49d39cRoger Jönsson                CHECK(msg->findInt32("pausecheck", &generation));
10640955986e6c1c27ba752e293246086ea79c49d39cRoger Jönsson                if (generation != mPauseGeneration) {
10650955986e6c1c27ba752e293246086ea79c49d39cRoger Jönsson                    ALOGV("Ignoring outdated pause message.");
10660955986e6c1c27ba752e293246086ea79c49d39cRoger Jönsson                    break;
10670955986e6c1c27ba752e293246086ea79c49d39cRoger Jönsson                }
10680955986e6c1c27ba752e293246086ea79c49d39cRoger Jönsson
106946d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                if (!mSeekable) {
107046d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    ALOGW("This is a live stream, ignoring pause request.");
107146d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    break;
107246d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                }
107346d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                mCheckPending = true;
107446d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                ++mCheckGeneration;
107546d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                mPausing = true;
107646d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
107746d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                AString request = "PAUSE ";
1078b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher                request.append(mControlURL);
107946d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                request.append(" RTSP/1.0\r\n");
108046d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
108146d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                request.append("Session: ");
108246d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                request.append(mSessionID);
108346d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                request.append("\r\n");
108446d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
108546d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                request.append("\r\n");
108646d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
10871d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                sp<AMessage> reply = new AMessage('pau2', this);
108846d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                mConn->sendRequest(request.c_str(), reply);
108946d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                break;
109046d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson            }
109146d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
109246d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson            case 'pau2':
109346d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson            {
109446d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                int32_t result;
109546d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                CHECK(msg->findInt32("result", &result));
10961a37ee3c877165c812734b405f922f6e0d747052joakim johansson                mCheckTimeoutGeneration++;
109746d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
109846d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                ALOGI("PAUSE completed with result %d (%s)",
109946d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                     result, strerror(-result));
110046d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                break;
110146d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson            }
110246d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
110346d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson            case 'resu':
110446d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson            {
110546d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                if (mPausing && mSeekPending) {
110646d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    // If seeking, Play will be sent from see1 instead
110746d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    break;
110846d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                }
110946d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
111046d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                if (!mPausing) {
111146d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    // Dont send PLAY if we have not paused
111246d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    break;
111346d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                }
111446d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                AString request = "PLAY ";
1115b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher                request.append(mControlURL);
111646d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                request.append(" RTSP/1.0\r\n");
111746d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
111846d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                request.append("Session: ");
111946d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                request.append(mSessionID);
112046d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                request.append("\r\n");
112146d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
112246d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                request.append("\r\n");
112346d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
11241d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                sp<AMessage> reply = new AMessage('res2', this);
112546d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                mConn->sendRequest(request.c_str(), reply);
112646d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                break;
112746d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson            }
112846d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
112946d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson            case 'res2':
113046d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson            {
113146d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                int32_t result;
113246d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                CHECK(msg->findInt32("result", &result));
113346d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
113446d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                ALOGI("PLAY completed with result %d (%s)",
113546d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                     result, strerror(-result));
113646d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
113746d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                mCheckPending = false;
113846d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                postAccessUnitTimeoutCheck();
113946d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
114046d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                if (result == OK) {
114146d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    sp<RefBase> obj;
114246d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    CHECK(msg->findObject("response", &obj));
114346d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    sp<ARTSPResponse> response =
114446d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                        static_cast<ARTSPResponse *>(obj.get());
114546d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
114646d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    if (response->mStatusCode != 200) {
114746d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                        result = UNKNOWN_ERROR;
114846d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    } else {
114946d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                        parsePlayResponse(response);
11501a37ee3c877165c812734b405f922f6e0d747052joakim johansson
11511a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        // Post new timeout in order to make sure to use
11521a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        // fake timestamps if no new Sender Reports arrive
11531d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                        sp<AMessage> timeout = new AMessage('tiou', this);
11541a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        mCheckTimeoutGeneration++;
11551a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        timeout->setInt32("tioucheck", mCheckTimeoutGeneration);
11561a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        timeout->post(kStartupTimeoutUs);
115746d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    }
115846d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                }
115946d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
116046d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                if (result != OK) {
116146d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    ALOGE("resume failed, aborting.");
11621d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                    (new AMessage('abor', this))->post();
116346d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                }
116446d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
116546d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                mPausing = false;
116646d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                break;
116746d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson            }
116846d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
1169cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            case 'seek':
1170cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            {
11710dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber                if (!mSeekable) {
11725ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block                    ALOGW("This is a live stream, ignoring seek request.");
11732bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
11742bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                    sp<AMessage> msg = mNotify->dup();
11752bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                    msg->setInt32("what", kWhatSeekDone);
11762bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                    msg->post();
1177cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                    break;
1178cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                }
1179cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
1180cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                int64_t timeUs;
1181cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                CHECK(msg->findInt64("time", &timeUs));
1182cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
1183cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                mSeekPending = true;
1184cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
1185a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber                // Disable the access unit timeout until we resumed
1186a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber                // playback again.
1187a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber                mCheckPending = true;
1188a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber                ++mCheckGeneration;
1189a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber
11908d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                sp<AMessage> reply = new AMessage('see0', this);
119146d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                reply->setInt64("time", timeUs);
119246d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson
119346d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                if (mPausing) {
119446d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    // PAUSE already sent
119546d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    ALOGI("Pause already sent");
119646d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    reply->post();
119746d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    break;
119846d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                }
1199cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                AString request = "PAUSE ";
1200b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher                request.append(mControlURL);
1201cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append(" RTSP/1.0\r\n");
1202cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
1203cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append("Session: ");
1204cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append(mSessionID);
1205cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append("\r\n");
1206cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
1207cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append("\r\n");
1208cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
1209cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                mConn->sendRequest(request.c_str(), reply);
1210cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                break;
1211cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            }
1212cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
12138d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih            case 'see0':
1214cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            {
12158d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                // Session is paused now.
12168d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                status_t err = OK;
12178d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                msg->findInt32("result", &err);
12188d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih
12198d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                int64_t timeUs;
12208d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                CHECK(msg->findInt64("time", &timeUs));
12218d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih
12228d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                sp<AMessage> notify = mNotify->dup();
12238d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                notify->setInt32("what", kWhatSeekPaused);
12248d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                notify->setInt32("err", err);
12258d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                notify->setInt64("time", timeUs);
12268d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                notify->post();
12278d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih                break;
12288d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih
12298d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih            }
12308d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih
12318d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih            case 'see1':
12328d237a5ce1e3c1dbc1d538f47e68cff2cc52d799Robert Shih            {
12338d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                for (size_t i = 0; i < mTracks.size(); ++i) {
1234100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                    TrackInfo *info = &mTracks.editItemAt(i);
1235100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
12362bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                    postQueueSeekDiscontinuity(i);
12371a37ee3c877165c812734b405f922f6e0d747052joakim johansson                    info->mEOSReceived = false;
12382bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
1239100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                    info->mRTPAnchor = 0;
1240100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                    info->mNTPAnchorUs = -1;
12418d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                }
12428d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
12437e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber                mAllTracksHaveTime = false;
1244100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                mNTPAnchorUs = -1;
1245100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
12461a37ee3c877165c812734b405f922f6e0d747052joakim johansson                // Start new timeoutgeneration to avoid getting timeout
12471a37ee3c877165c812734b405f922f6e0d747052joakim johansson                // before PLAY response arrive
12481d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                sp<AMessage> timeout = new AMessage('tiou', this);
12491a37ee3c877165c812734b405f922f6e0d747052joakim johansson                mCheckTimeoutGeneration++;
12501a37ee3c877165c812734b405f922f6e0d747052joakim johansson                timeout->setInt32("tioucheck", mCheckTimeoutGeneration);
12511a37ee3c877165c812734b405f922f6e0d747052joakim johansson                timeout->post(kStartupTimeoutUs);
12521a37ee3c877165c812734b405f922f6e0d747052joakim johansson
1253cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                int64_t timeUs;
1254cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                CHECK(msg->findInt64("time", &timeUs));
1255cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
1256cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                AString request = "PLAY ";
1257b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher                request.append(mControlURL);
1258cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append(" RTSP/1.0\r\n");
1259cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
1260cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append("Session: ");
1261cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append(mSessionID);
1262cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append("\r\n");
1263cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
1264cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append(
1265a1e8944a21e5833b7aadc451776f11797f5f9273Elliott Hughes                        AStringPrintf(
1266cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                            "Range: npt=%lld-\r\n", timeUs / 1000000ll));
1267cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
1268cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                request.append("\r\n");
1269cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
12701d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                sp<AMessage> reply = new AMessage('see2', this);
1271cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                mConn->sendRequest(request.c_str(), reply);
1272cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                break;
1273cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            }
1274cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
1275cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            case 'see2':
1276cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            {
127746d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                if (mTracks.size() == 0) {
127846d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    // We have already hit abor, break
127946d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                    break;
128046d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                }
1281cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
1282cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                int32_t result;
1283cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                CHECK(msg->findInt32("result", &result));
12848d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
1285df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block                ALOGI("PLAY completed with result %d (%s)",
12866e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber                     result, strerror(-result));
12878d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
1288a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber                mCheckPending = false;
1289a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber                postAccessUnitTimeoutCheck();
1290a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber
12916f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                if (result == OK) {
12926f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                    sp<RefBase> obj;
12936f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                    CHECK(msg->findObject("response", &obj));
12946f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                    sp<ARTSPResponse> response =
12956f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                        static_cast<ARTSPResponse *>(obj.get());
1296cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
12976f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                    if (response->mStatusCode != 200) {
12986f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                        result = UNKNOWN_ERROR;
12996f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                    } else {
13006f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                        parsePlayResponse(response);
1301cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
13021a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        // Post new timeout in order to make sure to use
13031a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        // fake timestamps if no new Sender Reports arrive
13041d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                        sp<AMessage> timeout = new AMessage('tiou', this);
13051a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        mCheckTimeoutGeneration++;
13061a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        timeout->setInt32("tioucheck", mCheckTimeoutGeneration);
13071a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        timeout->post(kStartupTimeoutUs);
13081a37ee3c877165c812734b405f922f6e0d747052joakim johansson
1309100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                        ssize_t i = response->mHeaders.indexOfKey("rtp-info");
1310100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                        CHECK_GE(i, 0);
1311100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
13123856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                        ALOGV("rtp-info: %s", response->mHeaders.valueAt(i).c_str());
1313100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1314df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block                        ALOGI("seek completed.");
13156f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                    }
13166f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                }
1317cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
13186f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                if (result != OK) {
131929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("seek failed, aborting.");
13201d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                    (new AMessage('abor', this))->post();
13216f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber                }
13228d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
132346d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson                mPausing = false;
13248d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                mSeekPending = false;
13250dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber
13262bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                sp<AMessage> msg = mNotify->dup();
13272bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                msg->setInt32("what", kWhatSeekDone);
13282bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                msg->post();
1329cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber                break;
1330cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber            }
1331cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber
13320792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            case 'biny':
13330792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            {
13342d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber                sp<ABuffer> buffer;
13352d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber                CHECK(msg->findBuffer("buffer", &buffer));
13360792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
13370792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                int32_t index;
13380792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                CHECK(buffer->meta()->findInt32("index", &index));
13390792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
13400792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                mRTPConn->injectPacket(index, buffer);
13410792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                break;
13420792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            }
13430792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
13440792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            case 'tiou':
13450792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            {
13461a37ee3c877165c812734b405f922f6e0d747052joakim johansson                int32_t timeoutGenerationCheck;
13471a37ee3c877165c812734b405f922f6e0d747052joakim johansson                CHECK(msg->findInt32("tioucheck", &timeoutGenerationCheck));
13481a37ee3c877165c812734b405f922f6e0d747052joakim johansson                if (timeoutGenerationCheck != mCheckTimeoutGeneration) {
13491a37ee3c877165c812734b405f922f6e0d747052joakim johansson                    // This is an outdated message. Ignore.
13501a37ee3c877165c812734b405f922f6e0d747052joakim johansson                    // This typically happens if a lot of seeks are
13511a37ee3c877165c812734b405f922f6e0d747052joakim johansson                    // performed, since new timeout messages now are
13521a37ee3c877165c812734b405f922f6e0d747052joakim johansson                    // posted at seek as well.
13531a37ee3c877165c812734b405f922f6e0d747052joakim johansson                    break;
13541a37ee3c877165c812734b405f922f6e0d747052joakim johansson                }
1355e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber                if (!mReceivedFirstRTCPPacket) {
13561a37ee3c877165c812734b405f922f6e0d747052joakim johansson                    if (dataReceivedOnAllChannels() && !mTryFakeRTCP) {
13575ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block                        ALOGW("We received RTP packets but no RTCP packets, "
1358f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber                             "using fake timestamps.");
1359f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber
1360f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber                        mTryFakeRTCP = true;
1361f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber
1362f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber                        mReceivedFirstRTCPPacket = true;
1363dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber
1364dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                        fakeTimestamps();
1365dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                    } else if (!mReceivedFirstRTPPacket && !mTryTCPInterleaving) {
13665ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block                        ALOGW("Never received any data, switching transports.");
13677aef03379179c109c2547c33c410bfc93c8db576Andreas Huber
13687aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                        mTryTCPInterleaving = true;
13697aef03379179c109c2547c33c410bfc93c8db576Andreas Huber
13701d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                        sp<AMessage> msg = new AMessage('abor', this);
13717aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                        msg->setInt32("reconnect", true);
13727aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                        msg->post();
1373dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber                    } else {
13745ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block                        ALOGW("Never received any data, disconnecting.");
13751d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar                        (new AMessage('abor', this))->post();
13767aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                    }
13777e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber                } else {
13787e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber                    if (!mAllTracksHaveTime) {
13797e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber                        ALOGW("We received some RTCP packets, but time "
13807e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber                              "could not be established on all tracks, now "
13817e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber                              "using fake timestamps");
13827e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber
13837e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber                        fakeTimestamps();
13847e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber                    }
13850792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                }
13860792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                break;
13870792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            }
13880792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
1389cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            default:
1390cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                TRESPASS();
1391cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
1392cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
1393cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
1394cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1395908dbdee96856693decc04fa143c2ba525495d43Andreas Huber    void postKeepAlive() {
13961d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> msg = new AMessage('aliv', this);
1397908dbdee96856693decc04fa143c2ba525495d43Andreas Huber        msg->setInt32("generation", mKeepAliveGeneration);
1398908dbdee96856693decc04fa143c2ba525495d43Andreas Huber        msg->post((mKeepAliveTimeoutUs * 9) / 10);
1399908dbdee96856693decc04fa143c2ba525495d43Andreas Huber    }
1400908dbdee96856693decc04fa143c2ba525495d43Andreas Huber
1401a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber    void postAccessUnitTimeoutCheck() {
1402a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber        if (mCheckPending) {
1403a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber            return;
1404a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber        }
1405a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber
1406a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber        mCheckPending = true;
14071d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> check = new AMessage('chek', this);
1408a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber        check->setInt32("generation", mCheckGeneration);
1409a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber        check->post(kAccessUnitTimeoutUs);
1410a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber    }
1411a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber
14128d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    static void SplitString(
14138d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            const AString &s, const char *separator, List<AString> *items) {
14148d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        items->clear();
14158d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        size_t start = 0;
14168d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        while (start < s.size()) {
14178d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            ssize_t offset = s.find(separator, start);
14188d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14198d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            if (offset < 0) {
14208d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                items->push_back(AString(s, start, s.size() - start));
14218d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                break;
14228d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            }
14238d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14248d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            items->push_back(AString(s, start, offset - start));
14258d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            start = offset + strlen(separator);
14268d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        }
14278d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    }
14288d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14298d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    void parsePlayResponse(const sp<ARTSPResponse> &response) {
1430bbbf9c4552402ab18b255f4058e9e6e506f3f106Yajun Zeng        mPlayResponseParsed = true;
1431e1a31d16dda3460a34e5dfd65c4e96e422dbdbfcPatric Frederiksen        if (mTracks.size() == 0) {
1432e1a31d16dda3460a34e5dfd65c4e96e422dbdbfcPatric Frederiksen            ALOGV("parsePlayResponse: late packets ignored.");
1433e1a31d16dda3460a34e5dfd65c4e96e422dbdbfcPatric Frederiksen            return;
1434e1a31d16dda3460a34e5dfd65c4e96e422dbdbfcPatric Frederiksen        }
14350dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber
14368d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        ssize_t i = response->mHeaders.indexOfKey("range");
14378d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        if (i < 0) {
14388d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            // Server doesn't even tell use what range it is going to
14398d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            // play, therefore we won't support seeking.
14408d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            return;
14418d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        }
14428d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14438d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        AString range = response->mHeaders.valueAt(i);
14443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Range: %s", range.c_str());
14458d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14468d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        AString val;
14478d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        CHECK(GetAttribute(range.c_str(), "npt", &val));
14488d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
1449783e5cd85d4bd40b1a04dfdfed256c5dcb2525ccAndreas Huber        float npt1, npt2;
1450783e5cd85d4bd40b1a04dfdfed256c5dcb2525ccAndreas Huber        if (!ASessionDescription::parseNTPRange(val.c_str(), &npt1, &npt2)) {
14518d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            // This is a live stream and therefore not seekable.
14521906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber
1453df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("This is a live stream");
1454ac5767a96df9fae46a37ffba62611472135a0f6dAndreas Huber            return;
14558d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        }
14568d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14578d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        i = response->mHeaders.indexOfKey("rtp-info");
14588d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        CHECK_GE(i, 0);
14598d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14608d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        AString rtpInfo = response->mHeaders.valueAt(i);
14618d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        List<AString> streamInfos;
14628d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        SplitString(rtpInfo, ",", &streamInfos);
14638d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14648d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        int n = 1;
14658d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        for (List<AString>::iterator it = streamInfos.begin();
14668d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber             it != streamInfos.end(); ++it) {
14678d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            (*it).trim();
14683856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("streamInfo[%d] = %s", n, (*it).c_str());
14698d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14708d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            CHECK(GetAttribute((*it).c_str(), "url", &val));
14718d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14728d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            size_t trackIndex = 0;
14738d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            while (trackIndex < mTracks.size()
14748d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                    && !(val == mTracks.editItemAt(trackIndex).mURL)) {
14758d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber                ++trackIndex;
14768d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            }
14778d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            CHECK_LT(trackIndex, mTracks.size());
14788d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14798d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            CHECK(GetAttribute((*it).c_str(), "seq", &val));
14808d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14818d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            char *end;
14828d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            unsigned long seq = strtoul(val.c_str(), &end, 10);
14838d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14848d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            TrackInfo *info = &mTracks.editItemAt(trackIndex);
14858d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            info->mFirstSeqNumInSegment = seq;
14868d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            info->mNewSegment = true;
14878d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14888d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            CHECK(GetAttribute((*it).c_str(), "rtptime", &val));
14898d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14908d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            uint32_t rtpTime = strtoul(val.c_str(), &end, 10);
14918d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("track #%d: rtpTime=%u <=> npt=%.2f", n, rtpTime, npt1);
14938d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
14942bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            info->mNormalPlayTimeRTP = rtpTime;
14952bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            info->mNormalPlayTimeUs = (int64_t)(npt1 * 1E6);
14962bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
14972bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            if (!mFirstAccessUnit) {
14982bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                postNormalPlayTimeMapping(
14992bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                        trackIndex,
15002bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                        info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs);
15012bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            }
15028d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
15038d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber            ++n;
15048d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        }
15058d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    }
15068d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
15072bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    sp<MetaData> getTrackFormat(size_t index, int32_t *timeScale) {
1508cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        CHECK_GE(index, 0u);
1509cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        CHECK_LT(index, mTracks.size());
1510cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
15112bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        const TrackInfo &info = mTracks.itemAt(index);
15122bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
15132bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        *timeScale = info.mTimeScale;
15142bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
15152bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        return info.mPacketSource->getFormat();
1516cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
1517cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1518cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    size_t countTracks() const {
1519cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return mTracks.size();
1520cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
1521cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1522cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberprivate:
1523100a4408968b90e314526185d572c72ea4cc784aAndreas Huber    struct TrackInfo {
1524100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        AString mURL;
1525100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        int mRTPSocket;
1526100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        int mRTCPSocket;
1527100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        bool mUsingInterleavedTCP;
1528100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        uint32_t mFirstSeqNumInSegment;
1529100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        bool mNewSegment;
1530100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1531100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        uint32_t mRTPAnchor;
1532100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        int64_t mNTPAnchorUs;
1533100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        int32_t mTimeScale;
15341a37ee3c877165c812734b405f922f6e0d747052joakim johansson        bool mEOSReceived;
1535100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
15362bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        uint32_t mNormalPlayTimeRTP;
15372bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        int64_t mNormalPlayTimeUs;
15382bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
1539100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        sp<APacketSource> mPacketSource;
1540100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1541100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        // Stores packets temporarily while no notion of time
1542100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        // has been established yet.
1543100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        List<sp<ABuffer> > mPackets;
1544100a4408968b90e314526185d572c72ea4cc784aAndreas Huber    };
1545100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
15462bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    sp<AMessage> mNotify;
15479b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber    bool mUIDValid;
15489b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber    uid_t mUID;
1549348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber    sp<ALooper> mNetLooper;
1550cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<ARTSPConnection> mConn;
1551cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<ARTPConnection> mRTPConn;
1552cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<ASessionDescription> mSessionDesc;
15534579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString mOriginalSessionURL;  // This one still has user:pass@
1554cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString mSessionURL;
1555de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber    AString mSessionHost;
1556cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString mBaseURL;
1557b6ec588faa7728ff3b518bf809ff75e8dd14f08cMåns Zigher    AString mControlURL;
1558cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString mSessionID;
1559cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    bool mSetupTracksSuccessful;
1560cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber    bool mSeekPending;
1561cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber    bool mFirstAccessUnit;
1562100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
15637e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber    bool mAllTracksHaveTime;
1564100a4408968b90e314526185d572c72ea4cc784aAndreas Huber    int64_t mNTPAnchorUs;
1565100a4408968b90e314526185d572c72ea4cc784aAndreas Huber    int64_t mMediaAnchorUs;
1566100a4408968b90e314526185d572c72ea4cc784aAndreas Huber    int64_t mLastMediaTimeUs;
1567100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
15688d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    int64_t mNumAccessUnitsReceived;
15698d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber    bool mCheckPending;
1570a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber    int32_t mCheckGeneration;
15711a37ee3c877165c812734b405f922f6e0d747052joakim johansson    int32_t mCheckTimeoutGeneration;
15727aef03379179c109c2547c33c410bfc93c8db576Andreas Huber    bool mTryTCPInterleaving;
1573f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber    bool mTryFakeRTCP;
1574e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber    bool mReceivedFirstRTCPPacket;
1575f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber    bool mReceivedFirstRTPPacket;
15760dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber    bool mSeekable;
1577908dbdee96856693decc04fa143c2ba525495d43Andreas Huber    int64_t mKeepAliveTimeoutUs;
1578908dbdee96856693decc04fa143c2ba525495d43Andreas Huber    int32_t mKeepAliveGeneration;
157946d13e3606b87d71379287672b54b50d0d9aa5ccRoger Jönsson    bool mPausing;
15800955986e6c1c27ba752e293246086ea79c49d39cRoger Jönsson    int32_t mPauseGeneration;
1581cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1582cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    Vector<TrackInfo> mTracks;
1583cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1584bbbf9c4552402ab18b255f4058e9e6e506f3f106Yajun Zeng    bool mPlayResponseParsed;
1585bbbf9c4552402ab18b255f4058e9e6e506f3f106Yajun Zeng
1586cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    void setupTrack(size_t index) {
158739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sp<APacketSource> source =
158839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            new APacketSource(mSessionDesc, index);
15897aef03379179c109c2547c33c410bfc93c8db576Andreas Huber
159039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        if (source->initCheck() != OK) {
15916d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar            ALOGW("Unsupported format. Ignoring track #%zu.", index);
159239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
15931d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar            sp<AMessage> reply = new AMessage('setu', this);
159439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            reply->setSize("index", index);
159539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            reply->setInt32("result", ERROR_UNSUPPORTED);
159639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            reply->post();
159739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            return;
159839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        }
159939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
1600cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        AString url;
1601cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        CHECK(mSessionDesc->findAttribute(index, "a=control", &url));
1602cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1603cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        AString trackURL;
1604cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        CHECK(MakeURL(mBaseURL.c_str(), url.c_str(), &trackURL));
1605cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1606cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mTracks.push(TrackInfo());
1607cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        TrackInfo *info = &mTracks.editItemAt(mTracks.size() - 1);
16088d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        info->mURL = trackURL;
160939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        info->mPacketSource = source;
16100792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        info->mUsingInterleavedTCP = false;
16118d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        info->mFirstSeqNumInSegment = 0;
16128d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber        info->mNewSegment = true;
1613b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund        info->mRTPSocket = -1;
1614b6f7642496f955da04d1eb9e33df0dab653c9c4eHenrik Backlund        info->mRTCPSocket = -1;
1615100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        info->mRTPAnchor = 0;
1616100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        info->mNTPAnchorUs = -1;
16172bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        info->mNormalPlayTimeRTP = 0;
16182bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        info->mNormalPlayTimeUs = 0ll;
1619100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1620100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        unsigned long PT;
1621100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        AString formatDesc;
1622100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        AString formatParams;
1623100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        mSessionDesc->getFormatType(index, &PT, &formatDesc, &formatParams);
1624100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1625100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        int32_t timescale;
1626100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        int32_t numChannels;
1627100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        ASessionDescription::ParseFormatDesc(
1628100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                formatDesc.c_str(), &timescale, &numChannels);
1629100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1630100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        info->mTimeScale = timescale;
16311a37ee3c877165c812734b405f922f6e0d747052joakim johansson        info->mEOSReceived = false;
16328d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber
16336d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar        ALOGV("track #%zu URL=%s", mTracks.size(), trackURL.c_str());
1634cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1635cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        AString request = "SETUP ";
1636cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        request.append(trackURL);
1637cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        request.append(" RTSP/1.0\r\n");
1638cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
16397aef03379179c109c2547c33c410bfc93c8db576Andreas Huber        if (mTryTCPInterleaving) {
16407aef03379179c109c2547c33c410bfc93c8db576Andreas Huber            size_t interleaveIndex = 2 * (mTracks.size() - 1);
16417aef03379179c109c2547c33c410bfc93c8db576Andreas Huber            info->mUsingInterleavedTCP = true;
16427aef03379179c109c2547c33c410bfc93c8db576Andreas Huber            info->mRTPSocket = interleaveIndex;
16437aef03379179c109c2547c33c410bfc93c8db576Andreas Huber            info->mRTCPSocket = interleaveIndex + 1;
16447aef03379179c109c2547c33c410bfc93c8db576Andreas Huber
16457aef03379179c109c2547c33c410bfc93c8db576Andreas Huber            request.append("Transport: RTP/AVP/TCP;interleaved=");
16467aef03379179c109c2547c33c410bfc93c8db576Andreas Huber            request.append(interleaveIndex);
16477aef03379179c109c2547c33c410bfc93c8db576Andreas Huber            request.append("-");
16487aef03379179c109c2547c33c410bfc93c8db576Andreas Huber            request.append(interleaveIndex + 1);
16497aef03379179c109c2547c33c410bfc93c8db576Andreas Huber        } else {
16507aef03379179c109c2547c33c410bfc93c8db576Andreas Huber            unsigned rtpPort;
16517aef03379179c109c2547c33c410bfc93c8db576Andreas Huber            ARTPConnection::MakePortPair(
16527aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                    &info->mRTPSocket, &info->mRTCPSocket, &rtpPort);
16537aef03379179c109c2547c33c410bfc93c8db576Andreas Huber
16549b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber            if (mUIDValid) {
1655a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma                HTTPBase::RegisterSocketUserTag(info->mRTPSocket, mUID,
1656a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma                                                (uint32_t)*(uint32_t*) "RTP_");
1657a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma                HTTPBase::RegisterSocketUserTag(info->mRTCPSocket, mUID,
1658a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma                                                (uint32_t)*(uint32_t*) "RTP_");
16595908f88a7e45380a9b0d71a3b1ea535d76c420b3Chad Brubaker                HTTPBase::RegisterSocketUserMark(info->mRTPSocket, mUID);
16605908f88a7e45380a9b0d71a3b1ea535d76c420b3Chad Brubaker                HTTPBase::RegisterSocketUserMark(info->mRTCPSocket, mUID);
16619b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber            }
16629b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
16637aef03379179c109c2547c33c410bfc93c8db576Andreas Huber            request.append("Transport: RTP/AVP/UDP;unicast;client_port=");
16647aef03379179c109c2547c33c410bfc93c8db576Andreas Huber            request.append(rtpPort);
16657aef03379179c109c2547c33c410bfc93c8db576Andreas Huber            request.append("-");
16667aef03379179c109c2547c33c410bfc93c8db576Andreas Huber            request.append(rtpPort + 1);
16677aef03379179c109c2547c33c410bfc93c8db576Andreas Huber        }
16680792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
1669cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        request.append("\r\n");
1670cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1671cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (index > 1) {
1672cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            request.append("Session: ");
1673cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            request.append(mSessionID);
1674cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            request.append("\r\n");
1675cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
1676cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1677cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        request.append("\r\n");
1678cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
16791d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> reply = new AMessage('setu', this);
1680cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setSize("index", index);
1681cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setSize("track-index", mTracks.size() - 1);
1682cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mConn->sendRequest(request.c_str(), reply);
1683cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
1684cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1685cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    static bool MakeURL(const char *baseURL, const char *url, AString *out) {
1686cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        out->clear();
1687cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1688cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (strncasecmp("rtsp://", baseURL, 7)) {
1689cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // Base URL must be absolute
1690cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return false;
1691cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
1692cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1693cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (!strncasecmp("rtsp://", url, 7)) {
1694cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // "url" is already an absolute URL, ignore base URL.
1695cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            out->setTo(url);
1696cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return true;
1697cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
1698cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1699cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size_t n = strlen(baseURL);
17005efccd8da813133060c089c647b07434116406cbChong Zhang        out->setTo(baseURL);
17015efccd8da813133060c089c647b07434116406cbChong Zhang        if (baseURL[n - 1] != '/') {
1702cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            out->append("/");
1703cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
17045efccd8da813133060c089c647b07434116406cbChong Zhang        out->append(url);
1705cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1706cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return true;
1707cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
1708cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1709dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber    void fakeTimestamps() {
17107e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber        mNTPAnchorUs = -1ll;
1711dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber        for (size_t i = 0; i < mTracks.size(); ++i) {
1712dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber            onTimeUpdate(i, 0, 0ll);
1713dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber        }
1714dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber    }
1715dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber
17161a37ee3c877165c812734b405f922f6e0d747052joakim johansson    bool dataReceivedOnAllChannels() {
17171a37ee3c877165c812734b405f922f6e0d747052joakim johansson        TrackInfo *track;
17181a37ee3c877165c812734b405f922f6e0d747052joakim johansson        for (size_t i = 0; i < mTracks.size(); ++i) {
17191a37ee3c877165c812734b405f922f6e0d747052joakim johansson            track = &mTracks.editItemAt(i);
17201a37ee3c877165c812734b405f922f6e0d747052joakim johansson            if (track->mPackets.empty()) {
17211a37ee3c877165c812734b405f922f6e0d747052joakim johansson                return false;
17221a37ee3c877165c812734b405f922f6e0d747052joakim johansson            }
17231a37ee3c877165c812734b405f922f6e0d747052joakim johansson        }
17241a37ee3c877165c812734b405f922f6e0d747052joakim johansson        return true;
17251a37ee3c877165c812734b405f922f6e0d747052joakim johansson    }
17261a37ee3c877165c812734b405f922f6e0d747052joakim johansson
1727ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang    void handleFirstAccessUnit() {
1728ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang        if (mFirstAccessUnit) {
1729ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang            sp<AMessage> msg = mNotify->dup();
1730ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang            msg->setInt32("what", kWhatConnected);
1731ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang            msg->post();
1732ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang
1733ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang            if (mSeekable) {
1734ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang                for (size_t i = 0; i < mTracks.size(); ++i) {
1735ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang                    TrackInfo *info = &mTracks.editItemAt(i);
1736ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang
1737ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang                    postNormalPlayTimeMapping(
1738ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang                            i,
1739ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang                            info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs);
1740ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang                }
1741ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang            }
1742ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang
1743ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang            mFirstAccessUnit = false;
1744ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang        }
1745ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang    }
1746ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang
1747100a4408968b90e314526185d572c72ea4cc784aAndreas Huber    void onTimeUpdate(int32_t trackIndex, uint32_t rtpTime, uint64_t ntpTime) {
17486d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar        ALOGV("onTimeUpdate track %d, rtpTime = 0x%08x, ntpTime = %#016llx",
17496d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar             trackIndex, rtpTime, (long long)ntpTime);
1750100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1751100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        int64_t ntpTimeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32));
1752100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1753100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        TrackInfo *track = &mTracks.editItemAt(trackIndex);
1754100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1755100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        track->mRTPAnchor = rtpTime;
1756100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        track->mNTPAnchorUs = ntpTimeUs;
1757100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1758100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        if (mNTPAnchorUs < 0) {
1759100a4408968b90e314526185d572c72ea4cc784aAndreas Huber            mNTPAnchorUs = ntpTimeUs;
1760100a4408968b90e314526185d572c72ea4cc784aAndreas Huber            mMediaAnchorUs = mLastMediaTimeUs;
1761100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        }
17627e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber
17637e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber        if (!mAllTracksHaveTime) {
176448910f120c59bfcbbe298fdd4a72c6e72e8945e9Wei Jia            bool allTracksHaveTime = (mTracks.size() > 0);
17657e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber            for (size_t i = 0; i < mTracks.size(); ++i) {
17667e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber                TrackInfo *track = &mTracks.editItemAt(i);
17677e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber                if (track->mNTPAnchorUs < 0) {
17687e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber                    allTracksHaveTime = false;
17697e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber                    break;
17707e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber                }
17717e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber            }
17727e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber            if (allTracksHaveTime) {
17737e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber                mAllTracksHaveTime = true;
17747e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber                ALOGI("Time now established for all tracks.");
17757e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber            }
17767e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber        }
17771a37ee3c877165c812734b405f922f6e0d747052joakim johansson        if (mAllTracksHaveTime && dataReceivedOnAllChannels()) {
1778ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang            handleFirstAccessUnit();
1779ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang
17801a37ee3c877165c812734b405f922f6e0d747052joakim johansson            // Time is now established, lets start timestamping immediately
17811a37ee3c877165c812734b405f922f6e0d747052joakim johansson            for (size_t i = 0; i < mTracks.size(); ++i) {
17821a37ee3c877165c812734b405f922f6e0d747052joakim johansson                TrackInfo *trackInfo = &mTracks.editItemAt(i);
17831a37ee3c877165c812734b405f922f6e0d747052joakim johansson                while (!trackInfo->mPackets.empty()) {
17841a37ee3c877165c812734b405f922f6e0d747052joakim johansson                    sp<ABuffer> accessUnit = *trackInfo->mPackets.begin();
17851a37ee3c877165c812734b405f922f6e0d747052joakim johansson                    trackInfo->mPackets.erase(trackInfo->mPackets.begin());
17861a37ee3c877165c812734b405f922f6e0d747052joakim johansson
17871a37ee3c877165c812734b405f922f6e0d747052joakim johansson                    if (addMediaTimestamp(i, trackInfo, accessUnit)) {
17881a37ee3c877165c812734b405f922f6e0d747052joakim johansson                        postQueueAccessUnit(i, accessUnit);
17891a37ee3c877165c812734b405f922f6e0d747052joakim johansson                    }
17901a37ee3c877165c812734b405f922f6e0d747052joakim johansson                }
17911a37ee3c877165c812734b405f922f6e0d747052joakim johansson            }
17921a37ee3c877165c812734b405f922f6e0d747052joakim johansson            for (size_t i = 0; i < mTracks.size(); ++i) {
17931a37ee3c877165c812734b405f922f6e0d747052joakim johansson                TrackInfo *trackInfo = &mTracks.editItemAt(i);
17941a37ee3c877165c812734b405f922f6e0d747052joakim johansson                if (trackInfo->mEOSReceived) {
17951a37ee3c877165c812734b405f922f6e0d747052joakim johansson                    postQueueEOS(i, ERROR_END_OF_STREAM);
17961a37ee3c877165c812734b405f922f6e0d747052joakim johansson                    trackInfo->mEOSReceived = false;
17971a37ee3c877165c812734b405f922f6e0d747052joakim johansson                }
17981a37ee3c877165c812734b405f922f6e0d747052joakim johansson            }
17991a37ee3c877165c812734b405f922f6e0d747052joakim johansson        }
1800100a4408968b90e314526185d572c72ea4cc784aAndreas Huber    }
1801100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1802100a4408968b90e314526185d572c72ea4cc784aAndreas Huber    void onAccessUnitComplete(
1803100a4408968b90e314526185d572c72ea4cc784aAndreas Huber            int32_t trackIndex, const sp<ABuffer> &accessUnit) {
18043856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("onAccessUnitComplete track %d", trackIndex);
1805100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1806bbbf9c4552402ab18b255f4058e9e6e506f3f106Yajun Zeng        if(!mPlayResponseParsed){
1807bbbf9c4552402ab18b255f4058e9e6e506f3f106Yajun Zeng            ALOGI("play response is not parsed, storing accessunit");
1808bbbf9c4552402ab18b255f4058e9e6e506f3f106Yajun Zeng            TrackInfo *track = &mTracks.editItemAt(trackIndex);
1809bbbf9c4552402ab18b255f4058e9e6e506f3f106Yajun Zeng            track->mPackets.push_back(accessUnit);
1810bbbf9c4552402ab18b255f4058e9e6e506f3f106Yajun Zeng            return;
1811bbbf9c4552402ab18b255f4058e9e6e506f3f106Yajun Zeng        }
1812bbbf9c4552402ab18b255f4058e9e6e506f3f106Yajun Zeng
1813ffd5687c9ece8e28779793a20f06f99c7199ce44Chong Zhang        handleFirstAccessUnit();
1814100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1815100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        TrackInfo *track = &mTracks.editItemAt(trackIndex);
1816100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
18177e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber        if (!mAllTracksHaveTime) {
18183856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("storing accessUnit, no time established yet");
1819100a4408968b90e314526185d572c72ea4cc784aAndreas Huber            track->mPackets.push_back(accessUnit);
1820100a4408968b90e314526185d572c72ea4cc784aAndreas Huber            return;
1821100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        }
1822100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1823100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        while (!track->mPackets.empty()) {
1824100a4408968b90e314526185d572c72ea4cc784aAndreas Huber            sp<ABuffer> accessUnit = *track->mPackets.begin();
1825100a4408968b90e314526185d572c72ea4cc784aAndreas Huber            track->mPackets.erase(track->mPackets.begin());
1826100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1827100a4408968b90e314526185d572c72ea4cc784aAndreas Huber            if (addMediaTimestamp(trackIndex, track, accessUnit)) {
18282bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber                postQueueAccessUnit(trackIndex, accessUnit);
1829100a4408968b90e314526185d572c72ea4cc784aAndreas Huber            }
1830100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        }
1831100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1832100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        if (addMediaTimestamp(trackIndex, track, accessUnit)) {
18332bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            postQueueAccessUnit(trackIndex, accessUnit);
1834100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        }
18351a37ee3c877165c812734b405f922f6e0d747052joakim johansson
18361a37ee3c877165c812734b405f922f6e0d747052joakim johansson        if (track->mEOSReceived) {
18371a37ee3c877165c812734b405f922f6e0d747052joakim johansson            postQueueEOS(trackIndex, ERROR_END_OF_STREAM);
18381a37ee3c877165c812734b405f922f6e0d747052joakim johansson            track->mEOSReceived = false;
18391a37ee3c877165c812734b405f922f6e0d747052joakim johansson        }
1840100a4408968b90e314526185d572c72ea4cc784aAndreas Huber    }
1841100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1842100a4408968b90e314526185d572c72ea4cc784aAndreas Huber    bool addMediaTimestamp(
1843100a4408968b90e314526185d572c72ea4cc784aAndreas Huber            int32_t trackIndex, const TrackInfo *track,
1844100a4408968b90e314526185d572c72ea4cc784aAndreas Huber            const sp<ABuffer> &accessUnit) {
184584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        UNUSED_UNLESS_VERBOSE(trackIndex);
184684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber
1847100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        uint32_t rtpTime;
1848100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        CHECK(accessUnit->meta()->findInt32(
1849100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                    "rtp-time", (int32_t *)&rtpTime));
1850100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1851100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        int64_t relRtpTimeUs =
1852100a4408968b90e314526185d572c72ea4cc784aAndreas Huber            (((int64_t)rtpTime - (int64_t)track->mRTPAnchor) * 1000000ll)
1853100a4408968b90e314526185d572c72ea4cc784aAndreas Huber                / track->mTimeScale;
1854100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1855100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        int64_t ntpTimeUs = track->mNTPAnchorUs + relRtpTimeUs;
1856100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1857100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        int64_t mediaTimeUs = mMediaAnchorUs + ntpTimeUs - mNTPAnchorUs;
1858100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1859100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        if (mediaTimeUs > mLastMediaTimeUs) {
1860100a4408968b90e314526185d572c72ea4cc784aAndreas Huber            mLastMediaTimeUs = mediaTimeUs;
1861100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        }
1862100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1863100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        if (mediaTimeUs < 0) {
18643856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("dropping early accessUnit.");
1865100a4408968b90e314526185d572c72ea4cc784aAndreas Huber            return false;
1866100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        }
1867100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
18686d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar        ALOGV("track %d rtpTime=%u mediaTimeUs = %lld us (%.2f secs)",
18696d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnar             trackIndex, rtpTime, (long long)mediaTimeUs, mediaTimeUs / 1E6);
1870100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1871100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        accessUnit->meta()->setInt64("timeUs", mediaTimeUs);
1872100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1873100a4408968b90e314526185d572c72ea4cc784aAndreas Huber        return true;
1874100a4408968b90e314526185d572c72ea4cc784aAndreas Huber    }
1875100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
18762bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    void postQueueAccessUnit(
18772bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            size_t trackIndex, const sp<ABuffer> &accessUnit) {
18782bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        sp<AMessage> msg = mNotify->dup();
18792bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        msg->setInt32("what", kWhatAccessUnit);
18802bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        msg->setSize("trackIndex", trackIndex);
18812d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber        msg->setBuffer("accessUnit", accessUnit);
18822bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        msg->post();
18832bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
18842bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
18852bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    void postQueueEOS(size_t trackIndex, status_t finalResult) {
18862bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        sp<AMessage> msg = mNotify->dup();
18872bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        msg->setInt32("what", kWhatEOS);
18882bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        msg->setSize("trackIndex", trackIndex);
18892bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        msg->setInt32("finalResult", finalResult);
18902bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        msg->post();
18912bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
18922bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
18932bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    void postQueueSeekDiscontinuity(size_t trackIndex) {
18942bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        sp<AMessage> msg = mNotify->dup();
18952bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        msg->setInt32("what", kWhatSeekDiscontinuity);
18962bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        msg->setSize("trackIndex", trackIndex);
18972bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        msg->post();
18982bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
18992bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber
19002bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    void postNormalPlayTimeMapping(
19012bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber            size_t trackIndex, uint32_t rtpTime, int64_t nptUs) {
19022bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        sp<AMessage> msg = mNotify->dup();
19032bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        msg->setInt32("what", kWhatNormalPlayTimeMapping);
19042bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        msg->setSize("trackIndex", trackIndex);
19052bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        msg->setInt32("rtpTime", rtpTime);
19062bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        msg->setInt64("nptUs", nptUs);
19072bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber        msg->post();
19082bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber    }
1909100a4408968b90e314526185d572c72ea4cc784aAndreas Huber
1910cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(MyHandler);
1911cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber};
1912cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1913cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}  // namespace android
1914cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1915cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif  // MY_HANDLER_H_
1916