MyHandler.h revision 2bc940b4f961e588459c83862b2c6bea314a4027
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> 412bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 42e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// If no access units are received within 3 secs, assume that the rtp 43e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// stream has ended and signal end of stream. 44e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huberstatic int64_t kAccessUnitTimeoutUs = 3000000ll; 45e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber 46e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// If no access units arrive for the first 10 secs after starting the 47e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// stream, assume none ever will and signal EOS or switch transports. 48e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huberstatic int64_t kStartupTimeoutUs = 10000000ll; 49e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber 50cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubernamespace android { 51cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 522bc940b4f961e588459c83862b2c6bea314a4027Andreas Huberstatic void MakeUserAgentString(AString *s) { 532bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber s->setTo("stagefright/1.1 (Linux;Android "); 542bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 552bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber#if (PROPERTY_VALUE_MAX < 8) 562bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber#error "PROPERTY_VALUE_MAX must be at least 8" 572bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber#endif 582bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 592bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber char value[PROPERTY_VALUE_MAX]; 602bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber property_get("ro.build.version.release", value, "Unknown"); 612bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber s->append(value); 622bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber s->append(")"); 632bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber} 642bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 658d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huberstatic bool GetAttribute(const char *s, const char *key, AString *value) { 668d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber value->clear(); 678d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 688d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber size_t keyLen = strlen(key); 698d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 708d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber for (;;) { 718d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber while (isspace(*s)) { 728d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ++s; 738d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 748d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 758d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber const char *colonPos = strchr(s, ';'); 768d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 778d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber size_t len = 788d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber (colonPos == NULL) ? strlen(s) : colonPos - s; 798d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 808d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) { 818d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber value->setTo(&s[keyLen + 1], len - keyLen - 1); 828d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return true; 838d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 848d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 858d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (colonPos == NULL) { 868d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return false; 878d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 888d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 898d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber s = colonPos + 1; 908d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 918d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber} 928d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 93cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstruct MyHandler : public AHandler { 94cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber MyHandler(const char *url, const sp<ALooper> &looper) 95cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber : mLooper(looper), 96348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber mNetLooper(new ALooper), 97cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn(new ARTSPConnection), 98cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRTPConn(new ARTPConnection), 99cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionURL(url), 100cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mSetupTracksSuccessful(false), 101cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mSeekPending(false), 102cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mFirstAccessUnit(true), 1038d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mFirstAccessUnitNTP(0), 1048d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mNumAccessUnitsReceived(0), 1057aef03379179c109c2547c33c410bfc93c8db576Andreas Huber mCheckPending(false), 106a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber mCheckGeneration(0), 107e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mTryTCPInterleaving(false), 1080dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber mReceivedFirstRTCPPacket(false), 1090dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber mSeekable(false) { 110a814c1fdc2acf0ed2ee3b175110f6039be7c4873Andreas Huber mNetLooper->setName("rtsp net"); 111348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber mNetLooper->start(false /* runOnCallingThread */, 112348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber false /* canCallJava */, 113348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber PRIORITY_HIGHEST); 114348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber } 115348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber 1161b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber void connect(const sp<AMessage> &doneMsg) { 1171b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg = doneMsg; 1181b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber 119cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLooper->registerHandler(this); 120cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLooper->registerHandler(mConn); 121348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber (1 ? mNetLooper : mLooper)->registerHandler(mRTPConn); 122348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber 1230792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber sp<AMessage> notify = new AMessage('biny', id()); 1240792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber mConn->observeBinaryData(notify); 1250792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 1261b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber sp<AMessage> reply = new AMessage('conn', id()); 127cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->connect(mSessionURL.c_str(), reply); 128cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 129cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1301b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber void disconnect(const sp<AMessage> &doneMsg) { 1311b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg = doneMsg; 1321b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber 1331b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber (new AMessage('abor', id()))->post(); 134348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber } 135348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber 1360dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber void seek(int64_t timeUs, const sp<AMessage> &doneMsg) { 137cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber sp<AMessage> msg = new AMessage('seek', id()); 138cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber msg->setInt64("time", timeUs); 1390dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber msg->setMessage("doneMsg", doneMsg); 140cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber msg->post(); 141cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 142cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 1438d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int64_t getNormalPlayTimeUs() { 1448d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int64_t maxTimeUs = 0; 1458d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 1468d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int64_t timeUs = mTracks.editItemAt(i).mPacketSource 1478d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ->getNormalPlayTimeUs(); 1488d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 1498d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (i == 0 || timeUs > maxTimeUs) { 1508d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber maxTimeUs = timeUs; 1518d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 1528d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 1538d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 1548d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return maxTimeUs; 1558d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 1568d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 1572bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber static void addRR(const sp<ABuffer> &buf) { 1582bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber uint8_t *ptr = buf->data() + buf->size(); 1592bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[0] = 0x80 | 0; 1602bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[1] = 201; // RR 1612bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[2] = 0; 1622bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[3] = 1; 1632bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[4] = 0xde; // SSRC 1642bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[5] = 0xad; 1652bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[6] = 0xbe; 1662bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ptr[7] = 0xef; 1672bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 1682bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber buf->setRange(0, buf->size() + 8); 1692bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 1702bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 1712bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber static void addSDES(int s, const sp<ABuffer> &buffer) { 1722bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber struct sockaddr_in addr; 1732bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber socklen_t addrSize = sizeof(addr); 1742bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber CHECK_EQ(0, getsockname(s, (sockaddr *)&addr, &addrSize)); 1752bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 1762bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber uint8_t *data = buffer->data() + buffer->size(); 1772bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[0] = 0x80 | 1; 1782bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[1] = 202; // SDES 1792bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[4] = 0xde; // SSRC 1802bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[5] = 0xad; 1812bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[6] = 0xbe; 1822bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[7] = 0xef; 1832bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 1842bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber size_t offset = 8; 1852bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 1862bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 1; // CNAME 1872bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 1882bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber AString cname = "stagefright@"; 1892bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber cname.append(inet_ntoa(addr.sin_addr)); 1902bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = cname.size(); 1912bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 1922bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber memcpy(&data[offset], cname.c_str(), cname.size()); 1932bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber offset += cname.size(); 1942bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 1952bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 6; // TOOL 1962bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 1972bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber AString tool; 1982bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber MakeUserAgentString(&tool); 1992bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2002bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = tool.size(); 2012bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2022bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber memcpy(&data[offset], tool.c_str(), tool.size()); 2032bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber offset += tool.size(); 2042bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2052bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 0; 2062bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2072bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber if ((offset % 4) > 0) { 2082bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber size_t count = 4 - (offset % 4); 2092bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber switch (count) { 2102bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber case 3: 2112bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 0; 2122bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber case 2: 2132bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 0; 2142bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber case 1: 2152bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[offset++] = 0; 2162bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 2172bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 2182bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2192bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber size_t numWords = (offset / 4) - 1; 2202bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[2] = numWords >> 8; 2212bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber data[3] = numWords & 0xff; 2222bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2232bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber buffer->setRange(buffer->offset(), buffer->size() + offset); 2242bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 2252bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2262bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber // In case we're behind NAT, fire off two UDP packets to the remote 2272bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber // rtp/rtcp ports to poke a hole into the firewall for future incoming 2282bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber // packets. We're going to send an RR/SDES RTCP packet to both of them. 2292bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber void pokeAHole(int rtpSocket, int rtcpSocket, const AString &transport) { 2302bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber AString source; 2312bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber AString server_port; 2322bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber if (!GetAttribute(transport.c_str(), 2332bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber "source", 2342bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber &source) 2352bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber || !GetAttribute(transport.c_str(), 2362bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber "server_port", 2372bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber &server_port)) { 2382bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber return; 2392bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 2402bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2412bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber int rtpPort, rtcpPort; 2422bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber if (sscanf(server_port.c_str(), "%d-%d", &rtpPort, &rtcpPort) != 2 2432bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber || rtpPort <= 0 || rtpPort > 65535 2442bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber || rtcpPort <=0 || rtcpPort > 65535 2452bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber || rtcpPort != rtpPort + 1 2462bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber || (rtpPort & 1) != 0) { 2472bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber return; 2482bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 2492bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2502bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber struct sockaddr_in addr; 2512bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); 2522bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber addr.sin_family = AF_INET; 2532bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber addr.sin_addr.s_addr = inet_addr(source.c_str()); 2542bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2552bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber if (addr.sin_addr.s_addr == INADDR_NONE) { 2562bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber return; 2572bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 2582bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2592bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber // Make up an RR/SDES RTCP packet. 2602bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber sp<ABuffer> buf = new ABuffer(65536); 2612bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber buf->setRange(0, 0); 2622bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber addRR(buf); 2632bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber addSDES(rtpSocket, buf); 2642bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2652bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber addr.sin_port = htons(rtpPort); 2662bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2672bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber ssize_t n = sendto( 2682bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber rtpSocket, buf->data(), buf->size(), 0, 2692bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber (const sockaddr *)&addr, sizeof(addr)); 2702bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber CHECK_EQ(n, (ssize_t)buf->size()); 2712bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2722bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber addr.sin_port = htons(rtcpPort); 2732bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2742bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber n = sendto( 2752bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber rtcpSocket, buf->data(), buf->size(), 0, 2762bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber (const sockaddr *)&addr, sizeof(addr)); 2772bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber CHECK_EQ(n, (ssize_t)buf->size()); 2782bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 2792bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber LOGV("successfully poked holes."); 2802bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 2812bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 282cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber virtual void onMessageReceived(const sp<AMessage> &msg) { 283cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber switch (msg->what()) { 284cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'conn': 285cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 286cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 287cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 288cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 2896e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("connection request completed with result %d (%s)", 2906e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber result, strerror(-result)); 291cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 292cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 293cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 294cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request = "DESCRIBE "; 295cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 296cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 297cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Accept: application/sdp\r\n"); 298cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 299cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 300cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('desc', id()); 301cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 3020792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } else { 3030792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber (new AMessage('disc', id()))->post(); 304cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 305cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 306cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 307cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 308cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'disc': 309cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 3107aef03379179c109c2547c33c410bfc93c8db576Andreas Huber int32_t reconnect; 3117aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (msg->findInt32("reconnect", &reconnect) && reconnect) { 3127aef03379179c109c2547c33c410bfc93c8db576Andreas Huber sp<AMessage> reply = new AMessage('conn', id()); 3137aef03379179c109c2547c33c410bfc93c8db576Andreas Huber mConn->connect(mSessionURL.c_str(), reply); 3147aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } else { 3157aef03379179c109c2547c33c410bfc93c8db576Andreas Huber (new AMessage('quit', id()))->post(); 3167aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 317cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 318cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 319cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 320cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'desc': 321cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 322cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 323cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 324cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 3256e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("DESCRIBE completed with result %d (%s)", 3266e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber result, strerror(-result)); 327cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 328cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 329cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 330cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 331cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response = 332cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 333cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 334cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (response->mStatusCode == 302) { 335cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ssize_t i = response->mHeaders.indexOfKey("location"); 336cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(i, 0); 337cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 338cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionURL = response->mHeaders.valueAt(i); 339cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 340cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 341cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request = "DESCRIBE "; 342cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 343cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 344cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Accept: application/sdp\r\n"); 345cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 346cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 347cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('desc', id()); 348cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 349cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 350cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 351cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 352e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (response->mStatusCode != 200) { 353e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber result = UNKNOWN_ERROR; 354e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } else { 355e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mSessionDesc = new ASessionDescription; 356cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 357e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mSessionDesc->setTo( 358e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber response->mContent->data(), 359e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber response->mContent->size()); 360cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 3616f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (!mSessionDesc->isValid()) { 3626f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber result = ERROR_MALFORMED; 363cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 3646f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber ssize_t i = response->mHeaders.indexOfKey("content-base"); 365e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (i >= 0) { 366e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mBaseURL = response->mHeaders.valueAt(i); 367e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } else { 3686f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber i = response->mHeaders.indexOfKey("content-location"); 3696f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (i >= 0) { 3706f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber mBaseURL = response->mHeaders.valueAt(i); 3716f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } else { 3726f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber mBaseURL = mSessionURL; 3736f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 374e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 375e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber 3766f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber CHECK_GT(mSessionDesc->countTracks(), 1u); 3776f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber setupTrack(1); 3786f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 379cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 380e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 381cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 382e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (result != OK) { 383cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 384cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 385cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 386cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 387cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 388cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 389cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'setu': 390cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 391cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t index; 392cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findSize("index", &index)); 393cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 39439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber TrackInfo *track = NULL; 395cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t trackIndex; 39639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (msg->findSize("track-index", &trackIndex)) { 39739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber track = &mTracks.editItemAt(trackIndex); 39839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 399cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 400cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 401cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 402cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 4036e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("SETUP(%d) completed with result %d (%s)", 4046e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber index, result, strerror(-result)); 405cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 406e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (result == OK) { 40739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK(track != NULL); 408cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 409cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 410cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 411cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response = 412cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 413cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 414e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (response->mStatusCode != 200) { 415e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber result = UNKNOWN_ERROR; 416e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } else { 417e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber ssize_t i = response->mHeaders.indexOfKey("session"); 418e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber CHECK_GE(i, 0); 419cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 420cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionID = response->mHeaders.valueAt(i); 421cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber i = mSessionID.find(";"); 422cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (i >= 0) { 423cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // Remove options, i.e. ";timeout=90" 424cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionID.erase(i, mSessionID.size() - i); 425cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 426cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 427e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber sp<AMessage> notify = new AMessage('accu', id()); 428e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber notify->setSize("track-index", trackIndex); 429cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 4302bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber i = response->mHeaders.indexOfKey("transport"); 4312bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber CHECK_GE(i, 0); 4322bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 4332bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber if (!track->mUsingInterleavedTCP) { 4342bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber AString transport = response->mHeaders.valueAt(i); 4352bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 4362bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber pokeAHole(track->mRTPSocket, 4372bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber track->mRTCPSocket, 4382bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber transport); 4392bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber } 4402bc940b4f961e588459c83862b2c6bea314a4027Andreas Huber 441e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mRTPConn->addStream( 442e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber track->mRTPSocket, track->mRTCPSocket, 443e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mSessionDesc, index, 444e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber notify, track->mUsingInterleavedTCP); 445cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 446e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mSetupTracksSuccessful = true; 447e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 448e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 449e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber 450e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (result != OK) { 451e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (track) { 452e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (!track->mUsingInterleavedTCP) { 453e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber close(track->mRTPSocket); 454e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber close(track->mRTCPSocket); 455e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 456e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber 457e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mTracks.removeItemsAt(trackIndex); 458e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 459cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 460cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 46139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber ++index; 46239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (index < mSessionDesc->countTracks()) { 46339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber setupTrack(index); 46439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } else if (mSetupTracksSuccessful) { 465cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request = "PLAY "; 466cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 467cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 468cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 469cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 470cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 471cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 472cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 473cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 474cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 475cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('play', id()); 476cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 477cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 478cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 479cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 480cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 481cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 482cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 483cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 484cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'play': 485cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 486cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 487cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 488cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 4896e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("PLAY completed with result %d (%s)", 4906e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber result, strerror(-result)); 491cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 492cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 493cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 494cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 495cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response = 496cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 497cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 4986f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (response->mStatusCode != 200) { 4996f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber result = UNKNOWN_ERROR; 5006f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } else { 5016f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber parsePlayResponse(response); 502cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 5036f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber sp<AMessage> timeout = new AMessage('tiou', id()); 5046f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber timeout->post(kStartupTimeoutUs); 5056f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 5066f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 5078d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 5086f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (result != OK) { 509cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 510cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 511cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 512cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 513cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 514cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 515cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 516cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'abor': 517cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 518cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 5197aef03379179c109c2547c33c410bfc93c8db576Andreas Huber TrackInfo *info = &mTracks.editItemAt(i); 5207aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 5217aef03379179c109c2547c33c410bfc93c8db576Andreas Huber info->mPacketSource->signalEOS(ERROR_END_OF_STREAM); 5227aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 5237aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (!info->mUsingInterleavedTCP) { 5247aef03379179c109c2547c33c410bfc93c8db576Andreas Huber mRTPConn->removeStream(info->mRTPSocket, info->mRTCPSocket); 5257aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 5267aef03379179c109c2547c33c410bfc93c8db576Andreas Huber close(info->mRTPSocket); 5277aef03379179c109c2547c33c410bfc93c8db576Andreas Huber close(info->mRTCPSocket); 5287aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 529cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 5307aef03379179c109c2547c33c410bfc93c8db576Andreas Huber mTracks.clear(); 531e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mSetupTracksSuccessful = false; 532e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mSeekPending = false; 533e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mFirstAccessUnit = true; 534e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mFirstAccessUnitNTP = 0; 535e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mNumAccessUnitsReceived = 0; 536e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mReceivedFirstRTCPPacket = false; 5370dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber mSeekable = false; 538cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 539cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('tear', id()); 540cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 5417aef03379179c109c2547c33c410bfc93c8db576Andreas Huber int32_t reconnect; 5427aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (msg->findInt32("reconnect", &reconnect) && reconnect) { 5437aef03379179c109c2547c33c410bfc93c8db576Andreas Huber reply->setInt32("reconnect", true); 5447aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 5457aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 546cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 547cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request = "TEARDOWN "; 548cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 549cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // XXX should use aggregate url from SDP here... 550cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 551cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 552cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 553cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 554cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 555cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 556cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 557cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 558cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 559cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 560cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 561cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 562cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 563cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'tear': 564cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 565cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 566cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 567cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 5686e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("TEARDOWN completed with result %d (%s)", 5696e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber result, strerror(-result)); 570cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 571cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 5727aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 5737aef03379179c109c2547c33c410bfc93c8db576Andreas Huber int32_t reconnect; 5747aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (msg->findInt32("reconnect", &reconnect) && reconnect) { 5757aef03379179c109c2547c33c410bfc93c8db576Andreas Huber reply->setInt32("reconnect", true); 5767aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 5777aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 578cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 579cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 580cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 581cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 582cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'quit': 583cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 5841b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber if (mDoneMsg != NULL) { 5851b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg->setInt32("result", UNKNOWN_ERROR); 5861b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg->post(); 5871b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg = NULL; 5881b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber } 589cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 590cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 591cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 5928d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber case 'chek': 5938d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber { 594a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber int32_t generation; 595a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber CHECK(msg->findInt32("generation", &generation)); 596a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber if (generation != mCheckGeneration) { 597a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber // This is an outdated message. Ignore. 598a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber break; 599a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber } 600a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber 6018d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (mNumAccessUnitsReceived == 0) { 6026e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("stream ended? aborting."); 6038d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber (new AMessage('abor', id()))->post(); 6048d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber break; 6058d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 6068d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6078d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mNumAccessUnitsReceived = 0; 608e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber msg->post(kAccessUnitTimeoutUs); 6098d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber break; 6108d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 6118d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 612cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'accu': 613cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 614e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber int32_t firstRTCP; 615e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (msg->findInt32("first-rtcp", &firstRTCP)) { 616e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber mReceivedFirstRTCPPacket = true; 617e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber break; 618e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber } 619e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber 6208d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ++mNumAccessUnitsReceived; 621a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber postAccessUnitTimeoutCheck(); 6228d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 623cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t trackIndex; 624cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findSize("track-index", &trackIndex)); 625cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 6267aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (trackIndex >= mTracks.size()) { 6276e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGV("late packets ignored."); 6287aef03379179c109c2547c33c410bfc93c8db576Andreas Huber break; 6297aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 6307aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 6318d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 6328d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 633ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber int32_t eos; 634ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber if (msg->findInt32("eos", &eos)) { 6356e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("received BYE on track index %d", trackIndex); 636ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber#if 0 637ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber track->mPacketSource->signalEOS(ERROR_END_OF_STREAM); 638ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber#endif 639ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber return; 640ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber } 641ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber 642cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 643cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("access-unit", &obj)); 644cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 645cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ABuffer> accessUnit = static_cast<ABuffer *>(obj.get()); 646cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 6478d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber uint32_t seqNum = (uint32_t)accessUnit->int32Data(); 6488d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6496f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (mSeekPending) { 6506e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGV("we're seeking, dropping stale packet."); 6516f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber break; 6526f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 6536f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber 6548d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (seqNum < track->mFirstSeqNumInSegment) { 6556e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGV("dropping stale access-unit (%d < %d)", 6566e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber seqNum, track->mFirstSeqNumInSegment); 6578d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber break; 6588d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 6598d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 660cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint64_t ntpTime; 661cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(accessUnit->meta()->findInt64( 662cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber "ntp-time", (int64_t *)&ntpTime)); 663cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 6648d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber uint32_t rtpTime; 6658d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(accessUnit->meta()->findInt32( 6668d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber "rtp-time", (int32_t *)&rtpTime)); 6678d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6688d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (track->mNewSegment) { 6698d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber track->mNewSegment = false; 6708d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6716e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGV("first segment unit ntpTime=0x%016llx rtpTime=%u seq=%d", 6726e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber ntpTime, rtpTime, seqNum); 6738d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 6748d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 675cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber if (mFirstAccessUnit) { 6767aef03379179c109c2547c33c410bfc93c8db576Andreas Huber mDoneMsg->setInt32("result", OK); 6777aef03379179c109c2547c33c410bfc93c8db576Andreas Huber mDoneMsg->post(); 6787aef03379179c109c2547c33c410bfc93c8db576Andreas Huber mDoneMsg = NULL; 6797aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 680cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mFirstAccessUnit = false; 681cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mFirstAccessUnitNTP = ntpTime; 682cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 683cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 684cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber if (ntpTime >= mFirstAccessUnitNTP) { 685cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber ntpTime -= mFirstAccessUnitNTP; 686cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } else { 687cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber ntpTime = 0; 688cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 689cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 690cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber int64_t timeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32)); 691cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 692cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber accessUnit->meta()->setInt64("timeUs", timeUs); 693cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 694348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber#if 0 695348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber int32_t damaged; 696348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber if (accessUnit->meta()->findInt32("damaged", &damaged) 697348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber && damaged != 0) { 6986e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("ignoring damaged AU"); 699348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber } else 700348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber#endif 701348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber { 702348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 703348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber track->mPacketSource->queueAccessUnit(accessUnit); 704348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber } 705cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 706cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 707cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 708cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber case 'seek': 709cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber { 7100dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber sp<AMessage> doneMsg; 7110dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber CHECK(msg->findMessage("doneMsg", &doneMsg)); 7120dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 713cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber if (mSeekPending) { 7140dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber doneMsg->post(); 7150dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber break; 7160dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber } 7170dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 7180dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber if (!mSeekable) { 7190dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber LOGW("This is a live stream, ignoring seek request."); 7200dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber doneMsg->post(); 721cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber break; 722cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 723cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 724cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber int64_t timeUs; 725cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(msg->findInt64("time", &timeUs)); 726cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 727cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mSeekPending = true; 728cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 729a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber // Disable the access unit timeout until we resumed 730a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber // playback again. 731a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber mCheckPending = true; 732a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber ++mCheckGeneration; 733a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber 734cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber AString request = "PAUSE "; 735cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(mSessionURL); 736cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(" RTSP/1.0\r\n"); 737cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 738cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("Session: "); 739cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(mSessionID); 740cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("\r\n"); 741cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 742cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("\r\n"); 743cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 744cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber sp<AMessage> reply = new AMessage('see1', id()); 745cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber reply->setInt64("time", timeUs); 7460dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber reply->setMessage("doneMsg", doneMsg); 747cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mConn->sendRequest(request.c_str(), reply); 748cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber break; 749cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 750cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 751cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber case 'see1': 752cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber { 7538d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // Session is paused now. 7548d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 7558d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mTracks.editItemAt(i).mPacketSource->flushQueue(); 7568d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 7578d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 758cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber int64_t timeUs; 759cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(msg->findInt64("time", &timeUs)); 760cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 761cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber AString request = "PLAY "; 762cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(mSessionURL); 763cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(" RTSP/1.0\r\n"); 764cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 765cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("Session: "); 766cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(mSessionID); 767cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("\r\n"); 768cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 769cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append( 770cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber StringPrintf( 771cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber "Range: npt=%lld-\r\n", timeUs / 1000000ll)); 772cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 773cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("\r\n"); 774cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 7750dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber sp<AMessage> doneMsg; 7760dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber CHECK(msg->findMessage("doneMsg", &doneMsg)); 7770dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 778cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber sp<AMessage> reply = new AMessage('see2', id()); 7790dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber reply->setMessage("doneMsg", doneMsg); 780cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mConn->sendRequest(request.c_str(), reply); 781cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber break; 782cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 783cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 784cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber case 'see2': 785cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber { 786cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(mSeekPending); 787cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 788cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber int32_t result; 789cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(msg->findInt32("result", &result)); 7908d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 7916e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("PLAY completed with result %d (%s)", 7926e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber result, strerror(-result)); 7938d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 794a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber mCheckPending = false; 795a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber postAccessUnitTimeoutCheck(); 796a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber 7976f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (result == OK) { 7986f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber sp<RefBase> obj; 7996f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber CHECK(msg->findObject("response", &obj)); 8006f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber sp<ARTSPResponse> response = 8016f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 802cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 8036f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (response->mStatusCode != 200) { 8046f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber result = UNKNOWN_ERROR; 8056f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } else { 8066f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber parsePlayResponse(response); 807cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 8086e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGI("seek completed."); 8096f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 8106f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 811cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 8126f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber if (result != OK) { 8136e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGE("seek failed, aborting."); 8146f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber (new AMessage('abor', id()))->post(); 8156f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber } 8168d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 8178d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mSeekPending = false; 8180dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 8190dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber sp<AMessage> doneMsg; 8200dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber CHECK(msg->findMessage("doneMsg", &doneMsg)); 8210dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 8220dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber doneMsg->post(); 823cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber break; 824cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 825cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 8260792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber case 'biny': 8270792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber { 8280792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber sp<RefBase> obj; 8290792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber CHECK(msg->findObject("buffer", &obj)); 8300792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); 8310792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 8320792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber int32_t index; 8330792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber CHECK(buffer->meta()->findInt32("index", &index)); 8340792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 8350792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber mRTPConn->injectPacket(index, buffer); 8360792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber break; 8370792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } 8380792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 8390792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber case 'tiou': 8400792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber { 841e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber if (!mReceivedFirstRTCPPacket) { 8427aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (mTryTCPInterleaving) { 8436e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGW("Never received any data, disconnecting."); 8447aef03379179c109c2547c33c410bfc93c8db576Andreas Huber (new AMessage('abor', id()))->post(); 8457aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } else { 8466e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGW("Never received any data, switching transports."); 8477aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 8487aef03379179c109c2547c33c410bfc93c8db576Andreas Huber mTryTCPInterleaving = true; 8497aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 8507aef03379179c109c2547c33c410bfc93c8db576Andreas Huber sp<AMessage> msg = new AMessage('abor', id()); 8517aef03379179c109c2547c33c410bfc93c8db576Andreas Huber msg->setInt32("reconnect", true); 8527aef03379179c109c2547c33c410bfc93c8db576Andreas Huber msg->post(); 8537aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 8540792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } 8550792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber break; 8560792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } 8570792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 858cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber default: 859cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber TRESPASS(); 860cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 861cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 862cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 863cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 864a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber void postAccessUnitTimeoutCheck() { 865a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber if (mCheckPending) { 866a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber return; 867a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber } 868a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber 869a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber mCheckPending = true; 870a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber sp<AMessage> check = new AMessage('chek', id()); 871a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber check->setInt32("generation", mCheckGeneration); 872a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber check->post(kAccessUnitTimeoutUs); 873a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber } 874a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber 8758d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber static void SplitString( 8768d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber const AString &s, const char *separator, List<AString> *items) { 8778d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber items->clear(); 8788d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber size_t start = 0; 8798d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber while (start < s.size()) { 8808d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ssize_t offset = s.find(separator, start); 8818d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 8828d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (offset < 0) { 8838d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber items->push_back(AString(s, start, s.size() - start)); 8848d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber break; 8858d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 8868d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 8878d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber items->push_back(AString(s, start, offset - start)); 8888d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber start = offset + strlen(separator); 8898d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 8908d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 8918d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 8928d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber void parsePlayResponse(const sp<ARTSPResponse> &response) { 8930dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber mSeekable = false; 8940dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 8958d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ssize_t i = response->mHeaders.indexOfKey("range"); 8968d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (i < 0) { 8978d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // Server doesn't even tell use what range it is going to 8988d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // play, therefore we won't support seeking. 8998d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return; 9008d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 9018d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9028d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber AString range = response->mHeaders.valueAt(i); 9036e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGV("Range: %s", range.c_str()); 9048d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9058d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber AString val; 9068d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(GetAttribute(range.c_str(), "npt", &val)); 9078d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber float npt1, npt2; 9088d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9098d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (val == "now-") { 9108d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // This is a live stream and therefore not seekable. 9118d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return; 9128d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } else { 9138d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK_EQ(sscanf(val.c_str(), "%f-%f", &npt1, &npt2), 2); 9148d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 9158d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9168d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber i = response->mHeaders.indexOfKey("rtp-info"); 9178d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK_GE(i, 0); 9188d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9198d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber AString rtpInfo = response->mHeaders.valueAt(i); 9208d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber List<AString> streamInfos; 9218d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber SplitString(rtpInfo, ",", &streamInfos); 9228d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9238d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int n = 1; 9248d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber for (List<AString>::iterator it = streamInfos.begin(); 9258d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber it != streamInfos.end(); ++it) { 9268d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber (*it).trim(); 9276e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGV("streamInfo[%d] = %s", n, (*it).c_str()); 9288d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9298d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(GetAttribute((*it).c_str(), "url", &val)); 9308d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9318d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber size_t trackIndex = 0; 9328d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber while (trackIndex < mTracks.size() 9338d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber && !(val == mTracks.editItemAt(trackIndex).mURL)) { 9348d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ++trackIndex; 9358d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 9368d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK_LT(trackIndex, mTracks.size()); 9378d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9388d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(GetAttribute((*it).c_str(), "seq", &val)); 9398d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9408d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber char *end; 9418d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber unsigned long seq = strtoul(val.c_str(), &end, 10); 9428d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9438d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber TrackInfo *info = &mTracks.editItemAt(trackIndex); 9448d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mFirstSeqNumInSegment = seq; 9458d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mNewSegment = true; 9468d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9478d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(GetAttribute((*it).c_str(), "rtptime", &val)); 9488d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9498d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber uint32_t rtpTime = strtoul(val.c_str(), &end, 10); 9508d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9516e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGV("track #%d: rtpTime=%u <=> ntp=%.2f", n, rtpTime, npt1); 9528d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9538d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mPacketSource->setNormalPlayTimeMapping( 9548d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber rtpTime, (int64_t)(npt1 * 1E6)); 9558d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 9568d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ++n; 9578d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 9580dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber 9590dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber mSeekable = true; 9608d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 9618d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 962cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<APacketSource> getPacketSource(size_t index) { 963cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(index, 0u); 964cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_LT(index, mTracks.size()); 965cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 966cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return mTracks.editItemAt(index).mPacketSource; 967cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 968cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 969cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t countTracks() const { 970cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return mTracks.size(); 971cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 972cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 973cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberprivate: 974cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ALooper> mLooper; 975348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber sp<ALooper> mNetLooper; 976cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPConnection> mConn; 977cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTPConnection> mRTPConn; 978cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ASessionDescription> mSessionDesc; 979cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mSessionURL; 980cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mBaseURL; 981cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mSessionID; 982cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber bool mSetupTracksSuccessful; 983cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber bool mSeekPending; 984cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber bool mFirstAccessUnit; 985cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber uint64_t mFirstAccessUnitNTP; 9868d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int64_t mNumAccessUnitsReceived; 9878d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber bool mCheckPending; 988a9d9dd2425c32f6868c35f49a3e8f29aafba931aAndreas Huber int32_t mCheckGeneration; 9897aef03379179c109c2547c33c410bfc93c8db576Andreas Huber bool mTryTCPInterleaving; 990e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber bool mReceivedFirstRTCPPacket; 9910dcd837af4169bdb6fb2a0c384722dc4f57433c6Andreas Huber bool mSeekable; 992cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 993cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber struct TrackInfo { 9948d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber AString mURL; 995cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int mRTPSocket; 996cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int mRTCPSocket; 9970792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber bool mUsingInterleavedTCP; 9988d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber uint32_t mFirstSeqNumInSegment; 9998d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber bool mNewSegment; 1000cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1001cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<APacketSource> mPacketSource; 1002cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber }; 1003cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber Vector<TrackInfo> mTracks; 1004cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 10051b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber sp<AMessage> mDoneMsg; 10061b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber 1007cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber void setupTrack(size_t index) { 100839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber sp<APacketSource> source = 100939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber new APacketSource(mSessionDesc, index); 10107aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 101139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (source->initCheck() != OK) { 10126e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGW("Unsupported format. Ignoring track #%d.", index); 101339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 101439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber sp<AMessage> reply = new AMessage('setu', id()); 101539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber reply->setSize("index", index); 101639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber reply->setInt32("result", ERROR_UNSUPPORTED); 101739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber reply->post(); 101839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return; 101939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 102039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 1021cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString url; 1022cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(mSessionDesc->findAttribute(index, "a=control", &url)); 1023cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1024cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString trackURL; 1025cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(MakeURL(mBaseURL.c_str(), url.c_str(), &trackURL)); 1026cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1027cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mTracks.push(TrackInfo()); 1028cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber TrackInfo *info = &mTracks.editItemAt(mTracks.size() - 1); 10298d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mURL = trackURL; 103039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber info->mPacketSource = source; 10310792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber info->mUsingInterleavedTCP = false; 10328d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mFirstSeqNumInSegment = 0; 10338d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mNewSegment = true; 10348d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 10356e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber LOGV("track #%d URL=%s", mTracks.size(), trackURL.c_str()); 1036cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1037cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request = "SETUP "; 1038cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(trackURL); 1039cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 1040cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 10417aef03379179c109c2547c33c410bfc93c8db576Andreas Huber if (mTryTCPInterleaving) { 10427aef03379179c109c2547c33c410bfc93c8db576Andreas Huber size_t interleaveIndex = 2 * (mTracks.size() - 1); 10437aef03379179c109c2547c33c410bfc93c8db576Andreas Huber info->mUsingInterleavedTCP = true; 10447aef03379179c109c2547c33c410bfc93c8db576Andreas Huber info->mRTPSocket = interleaveIndex; 10457aef03379179c109c2547c33c410bfc93c8db576Andreas Huber info->mRTCPSocket = interleaveIndex + 1; 10467aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 10477aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append("Transport: RTP/AVP/TCP;interleaved="); 10487aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append(interleaveIndex); 10497aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append("-"); 10507aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append(interleaveIndex + 1); 10517aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } else { 10527aef03379179c109c2547c33c410bfc93c8db576Andreas Huber unsigned rtpPort; 10537aef03379179c109c2547c33c410bfc93c8db576Andreas Huber ARTPConnection::MakePortPair( 10547aef03379179c109c2547c33c410bfc93c8db576Andreas Huber &info->mRTPSocket, &info->mRTCPSocket, &rtpPort); 10557aef03379179c109c2547c33c410bfc93c8db576Andreas Huber 10567aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append("Transport: RTP/AVP/UDP;unicast;client_port="); 10577aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append(rtpPort); 10587aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append("-"); 10597aef03379179c109c2547c33c410bfc93c8db576Andreas Huber request.append(rtpPort + 1); 10607aef03379179c109c2547c33c410bfc93c8db576Andreas Huber } 10610792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 1062cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 1063cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1064cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (index > 1) { 1065cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 1066cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 1067cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 1068cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1069cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1070cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 1071cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1072cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('setu', id()); 1073cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber reply->setSize("index", index); 1074cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber reply->setSize("track-index", mTracks.size() - 1); 1075cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 1076cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1077cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1078cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static bool MakeURL(const char *baseURL, const char *url, AString *out) { 1079cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->clear(); 1080cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1081cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (strncasecmp("rtsp://", baseURL, 7)) { 1082cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // Base URL must be absolute 1083cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return false; 1084cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1085cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1086cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (!strncasecmp("rtsp://", url, 7)) { 1087cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // "url" is already an absolute URL, ignore base URL. 1088cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(url); 1089cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return true; 1090cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1091cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1092cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t n = strlen(baseURL); 1093cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (baseURL[n - 1] == '/') { 1094cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(baseURL); 1095cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append(url); 1096cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 1097cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber char *slashPos = strrchr(baseURL, '/'); 1098cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1099cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (slashPos > &baseURL[6]) { 1100cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(baseURL, slashPos - baseURL); 1101cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 1102cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(baseURL); 1103cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1104cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1105cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append("/"); 1106cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append(url); 1107cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1108cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1109cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return true; 1110cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 1111cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1112cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber DISALLOW_EVIL_CONSTRUCTORS(MyHandler); 1113cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}; 1114cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1115cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber} // namespace android 1116cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1117cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif // MY_HANDLER_H_ 1118