17a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber/* 27a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * Copyright (C) 2010 The Android Open Source Project 37a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * 47a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 57a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * you may not use this file except in compliance with the License. 67a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * You may obtain a copy of the License at 77a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * 87a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 97a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * 107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * Unless required by applicable law or agreed to in writing, software 117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * See the License for the specific language governing permissions and 147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber * limitations under the License. 157a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber */ 167a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 177a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#ifndef MY_HANDLER_H_ 187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#define MY_HANDLER_H_ 207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 216e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber//#define LOG_NDEBUG 0 226e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber#define LOG_TAG "MyHandler" 236e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber#include <utils/Log.h> 246e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber 257a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include "APacketSource.h" 267a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include "ARTPConnection.h" 277a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include "ARTSPConnection.h" 287a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include "ASessionDescription.h" 297a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 30eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber#include <ctype.h> 310dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber#include <cutils/properties.h> 32eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <media/stagefright/foundation/ADebug.h> 357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <media/stagefright/foundation/ALooper.h> 367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <media/stagefright/foundation/AMessage.h> 377a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <media/stagefright/MediaErrors.h> 387a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 390dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber#include <arpa/inet.h> 400dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber#include <sys/socket.h> 4127db53de35bbe83ce3b906da675b065803471481Andreas Huber#include <netdb.h> 420dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 43c3119330a56c2dafa282b0b7450893c3f8cb5636Andreas Huber#include "HTTPBase.h" 44603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber 45b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber// If no access units are received within 5 secs, assume that the rtp 46f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huber// stream has ended and signal end of stream. 47a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huberstatic int64_t kAccessUnitTimeoutUs = 10000000ll; 48f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huber 49f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huber// If no access units arrive for the first 10 secs after starting the 50f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huber// stream, assume none ever will and signal EOS or switch transports. 51f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huberstatic int64_t kStartupTimeoutUs = 10000000ll; 52f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huber 53a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huberstatic int64_t kDefaultKeepAliveTimeoutUs = 60000000ll; 54a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Hubernamespace android { 567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 570dc6403f3c660f6e6f1840276e3240365889103dAndreas Huberstatic void MakeUserAgentString(AString *s) { 580dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber s->setTo("stagefright/1.1 (Linux;Android "); 590dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 600dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber#if (PROPERTY_VALUE_MAX < 8) 610dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber#error "PROPERTY_VALUE_MAX must be at least 8" 620dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber#endif 630dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 640dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber char value[PROPERTY_VALUE_MAX]; 650dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber property_get("ro.build.version.release", value, "Unknown"); 660dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber s->append(value); 670dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber s->append(")"); 680dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber} 690dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 70eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huberstatic bool GetAttribute(const char *s, const char *key, AString *value) { 71eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber value->clear(); 72eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 73eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber size_t keyLen = strlen(key); 74eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 75eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber for (;;) { 76eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber while (isspace(*s)) { 77eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber ++s; 78eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 79eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 80eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber const char *colonPos = strchr(s, ';'); 81eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 82eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber size_t len = 83eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber (colonPos == NULL) ? strlen(s) : colonPos - s; 84eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 85eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) { 86eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber value->setTo(&s[keyLen + 1], len - keyLen - 1); 87eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber return true; 88eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 89eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 90eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (colonPos == NULL) { 91eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber return false; 92eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 93eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 94eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber s = colonPos + 1; 95eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 96eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber} 97eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huberstruct MyHandler : public AHandler { 99a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber enum { 100a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber kWhatConnected = 'conn', 101a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber kWhatDisconnected = 'disc', 102a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber kWhatSeekDone = 'sdon', 103a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber 104a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber kWhatAccessUnit = 'accU', 105a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber kWhatEOS = 'eos!', 106a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber kWhatSeekDiscontinuity = 'seeD', 107a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber kWhatNormalPlayTimeMapping = 'nptM', 108a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber }; 109a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber 110603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber MyHandler( 111a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber const char *url, 112a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber const sp<AMessage> ¬ify, 113603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber bool uidValid = false, uid_t uid = 0) 114a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber : mNotify(notify), 115a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber mUIDValid(uidValid), 116603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber mUID(uid), 1174e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber mNetLooper(new ALooper), 118603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber mConn(new ARTSPConnection(mUIDValid, mUID)), 1197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mRTPConn(new ARTPConnection), 120a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber mOriginalSessionURL(url), 1217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mSessionURL(url), 122e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber mSetupTracksSuccessful(false), 123e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber mSeekPending(false), 124e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber mFirstAccessUnit(true), 125b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber mNTPAnchorUs(-1), 126b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber mMediaAnchorUs(-1), 127b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber mLastMediaTimeUs(0), 128eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber mNumAccessUnitsReceived(0), 129f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber mCheckPending(false), 130e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber mCheckGeneration(0), 1313a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mTryTCPInterleaving(false), 132cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber mTryFakeRTCP(false), 1330c46b69f612da61ed39b32823d2d6baf2e8215e9Andreas Huber mReceivedFirstRTCPPacket(false), 134cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber mReceivedFirstRTPPacket(false), 135a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber mSeekable(false), 136a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber mKeepAliveTimeoutUs(kDefaultKeepAliveTimeoutUs), 137a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber mKeepAliveGeneration(0) { 138c4e0b70a21fadb47d70955c71fc31ce1473da925Andreas Huber mNetLooper->setName("rtsp net"); 1394e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber mNetLooper->start(false /* runOnCallingThread */, 1404e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber false /* canCallJava */, 1414e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber PRIORITY_HIGHEST); 142a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber 143a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber // Strip any authentication info from the session url, we don't 144a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber // want to transmit user/pass in cleartext. 145a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber AString host, path, user, pass; 146a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber unsigned port; 14727db53de35bbe83ce3b906da675b065803471481Andreas Huber CHECK(ARTSPConnection::ParseURL( 14827db53de35bbe83ce3b906da675b065803471481Andreas Huber mSessionURL.c_str(), &host, &port, &path, &user, &pass)); 14927db53de35bbe83ce3b906da675b065803471481Andreas Huber 15027db53de35bbe83ce3b906da675b065803471481Andreas Huber if (user.size() > 0) { 151a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber mSessionURL.clear(); 152a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber mSessionURL.append("rtsp://"); 153a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber mSessionURL.append(host); 154a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber mSessionURL.append(":"); 155a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber mSessionURL.append(StringPrintf("%u", port)); 156a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber mSessionURL.append(path); 157a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber 158a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber LOGI("rewritten session url: '%s'", mSessionURL.c_str()); 159a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber } 16027db53de35bbe83ce3b906da675b065803471481Andreas Huber 16127db53de35bbe83ce3b906da675b065803471481Andreas Huber mSessionHost = host; 1624e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber } 1634e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber 164a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber void connect() { 165a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber looper()->registerHandler(mConn); 166a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber (1 ? mNetLooper : looper())->registerHandler(mRTPConn); 1674e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber 1680416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber sp<AMessage> notify = new AMessage('biny', id()); 1690416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber mConn->observeBinaryData(notify); 1700416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber 1718370be11debc574b4a9fee62009009d999e29fa3Andreas Huber sp<AMessage> reply = new AMessage('conn', id()); 172a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber mConn->connect(mOriginalSessionURL.c_str(), reply); 1737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 1747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 175a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber void disconnect() { 1768370be11debc574b4a9fee62009009d999e29fa3Andreas Huber (new AMessage('abor', id()))->post(); 1774e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber } 1784e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber 179a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber void seek(int64_t timeUs) { 180e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber sp<AMessage> msg = new AMessage('seek', id()); 181e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber msg->setInt64("time", timeUs); 182e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber msg->post(); 183e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber } 184e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 1850dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber static void addRR(const sp<ABuffer> &buf) { 1860dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber uint8_t *ptr = buf->data() + buf->size(); 1870dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber ptr[0] = 0x80 | 0; 1880dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber ptr[1] = 201; // RR 1890dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber ptr[2] = 0; 1900dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber ptr[3] = 1; 1910dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber ptr[4] = 0xde; // SSRC 1920dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber ptr[5] = 0xad; 1930dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber ptr[6] = 0xbe; 1940dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber ptr[7] = 0xef; 1950dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 1960dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber buf->setRange(0, buf->size() + 8); 1970dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber } 1980dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 1990dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber static void addSDES(int s, const sp<ABuffer> &buffer) { 2000dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber struct sockaddr_in addr; 2010dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber socklen_t addrSize = sizeof(addr); 2020dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber CHECK_EQ(0, getsockname(s, (sockaddr *)&addr, &addrSize)); 2030dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 2040dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber uint8_t *data = buffer->data() + buffer->size(); 2050dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber data[0] = 0x80 | 1; 2060dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber data[1] = 202; // SDES 2070dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber data[4] = 0xde; // SSRC 2080dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber data[5] = 0xad; 2090dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber data[6] = 0xbe; 2100dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber data[7] = 0xef; 2110dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 2120dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber size_t offset = 8; 2130dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 2140dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber data[offset++] = 1; // CNAME 2150dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 2160dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber AString cname = "stagefright@"; 2170dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber cname.append(inet_ntoa(addr.sin_addr)); 2180dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber data[offset++] = cname.size(); 2190dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 2200dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber memcpy(&data[offset], cname.c_str(), cname.size()); 2210dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber offset += cname.size(); 2220dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 2230dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber data[offset++] = 6; // TOOL 2240dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 2250dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber AString tool; 2260dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber MakeUserAgentString(&tool); 2270dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 2280dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber data[offset++] = tool.size(); 2290dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 2300dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber memcpy(&data[offset], tool.c_str(), tool.size()); 2310dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber offset += tool.size(); 2320dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 2330dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber data[offset++] = 0; 2340dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 2350dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber if ((offset % 4) > 0) { 2360dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber size_t count = 4 - (offset % 4); 2370dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber switch (count) { 2380dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber case 3: 2390dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber data[offset++] = 0; 2400dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber case 2: 2410dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber data[offset++] = 0; 2420dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber case 1: 2430dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber data[offset++] = 0; 2440dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber } 2450dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber } 2460dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 2470dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber size_t numWords = (offset / 4) - 1; 2480dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber data[2] = numWords >> 8; 2490dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber data[3] = numWords & 0xff; 2500dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 2510dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber buffer->setRange(buffer->offset(), buffer->size() + offset); 2520dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber } 2530dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 2540dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber // In case we're behind NAT, fire off two UDP packets to the remote 2550dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber // rtp/rtcp ports to poke a hole into the firewall for future incoming 2560dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber // packets. We're going to send an RR/SDES RTCP packet to both of them. 2570407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber bool pokeAHole(int rtpSocket, int rtcpSocket, const AString &transport) { 25827db53de35bbe83ce3b906da675b065803471481Andreas Huber struct sockaddr_in addr; 25927db53de35bbe83ce3b906da675b065803471481Andreas Huber memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); 26027db53de35bbe83ce3b906da675b065803471481Andreas Huber addr.sin_family = AF_INET; 26127db53de35bbe83ce3b906da675b065803471481Andreas Huber 2620dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber AString source; 2630dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber AString server_port; 2640dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber if (!GetAttribute(transport.c_str(), 2650dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber "source", 26627db53de35bbe83ce3b906da675b065803471481Andreas Huber &source)) { 26727db53de35bbe83ce3b906da675b065803471481Andreas Huber LOGW("Missing 'source' field in Transport response. Using " 26827db53de35bbe83ce3b906da675b065803471481Andreas Huber "RTSP endpoint address."); 26927db53de35bbe83ce3b906da675b065803471481Andreas Huber 27027db53de35bbe83ce3b906da675b065803471481Andreas Huber struct hostent *ent = gethostbyname(mSessionHost.c_str()); 27127db53de35bbe83ce3b906da675b065803471481Andreas Huber if (ent == NULL) { 27227db53de35bbe83ce3b906da675b065803471481Andreas Huber LOGE("Failed to look up address of session host '%s'", 27327db53de35bbe83ce3b906da675b065803471481Andreas Huber mSessionHost.c_str()); 27427db53de35bbe83ce3b906da675b065803471481Andreas Huber 27527db53de35bbe83ce3b906da675b065803471481Andreas Huber return false; 27627db53de35bbe83ce3b906da675b065803471481Andreas Huber } 27727db53de35bbe83ce3b906da675b065803471481Andreas Huber 27827db53de35bbe83ce3b906da675b065803471481Andreas Huber addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr; 27927db53de35bbe83ce3b906da675b065803471481Andreas Huber } else { 28027db53de35bbe83ce3b906da675b065803471481Andreas Huber addr.sin_addr.s_addr = inet_addr(source.c_str()); 28127db53de35bbe83ce3b906da675b065803471481Andreas Huber } 28227db53de35bbe83ce3b906da675b065803471481Andreas Huber 28327db53de35bbe83ce3b906da675b065803471481Andreas Huber if (!GetAttribute(transport.c_str(), 2840dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber "server_port", 2850dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber &server_port)) { 28627db53de35bbe83ce3b906da675b065803471481Andreas Huber LOGI("Missing 'server_port' field in Transport response."); 2870407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber return false; 2880dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber } 2890dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 2900dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber int rtpPort, rtcpPort; 2910dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber if (sscanf(server_port.c_str(), "%d-%d", &rtpPort, &rtcpPort) != 2 2920dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber || rtpPort <= 0 || rtpPort > 65535 2930dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber || rtcpPort <=0 || rtcpPort > 65535 2940407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber || rtcpPort != rtpPort + 1) { 2950407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber LOGE("Server picked invalid RTP/RTCP port pair %s," 2960407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber " RTP port must be even, RTCP port must be one higher.", 2970407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber server_port.c_str()); 2980407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber 2990407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber return false; 3000407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber } 3010407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber 3020407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber if (rtpPort & 1) { 3030407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber LOGW("Server picked an odd RTP port, it should've picked an " 3040407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber "even one, we'll let it pass for now, but this may break " 3050407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber "in the future."); 3060dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber } 3070dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 3080dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber if (addr.sin_addr.s_addr == INADDR_NONE) { 3090407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber return true; 3100407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber } 3110407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber 3120407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber if (IN_LOOPBACK(ntohl(addr.sin_addr.s_addr))) { 3130407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber // No firewalls to traverse on the loopback interface. 3140407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber return true; 3150dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber } 3160dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 3170dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber // Make up an RR/SDES RTCP packet. 3180dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber sp<ABuffer> buf = new ABuffer(65536); 3190dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber buf->setRange(0, 0); 3200dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber addRR(buf); 3210dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber addSDES(rtpSocket, buf); 3220dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 3230dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber addr.sin_port = htons(rtpPort); 3240dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 3250dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber ssize_t n = sendto( 3260dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber rtpSocket, buf->data(), buf->size(), 0, 3270dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber (const sockaddr *)&addr, sizeof(addr)); 3280407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber 3290407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber if (n < (ssize_t)buf->size()) { 3300407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber LOGE("failed to poke a hole for RTP packets"); 3310407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber return false; 3320407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber } 3330dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 3340dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber addr.sin_port = htons(rtcpPort); 3350dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 3360dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber n = sendto( 3370dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber rtcpSocket, buf->data(), buf->size(), 0, 3380dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber (const sockaddr *)&addr, sizeof(addr)); 3390407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber 3400407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber if (n < (ssize_t)buf->size()) { 3410407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber LOGE("failed to poke a hole for RTCP packets"); 3420407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber return false; 3430407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber } 3440dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 3450dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber LOGV("successfully poked holes."); 3460407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber 3470407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber return true; 3480dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber } 3490dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 3507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber virtual void onMessageReceived(const sp<AMessage> &msg) { 3517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber switch (msg->what()) { 3527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'conn': 3537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 3547a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber int32_t result; 3557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findInt32("result", &result)); 3567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3576e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGI("connection request completed with result %d (%s)", 3586e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber result, strerror(-result)); 3597a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (result == OK) { 3617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString request; 3627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request = "DESCRIBE "; 3637a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(mSessionURL); 3647a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(" RTSP/1.0\r\n"); 3657a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("Accept: application/sdp\r\n"); 3667a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 3677a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3687a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('desc', id()); 3697a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->sendRequest(request.c_str(), reply); 3700416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber } else { 3710416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber (new AMessage('disc', id()))->post(); 3727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 3737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 3747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 3757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'disc': 3777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 378a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber ++mKeepAliveGeneration; 379a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 380f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber int32_t reconnect; 381f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber if (msg->findInt32("reconnect", &reconnect) && reconnect) { 382f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber sp<AMessage> reply = new AMessage('conn', id()); 383a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber mConn->connect(mOriginalSessionURL.c_str(), reply); 384f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } else { 385f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber (new AMessage('quit', id()))->post(); 386f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } 3877a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 3887a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 3897a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3907a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'desc': 3917a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 3927a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber int32_t result; 3937a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findInt32("result", &result)); 3947a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3956e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGI("DESCRIBE completed with result %d (%s)", 3966e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber result, strerror(-result)); 3977a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (result == OK) { 3997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<RefBase> obj; 4007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findObject("response", &obj)); 4017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<ARTSPResponse> response = 4027a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 4037a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 4047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (response->mStatusCode == 302) { 4057a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber ssize_t i = response->mHeaders.indexOfKey("location"); 4067a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK_GE(i, 0); 4077a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 4087a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mSessionURL = response->mHeaders.valueAt(i); 4097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 4107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString request; 4117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request = "DESCRIBE "; 4127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(mSessionURL); 4137a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(" RTSP/1.0\r\n"); 4147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("Accept: application/sdp\r\n"); 4157a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 4167a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 4177a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('desc', id()); 4187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->sendRequest(request.c_str(), reply); 4197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 4207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 4217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 4223a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (response->mStatusCode != 200) { 4233a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber result = UNKNOWN_ERROR; 4243a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } else { 4253a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mSessionDesc = new ASessionDescription; 4267a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 4273a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mSessionDesc->setTo( 4283a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber response->mContent->data(), 4293a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber response->mContent->size()); 4307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 431f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber if (!mSessionDesc->isValid()) { 4320407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber LOGE("Failed to parse session description."); 433f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber result = ERROR_MALFORMED; 4347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } else { 435f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber ssize_t i = response->mHeaders.indexOfKey("content-base"); 4363a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (i >= 0) { 4373a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mBaseURL = response->mHeaders.valueAt(i); 4383a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } else { 439f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber i = response->mHeaders.indexOfKey("content-location"); 440f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber if (i >= 0) { 441f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber mBaseURL = response->mHeaders.valueAt(i); 442f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } else { 443f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber mBaseURL = mSessionURL; 444f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } 4453a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } 4463a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber 4470407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber if (!mBaseURL.startsWith("rtsp://")) { 4480407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber // Some misbehaving servers specify a relative 4490407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber // URL in one of the locations above, combine 4500407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber // it with the absolute session URL to get 4510407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber // something usable... 4520407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber 4530407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber LOGW("Server specified a non-absolute base URL" 4540407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber ", combining it with the session URL to " 4550407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber "get something usable..."); 4560407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber 4570407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber AString tmp; 4580407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber CHECK(MakeURL( 4590407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber mSessionURL.c_str(), 4600407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber mBaseURL.c_str(), 4610407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber &tmp)); 4620407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber 4630407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber mBaseURL = tmp; 4640407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber } 4650407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber 46657cc14fcc1642e0437b791ca3056e3728808092eAndreas Huber if (mSessionDesc->countTracks() < 2) { 46757cc14fcc1642e0437b791ca3056e3728808092eAndreas Huber // There's no actual tracks in this session. 46857cc14fcc1642e0437b791ca3056e3728808092eAndreas Huber // The first "track" is merely session meta 46957cc14fcc1642e0437b791ca3056e3728808092eAndreas Huber // data. 47057cc14fcc1642e0437b791ca3056e3728808092eAndreas Huber 47157cc14fcc1642e0437b791ca3056e3728808092eAndreas Huber LOGW("Session doesn't contain any playable " 47257cc14fcc1642e0437b791ca3056e3728808092eAndreas Huber "tracks. Aborting."); 47357cc14fcc1642e0437b791ca3056e3728808092eAndreas Huber result = ERROR_UNSUPPORTED; 47457cc14fcc1642e0437b791ca3056e3728808092eAndreas Huber } else { 47557cc14fcc1642e0437b791ca3056e3728808092eAndreas Huber setupTrack(1); 47657cc14fcc1642e0437b791ca3056e3728808092eAndreas Huber } 477f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } 4787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 4793a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } 4807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 4813a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (result != OK) { 4827a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 4837a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->disconnect(reply); 4847a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 4857a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 4867a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 4877a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 4887a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'setu': 4897a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 4907a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber size_t index; 4917a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findSize("index", &index)); 4927a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 49357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber TrackInfo *track = NULL; 4947a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber size_t trackIndex; 49557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber if (msg->findSize("track-index", &trackIndex)) { 49657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber track = &mTracks.editItemAt(trackIndex); 49757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber } 4987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 4997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber int32_t result; 5007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findInt32("result", &result)); 5017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 5026e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGI("SETUP(%d) completed with result %d (%s)", 5036e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber index, result, strerror(-result)); 5047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 5053a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (result == OK) { 50657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber CHECK(track != NULL); 5077a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 5087a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<RefBase> obj; 5097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findObject("response", &obj)); 5107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<ARTSPResponse> response = 5117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 5127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 5133a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (response->mStatusCode != 200) { 5143a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber result = UNKNOWN_ERROR; 5153a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } else { 5163a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber ssize_t i = response->mHeaders.indexOfKey("session"); 5173a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber CHECK_GE(i, 0); 5187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 5197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mSessionID = response->mHeaders.valueAt(i); 520a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 521a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs; 522a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber AString timeoutStr; 523a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber if (GetAttribute( 524a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber mSessionID.c_str(), "timeout", &timeoutStr)) { 525a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber char *end; 526a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber unsigned long timeoutSecs = 527a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber strtoul(timeoutStr.c_str(), &end, 10); 528a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 529a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber if (end == timeoutStr.c_str() || *end != '\0') { 530a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber LOGW("server specified malformed timeout '%s'", 531a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber timeoutStr.c_str()); 532a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 533a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs; 534a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber } else if (timeoutSecs < 15) { 535a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber LOGW("server specified too short a timeout " 536a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber "(%lu secs), using default.", 537a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber timeoutSecs); 538a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 539a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs; 540a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber } else { 541a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber mKeepAliveTimeoutUs = timeoutSecs * 1000000ll; 542a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 543a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber LOGI("server specified timeout of %lu secs.", 544a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber timeoutSecs); 545a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber } 546a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber } 547a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 5487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber i = mSessionID.find(";"); 5497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (i >= 0) { 5507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber // Remove options, i.e. ";timeout=90" 5517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mSessionID.erase(i, mSessionID.size() - i); 5527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 5537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 5543a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber sp<AMessage> notify = new AMessage('accu', id()); 5553a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber notify->setSize("track-index", trackIndex); 5567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 5570dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber i = response->mHeaders.indexOfKey("transport"); 5580dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber CHECK_GE(i, 0); 5590dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 5600dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber if (!track->mUsingInterleavedTCP) { 5610dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber AString transport = response->mHeaders.valueAt(i); 5620dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 56327db53de35bbe83ce3b906da675b065803471481Andreas Huber // We are going to continue even if we were 56427db53de35bbe83ce3b906da675b065803471481Andreas Huber // unable to poke a hole into the firewall... 56527db53de35bbe83ce3b906da675b065803471481Andreas Huber pokeAHole( 56627db53de35bbe83ce3b906da675b065803471481Andreas Huber track->mRTPSocket, 56727db53de35bbe83ce3b906da675b065803471481Andreas Huber track->mRTCPSocket, 56827db53de35bbe83ce3b906da675b065803471481Andreas Huber transport); 5690dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber } 5700dc6403f3c660f6e6f1840276e3240365889103dAndreas Huber 57127db53de35bbe83ce3b906da675b065803471481Andreas Huber mRTPConn->addStream( 57227db53de35bbe83ce3b906da675b065803471481Andreas Huber track->mRTPSocket, track->mRTCPSocket, 57327db53de35bbe83ce3b906da675b065803471481Andreas Huber mSessionDesc, index, 57427db53de35bbe83ce3b906da675b065803471481Andreas Huber notify, track->mUsingInterleavedTCP); 5757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 57627db53de35bbe83ce3b906da675b065803471481Andreas Huber mSetupTracksSuccessful = true; 5773a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } 5783a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } 5793a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber 5803a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (result != OK) { 5813a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (track) { 5823a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (!track->mUsingInterleavedTCP) { 583d5a20d8d75718fda8a9435d7113f3d6bb8f79a33Ashish Sharma // Clear the tag 584d5a20d8d75718fda8a9435d7113f3d6bb8f79a33Ashish Sharma if (mUIDValid) { 585d5a20d8d75718fda8a9435d7113f3d6bb8f79a33Ashish Sharma HTTPBase::UnRegisterSocketUserTag(track->mRTPSocket); 586d5a20d8d75718fda8a9435d7113f3d6bb8f79a33Ashish Sharma HTTPBase::UnRegisterSocketUserTag(track->mRTCPSocket); 587d5a20d8d75718fda8a9435d7113f3d6bb8f79a33Ashish Sharma } 588d5a20d8d75718fda8a9435d7113f3d6bb8f79a33Ashish Sharma 5893a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber close(track->mRTPSocket); 5903a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber close(track->mRTCPSocket); 5913a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } 5923a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber 5933a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mTracks.removeItemsAt(trackIndex); 5943a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } 5957a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 5967a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 59757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber ++index; 59857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber if (index < mSessionDesc->countTracks()) { 59957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber setupTrack(index); 60057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber } else if (mSetupTracksSuccessful) { 601a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber ++mKeepAliveGeneration; 602a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber postKeepAlive(); 603a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 6047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString request = "PLAY "; 6057a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(mSessionURL); 6067a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(" RTSP/1.0\r\n"); 6077a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 6087a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("Session: "); 6097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(mSessionID); 6107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 6117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 6127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 6137a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 6147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('play', id()); 6157a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->sendRequest(request.c_str(), reply); 6167a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } else { 6177a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 6187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->disconnect(reply); 6197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 6207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 6217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 6227a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 6237a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'play': 6247a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 6257a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber int32_t result; 6267a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findInt32("result", &result)); 6277a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 6286e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGI("PLAY completed with result %d (%s)", 6296e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber result, strerror(-result)); 6307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 6317a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (result == OK) { 6327a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<RefBase> obj; 6337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findObject("response", &obj)); 6347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<ARTSPResponse> response = 6357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 6367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 637f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber if (response->mStatusCode != 200) { 638f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber result = UNKNOWN_ERROR; 639f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } else { 640f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber parsePlayResponse(response); 6417a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 642f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber sp<AMessage> timeout = new AMessage('tiou', id()); 643f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber timeout->post(kStartupTimeoutUs); 644f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } 645f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } 646eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 647f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber if (result != OK) { 6487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 6497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->disconnect(reply); 6507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 6517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 6527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 6537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 6547a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 655a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber case 'aliv': 656a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber { 657a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber int32_t generation; 658a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber CHECK(msg->findInt32("generation", &generation)); 659a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 660a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber if (generation != mKeepAliveGeneration) { 661a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber // obsolete event. 662a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber break; 663a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber } 664a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 665a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber AString request; 666a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber request.append("OPTIONS "); 667a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber request.append(mSessionURL); 668a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber request.append(" RTSP/1.0\r\n"); 669a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber request.append("Session: "); 670a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber request.append(mSessionID); 671a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber request.append("\r\n"); 672a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber request.append("\r\n"); 673a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 674a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber sp<AMessage> reply = new AMessage('opts', id()); 675a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber reply->setInt32("generation", mKeepAliveGeneration); 676a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber mConn->sendRequest(request.c_str(), reply); 677a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber break; 678a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber } 679a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 680a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber case 'opts': 681a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber { 682a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber int32_t result; 683a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber CHECK(msg->findInt32("result", &result)); 684a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 685a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber LOGI("OPTIONS completed with result %d (%s)", 686a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber result, strerror(-result)); 687a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 688a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber int32_t generation; 689a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber CHECK(msg->findInt32("generation", &generation)); 690a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 691a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber if (generation != mKeepAliveGeneration) { 692a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber // obsolete event. 693a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber break; 694a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber } 695a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 696a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber postKeepAlive(); 697a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber break; 698a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber } 699a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 7007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'abor': 7017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 7027a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 703f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber TrackInfo *info = &mTracks.editItemAt(i); 704f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 705a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber if (!mFirstAccessUnit) { 706a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber postQueueEOS(i, ERROR_END_OF_STREAM); 707a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber } 708f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 709f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber if (!info->mUsingInterleavedTCP) { 710f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber mRTPConn->removeStream(info->mRTPSocket, info->mRTCPSocket); 711f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 712d5a20d8d75718fda8a9435d7113f3d6bb8f79a33Ashish Sharma // Clear the tag 713d5a20d8d75718fda8a9435d7113f3d6bb8f79a33Ashish Sharma if (mUIDValid) { 714d5a20d8d75718fda8a9435d7113f3d6bb8f79a33Ashish Sharma HTTPBase::UnRegisterSocketUserTag(info->mRTPSocket); 715d5a20d8d75718fda8a9435d7113f3d6bb8f79a33Ashish Sharma HTTPBase::UnRegisterSocketUserTag(info->mRTCPSocket); 716d5a20d8d75718fda8a9435d7113f3d6bb8f79a33Ashish Sharma } 717d5a20d8d75718fda8a9435d7113f3d6bb8f79a33Ashish Sharma 718f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber close(info->mRTPSocket); 719f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber close(info->mRTCPSocket); 720f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } 7217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 722f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber mTracks.clear(); 7233a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mSetupTracksSuccessful = false; 7243a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mSeekPending = false; 7253a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mFirstAccessUnit = true; 726b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber mNTPAnchorUs = -1; 727b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber mMediaAnchorUs = -1; 7283a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mNumAccessUnitsReceived = 0; 7293a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mReceivedFirstRTCPPacket = false; 730cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber mReceivedFirstRTPPacket = false; 7310c46b69f612da61ed39b32823d2d6baf2e8215e9Andreas Huber mSeekable = false; 7327a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 7337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('tear', id()); 7347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 735f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber int32_t reconnect; 736f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber if (msg->findInt32("reconnect", &reconnect) && reconnect) { 737f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber reply->setInt32("reconnect", true); 738f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } 739f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 7407a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString request; 7417a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request = "TEARDOWN "; 7427a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 7437a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber // XXX should use aggregate url from SDP here... 7447a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(mSessionURL); 7457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(" RTSP/1.0\r\n"); 7467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 7477a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("Session: "); 7487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(mSessionID); 7497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 7507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 7517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 7527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 7537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->sendRequest(request.c_str(), reply); 7547a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 7557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 7567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 7577a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'tear': 7587a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 7597a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber int32_t result; 7607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findInt32("result", &result)); 7617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 7626e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGI("TEARDOWN completed with result %d (%s)", 7636e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber result, strerror(-result)); 7647a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 7657a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 766f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 767f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber int32_t reconnect; 768f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber if (msg->findInt32("reconnect", &reconnect) && reconnect) { 769f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber reply->setInt32("reconnect", true); 770f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } 771f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 7727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->disconnect(reply); 7737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 7747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 7757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 7767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'quit': 7777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 778a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber sp<AMessage> msg = mNotify->dup(); 779a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setInt32("what", kWhatDisconnected); 780a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setInt32("result", UNKNOWN_ERROR); 781a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->post(); 7827a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 7837a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 7847a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 785eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber case 'chek': 786eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber { 787e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber int32_t generation; 788e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber CHECK(msg->findInt32("generation", &generation)); 789e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber if (generation != mCheckGeneration) { 790e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber // This is an outdated message. Ignore. 791e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber break; 792e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber } 793e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber 794eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (mNumAccessUnitsReceived == 0) { 79554c7efa4dd7300a2ab008d392a83bfbdf97cdfadAndreas Huber#if 1 7966e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGI("stream ended? aborting."); 797eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber (new AMessage('abor', id()))->post(); 798eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber break; 79957cc14fcc1642e0437b791ca3056e3728808092eAndreas Huber#else 80057cc14fcc1642e0437b791ca3056e3728808092eAndreas Huber LOGI("haven't seen an AU in a looong time."); 80157cc14fcc1642e0437b791ca3056e3728808092eAndreas Huber#endif 802eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 803eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 804eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber mNumAccessUnitsReceived = 0; 805f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huber msg->post(kAccessUnitTimeoutUs); 806eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber break; 807eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 808eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 8097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'accu': 8107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 811b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber int32_t timeUpdate; 812b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber if (msg->findInt32("time-update", &timeUpdate) && timeUpdate) { 813b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber size_t trackIndex; 814b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber CHECK(msg->findSize("track-index", &trackIndex)); 815b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 816b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber uint32_t rtpTime; 817b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber uint64_t ntpTime; 818b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber CHECK(msg->findInt32("rtp-time", (int32_t *)&rtpTime)); 819b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber CHECK(msg->findInt64("ntp-time", (int64_t *)&ntpTime)); 820b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 821b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber onTimeUpdate(trackIndex, rtpTime, ntpTime); 822b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber break; 823b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber } 824b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 825cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber int32_t first; 826cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber if (msg->findInt32("first-rtcp", &first)) { 8273a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mReceivedFirstRTCPPacket = true; 8283a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber break; 8293a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } 8303a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber 831cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber if (msg->findInt32("first-rtp", &first)) { 832cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber mReceivedFirstRTPPacket = true; 833cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber break; 834cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber } 835cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber 836eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber ++mNumAccessUnitsReceived; 837e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber postAccessUnitTimeoutCheck(); 838eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 8397a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber size_t trackIndex; 8407a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findSize("track-index", &trackIndex)); 8417a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 842f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber if (trackIndex >= mTracks.size()) { 8436e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGV("late packets ignored."); 844f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber break; 845f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } 846f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 847eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 848eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 849af063a67b291c4622321a35af6966b8568d5a564Andreas Huber int32_t eos; 850af063a67b291c4622321a35af6966b8568d5a564Andreas Huber if (msg->findInt32("eos", &eos)) { 8516e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGI("received BYE on track index %d", trackIndex); 852af063a67b291c4622321a35af6966b8568d5a564Andreas Huber#if 0 853af063a67b291c4622321a35af6966b8568d5a564Andreas Huber track->mPacketSource->signalEOS(ERROR_END_OF_STREAM); 854af063a67b291c4622321a35af6966b8568d5a564Andreas Huber#endif 855af063a67b291c4622321a35af6966b8568d5a564Andreas Huber return; 856af063a67b291c4622321a35af6966b8568d5a564Andreas Huber } 857af063a67b291c4622321a35af6966b8568d5a564Andreas Huber 8587a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<RefBase> obj; 8597a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findObject("access-unit", &obj)); 8607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 8617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<ABuffer> accessUnit = static_cast<ABuffer *>(obj.get()); 8627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 863eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber uint32_t seqNum = (uint32_t)accessUnit->int32Data(); 864eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 865f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber if (mSeekPending) { 8666e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGV("we're seeking, dropping stale packet."); 867f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber break; 868f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } 869f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber 870eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (seqNum < track->mFirstSeqNumInSegment) { 8716e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGV("dropping stale access-unit (%d < %d)", 8726e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber seqNum, track->mFirstSeqNumInSegment); 873eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber break; 874eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 875eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 876eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (track->mNewSegment) { 877eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber track->mNewSegment = false; 878eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 879eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 880b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber onAccessUnitComplete(trackIndex, accessUnit); 8817a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 8827a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 8837a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 884e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber case 'seek': 885e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber { 8860c46b69f612da61ed39b32823d2d6baf2e8215e9Andreas Huber if (!mSeekable) { 8870c46b69f612da61ed39b32823d2d6baf2e8215e9Andreas Huber LOGW("This is a live stream, ignoring seek request."); 888a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber 889a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber sp<AMessage> msg = mNotify->dup(); 890a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setInt32("what", kWhatSeekDone); 891a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->post(); 892e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber break; 893e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber } 894e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 895e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber int64_t timeUs; 896e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber CHECK(msg->findInt64("time", &timeUs)); 897e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 898e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber mSeekPending = true; 899e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 900e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber // Disable the access unit timeout until we resumed 901e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber // playback again. 902e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber mCheckPending = true; 903e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber ++mCheckGeneration; 904e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber 905e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber AString request = "PAUSE "; 906e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append(mSessionURL); 907e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append(" RTSP/1.0\r\n"); 908e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 909e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append("Session: "); 910e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append(mSessionID); 911e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append("\r\n"); 912e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 913e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append("\r\n"); 914e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 915e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber sp<AMessage> reply = new AMessage('see1', id()); 916e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber reply->setInt64("time", timeUs); 917e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber mConn->sendRequest(request.c_str(), reply); 918e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber break; 919e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber } 920e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 921e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber case 'see1': 922e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber { 923eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber // Session is paused now. 924eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 925b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber TrackInfo *info = &mTracks.editItemAt(i); 926b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 927a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber postQueueSeekDiscontinuity(i); 928a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber 929b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber info->mRTPAnchor = 0; 930b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber info->mNTPAnchorUs = -1; 931eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 932eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 933b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber mNTPAnchorUs = -1; 934b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 935e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber int64_t timeUs; 936e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber CHECK(msg->findInt64("time", &timeUs)); 937e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 938e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber AString request = "PLAY "; 939e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append(mSessionURL); 940e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append(" RTSP/1.0\r\n"); 941e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 942e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append("Session: "); 943e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append(mSessionID); 944e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append("\r\n"); 945e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 946e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append( 947e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber StringPrintf( 948e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber "Range: npt=%lld-\r\n", timeUs / 1000000ll)); 949e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 950e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append("\r\n"); 951e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 952e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber sp<AMessage> reply = new AMessage('see2', id()); 953e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber mConn->sendRequest(request.c_str(), reply); 954e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber break; 955e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber } 956e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 957e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber case 'see2': 958e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber { 959e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber CHECK(mSeekPending); 960e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 961e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber int32_t result; 962e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber CHECK(msg->findInt32("result", &result)); 963eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 9646e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGI("PLAY completed with result %d (%s)", 9656e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber result, strerror(-result)); 966eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 967e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber mCheckPending = false; 968e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber postAccessUnitTimeoutCheck(); 969e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber 970f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber if (result == OK) { 971f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber sp<RefBase> obj; 972f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber CHECK(msg->findObject("response", &obj)); 973f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber sp<ARTSPResponse> response = 974f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber static_cast<ARTSPResponse *>(obj.get()); 975e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 976f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber if (response->mStatusCode != 200) { 977f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber result = UNKNOWN_ERROR; 978f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } else { 979f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber parsePlayResponse(response); 980e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 981b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber ssize_t i = response->mHeaders.indexOfKey("rtp-info"); 982b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber CHECK_GE(i, 0); 983b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 984b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber LOGV("rtp-info: %s", response->mHeaders.valueAt(i).c_str()); 985b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 9866e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGI("seek completed."); 987f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } 988f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } 989e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 990f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber if (result != OK) { 9916e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGE("seek failed, aborting."); 992f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber (new AMessage('abor', id()))->post(); 993f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } 994eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 995eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber mSeekPending = false; 9960c46b69f612da61ed39b32823d2d6baf2e8215e9Andreas Huber 997a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber sp<AMessage> msg = mNotify->dup(); 998a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setInt32("what", kWhatSeekDone); 999a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->post(); 1000e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber break; 1001e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber } 1002e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 10030416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber case 'biny': 10040416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber { 10050416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber sp<RefBase> obj; 10060416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber CHECK(msg->findObject("buffer", &obj)); 10070416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); 10080416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber 10090416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber int32_t index; 10100416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber CHECK(buffer->meta()->findInt32("index", &index)); 10110416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber 10120416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber mRTPConn->injectPacket(index, buffer); 10130416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber break; 10140416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber } 10150416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber 10160416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber case 'tiou': 10170416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber { 10183a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (!mReceivedFirstRTCPPacket) { 10190407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber if (mReceivedFirstRTPPacket && !mTryFakeRTCP) { 1020cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber LOGW("We received RTP packets but no RTCP packets, " 1021cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber "using fake timestamps."); 1022cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber 1023cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber mTryFakeRTCP = true; 1024cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber 1025cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber mReceivedFirstRTCPPacket = true; 10260407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber 10270407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber fakeTimestamps(); 10280407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber } else if (!mReceivedFirstRTPPacket && !mTryTCPInterleaving) { 10296e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGW("Never received any data, switching transports."); 1030f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 1031f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber mTryTCPInterleaving = true; 1032f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 1033f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber sp<AMessage> msg = new AMessage('abor', id()); 1034f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber msg->setInt32("reconnect", true); 1035f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber msg->post(); 10360407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber } else { 10370407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber LOGW("Never received any data, disconnecting."); 10380407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber (new AMessage('abor', id()))->post(); 1039f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } 10400416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber } 10410416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber break; 10420416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber } 10430416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber 10447a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber default: 10457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber TRESPASS(); 10467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 10477a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 10487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 10497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 1050a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber void postKeepAlive() { 1051a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber sp<AMessage> msg = new AMessage('aliv', id()); 1052a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber msg->setInt32("generation", mKeepAliveGeneration); 1053a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber msg->post((mKeepAliveTimeoutUs * 9) / 10); 1054a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber } 1055a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber 1056e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber void postAccessUnitTimeoutCheck() { 1057e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber if (mCheckPending) { 1058e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber return; 1059e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber } 1060e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber 1061e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber mCheckPending = true; 1062e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber sp<AMessage> check = new AMessage('chek', id()); 1063e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber check->setInt32("generation", mCheckGeneration); 1064e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber check->post(kAccessUnitTimeoutUs); 1065e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber } 1066e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber 1067eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber static void SplitString( 1068eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber const AString &s, const char *separator, List<AString> *items) { 1069eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber items->clear(); 1070eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber size_t start = 0; 1071eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber while (start < s.size()) { 1072eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber ssize_t offset = s.find(separator, start); 1073eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1074eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (offset < 0) { 1075eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber items->push_back(AString(s, start, s.size() - start)); 1076eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber break; 1077eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 1078eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1079eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber items->push_back(AString(s, start, offset - start)); 1080eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber start = offset + strlen(separator); 1081eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 1082eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 1083eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1084eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber void parsePlayResponse(const sp<ARTSPResponse> &response) { 10850c46b69f612da61ed39b32823d2d6baf2e8215e9Andreas Huber mSeekable = false; 10860c46b69f612da61ed39b32823d2d6baf2e8215e9Andreas Huber 1087eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber ssize_t i = response->mHeaders.indexOfKey("range"); 1088eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (i < 0) { 1089eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber // Server doesn't even tell use what range it is going to 1090eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber // play, therefore we won't support seeking. 1091eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber return; 1092eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 1093eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1094eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber AString range = response->mHeaders.valueAt(i); 10956e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGV("Range: %s", range.c_str()); 1096eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1097eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber AString val; 1098eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber CHECK(GetAttribute(range.c_str(), "npt", &val)); 1099eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1100a2edd7d8d1323aad756d6f58f545d01c0bf33458Andreas Huber float npt1, npt2; 1101a2edd7d8d1323aad756d6f58f545d01c0bf33458Andreas Huber if (!ASessionDescription::parseNTPRange(val.c_str(), &npt1, &npt2)) { 1102eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber // This is a live stream and therefore not seekable. 1103f6ae711450581d248e646b8d8d6b0bf75c4d19eaAndreas Huber 1104f6ae711450581d248e646b8d8d6b0bf75c4d19eaAndreas Huber LOGI("This is a live stream"); 1105d4a6cac34d9e75dc708f894863d1870e456c93d6Andreas Huber return; 1106eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 1107eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1108eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber i = response->mHeaders.indexOfKey("rtp-info"); 1109eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber CHECK_GE(i, 0); 1110eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1111eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber AString rtpInfo = response->mHeaders.valueAt(i); 1112eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber List<AString> streamInfos; 1113eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber SplitString(rtpInfo, ",", &streamInfos); 1114eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1115eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber int n = 1; 1116eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber for (List<AString>::iterator it = streamInfos.begin(); 1117eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber it != streamInfos.end(); ++it) { 1118eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber (*it).trim(); 11196e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGV("streamInfo[%d] = %s", n, (*it).c_str()); 1120eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1121eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber CHECK(GetAttribute((*it).c_str(), "url", &val)); 1122eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1123eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber size_t trackIndex = 0; 1124eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber while (trackIndex < mTracks.size() 1125eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber && !(val == mTracks.editItemAt(trackIndex).mURL)) { 1126eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber ++trackIndex; 1127eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 1128eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber CHECK_LT(trackIndex, mTracks.size()); 1129eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1130eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber CHECK(GetAttribute((*it).c_str(), "seq", &val)); 1131eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1132eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber char *end; 1133eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber unsigned long seq = strtoul(val.c_str(), &end, 10); 1134eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1135eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber TrackInfo *info = &mTracks.editItemAt(trackIndex); 1136eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber info->mFirstSeqNumInSegment = seq; 1137eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber info->mNewSegment = true; 1138eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1139eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber CHECK(GetAttribute((*it).c_str(), "rtptime", &val)); 1140eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1141eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber uint32_t rtpTime = strtoul(val.c_str(), &end, 10); 1142eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1143b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber LOGV("track #%d: rtpTime=%u <=> npt=%.2f", n, rtpTime, npt1); 1144eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1145a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber info->mNormalPlayTimeRTP = rtpTime; 1146a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber info->mNormalPlayTimeUs = (int64_t)(npt1 * 1E6); 1147a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber 1148a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber if (!mFirstAccessUnit) { 1149a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber postNormalPlayTimeMapping( 1150a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber trackIndex, 1151a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs); 1152a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber } 1153eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1154eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber ++n; 1155eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 11560c46b69f612da61ed39b32823d2d6baf2e8215e9Andreas Huber 1157d4a6cac34d9e75dc708f894863d1870e456c93d6Andreas Huber mSeekable = true; 1158eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 1159eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1160a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber sp<MetaData> getTrackFormat(size_t index, int32_t *timeScale) { 11617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK_GE(index, 0u); 11627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK_LT(index, mTracks.size()); 11637a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 1164a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber const TrackInfo &info = mTracks.itemAt(index); 1165a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber 1166a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber *timeScale = info.mTimeScale; 1167a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber 1168a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber return info.mPacketSource->getFormat(); 11697a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 11707a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 11717a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber size_t countTracks() const { 11727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber return mTracks.size(); 11737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 11747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 11757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huberprivate: 1176b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber struct TrackInfo { 1177b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber AString mURL; 1178b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber int mRTPSocket; 1179b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber int mRTCPSocket; 1180b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber bool mUsingInterleavedTCP; 1181b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber uint32_t mFirstSeqNumInSegment; 1182b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber bool mNewSegment; 1183b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1184b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber uint32_t mRTPAnchor; 1185b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber int64_t mNTPAnchorUs; 1186b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber int32_t mTimeScale; 1187b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1188a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber uint32_t mNormalPlayTimeRTP; 1189a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber int64_t mNormalPlayTimeUs; 1190a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber 1191b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber sp<APacketSource> mPacketSource; 1192b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1193b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber // Stores packets temporarily while no notion of time 1194b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber // has been established yet. 1195b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber List<sp<ABuffer> > mPackets; 1196b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber }; 1197b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1198a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber sp<AMessage> mNotify; 1199603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber bool mUIDValid; 1200603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber uid_t mUID; 12014e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber sp<ALooper> mNetLooper; 12027a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<ARTSPConnection> mConn; 12037a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<ARTPConnection> mRTPConn; 12047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<ASessionDescription> mSessionDesc; 1205a0b442edbf6e1f602f89b3bda1c8894ef8740d72Andreas Huber AString mOriginalSessionURL; // This one still has user:pass@ 12067a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString mSessionURL; 120727db53de35bbe83ce3b906da675b065803471481Andreas Huber AString mSessionHost; 12087a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString mBaseURL; 12097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString mSessionID; 12107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber bool mSetupTracksSuccessful; 1211e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber bool mSeekPending; 1212e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber bool mFirstAccessUnit; 1213b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1214b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber int64_t mNTPAnchorUs; 1215b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber int64_t mMediaAnchorUs; 1216b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber int64_t mLastMediaTimeUs; 1217b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1218eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber int64_t mNumAccessUnitsReceived; 1219eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber bool mCheckPending; 1220e51e80990e72dee6372e3300fbbcdac3a115b60aAndreas Huber int32_t mCheckGeneration; 1221f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber bool mTryTCPInterleaving; 1222cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber bool mTryFakeRTCP; 12233a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber bool mReceivedFirstRTCPPacket; 1224cc5fb1d5e5c1971cabfc2cba89de63ba65678882Andreas Huber bool mReceivedFirstRTPPacket; 12250c46b69f612da61ed39b32823d2d6baf2e8215e9Andreas Huber bool mSeekable; 1226a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber int64_t mKeepAliveTimeoutUs; 1227a1b3e3d49ea04cc42aadbd07a6304008fda1e515Andreas Huber int32_t mKeepAliveGeneration; 12287a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 12297a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber Vector<TrackInfo> mTracks; 12307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 12317a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber void setupTrack(size_t index) { 123257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber sp<APacketSource> source = 123357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber new APacketSource(mSessionDesc, index); 1234f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 123557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber if (source->initCheck() != OK) { 12366e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGW("Unsupported format. Ignoring track #%d.", index); 123757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber 123857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber sp<AMessage> reply = new AMessage('setu', id()); 123957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber reply->setSize("index", index); 124057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber reply->setInt32("result", ERROR_UNSUPPORTED); 124157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber reply->post(); 124257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber return; 124357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber } 124457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber 12457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString url; 12467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(mSessionDesc->findAttribute(index, "a=control", &url)); 12477a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 12487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString trackURL; 12497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(MakeURL(mBaseURL.c_str(), url.c_str(), &trackURL)); 12507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 12517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mTracks.push(TrackInfo()); 12527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber TrackInfo *info = &mTracks.editItemAt(mTracks.size() - 1); 1253eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber info->mURL = trackURL; 125457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber info->mPacketSource = source; 12550416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber info->mUsingInterleavedTCP = false; 1256eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber info->mFirstSeqNumInSegment = 0; 1257eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber info->mNewSegment = true; 1258b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber info->mRTPAnchor = 0; 1259b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber info->mNTPAnchorUs = -1; 1260a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber info->mNormalPlayTimeRTP = 0; 1261a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber info->mNormalPlayTimeUs = 0ll; 1262b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1263b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber unsigned long PT; 1264b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber AString formatDesc; 1265b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber AString formatParams; 1266b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber mSessionDesc->getFormatType(index, &PT, &formatDesc, &formatParams); 1267b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1268b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber int32_t timescale; 1269b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber int32_t numChannels; 1270b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber ASessionDescription::ParseFormatDesc( 1271b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber formatDesc.c_str(), ×cale, &numChannels); 1272b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1273b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber info->mTimeScale = timescale; 1274eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 12756e3fa444c5b3970666707bb2b6d25e2615dafe80Andreas Huber LOGV("track #%d URL=%s", mTracks.size(), trackURL.c_str()); 12767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 12777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString request = "SETUP "; 12787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(trackURL); 12797a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(" RTSP/1.0\r\n"); 12807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 1281f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber if (mTryTCPInterleaving) { 1282f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber size_t interleaveIndex = 2 * (mTracks.size() - 1); 1283f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber info->mUsingInterleavedTCP = true; 1284f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber info->mRTPSocket = interleaveIndex; 1285f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber info->mRTCPSocket = interleaveIndex + 1; 1286f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 1287f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber request.append("Transport: RTP/AVP/TCP;interleaved="); 1288f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber request.append(interleaveIndex); 1289f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber request.append("-"); 1290f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber request.append(interleaveIndex + 1); 1291f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } else { 1292f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber unsigned rtpPort; 1293f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber ARTPConnection::MakePortPair( 1294f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber &info->mRTPSocket, &info->mRTCPSocket, &rtpPort); 1295f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 1296603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber if (mUIDValid) { 1297d5a20d8d75718fda8a9435d7113f3d6bb8f79a33Ashish Sharma HTTPBase::RegisterSocketUserTag(info->mRTPSocket, mUID, 1298d5a20d8d75718fda8a9435d7113f3d6bb8f79a33Ashish Sharma (uint32_t)*(uint32_t*) "RTP_"); 1299d5a20d8d75718fda8a9435d7113f3d6bb8f79a33Ashish Sharma HTTPBase::RegisterSocketUserTag(info->mRTCPSocket, mUID, 1300d5a20d8d75718fda8a9435d7113f3d6bb8f79a33Ashish Sharma (uint32_t)*(uint32_t*) "RTP_"); 1301603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber } 1302603d739b5a444c52b63f1ec7cd2098034151ad25Andreas Huber 1303f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber request.append("Transport: RTP/AVP/UDP;unicast;client_port="); 1304f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber request.append(rtpPort); 1305f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber request.append("-"); 1306f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber request.append(rtpPort + 1); 1307f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } 13080416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber 13097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 13107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 13117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (index > 1) { 13127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("Session: "); 13137a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(mSessionID); 13147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 13157a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 13167a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 13177a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 13187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 13197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('setu', id()); 13207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber reply->setSize("index", index); 13217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber reply->setSize("track-index", mTracks.size() - 1); 13227a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->sendRequest(request.c_str(), reply); 13237a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 13247a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 13257a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber static bool MakeURL(const char *baseURL, const char *url, AString *out) { 13267a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber out->clear(); 13277a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 13287a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (strncasecmp("rtsp://", baseURL, 7)) { 13297a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber // Base URL must be absolute 13307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber return false; 13317a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 13327a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 13337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (!strncasecmp("rtsp://", url, 7)) { 13347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber // "url" is already an absolute URL, ignore base URL. 13357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber out->setTo(url); 13367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber return true; 13377a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 13387a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 13397a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber size_t n = strlen(baseURL); 13407a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (baseURL[n - 1] == '/') { 13417a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber out->setTo(baseURL); 13427a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber out->append(url); 13437a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } else { 13445a23f8c41ee83a0316ae8265841beaf6d97a66d9Mike Lockwood const char *slashPos = strrchr(baseURL, '/'); 13457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 13467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (slashPos > &baseURL[6]) { 13477a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber out->setTo(baseURL, slashPos - baseURL); 13487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } else { 13497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber out->setTo(baseURL); 13507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 13517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 13527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber out->append("/"); 13537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber out->append(url); 13547a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 13557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 13567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber return true; 13577a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 13587a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 13590407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber void fakeTimestamps() { 13600407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 13610407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber onTimeUpdate(i, 0, 0ll); 13620407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber } 13630407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber } 13640407269ae35e62a6aa2f6e40964970db1bd4b14aAndreas Huber 1365b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber void onTimeUpdate(int32_t trackIndex, uint32_t rtpTime, uint64_t ntpTime) { 1366b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber LOGV("onTimeUpdate track %d, rtpTime = 0x%08x, ntpTime = 0x%016llx", 1367b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber trackIndex, rtpTime, ntpTime); 1368b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1369b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber int64_t ntpTimeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32)); 1370b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1371b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 1372b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1373b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber track->mRTPAnchor = rtpTime; 1374b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber track->mNTPAnchorUs = ntpTimeUs; 1375b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1376b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber if (mNTPAnchorUs < 0) { 1377b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber mNTPAnchorUs = ntpTimeUs; 1378b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber mMediaAnchorUs = mLastMediaTimeUs; 1379b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber } 1380b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber } 1381b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1382b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber void onAccessUnitComplete( 1383b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber int32_t trackIndex, const sp<ABuffer> &accessUnit) { 1384b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber LOGV("onAccessUnitComplete track %d", trackIndex); 1385b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1386b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber if (mFirstAccessUnit) { 1387a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber sp<AMessage> msg = mNotify->dup(); 1388a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setInt32("what", kWhatConnected); 1389a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->post(); 1390a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber 1391f6ae711450581d248e646b8d8d6b0bf75c4d19eaAndreas Huber if (mSeekable) { 1392f6ae711450581d248e646b8d8d6b0bf75c4d19eaAndreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 1393f6ae711450581d248e646b8d8d6b0bf75c4d19eaAndreas Huber TrackInfo *info = &mTracks.editItemAt(i); 1394a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber 1395f6ae711450581d248e646b8d8d6b0bf75c4d19eaAndreas Huber postNormalPlayTimeMapping( 1396f6ae711450581d248e646b8d8d6b0bf75c4d19eaAndreas Huber i, 1397f6ae711450581d248e646b8d8d6b0bf75c4d19eaAndreas Huber info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs); 1398f6ae711450581d248e646b8d8d6b0bf75c4d19eaAndreas Huber } 1399a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber } 1400b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1401b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber mFirstAccessUnit = false; 1402b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber } 1403b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1404b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 1405b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1406b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber if (mNTPAnchorUs < 0 || mMediaAnchorUs < 0 || track->mNTPAnchorUs < 0) { 1407b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber LOGV("storing accessUnit, no time established yet"); 1408b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber track->mPackets.push_back(accessUnit); 1409b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber return; 1410b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber } 1411b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1412b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber while (!track->mPackets.empty()) { 1413b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber sp<ABuffer> accessUnit = *track->mPackets.begin(); 1414b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber track->mPackets.erase(track->mPackets.begin()); 1415b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1416b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber if (addMediaTimestamp(trackIndex, track, accessUnit)) { 1417a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber postQueueAccessUnit(trackIndex, accessUnit); 1418b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber } 1419b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber } 1420b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1421b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber if (addMediaTimestamp(trackIndex, track, accessUnit)) { 1422a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber postQueueAccessUnit(trackIndex, accessUnit); 1423b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber } 1424b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber } 1425b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1426b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber bool addMediaTimestamp( 1427b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber int32_t trackIndex, const TrackInfo *track, 1428b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber const sp<ABuffer> &accessUnit) { 1429b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber uint32_t rtpTime; 1430b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber CHECK(accessUnit->meta()->findInt32( 1431b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber "rtp-time", (int32_t *)&rtpTime)); 1432b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1433b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber int64_t relRtpTimeUs = 1434b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber (((int64_t)rtpTime - (int64_t)track->mRTPAnchor) * 1000000ll) 1435b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber / track->mTimeScale; 1436b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1437b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber int64_t ntpTimeUs = track->mNTPAnchorUs + relRtpTimeUs; 1438b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1439b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber int64_t mediaTimeUs = mMediaAnchorUs + ntpTimeUs - mNTPAnchorUs; 1440b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1441b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber if (mediaTimeUs > mLastMediaTimeUs) { 1442b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber mLastMediaTimeUs = mediaTimeUs; 1443b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber } 1444b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1445b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber if (mediaTimeUs < 0) { 1446b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber LOGV("dropping early accessUnit."); 1447b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber return false; 1448b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber } 1449b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1450b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber LOGV("track %d rtpTime=%d mediaTimeUs = %lld us (%.2f secs)", 1451b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber trackIndex, rtpTime, mediaTimeUs, mediaTimeUs / 1E6); 1452b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1453b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber accessUnit->meta()->setInt64("timeUs", mediaTimeUs); 1454b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1455b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber return true; 1456b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber } 1457b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 1458a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber void postQueueAccessUnit( 1459a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber size_t trackIndex, const sp<ABuffer> &accessUnit) { 1460a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber sp<AMessage> msg = mNotify->dup(); 1461a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setInt32("what", kWhatAccessUnit); 1462a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setSize("trackIndex", trackIndex); 1463a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setObject("accessUnit", accessUnit); 1464a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->post(); 1465a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber } 1466a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber 1467a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber void postQueueEOS(size_t trackIndex, status_t finalResult) { 1468a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber sp<AMessage> msg = mNotify->dup(); 1469a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setInt32("what", kWhatEOS); 1470a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setSize("trackIndex", trackIndex); 1471a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setInt32("finalResult", finalResult); 1472a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->post(); 1473a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber } 1474a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber 1475a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber void postQueueSeekDiscontinuity(size_t trackIndex) { 1476a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber sp<AMessage> msg = mNotify->dup(); 1477a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setInt32("what", kWhatSeekDiscontinuity); 1478a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setSize("trackIndex", trackIndex); 1479a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->post(); 1480a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber } 1481a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber 1482a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber void postNormalPlayTimeMapping( 1483a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber size_t trackIndex, uint32_t rtpTime, int64_t nptUs) { 1484a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber sp<AMessage> msg = mNotify->dup(); 1485a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setInt32("what", kWhatNormalPlayTimeMapping); 1486a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setSize("trackIndex", trackIndex); 1487a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setInt32("rtpTime", rtpTime); 1488a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->setInt64("nptUs", nptUs); 1489a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber msg->post(); 1490a6be6dcd03fbcce8999d495abdd2ae209a06b4c9Andreas Huber } 1491b2934b16eac8d8a866c37a7d1d7e03635f475b08Andreas Huber 14927a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber DISALLOW_EVIL_CONSTRUCTORS(MyHandler); 14937a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber}; 14947a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 14957a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber} // namespace android 14967a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 14977a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#endif // MY_HANDLER_H_ 1498