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> ¬ify, 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(), ×cale, &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