MyHandler.h revision dab718bba3945332dc75e268e1e7f0fe2eb91c4a
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. 47100a4408968b90e314526185d572c72ea4cc784aAndreas Huberstatic int64_t kAccessUnitTimeoutUs = 5000000ll; 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 53cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubernamespace android { 54cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 552bc940b4f961e588459c83862b2c6bea314a4027Andreas Huberstatic void MakeUserAgentString(AString *s) { 562bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber s->setTo("stagefright/1.1 (Linux;Android "); 572bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 582bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber#if (PROPERTY_VALUE_MAX < 8) 592bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber#error "PROPERTY_VALUE_MAX must be at least 8" 602bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber#endif 612bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 622bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber char value[PROPERTY_VALUE_MAX]; 632bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber property_get("ro.build.version.release", value, "Unknown"); 642bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber s->append(value); 652bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber s->append(")"); 662bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber} 672bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 688d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huberstatic bool GetAttribute(const char *s, const char *key, AString *value) { 698d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber value->clear(); 708d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 718d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber size_t keyLen = strlen(key); 728d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 738d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber for (;;) { 748d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber while (isspace(*s)) { 758d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ++s; 768d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 778d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 788d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber const char *colonPos = strchr(s, ';'); 798d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 808d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber size_t len = 818d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber (colonPos == NULL) ? strlen(s) : colonPos - s; 828d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 838d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) { 848d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber value->setTo(&s[keyLen + 1], len - keyLen - 1); 858d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return true; 868d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 878d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 888d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (colonPos == NULL) { 898d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return false; 908d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 918d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 928d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber s = colonPos + 1; 938d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 948d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber} 958d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 96cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstruct MyHandler : public AHandler { 979b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber MyHandler( 989b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber const char *url, const sp<ALooper> &looper, 999b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber bool uidValid = false, uid_t uid = 0) 1009b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber : mUIDValid(uidValid), 1019b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber mUID(uid), 1029b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber mLooper(looper), 103348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber mNetLooper(new ALooper), 1049b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber mConn(new ARTSPConnection(mUIDValid, mUID)), 105cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRTPConn(new ARTPConnection), 1064579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mOriginalSessionURL(url), 107cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionURL(url), 108cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mSetupTracksSuccessful(false), 109cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mSeekPending(false), 110cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mFirstAccessUnit(true), 111100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mNTPAnchorUs(-1), 112100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mMediaAnchorUs(-1), 113100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mLastMediaTimeUs(0), 1148d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mNumAccessUnitsReceived(0), 1157aef03379179c109c2547c33c410bfc93c8db576Andreas Huber mCheckPending(false), 116a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber mCheckGeneration(0), 117e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mTryTCPInterleaving(false), 118f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber mTryFakeRTCP(false), 1190dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber mReceivedFirstRTCPPacket(false), 120f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber mReceivedFirstRTPPacket(false), 1210dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber mSeekable(false) { 122a814c1fdc2acf0ed2ee3b175110f6039be7c4873Andreas Huber mNetLooper->setName("rtsp net"); 123348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber mNetLooper->start(false /* runOnCallingThread */, 124348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber false /* canCallJava */, 125348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber PRIORITY_HIGHEST); 1264579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber 1274579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber // Strip any authentication info from the session url, we don't 1284579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber // want to transmit user/pass in cleartext. 1294579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber AString host, path, user, pass; 1304579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber unsigned port; 131de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber CHECK(ARTSPConnection::ParseURL( 132de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber mSessionURL.c_str(), &host, &port, &path, &user, &pass)); 133de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber 134de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber if (user.size() > 0) { 1354579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mSessionURL.clear(); 1364579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mSessionURL.append("rtsp://"); 1374579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mSessionURL.append(host); 1384579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mSessionURL.append(":"); 1394579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mSessionURL.append(StringPrintf("%u", port)); 1404579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mSessionURL.append(path); 1414579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber 1424579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber LOGI("rewritten session url: '%s'", mSessionURL.c_str()); 1434579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber } 144de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber 145de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber mSessionHost = host; 146348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber } 147348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber 1481b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber void connect(const sp<AMessage> &doneMsg) { 1491b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg = doneMsg; 1501b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber 151cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLooper->registerHandler(this); 152cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLooper->registerHandler(mConn); 153348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber (1 ? mNetLooper : mLooper)->registerHandler(mRTPConn); 154348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber 1550792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber sp<AMessage> notify = new AMessage('biny', id()); 1560792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber mConn->observeBinaryData(notify); 1570792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 1581b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber sp<AMessage> reply = new AMessage('conn', id()); 1594579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mConn->connect(mOriginalSessionURL.c_str(), reply); 160cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 161cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1621b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber void disconnect(const sp<AMessage> &doneMsg) { 1631b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg = doneMsg; 1641b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber 1651b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber (new AMessage('abor', id()))->post(); 166348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber } 167348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber 1680dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber void seek(int64_t timeUs, const sp<AMessage> &doneMsg) { 169cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber sp<AMessage> msg = new AMessage('seek', id()); 170cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber msg->setInt64("time", timeUs); 1710dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber msg->setMessage("doneMsg", doneMsg); 172cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber msg->post(); 173cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 174cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 1758d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int64_t getNormalPlayTimeUs() { 1768d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int64_t maxTimeUs = 0; 1778d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 1788d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int64_t timeUs = mTracks.editItemAt(i).mPacketSource 1798d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ->getNormalPlayTimeUs(); 1808d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 1818d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (i == 0 || timeUs > maxTimeUs) { 1828d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber maxTimeUs = timeUs; 1838d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 1848d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 1858d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 1868d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return maxTimeUs; 1878d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 1888d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 1892bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber static void addRR(const sp<ABuffer> &buf) { 1902bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber uint8_t *ptr = buf->data() + buf->size(); 1912bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[0] = 0x80 | 0; 1922bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[1] = 201; // RR 1932bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[2] = 0; 1942bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[3] = 1; 1952bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[4] = 0xde; // SSRC 1962bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[5] = 0xad; 1972bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[6] = 0xbe; 1982bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[7] = 0xef; 1992bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2002bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber buf->setRange(0, buf->size() + 8); 2012bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 2022bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2032bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber static void addSDES(int s, const sp<ABuffer> &buffer) { 2042bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber struct sockaddr_in addr; 2052bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber socklen_t addrSize = sizeof(addr); 2062bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber CHECK_EQ(0, getsockname(s, (sockaddr *)&addr, &addrSize)); 2072bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2082bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber uint8_t *data = buffer->data() + buffer->size(); 2092bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[0] = 0x80 | 1; 2102bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[1] = 202; // SDES 2112bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[4] = 0xde; // SSRC 2122bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[5] = 0xad; 2132bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[6] = 0xbe; 2142bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[7] = 0xef; 2152bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2162bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber size_t offset = 8; 2172bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2182bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 1; // CNAME 2192bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2202bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber AString cname = "stagefright@"; 2212bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber cname.append(inet_ntoa(addr.sin_addr)); 2222bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = cname.size(); 2232bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2242bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber memcpy(&data[offset], cname.c_str(), cname.size()); 2252bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber offset += cname.size(); 2262bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2272bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 6; // TOOL 2282bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2292bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber AString tool; 2302bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber MakeUserAgentString(&tool); 2312bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2322bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = tool.size(); 2332bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2342bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber memcpy(&data[offset], tool.c_str(), tool.size()); 2352bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber offset += tool.size(); 2362bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2372bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 0; 2382bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2392bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber if ((offset % 4) > 0) { 2402bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber size_t count = 4 - (offset % 4); 2412bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber switch (count) { 2422bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber case 3: 2432bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 0; 2442bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber case 2: 2452bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 0; 2462bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber case 1: 2472bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 0; 2482bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 2492bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 2502bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2512bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber size_t numWords = (offset / 4) - 1; 2522bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[2] = numWords >> 8; 2532bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[3] = numWords & 0xff; 2542bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2552bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber buffer->setRange(buffer->offset(), buffer->size() + offset); 2562bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 2572bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2582bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber // In case we're behind NAT, fire off two UDP packets to the remote 2592bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber // rtp/rtcp ports to poke a hole into the firewall for future incoming 2602bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber // packets. We're going to send an RR/SDES RTCP packet to both of them. 261dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber bool pokeAHole(int rtpSocket, int rtcpSocket, const AString &transport) { 262de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber struct sockaddr_in addr; 263de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); 264de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber addr.sin_family = AF_INET; 265de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber 2662bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber AString source; 2672bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber AString server_port; 2682bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber if (!GetAttribute(transport.c_str(), 2692bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber "source", 270de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber &source)) { 271de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber LOGW("Missing 'source' field in Transport response. Using " 272de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber "RTSP endpoint address."); 273de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber 274de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber struct hostent *ent = gethostbyname(mSessionHost.c_str()); 275de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber if (ent == NULL) { 276de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber LOGE("Failed to look up address of session host '%s'", 277de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber mSessionHost.c_str()); 278de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber 279de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber return false; 280de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber } 281de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber 282de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr; 283de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber } else { 284de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber addr.sin_addr.s_addr = inet_addr(source.c_str()); 285de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber } 286de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber 287de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber if (!GetAttribute(transport.c_str(), 2882bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber "server_port", 2892bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber &server_port)) { 290de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber LOGI("Missing 'server_port' field in Transport response."); 291dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber return false; 2922bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 2932bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2942bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber int rtpPort, rtcpPort; 2952bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber if (sscanf(server_port.c_str(), "%d-%d", &rtpPort, &rtcpPort) != 2 2962bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber || rtpPort <= 0 || rtpPort > 65535 2972bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber || rtcpPort <=0 || rtcpPort > 65535 298dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber || rtcpPort != rtpPort + 1) { 299dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber LOGE("Server picked invalid RTP/RTCP port pair %s," 300dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber " RTP port must be even, RTCP port must be one higher.", 301dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber server_port.c_str()); 302dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 303dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber return false; 304dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } 305dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 306dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber if (rtpPort & 1) { 307dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber LOGW("Server picked an odd RTP port, it should've picked an " 308dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber "even one, we'll let it pass for now, but this may break " 309dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber "in the future."); 3102bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 3112bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 3122bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber if (addr.sin_addr.s_addr == INADDR_NONE) { 313dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber return true; 314dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } 315dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 316dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber if (IN_LOOPBACK(ntohl(addr.sin_addr.s_addr))) { 317dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber // No firewalls to traverse on the loopback interface. 318dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber return true; 3192bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 3202bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 3212bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber // Make up an RR/SDES RTCP packet. 3222bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber sp<ABuffer> buf = new ABuffer(65536); 3232bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber buf->setRange(0, 0); 3242bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber addRR(buf); 3252bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber addSDES(rtpSocket, buf); 3262bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 3272bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber addr.sin_port = htons(rtpPort); 3282bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 3292bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ssize_t n = sendto( 3302bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber rtpSocket, buf->data(), buf->size(), 0, 3312bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber (const sockaddr *)&addr, sizeof(addr)); 332dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 333dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber if (n < (ssize_t)buf->size()) { 334dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber LOGE("failed to poke a hole for RTP packets"); 335dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber return false; 336dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } 3372bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 3382bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber addr.sin_port = htons(rtcpPort); 3392bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 3402bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber n = sendto( 3412bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber rtcpSocket, buf->data(), buf->size(), 0, 3422bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber (const sockaddr *)&addr, sizeof(addr)); 343dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 344dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber if (n < (ssize_t)buf->size()) { 345dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber LOGE("failed to poke a hole for RTCP packets"); 346dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber return false; 347dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } 3482bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 3492bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber LOGV("successfully poked holes."); 350dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 351dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber return true; 3522bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 3532bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 354cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber virtual void onMessageReceived(const sp<AMessage> &msg) { 355cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber switch (msg->what()) { 356cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'conn': 357cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 358cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 359cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 360cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 3616e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("connection request completed with result %d (%s)", 3626e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber result, strerror(-result)); 363cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 364cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 365cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 366cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request = "DESCRIBE "; 367cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 368cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 369cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Accept: application/sdp\r\n"); 370cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 371cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 372cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('desc', id()); 373cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 3740792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } else { 3750792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber (new AMessage('disc', id()))->post(); 376cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 377cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 378cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 379cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 380cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'disc': 381cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 3827aef03379179c109c2547c33c410bfc93c8db576Andreas Huber int32_t reconnect; 3837aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (msg->findInt32("reconnect", &reconnect) && reconnect) { 3847aef03379179c109c2547c33c410bfc93c8db576Andreas Huber sp<AMessage> reply = new AMessage('conn', id()); 3854579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber mConn->connect(mOriginalSessionURL.c_str(), reply); 3867aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } else { 3877aef03379179c109c2547c33c410bfc93c8db576Andreas Huber (new AMessage('quit', id()))->post(); 3887aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 389cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 390cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 391cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 392cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'desc': 393cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 394cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 395cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 396cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 3976e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("DESCRIBE completed with result %d (%s)", 3986e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber result, strerror(-result)); 399cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 400cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 401cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 402cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 403cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response = 404cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 405cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 406cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (response->mStatusCode == 302) { 407cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ssize_t i = response->mHeaders.indexOfKey("location"); 408cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(i, 0); 409cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 410cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionURL = response->mHeaders.valueAt(i); 411cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 412cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 413cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request = "DESCRIBE "; 414cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 415cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 416cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Accept: application/sdp\r\n"); 417cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 418cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 419cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('desc', id()); 420cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 421cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 422cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 423cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 424e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (response->mStatusCode != 200) { 425e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber result = UNKNOWN_ERROR; 426e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } else { 427e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mSessionDesc = new ASessionDescription; 428cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 429e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mSessionDesc->setTo( 430e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber response->mContent->data(), 431e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber response->mContent->size()); 432cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 4336f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (!mSessionDesc->isValid()) { 434dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber LOGE("Failed to parse session description."); 4356f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber result = ERROR_MALFORMED; 436cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 4376f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber ssize_t i = response->mHeaders.indexOfKey("content-base"); 438e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (i >= 0) { 439e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mBaseURL = response->mHeaders.valueAt(i); 440e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } else { 4416f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber i = response->mHeaders.indexOfKey("content-location"); 4426f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (i >= 0) { 4436f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber mBaseURL = response->mHeaders.valueAt(i); 4446f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } else { 4456f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber mBaseURL = mSessionURL; 4466f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 447e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 448e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber 449dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber if (!mBaseURL.startsWith("rtsp://")) { 450dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber // Some misbehaving servers specify a relative 451dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber // URL in one of the locations above, combine 452dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber // it with the absolute session URL to get 453dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber // something usable... 454dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 455dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber LOGW("Server specified a non-absolute base URL" 456dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber ", combining it with the session URL to " 457dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber "get something usable..."); 458dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 459dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber AString tmp; 460dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber CHECK(MakeURL( 461dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber mSessionURL.c_str(), 462dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber mBaseURL.c_str(), 463dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber &tmp)); 464dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 465dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber mBaseURL = tmp; 466dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } 467dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 4686f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber CHECK_GT(mSessionDesc->countTracks(), 1u); 4696f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber setupTrack(1); 4706f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 471cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 472e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 473cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 474e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (result != OK) { 475cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 476cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 477cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 478cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 479cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 480cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 481cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'setu': 482cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 483cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t index; 484cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findSize("index", &index)); 485cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 48639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber TrackInfo *track = NULL; 487cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t trackIndex; 48839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (msg->findSize("track-index", &trackIndex)) { 48939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber track = &mTracks.editItemAt(trackIndex); 49039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 491cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 492cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 493cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 494cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 4956e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("SETUP(%d) completed with result %d (%s)", 4966e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber index, result, strerror(-result)); 497cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 498e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (result == OK) { 49939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK(track != NULL); 500cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 501cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 502cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 503cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response = 504cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 505cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 506e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (response->mStatusCode != 200) { 507e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber result = UNKNOWN_ERROR; 508e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } else { 509e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber ssize_t i = response->mHeaders.indexOfKey("session"); 510e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber CHECK_GE(i, 0); 511cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 512cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionID = response->mHeaders.valueAt(i); 513cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber i = mSessionID.find(";"); 514cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (i >= 0) { 515cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // Remove options, i.e. ";timeout=90" 516cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionID.erase(i, mSessionID.size() - i); 517cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 518cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 519e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber sp<AMessage> notify = new AMessage('accu', id()); 520e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber notify->setSize("track-index", trackIndex); 521cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 5222bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber i = response->mHeaders.indexOfKey("transport"); 5232bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber CHECK_GE(i, 0); 5242bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 5252bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber if (!track->mUsingInterleavedTCP) { 5262bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber AString transport = response->mHeaders.valueAt(i); 5272bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 528de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber // We are going to continue even if we were 529de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber // unable to poke a hole into the firewall... 530de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber pokeAHole( 531de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber track->mRTPSocket, 532de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber track->mRTCPSocket, 533de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber transport); 5342bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 5352bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 536de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber mRTPConn->addStream( 537de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber track->mRTPSocket, track->mRTCPSocket, 538de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber mSessionDesc, index, 539de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber notify, track->mUsingInterleavedTCP); 540cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 541de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber mSetupTracksSuccessful = true; 542e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 543e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 544e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber 545e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (result != OK) { 546e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (track) { 547e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (!track->mUsingInterleavedTCP) { 548e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber close(track->mRTPSocket); 549e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber close(track->mRTCPSocket); 550e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 551e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber 552e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mTracks.removeItemsAt(trackIndex); 553e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 554cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 555cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 55639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber ++index; 55739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (index < mSessionDesc->countTracks()) { 55839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber setupTrack(index); 55939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } else if (mSetupTracksSuccessful) { 560cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request = "PLAY "; 561cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 562cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 563cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 564cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 565cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 566cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 567cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 568cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 569cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 570cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('play', id()); 571cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 572cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 573cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 574cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 575cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 576cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 577cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 578cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 579cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'play': 580cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 581cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 582cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 583cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 5846e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("PLAY completed with result %d (%s)", 5856e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber result, strerror(-result)); 586cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 587cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 588cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 589cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 590cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response = 591cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 592cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 5936f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (response->mStatusCode != 200) { 5946f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber result = UNKNOWN_ERROR; 5956f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } else { 5966f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber parsePlayResponse(response); 597cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 5986f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber sp<AMessage> timeout = new AMessage('tiou', id()); 5996f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber timeout->post(kStartupTimeoutUs); 6006f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 6016f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 6028d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6036f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (result != OK) { 604cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 605cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 606cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 607cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 608cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 609cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 610cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 611cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'abor': 612cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 613cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 6147aef03379179c109c2547c33c410bfc93c8db576Andreas Huber TrackInfo *info = &mTracks.editItemAt(i); 6157aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 6167aef03379179c109c2547c33c410bfc93c8db576Andreas Huber info->mPacketSource->signalEOS(ERROR_END_OF_STREAM); 6177aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 6187aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (!info->mUsingInterleavedTCP) { 6197aef03379179c109c2547c33c410bfc93c8db576Andreas Huber mRTPConn->removeStream(info->mRTPSocket, info->mRTCPSocket); 6207aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 6217aef03379179c109c2547c33c410bfc93c8db576Andreas Huber close(info->mRTPSocket); 6227aef03379179c109c2547c33c410bfc93c8db576Andreas Huber close(info->mRTCPSocket); 6237aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 624cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 6257aef03379179c109c2547c33c410bfc93c8db576Andreas Huber mTracks.clear(); 626e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mSetupTracksSuccessful = false; 627e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mSeekPending = false; 628e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mFirstAccessUnit = true; 629100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mNTPAnchorUs = -1; 630100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mMediaAnchorUs = -1; 631e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mNumAccessUnitsReceived = 0; 632e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mReceivedFirstRTCPPacket = false; 633f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber mReceivedFirstRTPPacket = false; 6340dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber mSeekable = false; 635cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 636cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('tear', id()); 637cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 6387aef03379179c109c2547c33c410bfc93c8db576Andreas Huber int32_t reconnect; 6397aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (msg->findInt32("reconnect", &reconnect) && reconnect) { 6407aef03379179c109c2547c33c410bfc93c8db576Andreas Huber reply->setInt32("reconnect", true); 6417aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 6427aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 643cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 644cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request = "TEARDOWN "; 645cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 646cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // XXX should use aggregate url from SDP here... 647cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 648cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 649cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 650cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 651cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 652cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 653cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 654cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 655cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 656cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 657cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 658cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 659cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 660cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'tear': 661cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 662cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 663cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 664cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 6656e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("TEARDOWN completed with result %d (%s)", 6666e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber result, strerror(-result)); 667cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 668cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 6697aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 6707aef03379179c109c2547c33c410bfc93c8db576Andreas Huber int32_t reconnect; 6717aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (msg->findInt32("reconnect", &reconnect) && reconnect) { 6727aef03379179c109c2547c33c410bfc93c8db576Andreas Huber reply->setInt32("reconnect", true); 6737aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 6747aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 675cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 676cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 677cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 678cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 679cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'quit': 680cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 6811b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber if (mDoneMsg != NULL) { 6821b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg->setInt32("result", UNKNOWN_ERROR); 6831b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg->post(); 6841b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg = NULL; 6851b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber } 686cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 687cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 688cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 6898d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber case 'chek': 6908d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber { 691a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber int32_t generation; 692a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber CHECK(msg->findInt32("generation", &generation)); 693a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber if (generation != mCheckGeneration) { 694a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber // This is an outdated message. Ignore. 695a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber break; 696a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber } 697a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber 6988d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (mNumAccessUnitsReceived == 0) { 6996e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("stream ended? aborting."); 7008d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber (new AMessage('abor', id()))->post(); 7018d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber break; 7028d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 7038d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 7048d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mNumAccessUnitsReceived = 0; 705e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber msg->post(kAccessUnitTimeoutUs); 7068d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber break; 7078d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 7088d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 709cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'accu': 710cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 711100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int32_t timeUpdate; 712100a4408968b90e314526185d572c72ea4cc784aAndreas Huber if (msg->findInt32("time-update", &timeUpdate) && timeUpdate) { 713100a4408968b90e314526185d572c72ea4cc784aAndreas Huber size_t trackIndex; 714100a4408968b90e314526185d572c72ea4cc784aAndreas Huber CHECK(msg->findSize("track-index", &trackIndex)); 715100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 716100a4408968b90e314526185d572c72ea4cc784aAndreas Huber uint32_t rtpTime; 717100a4408968b90e314526185d572c72ea4cc784aAndreas Huber uint64_t ntpTime; 718100a4408968b90e314526185d572c72ea4cc784aAndreas Huber CHECK(msg->findInt32("rtp-time", (int32_t *)&rtpTime)); 719100a4408968b90e314526185d572c72ea4cc784aAndreas Huber CHECK(msg->findInt64("ntp-time", (int64_t *)&ntpTime)); 720100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 721100a4408968b90e314526185d572c72ea4cc784aAndreas Huber onTimeUpdate(trackIndex, rtpTime, ntpTime); 722100a4408968b90e314526185d572c72ea4cc784aAndreas Huber break; 723100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 724100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 725f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber int32_t first; 726f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber if (msg->findInt32("first-rtcp", &first)) { 727e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mReceivedFirstRTCPPacket = true; 728e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber break; 729e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 730e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber 731f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber if (msg->findInt32("first-rtp", &first)) { 732f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber mReceivedFirstRTPPacket = true; 733f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber break; 734f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber } 735f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber 7368d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ++mNumAccessUnitsReceived; 737a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber postAccessUnitTimeoutCheck(); 7388d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 739cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t trackIndex; 740cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findSize("track-index", &trackIndex)); 741cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 7427aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (trackIndex >= mTracks.size()) { 7436e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGV("late packets ignored."); 7447aef03379179c109c2547c33c410bfc93c8db576Andreas Huber break; 7457aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 7467aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 7478d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 7488d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 749ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber int32_t eos; 750ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber if (msg->findInt32("eos", &eos)) { 7516e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("received BYE on track index %d", trackIndex); 752ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber#if 0 753ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber track->mPacketSource->signalEOS(ERROR_END_OF_STREAM); 754ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber#endif 755ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber return; 756ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber } 757ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber 758cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 759cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("access-unit", &obj)); 760cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 761cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ABuffer> accessUnit = static_cast<ABuffer *>(obj.get()); 762cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 7638d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber uint32_t seqNum = (uint32_t)accessUnit->int32Data(); 7648d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 7656f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (mSeekPending) { 7666e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGV("we're seeking, dropping stale packet."); 7676f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber break; 7686f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 7696f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber 7708d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (seqNum < track->mFirstSeqNumInSegment) { 7716e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGV("dropping stale access-unit (%d < %d)", 7726e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber seqNum, track->mFirstSeqNumInSegment); 7738d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber break; 7748d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 7758d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 7768d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (track->mNewSegment) { 7778d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber track->mNewSegment = false; 7788d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 7798d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 780100a4408968b90e314526185d572c72ea4cc784aAndreas Huber onAccessUnitComplete(trackIndex, accessUnit); 781cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 782cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 783cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 784cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber case 'seek': 785cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber { 7860dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber sp<AMessage> doneMsg; 7870dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber CHECK(msg->findMessage("doneMsg", &doneMsg)); 7880dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 789cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber if (mSeekPending) { 7900dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber doneMsg->post(); 7910dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber break; 7920dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber } 7930dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 7940dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber if (!mSeekable) { 7950dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber LOGW("This is a live stream, ignoring seek request."); 7960dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber doneMsg->post(); 797cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber break; 798cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 799cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 800cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber int64_t timeUs; 801cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(msg->findInt64("time", &timeUs)); 802cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 803cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mSeekPending = true; 804cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 805a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber // Disable the access unit timeout until we resumed 806a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber // playback again. 807a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber mCheckPending = true; 808a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber ++mCheckGeneration; 809a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber 810cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber AString request = "PAUSE "; 811cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(mSessionURL); 812cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(" RTSP/1.0\r\n"); 813cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 814cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("Session: "); 815cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(mSessionID); 816cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("\r\n"); 817cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 818cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("\r\n"); 819cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 820cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber sp<AMessage> reply = new AMessage('see1', id()); 821cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber reply->setInt64("time", timeUs); 8220dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber reply->setMessage("doneMsg", doneMsg); 823cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mConn->sendRequest(request.c_str(), reply); 824cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber break; 825cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 826cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 827cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber case 'see1': 828cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber { 8298d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // Session is paused now. 8308d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 831100a4408968b90e314526185d572c72ea4cc784aAndreas Huber TrackInfo *info = &mTracks.editItemAt(i); 832100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 833100a4408968b90e314526185d572c72ea4cc784aAndreas Huber info->mPacketSource->flushQueue(); 834100a4408968b90e314526185d572c72ea4cc784aAndreas Huber info->mRTPAnchor = 0; 835100a4408968b90e314526185d572c72ea4cc784aAndreas Huber info->mNTPAnchorUs = -1; 8368d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 8378d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 838100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mNTPAnchorUs = -1; 839100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 840cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber int64_t timeUs; 841cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(msg->findInt64("time", &timeUs)); 842cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 843cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber AString request = "PLAY "; 844cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(mSessionURL); 845cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(" RTSP/1.0\r\n"); 846cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 847cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("Session: "); 848cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(mSessionID); 849cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("\r\n"); 850cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 851cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append( 852cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber StringPrintf( 853cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber "Range: npt=%lld-\r\n", timeUs / 1000000ll)); 854cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 855cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("\r\n"); 856cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 8570dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber sp<AMessage> doneMsg; 8580dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber CHECK(msg->findMessage("doneMsg", &doneMsg)); 8590dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 860cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber sp<AMessage> reply = new AMessage('see2', id()); 8610dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber reply->setMessage("doneMsg", doneMsg); 862cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mConn->sendRequest(request.c_str(), reply); 863cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber break; 864cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 865cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 866cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber case 'see2': 867cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber { 868cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(mSeekPending); 869cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 870cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber int32_t result; 871cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(msg->findInt32("result", &result)); 8728d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 8736e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("PLAY completed with result %d (%s)", 8746e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber result, strerror(-result)); 8758d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 876a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber mCheckPending = false; 877a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber postAccessUnitTimeoutCheck(); 878a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber 8796f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (result == OK) { 8806f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber sp<RefBase> obj; 8816f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber CHECK(msg->findObject("response", &obj)); 8826f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber sp<ARTSPResponse> response = 8836f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 884cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 8856f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (response->mStatusCode != 200) { 8866f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber result = UNKNOWN_ERROR; 8876f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } else { 8886f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber parsePlayResponse(response); 889cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 890100a4408968b90e314526185d572c72ea4cc784aAndreas Huber ssize_t i = response->mHeaders.indexOfKey("rtp-info"); 891100a4408968b90e314526185d572c72ea4cc784aAndreas Huber CHECK_GE(i, 0); 892100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 893100a4408968b90e314526185d572c72ea4cc784aAndreas Huber LOGV("rtp-info: %s", response->mHeaders.valueAt(i).c_str()); 894100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 8956e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("seek completed."); 8966f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 8976f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 898cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 8996f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (result != OK) { 9006e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGE("seek failed, aborting."); 9016f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber (new AMessage('abor', id()))->post(); 9026f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 9038d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9048d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mSeekPending = false; 9050dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 9060dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber sp<AMessage> doneMsg; 9070dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber CHECK(msg->findMessage("doneMsg", &doneMsg)); 9080dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 9090dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber doneMsg->post(); 910cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber break; 911cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 912cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 9130792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber case 'biny': 9140792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber { 9150792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber sp<RefBase> obj; 9160792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber CHECK(msg->findObject("buffer", &obj)); 9170792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); 9180792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 9190792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber int32_t index; 9200792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber CHECK(buffer->meta()->findInt32("index", &index)); 9210792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 9220792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber mRTPConn->injectPacket(index, buffer); 9230792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber break; 9240792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } 9250792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 9260792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber case 'tiou': 9270792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber { 928e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (!mReceivedFirstRTCPPacket) { 929dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber if (mReceivedFirstRTPPacket && !mTryFakeRTCP) { 930f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber LOGW("We received RTP packets but no RTCP packets, " 931f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber "using fake timestamps."); 932f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber 933f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber mTryFakeRTCP = true; 934f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber 935f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber mReceivedFirstRTCPPacket = true; 936dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 937dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber fakeTimestamps(); 938dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } else if (!mReceivedFirstRTPPacket && !mTryTCPInterleaving) { 9396e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGW("Never received any data, switching transports."); 9407aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 9417aef03379179c109c2547c33c410bfc93c8db576Andreas Huber mTryTCPInterleaving = true; 9427aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 9437aef03379179c109c2547c33c410bfc93c8db576Andreas Huber sp<AMessage> msg = new AMessage('abor', id()); 9447aef03379179c109c2547c33c410bfc93c8db576Andreas Huber msg->setInt32("reconnect", true); 9457aef03379179c109c2547c33c410bfc93c8db576Andreas Huber msg->post(); 946dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } else { 947dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber LOGW("Never received any data, disconnecting."); 948dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber (new AMessage('abor', id()))->post(); 9497aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 9500792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } 9510792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber break; 9520792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } 9530792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 954cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber default: 955cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber TRESPASS(); 956cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 957cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 958cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 959cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 960a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber void postAccessUnitTimeoutCheck() { 961a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber if (mCheckPending) { 962a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber return; 963a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber } 964a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber 965a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber mCheckPending = true; 966a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber sp<AMessage> check = new AMessage('chek', id()); 967a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber check->setInt32("generation", mCheckGeneration); 968a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber check->post(kAccessUnitTimeoutUs); 969a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber } 970a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber 9718d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber static void SplitString( 9728d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber const AString &s, const char *separator, List<AString> *items) { 9738d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber items->clear(); 9748d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber size_t start = 0; 9758d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber while (start < s.size()) { 9768d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ssize_t offset = s.find(separator, start); 9778d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9788d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (offset < 0) { 9798d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber items->push_back(AString(s, start, s.size() - start)); 9808d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber break; 9818d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 9828d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9838d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber items->push_back(AString(s, start, offset - start)); 9848d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber start = offset + strlen(separator); 9858d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 9868d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 9878d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9888d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber void parsePlayResponse(const sp<ARTSPResponse> &response) { 9890dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber mSeekable = false; 9900dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 9918d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ssize_t i = response->mHeaders.indexOfKey("range"); 9928d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (i < 0) { 9938d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // Server doesn't even tell use what range it is going to 9948d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // play, therefore we won't support seeking. 9958d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return; 9968d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 9978d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9988d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber AString range = response->mHeaders.valueAt(i); 9996e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGV("Range: %s", range.c_str()); 10008d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10018d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber AString val; 10028d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(GetAttribute(range.c_str(), "npt", &val)); 10038d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 1004783e5cd85d4bd40b1a04dfdfed256c5dcb2525ccAndreas Huber float npt1, npt2; 1005783e5cd85d4bd40b1a04dfdfed256c5dcb2525ccAndreas Huber if (!ASessionDescription::parseNTPRange(val.c_str(), &npt1, &npt2)) { 10068d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // This is a live stream and therefore not seekable. 1007ac5767a96df9fae46a37ffba62611472135a0f6dAndreas Huber return; 10088d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 10098d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10108d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber i = response->mHeaders.indexOfKey("rtp-info"); 10118d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK_GE(i, 0); 10128d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10138d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber AString rtpInfo = response->mHeaders.valueAt(i); 10148d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber List<AString> streamInfos; 10158d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber SplitString(rtpInfo, ",", &streamInfos); 10168d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10178d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int n = 1; 10188d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber for (List<AString>::iterator it = streamInfos.begin(); 10198d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber it != streamInfos.end(); ++it) { 10208d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber (*it).trim(); 10216e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGV("streamInfo[%d] = %s", n, (*it).c_str()); 10228d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10238d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(GetAttribute((*it).c_str(), "url", &val)); 10248d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10258d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber size_t trackIndex = 0; 10268d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber while (trackIndex < mTracks.size() 10278d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber && !(val == mTracks.editItemAt(trackIndex).mURL)) { 10288d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ++trackIndex; 10298d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 10308d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK_LT(trackIndex, mTracks.size()); 10318d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10328d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(GetAttribute((*it).c_str(), "seq", &val)); 10338d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10348d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber char *end; 10358d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber unsigned long seq = strtoul(val.c_str(), &end, 10); 10368d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10378d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber TrackInfo *info = &mTracks.editItemAt(trackIndex); 10388d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mFirstSeqNumInSegment = seq; 10398d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mNewSegment = true; 10408d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10418d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(GetAttribute((*it).c_str(), "rtptime", &val)); 10428d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10438d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber uint32_t rtpTime = strtoul(val.c_str(), &end, 10); 10448d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 1045100a4408968b90e314526185d572c72ea4cc784aAndreas Huber LOGV("track #%d: rtpTime=%u <=> npt=%.2f", n, rtpTime, npt1); 10468d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10478d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mPacketSource->setNormalPlayTimeMapping( 10488d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber rtpTime, (int64_t)(npt1 * 1E6)); 10498d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10508d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ++n; 10518d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 10520dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 1053ac5767a96df9fae46a37ffba62611472135a0f6dAndreas Huber mSeekable = true; 10548d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 10558d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 1056cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<APacketSource> getPacketSource(size_t index) { 1057cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(index, 0u); 1058cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_LT(index, mTracks.size()); 1059cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1060cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return mTracks.editItemAt(index).mPacketSource; 1061cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1062cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1063cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t countTracks() const { 1064cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return mTracks.size(); 1065cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1066cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1067cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberprivate: 1068100a4408968b90e314526185d572c72ea4cc784aAndreas Huber struct TrackInfo { 1069100a4408968b90e314526185d572c72ea4cc784aAndreas Huber AString mURL; 1070100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int mRTPSocket; 1071100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int mRTCPSocket; 1072100a4408968b90e314526185d572c72ea4cc784aAndreas Huber bool mUsingInterleavedTCP; 1073100a4408968b90e314526185d572c72ea4cc784aAndreas Huber uint32_t mFirstSeqNumInSegment; 1074100a4408968b90e314526185d572c72ea4cc784aAndreas Huber bool mNewSegment; 1075100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1076100a4408968b90e314526185d572c72ea4cc784aAndreas Huber uint32_t mRTPAnchor; 1077100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int64_t mNTPAnchorUs; 1078100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int32_t mTimeScale; 1079100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1080100a4408968b90e314526185d572c72ea4cc784aAndreas Huber sp<APacketSource> mPacketSource; 1081100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1082100a4408968b90e314526185d572c72ea4cc784aAndreas Huber // Stores packets temporarily while no notion of time 1083100a4408968b90e314526185d572c72ea4cc784aAndreas Huber // has been established yet. 1084100a4408968b90e314526185d572c72ea4cc784aAndreas Huber List<sp<ABuffer> > mPackets; 1085100a4408968b90e314526185d572c72ea4cc784aAndreas Huber }; 1086100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 10879b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber bool mUIDValid; 10889b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber uid_t mUID; 1089cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ALooper> mLooper; 1090348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber sp<ALooper> mNetLooper; 1091cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPConnection> mConn; 1092cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTPConnection> mRTPConn; 1093cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ASessionDescription> mSessionDesc; 10944579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber AString mOriginalSessionURL; // This one still has user:pass@ 1095cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mSessionURL; 1096de9a20c274983d4f7a688acb68d5dfc6a432eb10Andreas Huber AString mSessionHost; 1097cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mBaseURL; 1098cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mSessionID; 1099cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber bool mSetupTracksSuccessful; 1100cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber bool mSeekPending; 1101cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber bool mFirstAccessUnit; 1102100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1103100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int64_t mNTPAnchorUs; 1104100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int64_t mMediaAnchorUs; 1105100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int64_t mLastMediaTimeUs; 1106100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 11078d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int64_t mNumAccessUnitsReceived; 11088d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber bool mCheckPending; 1109a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber int32_t mCheckGeneration; 11107aef03379179c109c2547c33c410bfc93c8db576Andreas Huber bool mTryTCPInterleaving; 1111f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber bool mTryFakeRTCP; 1112e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber bool mReceivedFirstRTCPPacket; 1113f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber bool mReceivedFirstRTPPacket; 11140dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber bool mSeekable; 1115cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1116cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber Vector<TrackInfo> mTracks; 1117cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 11181b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber sp<AMessage> mDoneMsg; 11191b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber 1120cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber void setupTrack(size_t index) { 112139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber sp<APacketSource> source = 112239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber new APacketSource(mSessionDesc, index); 11237aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 112439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (source->initCheck() != OK) { 11256e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGW("Unsupported format. Ignoring track #%d.", index); 112639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 112739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber sp<AMessage> reply = new AMessage('setu', id()); 112839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber reply->setSize("index", index); 112939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber reply->setInt32("result", ERROR_UNSUPPORTED); 113039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber reply->post(); 113139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return; 113239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 113339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 1134cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString url; 1135cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(mSessionDesc->findAttribute(index, "a=control", &url)); 1136cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1137cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString trackURL; 1138cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(MakeURL(mBaseURL.c_str(), url.c_str(), &trackURL)); 1139cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1140cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mTracks.push(TrackInfo()); 1141cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber TrackInfo *info = &mTracks.editItemAt(mTracks.size() - 1); 11428d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mURL = trackURL; 114339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber info->mPacketSource = source; 11440792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber info->mUsingInterleavedTCP = false; 11458d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mFirstSeqNumInSegment = 0; 11468d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mNewSegment = true; 1147100a4408968b90e314526185d572c72ea4cc784aAndreas Huber info->mRTPAnchor = 0; 1148100a4408968b90e314526185d572c72ea4cc784aAndreas Huber info->mNTPAnchorUs = -1; 1149100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1150100a4408968b90e314526185d572c72ea4cc784aAndreas Huber unsigned long PT; 1151100a4408968b90e314526185d572c72ea4cc784aAndreas Huber AString formatDesc; 1152100a4408968b90e314526185d572c72ea4cc784aAndreas Huber AString formatParams; 1153100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mSessionDesc->getFormatType(index, &PT, &formatDesc, &formatParams); 1154100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1155100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int32_t timescale; 1156100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int32_t numChannels; 1157100a4408968b90e314526185d572c72ea4cc784aAndreas Huber ASessionDescription::ParseFormatDesc( 1158100a4408968b90e314526185d572c72ea4cc784aAndreas Huber formatDesc.c_str(), ×cale, &numChannels); 1159100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1160100a4408968b90e314526185d572c72ea4cc784aAndreas Huber info->mTimeScale = timescale; 11618d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 11626e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGV("track #%d URL=%s", mTracks.size(), trackURL.c_str()); 1163cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1164cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request = "SETUP "; 1165cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(trackURL); 1166cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 1167cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 11687aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (mTryTCPInterleaving) { 11697aef03379179c109c2547c33c410bfc93c8db576Andreas Huber size_t interleaveIndex = 2 * (mTracks.size() - 1); 11707aef03379179c109c2547c33c410bfc93c8db576Andreas Huber info->mUsingInterleavedTCP = true; 11717aef03379179c109c2547c33c410bfc93c8db576Andreas Huber info->mRTPSocket = interleaveIndex; 11727aef03379179c109c2547c33c410bfc93c8db576Andreas Huber info->mRTCPSocket = interleaveIndex + 1; 11737aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 11747aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append("Transport: RTP/AVP/TCP;interleaved="); 11757aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append(interleaveIndex); 11767aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append("-"); 11777aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append(interleaveIndex + 1); 11787aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } else { 11797aef03379179c109c2547c33c410bfc93c8db576Andreas Huber unsigned rtpPort; 11807aef03379179c109c2547c33c410bfc93c8db576Andreas Huber ARTPConnection::MakePortPair( 11817aef03379179c109c2547c33c410bfc93c8db576Andreas Huber &info->mRTPSocket, &info->mRTCPSocket, &rtpPort); 11827aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 11839b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber if (mUIDValid) { 1184dab718bba3945332dc75e268e1e7f0fe2eb91c4aAndreas Huber HTTPBase::RegisterSocketUser(info->mRTPSocket, mUID); 1185dab718bba3945332dc75e268e1e7f0fe2eb91c4aAndreas Huber HTTPBase::RegisterSocketUser(info->mRTCPSocket, mUID); 11869b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber } 11879b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber 11887aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append("Transport: RTP/AVP/UDP;unicast;client_port="); 11897aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append(rtpPort); 11907aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append("-"); 11917aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append(rtpPort + 1); 11927aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 11930792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 1194cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 1195cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1196cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (index > 1) { 1197cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 1198cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 1199cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 1200cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1201cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1202cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 1203cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1204cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('setu', id()); 1205cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber reply->setSize("index", index); 1206cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber reply->setSize("track-index", mTracks.size() - 1); 1207cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 1208cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1209cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1210cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static bool MakeURL(const char *baseURL, const char *url, AString *out) { 1211cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->clear(); 1212cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1213cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (strncasecmp("rtsp://", baseURL, 7)) { 1214cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // Base URL must be absolute 1215cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return false; 1216cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1217cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1218cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (!strncasecmp("rtsp://", url, 7)) { 1219cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // "url" is already an absolute URL, ignore base URL. 1220cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(url); 1221cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return true; 1222cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1223cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1224cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t n = strlen(baseURL); 1225cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (baseURL[n - 1] == '/') { 1226cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(baseURL); 1227cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append(url); 1228cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 12294e2ffa400b82559cab2c5717c8dcdff393d334a9Mike Lockwood const char *slashPos = strrchr(baseURL, '/'); 1230cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1231cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (slashPos > &baseURL[6]) { 1232cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(baseURL, slashPos - baseURL); 1233cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 1234cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(baseURL); 1235cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1236cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1237cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append("/"); 1238cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append(url); 1239cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1240cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1241cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return true; 1242cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1243cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1244dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber void fakeTimestamps() { 1245dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 1246dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber onTimeUpdate(i, 0, 0ll); 1247dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } 1248dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber } 1249dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber 1250100a4408968b90e314526185d572c72ea4cc784aAndreas Huber void onTimeUpdate(int32_t trackIndex, uint32_t rtpTime, uint64_t ntpTime) { 1251100a4408968b90e314526185d572c72ea4cc784aAndreas Huber LOGV("onTimeUpdate track %d, rtpTime = 0x%08x, ntpTime = 0x%016llx", 1252100a4408968b90e314526185d572c72ea4cc784aAndreas Huber trackIndex, rtpTime, ntpTime); 1253100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1254100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int64_t ntpTimeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32)); 1255100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1256100a4408968b90e314526185d572c72ea4cc784aAndreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 1257100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1258100a4408968b90e314526185d572c72ea4cc784aAndreas Huber track->mRTPAnchor = rtpTime; 1259100a4408968b90e314526185d572c72ea4cc784aAndreas Huber track->mNTPAnchorUs = ntpTimeUs; 1260100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1261100a4408968b90e314526185d572c72ea4cc784aAndreas Huber if (mNTPAnchorUs < 0) { 1262100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mNTPAnchorUs = ntpTimeUs; 1263100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mMediaAnchorUs = mLastMediaTimeUs; 1264100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1265100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1266100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1267100a4408968b90e314526185d572c72ea4cc784aAndreas Huber void onAccessUnitComplete( 1268100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int32_t trackIndex, const sp<ABuffer> &accessUnit) { 1269100a4408968b90e314526185d572c72ea4cc784aAndreas Huber LOGV("onAccessUnitComplete track %d", trackIndex); 1270100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1271100a4408968b90e314526185d572c72ea4cc784aAndreas Huber if (mFirstAccessUnit) { 1272100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mDoneMsg->setInt32("result", OK); 1273100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mDoneMsg->post(); 1274100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mDoneMsg = NULL; 1275100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1276100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mFirstAccessUnit = false; 1277100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1278100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1279100a4408968b90e314526185d572c72ea4cc784aAndreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 1280100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1281100a4408968b90e314526185d572c72ea4cc784aAndreas Huber if (mNTPAnchorUs < 0 || mMediaAnchorUs < 0 || track->mNTPAnchorUs < 0) { 1282100a4408968b90e314526185d572c72ea4cc784aAndreas Huber LOGV("storing accessUnit, no time established yet"); 1283100a4408968b90e314526185d572c72ea4cc784aAndreas Huber track->mPackets.push_back(accessUnit); 1284100a4408968b90e314526185d572c72ea4cc784aAndreas Huber return; 1285100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1286100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1287100a4408968b90e314526185d572c72ea4cc784aAndreas Huber while (!track->mPackets.empty()) { 1288100a4408968b90e314526185d572c72ea4cc784aAndreas Huber sp<ABuffer> accessUnit = *track->mPackets.begin(); 1289100a4408968b90e314526185d572c72ea4cc784aAndreas Huber track->mPackets.erase(track->mPackets.begin()); 1290100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1291100a4408968b90e314526185d572c72ea4cc784aAndreas Huber if (addMediaTimestamp(trackIndex, track, accessUnit)) { 1292100a4408968b90e314526185d572c72ea4cc784aAndreas Huber track->mPacketSource->queueAccessUnit(accessUnit); 1293100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1294100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1295100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1296100a4408968b90e314526185d572c72ea4cc784aAndreas Huber if (addMediaTimestamp(trackIndex, track, accessUnit)) { 1297100a4408968b90e314526185d572c72ea4cc784aAndreas Huber track->mPacketSource->queueAccessUnit(accessUnit); 1298100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1299100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1300100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1301100a4408968b90e314526185d572c72ea4cc784aAndreas Huber bool addMediaTimestamp( 1302100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int32_t trackIndex, const TrackInfo *track, 1303100a4408968b90e314526185d572c72ea4cc784aAndreas Huber const sp<ABuffer> &accessUnit) { 1304100a4408968b90e314526185d572c72ea4cc784aAndreas Huber uint32_t rtpTime; 1305100a4408968b90e314526185d572c72ea4cc784aAndreas Huber CHECK(accessUnit->meta()->findInt32( 1306100a4408968b90e314526185d572c72ea4cc784aAndreas Huber "rtp-time", (int32_t *)&rtpTime)); 1307100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1308100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int64_t relRtpTimeUs = 1309100a4408968b90e314526185d572c72ea4cc784aAndreas Huber (((int64_t)rtpTime - (int64_t)track->mRTPAnchor) * 1000000ll) 1310100a4408968b90e314526185d572c72ea4cc784aAndreas Huber / track->mTimeScale; 1311100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1312100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int64_t ntpTimeUs = track->mNTPAnchorUs + relRtpTimeUs; 1313100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1314100a4408968b90e314526185d572c72ea4cc784aAndreas Huber int64_t mediaTimeUs = mMediaAnchorUs + ntpTimeUs - mNTPAnchorUs; 1315100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1316100a4408968b90e314526185d572c72ea4cc784aAndreas Huber if (mediaTimeUs > mLastMediaTimeUs) { 1317100a4408968b90e314526185d572c72ea4cc784aAndreas Huber mLastMediaTimeUs = mediaTimeUs; 1318100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1319100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1320100a4408968b90e314526185d572c72ea4cc784aAndreas Huber if (mediaTimeUs < 0) { 1321100a4408968b90e314526185d572c72ea4cc784aAndreas Huber LOGV("dropping early accessUnit."); 1322100a4408968b90e314526185d572c72ea4cc784aAndreas Huber return false; 1323100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1324100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1325100a4408968b90e314526185d572c72ea4cc784aAndreas Huber LOGV("track %d rtpTime=%d mediaTimeUs = %lld us (%.2f secs)", 1326100a4408968b90e314526185d572c72ea4cc784aAndreas Huber trackIndex, rtpTime, mediaTimeUs, mediaTimeUs / 1E6); 1327100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1328100a4408968b90e314526185d572c72ea4cc784aAndreas Huber accessUnit->meta()->setInt64("timeUs", mediaTimeUs); 1329100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1330100a4408968b90e314526185d572c72ea4cc784aAndreas Huber return true; 1331100a4408968b90e314526185d572c72ea4cc784aAndreas Huber } 1332100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1333100a4408968b90e314526185d572c72ea4cc784aAndreas Huber 1334cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber DISALLOW_EVIL_CONSTRUCTORS(MyHandler); 1335cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}; 1336cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1337cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber} // namespace android 1338cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1339cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif // MY_HANDLER_H_ 1340