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 226e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber#define LOG_TAG "MyHandler" 236e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber#include <utils/Log.h> 246e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber 25cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "APacketSource.h" 26cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ARTPConnection.h" 27cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ARTSPConnection.h" 28cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ASessionDescription.h" 29cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 308d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber#include <ctype.h> 312bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber#include <cutils/properties.h> 328d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 33cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 34cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ADebug.h> 35cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ALooper.h> 36cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/AMessage.h> 37cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/MediaErrors.h> 38cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 392bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber#include <arpa/inet.h> 402bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber#include <sys/socket.h> 41de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber#include <netdb.h> 422bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 43dab718bba3945332dc75e268e1e7f0fe2eb91c4aAndreas Huber#include "HTTPBase.h" 449b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber 45100a4408968b90e314526185d572c72ea4cc784aAndreas Huber// If no access units are received within 5 secs, assume that the rtp 46e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// stream has ended and signal end of stream. 47908dbdee96856693decc04fa143c2ba525495d43Andreas Huberstatic int64_t kAccessUnitTimeoutUs = 10000000ll; 48e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber 49e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// If no access units arrive for the first 10 secs after starting the 50e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// stream, assume none ever will and signal EOS or switch transports. 51e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huberstatic int64_t kStartupTimeoutUs = 10000000ll; 52e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber 53908dbdee96856693decc04fa143c2ba525495d43Andreas Huberstatic int64_t kDefaultKeepAliveTimeoutUs = 60000000ll; 54908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 55cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubernamespace android { 56cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 572bc940b4f961e588459c83862b2c6bea314a4027Andreas Huberstatic void MakeUserAgentString(AString *s) { 582bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber s->setTo("stagefright/1.1 (Linux;Android "); 592bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 602bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber#if (PROPERTY_VALUE_MAX < 8) 612bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber#error "PROPERTY_VALUE_MAX must be at least 8" 622bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber#endif 632bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 642bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber char value[PROPERTY_VALUE_MAX]; 652bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber property_get("ro.build.version.release", value, "Unknown"); 662bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber s->append(value); 672bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber s->append(")"); 682bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber} 692bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 708d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huberstatic bool GetAttribute(const char *s, const char *key, AString *value) { 718d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber value->clear(); 728d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 738d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber size_t keyLen = strlen(key); 748d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 758d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber for (;;) { 768d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber while (isspace(*s)) { 778d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ++s; 788d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 798d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 808d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber const char *colonPos = strchr(s, ';'); 818d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 828d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber size_t len = 838d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber (colonPos == NULL) ? strlen(s) : colonPos - s; 848d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 858d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) { 868d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber value->setTo(&s[keyLen + 1], len - keyLen - 1); 878d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return true; 888d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 898d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 908d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (colonPos == NULL) { 918d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return false; 928d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 938d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 948d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber s = colonPos + 1; 958d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 968d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber} 978d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 98cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstruct MyHandler : public AHandler { 992bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber enum { 1002bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber kWhatConnected = 'conn', 1012bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber kWhatDisconnected = 'disc', 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), 132e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mTryTCPInterleaving(false), 133f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber mTryFakeRTCP(false), 1340dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber mReceivedFirstRTCPPacket(false), 135f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber mReceivedFirstRTPPacket(false), 136908dbdee96856693decc04fa143c2ba525495d43Andreas Huber mSeekable(false), 137908dbdee96856693decc04fa143c2ba525495d43Andreas Huber mKeepAliveTimeoutUs(kDefaultKeepAliveTimeoutUs), 138908dbdee96856693decc04fa143c2ba525495d43Andreas Huber mKeepAliveGeneration(0) { 139a814c1fdc2acf0ed2ee3b175110f6039be7c4873Andreas Huber mNetLooper->setName("rtsp net"); 140348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber mNetLooper->start(false /* runOnCallingThread */, 141348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber false /* canCallJava */, 142348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber PRIORITY_HIGHEST); 1434579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber 1444579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber // Strip any authentication info from the session url, we don't 1454579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber // want to transmit user/pass in cleartext. 1464579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber AString host, path, user, pass; 1474579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber unsigned port; 148de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber CHECK(ARTSPConnection::ParseURL( 149de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber mSessionURL.c_str(), &host, &port, &path, &user, &pass)); 150de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber 151de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber if (user.size() > 0) { 1524579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mSessionURL.clear(); 1534579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mSessionURL.append("rtsp://"); 1544579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mSessionURL.append(host); 1554579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mSessionURL.append(":"); 1564579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mSessionURL.append(StringPrintf("%u", port)); 1574579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mSessionURL.append(path); 1584579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber 159df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("rewritten session url: '%s'", mSessionURL.c_str()); 1604579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber } 161de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber 162de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber mSessionHost = host; 163348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber } 164348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber 1652bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber void connect() { 1662bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber looper()->registerHandler(mConn); 1672bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber (1 ? mNetLooper : looper())->registerHandler(mRTPConn); 168348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber 1690792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber sp<AMessage> notify = new AMessage('biny', id()); 1700792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber mConn->observeBinaryData(notify); 1710792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 1721b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber sp<AMessage> reply = new AMessage('conn', id()); 1734579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mConn->connect(mOriginalSessionURL.c_str(), reply); 174cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 175cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1762bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber void disconnect() { 1771b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber (new AMessage('abor', id()))->post(); 178348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber } 179348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber 1802bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber void seek(int64_t timeUs) { 181cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber sp<AMessage> msg = new AMessage('seek', id()); 182cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber msg->setInt64("time", timeUs); 183cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber msg->post(); 184cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 185cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 1862bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber static void addRR(const sp<ABuffer> &buf) { 1872bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber uint8_t *ptr = buf->data() + buf->size(); 1882bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[0] = 0x80 | 0; 1892bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[1] = 201; // RR 1902bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[2] = 0; 1912bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[3] = 1; 1922bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[4] = 0xde; // SSRC 1932bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[5] = 0xad; 1942bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[6] = 0xbe; 1952bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[7] = 0xef; 1962bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 1972bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber buf->setRange(0, buf->size() + 8); 1982bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 1992bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2002bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber static void addSDES(int s, const sp<ABuffer> &buffer) { 2012bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber struct sockaddr_in addr; 2022bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber socklen_t addrSize = sizeof(addr); 2032bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber CHECK_EQ(0, getsockname(s, (sockaddr *)&addr, &addrSize)); 2042bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2052bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber uint8_t *data = buffer->data() + buffer->size(); 2062bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[0] = 0x80 | 1; 2072bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[1] = 202; // SDES 2082bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[4] = 0xde; // SSRC 2092bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[5] = 0xad; 2102bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[6] = 0xbe; 2112bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[7] = 0xef; 2122bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2132bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber size_t offset = 8; 2142bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2152bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 1; // CNAME 2162bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2172bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber AString cname = "stagefright@"; 2182bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber cname.append(inet_ntoa(addr.sin_addr)); 2192bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = cname.size(); 2202bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2212bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber memcpy(&data[offset], cname.c_str(), cname.size()); 2222bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber offset += cname.size(); 2232bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2242bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 6; // TOOL 2252bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2262bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber AString tool; 2272bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber MakeUserAgentString(&tool); 2282bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2292bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = tool.size(); 2302bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2312bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber memcpy(&data[offset], tool.c_str(), tool.size()); 2322bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber offset += tool.size(); 2332bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2342bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 0; 2352bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2362bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber if ((offset % 4) > 0) { 2372bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber size_t count = 4 - (offset % 4); 2382bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber switch (count) { 2392bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber case 3: 2402bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 0; 2412bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber case 2: 2422bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 0; 2432bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber case 1: 2442bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 0; 2452bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 2462bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 2472bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2482bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber size_t numWords = (offset / 4) - 1; 2492bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[2] = numWords >> 8; 2502bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[3] = numWords & 0xff; 2512bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2522bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber buffer->setRange(buffer->offset(), buffer->size() + offset); 2532bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 2542bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2552bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber // In case we're behind NAT, fire off two UDP packets to the remote 2562bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber // rtp/rtcp ports to poke a hole into the firewall for future incoming 2572bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber // packets. We're going to send an RR/SDES RTCP packet to both of them. 258dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber bool pokeAHole(int rtpSocket, int rtcpSocket, const AString &transport) { 259de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber struct sockaddr_in addr; 260de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); 261de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber addr.sin_family = AF_INET; 262de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber 2632bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber AString source; 2642bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber AString server_port; 2652bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber if (!GetAttribute(transport.c_str(), 2662bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber "source", 267de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber &source)) { 2685ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("Missing 'source' field in Transport response. Using " 269de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber "RTSP endpoint address."); 270de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber 271de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber struct hostent *ent = gethostbyname(mSessionHost.c_str()); 272de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber if (ent == NULL) { 27329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Failed to look up address of session host '%s'", 274de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber mSessionHost.c_str()); 275de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber 276de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber return false; 277de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber } 278de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber 279de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr; 280de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber } else { 281de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber addr.sin_addr.s_addr = inet_addr(source.c_str()); 282de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber } 283de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber 284de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber if (!GetAttribute(transport.c_str(), 2852bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber "server_port", 2862bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber &server_port)) { 287df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Missing 'server_port' field in Transport response."); 288dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber return false; 2892bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 2902bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2912bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber int rtpPort, rtcpPort; 2922bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber if (sscanf(server_port.c_str(), "%d-%d", &rtpPort, &rtcpPort) != 2 2932bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber || rtpPort <= 0 || rtpPort > 65535 2942bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber || rtcpPort <=0 || rtcpPort > 65535 295dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber || rtcpPort != rtpPort + 1) { 29629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Server picked invalid RTP/RTCP port pair %s," 297dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber " RTP port must be even, RTCP port must be one higher.", 298dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber server_port.c_str()); 299dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 300dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber return false; 301dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } 302dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 303dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber if (rtpPort & 1) { 3045ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("Server picked an odd RTP port, it should've picked an " 305dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber "even one, we'll let it pass for now, but this may break " 306dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber "in the future."); 3072bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 3082bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 3092bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber if (addr.sin_addr.s_addr == INADDR_NONE) { 310dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber return true; 311dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } 312dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 313dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber if (IN_LOOPBACK(ntohl(addr.sin_addr.s_addr))) { 314dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber // No firewalls to traverse on the loopback interface. 315dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber return true; 3162bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 3172bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 3182bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber // Make up an RR/SDES RTCP packet. 3192bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber sp<ABuffer> buf = new ABuffer(65536); 3202bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber buf->setRange(0, 0); 3212bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber addRR(buf); 3222bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber addSDES(rtpSocket, buf); 3232bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 3242bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber addr.sin_port = htons(rtpPort); 3252bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 3262bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ssize_t n = sendto( 3272bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber rtpSocket, buf->data(), buf->size(), 0, 3282bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber (const sockaddr *)&addr, sizeof(addr)); 329dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 330dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber if (n < (ssize_t)buf->size()) { 33129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("failed to poke a hole for RTP packets"); 332dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber return false; 333dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } 3342bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 3352bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber addr.sin_port = htons(rtcpPort); 3362bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 3372bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber n = sendto( 3382bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber rtcpSocket, buf->data(), buf->size(), 0, 3392bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber (const sockaddr *)&addr, sizeof(addr)); 340dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 341dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber if (n < (ssize_t)buf->size()) { 34229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("failed to poke a hole for RTCP packets"); 343dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber return false; 344dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } 3452bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 3463856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("successfully poked holes."); 347dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 348dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber return true; 3492bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 3502bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 351cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber virtual void onMessageReceived(const sp<AMessage> &msg) { 352cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber switch (msg->what()) { 353cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'conn': 354cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 355cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 356cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 357cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 358df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("connection request completed with result %d (%s)", 3596e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber result, strerror(-result)); 360cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 361cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 362cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 363cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request = "DESCRIBE "; 364cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 365cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 366cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Accept: application/sdp\r\n"); 367cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 368cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 369cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('desc', id()); 370cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 3710792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } else { 3720792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber (new AMessage('disc', id()))->post(); 373cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 374cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 375cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 376cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 377cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'disc': 378cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 379908dbdee96856693decc04fa143c2ba525495d43Andreas Huber ++mKeepAliveGeneration; 380908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 3817aef03379179c109c2547c33c410bfc93c8db576Andreas Huber int32_t reconnect; 3827aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (msg->findInt32("reconnect", &reconnect) && reconnect) { 3837aef03379179c109c2547c33c410bfc93c8db576Andreas Huber sp<AMessage> reply = new AMessage('conn', id()); 3844579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mConn->connect(mOriginalSessionURL.c_str(), reply); 3857aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } else { 3867aef03379179c109c2547c33c410bfc93c8db576Andreas Huber (new AMessage('quit', id()))->post(); 3877aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 388cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 389cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 390cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 391cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'desc': 392cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 393cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 394cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 395cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 396df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("DESCRIBE completed with result %d (%s)", 3976e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber result, strerror(-result)); 398cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 399cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 400cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 401cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 402cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response = 403cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 404cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 405cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (response->mStatusCode == 302) { 406cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ssize_t i = response->mHeaders.indexOfKey("location"); 407cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(i, 0); 408cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 409cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionURL = response->mHeaders.valueAt(i); 410cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 411cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 412cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request = "DESCRIBE "; 413cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 414cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 415cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Accept: application/sdp\r\n"); 416cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 417cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 418cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('desc', id()); 419cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 420cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 421cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 422cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 423e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (response->mStatusCode != 200) { 424e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber result = UNKNOWN_ERROR; 425e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } else { 426e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mSessionDesc = new ASessionDescription; 427cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 428e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mSessionDesc->setTo( 429e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber response->mContent->data(), 430e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber response->mContent->size()); 431cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 4326f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (!mSessionDesc->isValid()) { 43329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Failed to parse session description."); 4346f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber result = ERROR_MALFORMED; 435cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 4366f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber ssize_t i = response->mHeaders.indexOfKey("content-base"); 437e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (i >= 0) { 438e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mBaseURL = response->mHeaders.valueAt(i); 439e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } else { 4406f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber i = response->mHeaders.indexOfKey("content-location"); 4416f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (i >= 0) { 4426f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber mBaseURL = response->mHeaders.valueAt(i); 4436f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } else { 4446f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber mBaseURL = mSessionURL; 4456f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 446e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 447e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber 448dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber if (!mBaseURL.startsWith("rtsp://")) { 449dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber // Some misbehaving servers specify a relative 450dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber // URL in one of the locations above, combine 451dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber // it with the absolute session URL to get 452dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber // something usable... 453dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 4545ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("Server specified a non-absolute base URL" 455dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber ", combining it with the session URL to " 456dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber "get something usable..."); 457dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 458dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber AString tmp; 459dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber CHECK(MakeURL( 460dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber mSessionURL.c_str(), 461dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber mBaseURL.c_str(), 462dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber &tmp)); 463dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 464dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber mBaseURL = tmp; 465dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } 466dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 467f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber if (mSessionDesc->countTracks() < 2) { 468f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber // There's no actual tracks in this session. 469f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber // The first "track" is merely session meta 470f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber // data. 471f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber 4725ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("Session doesn't contain any playable " 473f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber "tracks. Aborting."); 474f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber result = ERROR_UNSUPPORTED; 475f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber } else { 476f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber setupTrack(1); 477f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber } 4786f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 479cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 480e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 481cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 482e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (result != OK) { 483cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 484cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 485cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 486cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 487cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 488cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 489cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'setu': 490cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 491cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t index; 492cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findSize("index", &index)); 493cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 49439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber TrackInfo *track = NULL; 495cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t trackIndex; 49639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (msg->findSize("track-index", &trackIndex)) { 49739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber track = &mTracks.editItemAt(trackIndex); 49839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 499cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 500cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 501cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 502cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 503df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("SETUP(%d) completed with result %d (%s)", 5046e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber index, result, strerror(-result)); 505cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 506e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (result == OK) { 50739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK(track != NULL); 508cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 509cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 510cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 511cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response = 512cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 513cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 514e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (response->mStatusCode != 200) { 515e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber result = UNKNOWN_ERROR; 516e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } else { 517e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber ssize_t i = response->mHeaders.indexOfKey("session"); 518e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber CHECK_GE(i, 0); 519cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 520cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionID = response->mHeaders.valueAt(i); 521908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 522908dbdee96856693decc04fa143c2ba525495d43Andreas Huber mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs; 523908dbdee96856693decc04fa143c2ba525495d43Andreas Huber AString timeoutStr; 524908dbdee96856693decc04fa143c2ba525495d43Andreas Huber if (GetAttribute( 525908dbdee96856693decc04fa143c2ba525495d43Andreas Huber mSessionID.c_str(), "timeout", &timeoutStr)) { 526908dbdee96856693decc04fa143c2ba525495d43Andreas Huber char *end; 527908dbdee96856693decc04fa143c2ba525495d43Andreas Huber unsigned long timeoutSecs = 528908dbdee96856693decc04fa143c2ba525495d43Andreas Huber strtoul(timeoutStr.c_str(), &end, 10); 529908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 530908dbdee96856693decc04fa143c2ba525495d43Andreas Huber if (end == timeoutStr.c_str() || *end != '\0') { 5315ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("server specified malformed timeout '%s'", 532908dbdee96856693decc04fa143c2ba525495d43Andreas Huber timeoutStr.c_str()); 533908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 534908dbdee96856693decc04fa143c2ba525495d43Andreas Huber mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs; 535908dbdee96856693decc04fa143c2ba525495d43Andreas Huber } else if (timeoutSecs < 15) { 5365ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("server specified too short a timeout " 537908dbdee96856693decc04fa143c2ba525495d43Andreas Huber "(%lu secs), using default.", 538908dbdee96856693decc04fa143c2ba525495d43Andreas Huber timeoutSecs); 539908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 540908dbdee96856693decc04fa143c2ba525495d43Andreas Huber mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs; 541908dbdee96856693decc04fa143c2ba525495d43Andreas Huber } else { 542908dbdee96856693decc04fa143c2ba525495d43Andreas Huber mKeepAliveTimeoutUs = timeoutSecs * 1000000ll; 543908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 544df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("server specified timeout of %lu secs.", 545908dbdee96856693decc04fa143c2ba525495d43Andreas Huber timeoutSecs); 546908dbdee96856693decc04fa143c2ba525495d43Andreas Huber } 547908dbdee96856693decc04fa143c2ba525495d43Andreas Huber } 548908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 549cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber i = mSessionID.find(";"); 550cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (i >= 0) { 551cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // Remove options, i.e. ";timeout=90" 552cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionID.erase(i, mSessionID.size() - i); 553cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 554cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 555e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber sp<AMessage> notify = new AMessage('accu', id()); 556e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber notify->setSize("track-index", trackIndex); 557cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 5582bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber i = response->mHeaders.indexOfKey("transport"); 5592bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber CHECK_GE(i, 0); 5602bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 5612bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber if (!track->mUsingInterleavedTCP) { 5622bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber AString transport = response->mHeaders.valueAt(i); 5632bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 564de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber // We are going to continue even if we were 565de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber // unable to poke a hole into the firewall... 566de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber pokeAHole( 567de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber track->mRTPSocket, 568de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber track->mRTCPSocket, 569de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber transport); 5702bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 5712bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 572de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber mRTPConn->addStream( 573de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber track->mRTPSocket, track->mRTCPSocket, 574de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber mSessionDesc, index, 575de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber notify, track->mUsingInterleavedTCP); 576cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 577de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber mSetupTracksSuccessful = true; 578e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 579e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 580e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber 581e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (result != OK) { 582e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (track) { 583e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (!track->mUsingInterleavedTCP) { 584a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma // Clear the tag 585a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma if (mUIDValid) { 586a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma HTTPBase::UnRegisterSocketUserTag(track->mRTPSocket); 587a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma HTTPBase::UnRegisterSocketUserTag(track->mRTCPSocket); 588a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma } 589a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma 590e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber close(track->mRTPSocket); 591e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber close(track->mRTCPSocket); 592e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 593e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber 594e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mTracks.removeItemsAt(trackIndex); 595e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 596cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 597cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 59839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber ++index; 59939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (index < mSessionDesc->countTracks()) { 60039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber setupTrack(index); 60139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } else if (mSetupTracksSuccessful) { 602908dbdee96856693decc04fa143c2ba525495d43Andreas Huber ++mKeepAliveGeneration; 603908dbdee96856693decc04fa143c2ba525495d43Andreas Huber postKeepAlive(); 604908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 605cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request = "PLAY "; 606cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 607cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 608cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 609cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 610cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 611cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 612cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 613cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 614cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 615cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('play', id()); 616cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 617cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 618cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 619cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 620cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 621cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 622cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 623cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 624cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'play': 625cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 626cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 627cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 628cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 629df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("PLAY completed with result %d (%s)", 6306e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber result, strerror(-result)); 631cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 632cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 633cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 634cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 635cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response = 636cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 637cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 6386f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (response->mStatusCode != 200) { 6396f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber result = UNKNOWN_ERROR; 6406f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } else { 6416f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber parsePlayResponse(response); 642cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 6436f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber sp<AMessage> timeout = new AMessage('tiou', id()); 6446f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber timeout->post(kStartupTimeoutUs); 6456f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 6466f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 6478d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6486f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (result != OK) { 649cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 650cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 651cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 652cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 653cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 654cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 655cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 656908dbdee96856693decc04fa143c2ba525495d43Andreas Huber case 'aliv': 657908dbdee96856693decc04fa143c2ba525495d43Andreas Huber { 658908dbdee96856693decc04fa143c2ba525495d43Andreas Huber int32_t generation; 659908dbdee96856693decc04fa143c2ba525495d43Andreas Huber CHECK(msg->findInt32("generation", &generation)); 660908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 661908dbdee96856693decc04fa143c2ba525495d43Andreas Huber if (generation != mKeepAliveGeneration) { 662908dbdee96856693decc04fa143c2ba525495d43Andreas Huber // obsolete event. 663908dbdee96856693decc04fa143c2ba525495d43Andreas Huber break; 664908dbdee96856693decc04fa143c2ba525495d43Andreas Huber } 665908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 666908dbdee96856693decc04fa143c2ba525495d43Andreas Huber AString request; 667908dbdee96856693decc04fa143c2ba525495d43Andreas Huber request.append("OPTIONS "); 668908dbdee96856693decc04fa143c2ba525495d43Andreas Huber request.append(mSessionURL); 669908dbdee96856693decc04fa143c2ba525495d43Andreas Huber request.append(" RTSP/1.0\r\n"); 670908dbdee96856693decc04fa143c2ba525495d43Andreas Huber request.append("Session: "); 671908dbdee96856693decc04fa143c2ba525495d43Andreas Huber request.append(mSessionID); 672908dbdee96856693decc04fa143c2ba525495d43Andreas Huber request.append("\r\n"); 673908dbdee96856693decc04fa143c2ba525495d43Andreas Huber request.append("\r\n"); 674908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 675908dbdee96856693decc04fa143c2ba525495d43Andreas Huber sp<AMessage> reply = new AMessage('opts', id()); 676908dbdee96856693decc04fa143c2ba525495d43Andreas Huber reply->setInt32("generation", mKeepAliveGeneration); 677908dbdee96856693decc04fa143c2ba525495d43Andreas Huber mConn->sendRequest(request.c_str(), reply); 678908dbdee96856693decc04fa143c2ba525495d43Andreas Huber break; 679908dbdee96856693decc04fa143c2ba525495d43Andreas Huber } 680908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 681908dbdee96856693decc04fa143c2ba525495d43Andreas Huber case 'opts': 682908dbdee96856693decc04fa143c2ba525495d43Andreas Huber { 683908dbdee96856693decc04fa143c2ba525495d43Andreas Huber int32_t result; 684908dbdee96856693decc04fa143c2ba525495d43Andreas Huber CHECK(msg->findInt32("result", &result)); 685908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 686df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("OPTIONS completed with result %d (%s)", 687908dbdee96856693decc04fa143c2ba525495d43Andreas Huber result, strerror(-result)); 688908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 689908dbdee96856693decc04fa143c2ba525495d43Andreas Huber int32_t generation; 690908dbdee96856693decc04fa143c2ba525495d43Andreas Huber CHECK(msg->findInt32("generation", &generation)); 691908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 692908dbdee96856693decc04fa143c2ba525495d43Andreas Huber if (generation != mKeepAliveGeneration) { 693908dbdee96856693decc04fa143c2ba525495d43Andreas Huber // obsolete event. 694908dbdee96856693decc04fa143c2ba525495d43Andreas Huber break; 695908dbdee96856693decc04fa143c2ba525495d43Andreas Huber } 696908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 697908dbdee96856693decc04fa143c2ba525495d43Andreas Huber postKeepAlive(); 698908dbdee96856693decc04fa143c2ba525495d43Andreas Huber break; 699908dbdee96856693decc04fa143c2ba525495d43Andreas Huber } 700908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 701cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'abor': 702cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 703cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 7047aef03379179c109c2547c33c410bfc93c8db576Andreas Huber TrackInfo *info = &mTracks.editItemAt(i); 7057aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 7062bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (!mFirstAccessUnit) { 7072bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber postQueueEOS(i, ERROR_END_OF_STREAM); 7082bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 7097aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 7107aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (!info->mUsingInterleavedTCP) { 7117aef03379179c109c2547c33c410bfc93c8db576Andreas Huber mRTPConn->removeStream(info->mRTPSocket, info->mRTCPSocket); 7127aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 713a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma // Clear the tag 714a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma if (mUIDValid) { 715a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma HTTPBase::UnRegisterSocketUserTag(info->mRTPSocket); 716a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma HTTPBase::UnRegisterSocketUserTag(info->mRTCPSocket); 717a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma } 718a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma 7197aef03379179c109c2547c33c410bfc93c8db576Andreas Huber close(info->mRTPSocket); 7207aef03379179c109c2547c33c410bfc93c8db576Andreas Huber close(info->mRTCPSocket); 7217aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 722cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 7237aef03379179c109c2547c33c410bfc93c8db576Andreas Huber mTracks.clear(); 724e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mSetupTracksSuccessful = false; 725e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mSeekPending = false; 726e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mFirstAccessUnit = true; 7277e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber mAllTracksHaveTime = false; 728100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mNTPAnchorUs = -1; 729100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mMediaAnchorUs = -1; 730e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mNumAccessUnitsReceived = 0; 731e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mReceivedFirstRTCPPacket = false; 732f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber mReceivedFirstRTPPacket = false; 7330dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber mSeekable = false; 734cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 735cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('tear', id()); 736cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 7377aef03379179c109c2547c33c410bfc93c8db576Andreas Huber int32_t reconnect; 7387aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (msg->findInt32("reconnect", &reconnect) && reconnect) { 7397aef03379179c109c2547c33c410bfc93c8db576Andreas Huber reply->setInt32("reconnect", true); 7407aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 7417aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 742cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 743cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request = "TEARDOWN "; 744cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 745cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // XXX should use aggregate url from SDP here... 746cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 747cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 748cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 749cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 750cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 751cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 752cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 753cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 754cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 755cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 756cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 757cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 758cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 759cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'tear': 760cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 761cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 762cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 763cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 764df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("TEARDOWN completed with result %d (%s)", 7656e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber result, strerror(-result)); 766cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 767cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 7687aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 7697aef03379179c109c2547c33c410bfc93c8db576Andreas Huber int32_t reconnect; 7707aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (msg->findInt32("reconnect", &reconnect) && reconnect) { 7717aef03379179c109c2547c33c410bfc93c8db576Andreas Huber reply->setInt32("reconnect", true); 7727aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 7737aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 774cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 775cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 776cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 777cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 778cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'quit': 779cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 7802bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AMessage> msg = mNotify->dup(); 7812bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->setInt32("what", kWhatDisconnected); 7822bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->setInt32("result", UNKNOWN_ERROR); 7832bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->post(); 784cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 785cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 786cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 7878d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber case 'chek': 7888d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber { 789a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber int32_t generation; 790a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber CHECK(msg->findInt32("generation", &generation)); 791a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber if (generation != mCheckGeneration) { 792a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber // This is an outdated message. Ignore. 793a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber break; 794a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber } 795a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber 7968d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (mNumAccessUnitsReceived == 0) { 79791f230461288a2a5091182ef9e17079aabf8ebaaAndreas Huber#if 1 798df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("stream ended? aborting."); 7998d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber (new AMessage('abor', id()))->post(); 8008d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber break; 801f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber#else 802df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("haven't seen an AU in a looong time."); 803f0c86a83c687074be79397e082e3775ca56641b1Andreas Huber#endif 8048d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 8058d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 8068d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mNumAccessUnitsReceived = 0; 807e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber msg->post(kAccessUnitTimeoutUs); 8088d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber break; 8098d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 8108d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 811cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'accu': 812cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 813100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int32_t timeUpdate; 814100a4408968b90e314526185d572c72ea4cc784aAndreas Huber if (msg->findInt32("time-update", &timeUpdate) && timeUpdate) { 815100a4408968b90e314526185d572c72ea4cc784aAndreas Huber size_t trackIndex; 816100a4408968b90e314526185d572c72ea4cc784aAndreas Huber CHECK(msg->findSize("track-index", &trackIndex)); 817100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 818100a4408968b90e314526185d572c72ea4cc784aAndreas Huber uint32_t rtpTime; 819100a4408968b90e314526185d572c72ea4cc784aAndreas Huber uint64_t ntpTime; 820100a4408968b90e314526185d572c72ea4cc784aAndreas Huber CHECK(msg->findInt32("rtp-time", (int32_t *)&rtpTime)); 821100a4408968b90e314526185d572c72ea4cc784aAndreas Huber CHECK(msg->findInt64("ntp-time", (int64_t *)&ntpTime)); 822100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 823100a4408968b90e314526185d572c72ea4cc784aAndreas Huber onTimeUpdate(trackIndex, rtpTime, ntpTime); 824100a4408968b90e314526185d572c72ea4cc784aAndreas Huber break; 825100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 826100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 827f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber int32_t first; 828f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber if (msg->findInt32("first-rtcp", &first)) { 829e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mReceivedFirstRTCPPacket = true; 830e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber break; 831e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 832e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber 833f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber if (msg->findInt32("first-rtp", &first)) { 834f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber mReceivedFirstRTPPacket = true; 835f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber break; 836f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber } 837f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber 8388d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ++mNumAccessUnitsReceived; 839a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber postAccessUnitTimeoutCheck(); 8408d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 841cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t trackIndex; 842cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findSize("track-index", &trackIndex)); 843cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 8447aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (trackIndex >= mTracks.size()) { 8453856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("late packets ignored."); 8467aef03379179c109c2547c33c410bfc93c8db576Andreas Huber break; 8477aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 8487aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 8498d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 8508d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 851ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber int32_t eos; 852ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber if (msg->findInt32("eos", &eos)) { 853df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("received BYE on track index %d", trackIndex); 854ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber#if 0 855ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber track->mPacketSource->signalEOS(ERROR_END_OF_STREAM); 856ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber#endif 857ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber return; 858ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber } 859ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber 8602d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber sp<ABuffer> accessUnit; 8612d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber CHECK(msg->findBuffer("access-unit", &accessUnit)); 862cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 8638d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber uint32_t seqNum = (uint32_t)accessUnit->int32Data(); 8648d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 8656f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (mSeekPending) { 8663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("we're seeking, dropping stale packet."); 8676f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber break; 8686f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 8696f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber 8708d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (seqNum < track->mFirstSeqNumInSegment) { 8713856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("dropping stale access-unit (%d < %d)", 8726e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber seqNum, track->mFirstSeqNumInSegment); 8738d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber break; 8748d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 8758d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 8768d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (track->mNewSegment) { 8778d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber track->mNewSegment = false; 8788d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 8798d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 880100a4408968b90e314526185d572c72ea4cc784aAndreas Huber onAccessUnitComplete(trackIndex, accessUnit); 881cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 882cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 883cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 884cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber case 'seek': 885cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber { 8860dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber if (!mSeekable) { 8875ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("This is a live stream, ignoring seek request."); 8882bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 8892bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AMessage> msg = mNotify->dup(); 8902bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->setInt32("what", kWhatSeekDone); 8912bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->post(); 892cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber break; 893cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 894cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 895cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber int64_t timeUs; 896cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(msg->findInt64("time", &timeUs)); 897cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 898cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mSeekPending = true; 899cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 900a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber // Disable the access unit timeout until we resumed 901a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber // playback again. 902a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber mCheckPending = true; 903a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber ++mCheckGeneration; 904a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber 905cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber AString request = "PAUSE "; 906cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(mSessionURL); 907cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(" RTSP/1.0\r\n"); 908cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 909cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("Session: "); 910cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(mSessionID); 911cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("\r\n"); 912cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 913cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("\r\n"); 914cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 915cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber sp<AMessage> reply = new AMessage('see1', id()); 916cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber reply->setInt64("time", timeUs); 917cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mConn->sendRequest(request.c_str(), reply); 918cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber break; 919cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 920cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 921cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber case 'see1': 922cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber { 9238d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // Session is paused now. 9248d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 925100a4408968b90e314526185d572c72ea4cc784aAndreas Huber TrackInfo *info = &mTracks.editItemAt(i); 926100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 9272bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber postQueueSeekDiscontinuity(i); 9282bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 929100a4408968b90e314526185d572c72ea4cc784aAndreas Huber info->mRTPAnchor = 0; 930100a4408968b90e314526185d572c72ea4cc784aAndreas Huber info->mNTPAnchorUs = -1; 9318d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 9328d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9337e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber mAllTracksHaveTime = false; 934100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mNTPAnchorUs = -1; 935100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 936cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber int64_t timeUs; 937cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(msg->findInt64("time", &timeUs)); 938cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 939cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber AString request = "PLAY "; 940cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(mSessionURL); 941cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(" RTSP/1.0\r\n"); 942cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 943cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("Session: "); 944cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(mSessionID); 945cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("\r\n"); 946cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 947cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append( 948cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber StringPrintf( 949cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber "Range: npt=%lld-\r\n", timeUs / 1000000ll)); 950cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 951cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("\r\n"); 952cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 953cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber sp<AMessage> reply = new AMessage('see2', id()); 954cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mConn->sendRequest(request.c_str(), reply); 955cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber break; 956cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 957cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 958cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber case 'see2': 959cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber { 960cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(mSeekPending); 961cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 962cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber int32_t result; 963cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(msg->findInt32("result", &result)); 9648d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 965df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("PLAY completed with result %d (%s)", 9666e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber result, strerror(-result)); 9678d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 968a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber mCheckPending = false; 969a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber postAccessUnitTimeoutCheck(); 970a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber 9716f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (result == OK) { 9726f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber sp<RefBase> obj; 9736f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber CHECK(msg->findObject("response", &obj)); 9746f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber sp<ARTSPResponse> response = 9756f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 976cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 9776f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (response->mStatusCode != 200) { 9786f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber result = UNKNOWN_ERROR; 9796f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } else { 9806f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber parsePlayResponse(response); 981cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 982100a4408968b90e314526185d572c72ea4cc784aAndreas Huber ssize_t i = response->mHeaders.indexOfKey("rtp-info"); 983100a4408968b90e314526185d572c72ea4cc784aAndreas Huber CHECK_GE(i, 0); 984100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 9853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("rtp-info: %s", response->mHeaders.valueAt(i).c_str()); 986100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 987df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("seek completed."); 9886f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 9896f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 990cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 9916f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (result != OK) { 99229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("seek failed, aborting."); 9936f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber (new AMessage('abor', id()))->post(); 9946f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 9958d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9968d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mSeekPending = false; 9970dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 9982bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AMessage> msg = mNotify->dup(); 9992bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->setInt32("what", kWhatSeekDone); 10002bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->post(); 1001cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber break; 1002cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 1003cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 10040792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber case 'biny': 10050792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber { 10062d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber sp<ABuffer> buffer; 10072d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber CHECK(msg->findBuffer("buffer", &buffer)); 10080792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 10090792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber int32_t index; 10100792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber CHECK(buffer->meta()->findInt32("index", &index)); 10110792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 10120792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber mRTPConn->injectPacket(index, buffer); 10130792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber break; 10140792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } 10150792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 10160792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber case 'tiou': 10170792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber { 1018e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (!mReceivedFirstRTCPPacket) { 1019dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber if (mReceivedFirstRTPPacket && !mTryFakeRTCP) { 10205ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("We received RTP packets but no RTCP packets, " 1021f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber "using fake timestamps."); 1022f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber 1023f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber mTryFakeRTCP = true; 1024f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber 1025f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber mReceivedFirstRTCPPacket = true; 1026dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 1027dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber fakeTimestamps(); 1028dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } else if (!mReceivedFirstRTPPacket && !mTryTCPInterleaving) { 10295ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("Never received any data, switching transports."); 10307aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 10317aef03379179c109c2547c33c410bfc93c8db576Andreas Huber mTryTCPInterleaving = true; 10327aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 10337aef03379179c109c2547c33c410bfc93c8db576Andreas Huber sp<AMessage> msg = new AMessage('abor', id()); 10347aef03379179c109c2547c33c410bfc93c8db576Andreas Huber msg->setInt32("reconnect", true); 10357aef03379179c109c2547c33c410bfc93c8db576Andreas Huber msg->post(); 1036dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } else { 10375ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("Never received any data, disconnecting."); 1038dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber (new AMessage('abor', id()))->post(); 10397aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 10407e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber } else { 10417e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber if (!mAllTracksHaveTime) { 10427e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber ALOGW("We received some RTCP packets, but time " 10437e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber "could not be established on all tracks, now " 10447e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber "using fake timestamps"); 10457e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber 10467e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber fakeTimestamps(); 10477e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber } 10480792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } 10490792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber break; 10500792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } 10510792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 1052cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber default: 1053cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber TRESPASS(); 1054cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 1055cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1056cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1057cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1058908dbdee96856693decc04fa143c2ba525495d43Andreas Huber void postKeepAlive() { 1059908dbdee96856693decc04fa143c2ba525495d43Andreas Huber sp<AMessage> msg = new AMessage('aliv', id()); 1060908dbdee96856693decc04fa143c2ba525495d43Andreas Huber msg->setInt32("generation", mKeepAliveGeneration); 1061908dbdee96856693decc04fa143c2ba525495d43Andreas Huber msg->post((mKeepAliveTimeoutUs * 9) / 10); 1062908dbdee96856693decc04fa143c2ba525495d43Andreas Huber } 1063908dbdee96856693decc04fa143c2ba525495d43Andreas Huber 1064a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber void postAccessUnitTimeoutCheck() { 1065a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber if (mCheckPending) { 1066a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber return; 1067a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber } 1068a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber 1069a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber mCheckPending = true; 1070a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber sp<AMessage> check = new AMessage('chek', id()); 1071a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber check->setInt32("generation", mCheckGeneration); 1072a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber check->post(kAccessUnitTimeoutUs); 1073a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber } 1074a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber 10758d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber static void SplitString( 10768d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber const AString &s, const char *separator, List<AString> *items) { 10778d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber items->clear(); 10788d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber size_t start = 0; 10798d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber while (start < s.size()) { 10808d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ssize_t offset = s.find(separator, start); 10818d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10828d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (offset < 0) { 10838d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber items->push_back(AString(s, start, s.size() - start)); 10848d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber break; 10858d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 10868d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10878d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber items->push_back(AString(s, start, offset - start)); 10888d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber start = offset + strlen(separator); 10898d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 10908d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 10918d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10928d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber void parsePlayResponse(const sp<ARTSPResponse> &response) { 10930dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber mSeekable = false; 10940dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 10958d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ssize_t i = response->mHeaders.indexOfKey("range"); 10968d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (i < 0) { 10978d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // Server doesn't even tell use what range it is going to 10988d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // play, therefore we won't support seeking. 10998d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return; 11008d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 11018d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11028d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber AString range = response->mHeaders.valueAt(i); 11033856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Range: %s", range.c_str()); 11048d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11058d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber AString val; 11068d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(GetAttribute(range.c_str(), "npt", &val)); 11078d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 1108783e5cd85d4bd40b1a04dfdfed256c5dcb2525ccAndreas Huber float npt1, npt2; 1109783e5cd85d4bd40b1a04dfdfed256c5dcb2525ccAndreas Huber if (!ASessionDescription::parseNTPRange(val.c_str(), &npt1, &npt2)) { 11108d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // This is a live stream and therefore not seekable. 11111906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber 1112df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("This is a live stream"); 1113ac5767a96df9fae46a37ffba62611472135a0f6dAndreas Huber return; 11148d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 11158d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11168d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber i = response->mHeaders.indexOfKey("rtp-info"); 11178d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK_GE(i, 0); 11188d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11198d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber AString rtpInfo = response->mHeaders.valueAt(i); 11208d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber List<AString> streamInfos; 11218d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber SplitString(rtpInfo, ",", &streamInfos); 11228d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11238d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int n = 1; 11248d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber for (List<AString>::iterator it = streamInfos.begin(); 11258d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber it != streamInfos.end(); ++it) { 11268d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber (*it).trim(); 11273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("streamInfo[%d] = %s", n, (*it).c_str()); 11288d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11298d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(GetAttribute((*it).c_str(), "url", &val)); 11308d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11318d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber size_t trackIndex = 0; 11328d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber while (trackIndex < mTracks.size() 11338d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber && !(val == mTracks.editItemAt(trackIndex).mURL)) { 11348d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ++trackIndex; 11358d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 11368d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK_LT(trackIndex, mTracks.size()); 11378d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11388d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(GetAttribute((*it).c_str(), "seq", &val)); 11398d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11408d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber char *end; 11418d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber unsigned long seq = strtoul(val.c_str(), &end, 10); 11428d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11438d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber TrackInfo *info = &mTracks.editItemAt(trackIndex); 11448d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mFirstSeqNumInSegment = seq; 11458d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mNewSegment = true; 11468d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11478d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(GetAttribute((*it).c_str(), "rtptime", &val)); 11488d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11498d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber uint32_t rtpTime = strtoul(val.c_str(), &end, 10); 11508d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("track #%d: rtpTime=%u <=> npt=%.2f", n, rtpTime, npt1); 11528d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11532bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber info->mNormalPlayTimeRTP = rtpTime; 11542bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber info->mNormalPlayTimeUs = (int64_t)(npt1 * 1E6); 11552bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 11562bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber if (!mFirstAccessUnit) { 11572bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber postNormalPlayTimeMapping( 11582bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber trackIndex, 11592bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs); 11602bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 11618d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11628d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ++n; 11638d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 11640dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 1165ac5767a96df9fae46a37ffba62611472135a0f6dAndreas Huber mSeekable = true; 11668d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 11678d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11682bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<MetaData> getTrackFormat(size_t index, int32_t *timeScale) { 1169cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(index, 0u); 1170cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_LT(index, mTracks.size()); 1171cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 11722bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber const TrackInfo &info = mTracks.itemAt(index); 11732bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 11742bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber *timeScale = info.mTimeScale; 11752bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 11762bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber return info.mPacketSource->getFormat(); 1177cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1178cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1179cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t countTracks() const { 1180cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return mTracks.size(); 1181cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1182cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1183cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberprivate: 1184100a4408968b90e314526185d572c72ea4cc784aAndreas Huber struct TrackInfo { 1185100a4408968b90e314526185d572c72ea4cc784aAndreas Huber AString mURL; 1186100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int mRTPSocket; 1187100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int mRTCPSocket; 1188100a4408968b90e314526185d572c72ea4cc784aAndreas Huber bool mUsingInterleavedTCP; 1189100a4408968b90e314526185d572c72ea4cc784aAndreas Huber uint32_t mFirstSeqNumInSegment; 1190100a4408968b90e314526185d572c72ea4cc784aAndreas Huber bool mNewSegment; 1191100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1192100a4408968b90e314526185d572c72ea4cc784aAndreas Huber uint32_t mRTPAnchor; 1193100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int64_t mNTPAnchorUs; 1194100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int32_t mTimeScale; 1195100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 11962bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber uint32_t mNormalPlayTimeRTP; 11972bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber int64_t mNormalPlayTimeUs; 11982bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 1199100a4408968b90e314526185d572c72ea4cc784aAndreas Huber sp<APacketSource> mPacketSource; 1200100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1201100a4408968b90e314526185d572c72ea4cc784aAndreas Huber // Stores packets temporarily while no notion of time 1202100a4408968b90e314526185d572c72ea4cc784aAndreas Huber // has been established yet. 1203100a4408968b90e314526185d572c72ea4cc784aAndreas Huber List<sp<ABuffer> > mPackets; 1204100a4408968b90e314526185d572c72ea4cc784aAndreas Huber }; 1205100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 12062bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AMessage> mNotify; 12079b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber bool mUIDValid; 12089b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber uid_t mUID; 1209348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber sp<ALooper> mNetLooper; 1210cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPConnection> mConn; 1211cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTPConnection> mRTPConn; 1212cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ASessionDescription> mSessionDesc; 12134579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber AString mOriginalSessionURL; // This one still has user:pass@ 1214cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mSessionURL; 1215de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber AString mSessionHost; 1216cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mBaseURL; 1217cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mSessionID; 1218cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber bool mSetupTracksSuccessful; 1219cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber bool mSeekPending; 1220cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber bool mFirstAccessUnit; 1221100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 12227e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber bool mAllTracksHaveTime; 1223100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int64_t mNTPAnchorUs; 1224100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int64_t mMediaAnchorUs; 1225100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int64_t mLastMediaTimeUs; 1226100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 12278d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int64_t mNumAccessUnitsReceived; 12288d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber bool mCheckPending; 1229a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber int32_t mCheckGeneration; 12307aef03379179c109c2547c33c410bfc93c8db576Andreas Huber bool mTryTCPInterleaving; 1231f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber bool mTryFakeRTCP; 1232e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber bool mReceivedFirstRTCPPacket; 1233f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber bool mReceivedFirstRTPPacket; 12340dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber bool mSeekable; 1235908dbdee96856693decc04fa143c2ba525495d43Andreas Huber int64_t mKeepAliveTimeoutUs; 1236908dbdee96856693decc04fa143c2ba525495d43Andreas Huber int32_t mKeepAliveGeneration; 1237cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1238cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber Vector<TrackInfo> mTracks; 1239cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1240cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber void setupTrack(size_t index) { 124139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber sp<APacketSource> source = 124239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber new APacketSource(mSessionDesc, index); 12437aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 124439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (source->initCheck() != OK) { 12455ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("Unsupported format. Ignoring track #%d.", index); 124639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 124739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber sp<AMessage> reply = new AMessage('setu', id()); 124839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber reply->setSize("index", index); 124939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber reply->setInt32("result", ERROR_UNSUPPORTED); 125039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber reply->post(); 125139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return; 125239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 125339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 1254cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString url; 1255cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(mSessionDesc->findAttribute(index, "a=control", &url)); 1256cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1257cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString trackURL; 1258cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(MakeURL(mBaseURL.c_str(), url.c_str(), &trackURL)); 1259cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1260cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mTracks.push(TrackInfo()); 1261cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber TrackInfo *info = &mTracks.editItemAt(mTracks.size() - 1); 12628d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mURL = trackURL; 126339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber info->mPacketSource = source; 12640792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber info->mUsingInterleavedTCP = false; 12658d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mFirstSeqNumInSegment = 0; 12668d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mNewSegment = true; 1267100a4408968b90e314526185d572c72ea4cc784aAndreas Huber info->mRTPAnchor = 0; 1268100a4408968b90e314526185d572c72ea4cc784aAndreas Huber info->mNTPAnchorUs = -1; 12692bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber info->mNormalPlayTimeRTP = 0; 12702bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber info->mNormalPlayTimeUs = 0ll; 1271100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1272100a4408968b90e314526185d572c72ea4cc784aAndreas Huber unsigned long PT; 1273100a4408968b90e314526185d572c72ea4cc784aAndreas Huber AString formatDesc; 1274100a4408968b90e314526185d572c72ea4cc784aAndreas Huber AString formatParams; 1275100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mSessionDesc->getFormatType(index, &PT, &formatDesc, &formatParams); 1276100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1277100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int32_t timescale; 1278100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int32_t numChannels; 1279100a4408968b90e314526185d572c72ea4cc784aAndreas Huber ASessionDescription::ParseFormatDesc( 1280100a4408968b90e314526185d572c72ea4cc784aAndreas Huber formatDesc.c_str(), ×cale, &numChannels); 1281100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1282100a4408968b90e314526185d572c72ea4cc784aAndreas Huber info->mTimeScale = timescale; 12838d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 12843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("track #%d URL=%s", mTracks.size(), trackURL.c_str()); 1285cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1286cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request = "SETUP "; 1287cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(trackURL); 1288cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 1289cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 12907aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (mTryTCPInterleaving) { 12917aef03379179c109c2547c33c410bfc93c8db576Andreas Huber size_t interleaveIndex = 2 * (mTracks.size() - 1); 12927aef03379179c109c2547c33c410bfc93c8db576Andreas Huber info->mUsingInterleavedTCP = true; 12937aef03379179c109c2547c33c410bfc93c8db576Andreas Huber info->mRTPSocket = interleaveIndex; 12947aef03379179c109c2547c33c410bfc93c8db576Andreas Huber info->mRTCPSocket = interleaveIndex + 1; 12957aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 12967aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append("Transport: RTP/AVP/TCP;interleaved="); 12977aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append(interleaveIndex); 12987aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append("-"); 12997aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append(interleaveIndex + 1); 13007aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } else { 13017aef03379179c109c2547c33c410bfc93c8db576Andreas Huber unsigned rtpPort; 13027aef03379179c109c2547c33c410bfc93c8db576Andreas Huber ARTPConnection::MakePortPair( 13037aef03379179c109c2547c33c410bfc93c8db576Andreas Huber &info->mRTPSocket, &info->mRTCPSocket, &rtpPort); 13047aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 13059b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber if (mUIDValid) { 1306a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma HTTPBase::RegisterSocketUserTag(info->mRTPSocket, mUID, 1307a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma (uint32_t)*(uint32_t*) "RTP_"); 1308a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma HTTPBase::RegisterSocketUserTag(info->mRTCPSocket, mUID, 1309a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma (uint32_t)*(uint32_t*) "RTP_"); 13109b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber } 13119b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber 13127aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append("Transport: RTP/AVP/UDP;unicast;client_port="); 13137aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append(rtpPort); 13147aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append("-"); 13157aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append(rtpPort + 1); 13167aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 13170792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 1318cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 1319cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1320cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (index > 1) { 1321cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 1322cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 1323cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 1324cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1325cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1326cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 1327cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1328cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('setu', id()); 1329cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber reply->setSize("index", index); 1330cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber reply->setSize("track-index", mTracks.size() - 1); 1331cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 1332cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1333cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1334cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static bool MakeURL(const char *baseURL, const char *url, AString *out) { 1335cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->clear(); 1336cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1337cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (strncasecmp("rtsp://", baseURL, 7)) { 1338cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // Base URL must be absolute 1339cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return false; 1340cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1341cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1342cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (!strncasecmp("rtsp://", url, 7)) { 1343cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // "url" is already an absolute URL, ignore base URL. 1344cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(url); 1345cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return true; 1346cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1347cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1348cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t n = strlen(baseURL); 1349cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (baseURL[n - 1] == '/') { 1350cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(baseURL); 1351cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append(url); 1352cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 13534e2ffa400b82559cab2c5717c8dcdff393d334a9Mike Lockwood const char *slashPos = strrchr(baseURL, '/'); 1354cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1355cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (slashPos > &baseURL[6]) { 1356cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(baseURL, slashPos - baseURL); 1357cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 1358cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(baseURL); 1359cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1360cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1361cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append("/"); 1362cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append(url); 1363cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1364cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1365cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return true; 1366cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1367cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1368dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber void fakeTimestamps() { 13697e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber mNTPAnchorUs = -1ll; 1370dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 1371dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber onTimeUpdate(i, 0, 0ll); 1372dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } 1373dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } 1374dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 1375100a4408968b90e314526185d572c72ea4cc784aAndreas Huber void onTimeUpdate(int32_t trackIndex, uint32_t rtpTime, uint64_t ntpTime) { 13763856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("onTimeUpdate track %d, rtpTime = 0x%08x, ntpTime = 0x%016llx", 1377100a4408968b90e314526185d572c72ea4cc784aAndreas Huber trackIndex, rtpTime, ntpTime); 1378100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1379100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int64_t ntpTimeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32)); 1380100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1381100a4408968b90e314526185d572c72ea4cc784aAndreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 1382100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1383100a4408968b90e314526185d572c72ea4cc784aAndreas Huber track->mRTPAnchor = rtpTime; 1384100a4408968b90e314526185d572c72ea4cc784aAndreas Huber track->mNTPAnchorUs = ntpTimeUs; 1385100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1386100a4408968b90e314526185d572c72ea4cc784aAndreas Huber if (mNTPAnchorUs < 0) { 1387100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mNTPAnchorUs = ntpTimeUs; 1388100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mMediaAnchorUs = mLastMediaTimeUs; 1389100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 13907e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber 13917e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber if (!mAllTracksHaveTime) { 13927e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber bool allTracksHaveTime = true; 13937e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 13947e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber TrackInfo *track = &mTracks.editItemAt(i); 13957e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber if (track->mNTPAnchorUs < 0) { 13967e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber allTracksHaveTime = false; 13977e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber break; 13987e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber } 13997e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber } 14007e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber if (allTracksHaveTime) { 14017e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber mAllTracksHaveTime = true; 14027e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber ALOGI("Time now established for all tracks."); 14037e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber } 14047e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber } 1405100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1406100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1407100a4408968b90e314526185d572c72ea4cc784aAndreas Huber void onAccessUnitComplete( 1408100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int32_t trackIndex, const sp<ABuffer> &accessUnit) { 14093856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("onAccessUnitComplete track %d", trackIndex); 1410100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1411100a4408968b90e314526185d572c72ea4cc784aAndreas Huber if (mFirstAccessUnit) { 14122bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AMessage> msg = mNotify->dup(); 14132bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->setInt32("what", kWhatConnected); 14142bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->post(); 14152bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 14161906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber if (mSeekable) { 14171906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 14181906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber TrackInfo *info = &mTracks.editItemAt(i); 14192bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 14201906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber postNormalPlayTimeMapping( 14211906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber i, 14221906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs); 14231906e5c7492b9cbc88601365536a69e9a490c963Andreas Huber } 14242bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 1425100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1426100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mFirstAccessUnit = false; 1427100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1428100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1429100a4408968b90e314526185d572c72ea4cc784aAndreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 1430100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 14317e73e44c2d2208a7079e562f7b0b9b73ef6a29f1Andreas Huber if (!mAllTracksHaveTime) { 14323856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("storing accessUnit, no time established yet"); 1433100a4408968b90e314526185d572c72ea4cc784aAndreas Huber track->mPackets.push_back(accessUnit); 1434100a4408968b90e314526185d572c72ea4cc784aAndreas Huber return; 1435100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1436100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1437100a4408968b90e314526185d572c72ea4cc784aAndreas Huber while (!track->mPackets.empty()) { 1438100a4408968b90e314526185d572c72ea4cc784aAndreas Huber sp<ABuffer> accessUnit = *track->mPackets.begin(); 1439100a4408968b90e314526185d572c72ea4cc784aAndreas Huber track->mPackets.erase(track->mPackets.begin()); 1440100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1441100a4408968b90e314526185d572c72ea4cc784aAndreas Huber if (addMediaTimestamp(trackIndex, track, accessUnit)) { 14422bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber postQueueAccessUnit(trackIndex, accessUnit); 1443100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1444100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1445100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1446100a4408968b90e314526185d572c72ea4cc784aAndreas Huber if (addMediaTimestamp(trackIndex, track, accessUnit)) { 14472bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber postQueueAccessUnit(trackIndex, accessUnit); 1448100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1449100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1450100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1451100a4408968b90e314526185d572c72ea4cc784aAndreas Huber bool addMediaTimestamp( 1452100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int32_t trackIndex, const TrackInfo *track, 1453100a4408968b90e314526185d572c72ea4cc784aAndreas Huber const sp<ABuffer> &accessUnit) { 1454100a4408968b90e314526185d572c72ea4cc784aAndreas Huber uint32_t rtpTime; 1455100a4408968b90e314526185d572c72ea4cc784aAndreas Huber CHECK(accessUnit->meta()->findInt32( 1456100a4408968b90e314526185d572c72ea4cc784aAndreas Huber "rtp-time", (int32_t *)&rtpTime)); 1457100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1458100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int64_t relRtpTimeUs = 1459100a4408968b90e314526185d572c72ea4cc784aAndreas Huber (((int64_t)rtpTime - (int64_t)track->mRTPAnchor) * 1000000ll) 1460100a4408968b90e314526185d572c72ea4cc784aAndreas Huber / track->mTimeScale; 1461100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1462100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int64_t ntpTimeUs = track->mNTPAnchorUs + relRtpTimeUs; 1463100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1464100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int64_t mediaTimeUs = mMediaAnchorUs + ntpTimeUs - mNTPAnchorUs; 1465100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1466100a4408968b90e314526185d572c72ea4cc784aAndreas Huber if (mediaTimeUs > mLastMediaTimeUs) { 1467100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mLastMediaTimeUs = mediaTimeUs; 1468100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1469100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1470100a4408968b90e314526185d572c72ea4cc784aAndreas Huber if (mediaTimeUs < 0) { 14713856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("dropping early accessUnit."); 1472100a4408968b90e314526185d572c72ea4cc784aAndreas Huber return false; 1473100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1474100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 14753856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("track %d rtpTime=%d mediaTimeUs = %lld us (%.2f secs)", 1476100a4408968b90e314526185d572c72ea4cc784aAndreas Huber trackIndex, rtpTime, mediaTimeUs, mediaTimeUs / 1E6); 1477100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1478100a4408968b90e314526185d572c72ea4cc784aAndreas Huber accessUnit->meta()->setInt64("timeUs", mediaTimeUs); 1479100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1480100a4408968b90e314526185d572c72ea4cc784aAndreas Huber return true; 1481100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1482100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 14832bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber void postQueueAccessUnit( 14842bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber size_t trackIndex, const sp<ABuffer> &accessUnit) { 14852bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AMessage> msg = mNotify->dup(); 14862bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->setInt32("what", kWhatAccessUnit); 14872bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->setSize("trackIndex", trackIndex); 14882d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber msg->setBuffer("accessUnit", accessUnit); 14892bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->post(); 14902bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 14912bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 14922bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber void postQueueEOS(size_t trackIndex, status_t finalResult) { 14932bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AMessage> msg = mNotify->dup(); 14942bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->setInt32("what", kWhatEOS); 14952bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->setSize("trackIndex", trackIndex); 14962bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->setInt32("finalResult", finalResult); 14972bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->post(); 14982bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 14992bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 15002bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber void postQueueSeekDiscontinuity(size_t trackIndex) { 15012bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AMessage> msg = mNotify->dup(); 15022bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->setInt32("what", kWhatSeekDiscontinuity); 15032bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->setSize("trackIndex", trackIndex); 15042bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->post(); 15052bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 15062bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber 15072bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber void postNormalPlayTimeMapping( 15082bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber size_t trackIndex, uint32_t rtpTime, int64_t nptUs) { 15092bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber sp<AMessage> msg = mNotify->dup(); 15102bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->setInt32("what", kWhatNormalPlayTimeMapping); 15112bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->setSize("trackIndex", trackIndex); 15122bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->setInt32("rtpTime", rtpTime); 15132bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->setInt64("nptUs", nptUs); 15142bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber msg->post(); 15152bfdd428c56c7524d1a11979f200a1762866032dAndreas Huber } 1516100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1517cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber DISALLOW_EVIL_CONSTRUCTORS(MyHandler); 1518cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}; 1519cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1520cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber} // namespace android 1521cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1522cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif // MY_HANDLER_H_ 1523