MyHandler.h revision f3d2bdf73c36be549f1ddff4238e97b3629c480d
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 217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include "APacketSource.h" 227a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include "ARTPConnection.h" 237a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include "ARTSPConnection.h" 247a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include "ASessionDescription.h" 257a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 26eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber#include <ctype.h> 27eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 287a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 297a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <media/stagefright/foundation/ADebug.h> 307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <media/stagefright/foundation/ALooper.h> 317a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <media/stagefright/foundation/AMessage.h> 327a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#include <media/stagefright/MediaErrors.h> 337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 34f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huber// If no access units are received within 3 secs, assume that the rtp 35f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huber// stream has ended and signal end of stream. 36f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huberstatic int64_t kAccessUnitTimeoutUs = 3000000ll; 37f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huber 38f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huber// If no access units arrive for the first 10 secs after starting the 39f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huber// stream, assume none ever will and signal EOS or switch transports. 40f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huberstatic int64_t kStartupTimeoutUs = 10000000ll; 41f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huber 427a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Hubernamespace android { 437a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 44eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huberstatic bool GetAttribute(const char *s, const char *key, AString *value) { 45eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber value->clear(); 46eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 47eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber size_t keyLen = strlen(key); 48eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 49eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber for (;;) { 50eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber while (isspace(*s)) { 51eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber ++s; 52eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 53eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 54eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber const char *colonPos = strchr(s, ';'); 55eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 56eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber size_t len = 57eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber (colonPos == NULL) ? strlen(s) : colonPos - s; 58eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 59eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) { 60eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber value->setTo(&s[keyLen + 1], len - keyLen - 1); 61eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber return true; 62eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 63eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 64eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (colonPos == NULL) { 65eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber return false; 66eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 67eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 68eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber s = colonPos + 1; 69eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 70eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber} 71eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huberstruct MyHandler : public AHandler { 737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber MyHandler(const char *url, const sp<ALooper> &looper) 747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber : mLooper(looper), 754e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber mNetLooper(new ALooper), 767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn(new ARTSPConnection), 777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mRTPConn(new ARTPConnection), 787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mSessionURL(url), 79e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber mSetupTracksSuccessful(false), 80e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber mSeekPending(false), 81e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber mFirstAccessUnit(true), 82eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber mFirstAccessUnitNTP(0), 83eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber mNumAccessUnitsReceived(0), 84f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber mCheckPending(false), 853a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mTryTCPInterleaving(false), 863a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mReceivedFirstRTCPPacket(false) { 87c4e0b70a21fadb47d70955c71fc31ce1473da925Andreas Huber mNetLooper->setName("rtsp net"); 884e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber mNetLooper->start(false /* runOnCallingThread */, 894e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber false /* canCallJava */, 904e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber PRIORITY_HIGHEST); 914e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber } 924e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber 938370be11debc574b4a9fee62009009d999e29fa3Andreas Huber void connect(const sp<AMessage> &doneMsg) { 948370be11debc574b4a9fee62009009d999e29fa3Andreas Huber mDoneMsg = doneMsg; 958370be11debc574b4a9fee62009009d999e29fa3Andreas Huber 967a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mLooper->registerHandler(this); 977a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mLooper->registerHandler(mConn); 984e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber (1 ? mNetLooper : mLooper)->registerHandler(mRTPConn); 994e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber 1000416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber sp<AMessage> notify = new AMessage('biny', id()); 1010416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber mConn->observeBinaryData(notify); 1020416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber 1038370be11debc574b4a9fee62009009d999e29fa3Andreas Huber sp<AMessage> reply = new AMessage('conn', id()); 1047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->connect(mSessionURL.c_str(), reply); 1057a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 1067a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 1078370be11debc574b4a9fee62009009d999e29fa3Andreas Huber void disconnect(const sp<AMessage> &doneMsg) { 1088370be11debc574b4a9fee62009009d999e29fa3Andreas Huber mDoneMsg = doneMsg; 1098370be11debc574b4a9fee62009009d999e29fa3Andreas Huber 1108370be11debc574b4a9fee62009009d999e29fa3Andreas Huber (new AMessage('abor', id()))->post(); 1114e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber } 1124e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber 113e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber void seek(int64_t timeUs) { 114e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber sp<AMessage> msg = new AMessage('seek', id()); 115e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber msg->setInt64("time", timeUs); 116e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber msg->post(); 117e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber } 118e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 119eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber int64_t getNormalPlayTimeUs() { 120eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber int64_t maxTimeUs = 0; 121eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 122eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber int64_t timeUs = mTracks.editItemAt(i).mPacketSource 123eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber ->getNormalPlayTimeUs(); 124eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 125eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (i == 0 || timeUs > maxTimeUs) { 126eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber maxTimeUs = timeUs; 127eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 128eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 129eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 130eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber return maxTimeUs; 131eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 132eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 1337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber virtual void onMessageReceived(const sp<AMessage> &msg) { 1347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber switch (msg->what()) { 1357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'conn': 1367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 1377a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber int32_t result; 1387a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findInt32("result", &result)); 1397a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 1407a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber LOG(INFO) << "connection request completed with result " 1417a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber << result << " (" << strerror(-result) << ")"; 1427a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 1437a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (result == OK) { 1447a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString request; 1457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request = "DESCRIBE "; 1467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(mSessionURL); 1477a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(" RTSP/1.0\r\n"); 1487a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("Accept: application/sdp\r\n"); 1497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 1507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 1517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('desc', id()); 1527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->sendRequest(request.c_str(), reply); 1530416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber } else { 1540416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber (new AMessage('disc', id()))->post(); 1557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 1567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 1577a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 1587a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 1597a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'disc': 1607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 161f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber int32_t reconnect; 162f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber if (msg->findInt32("reconnect", &reconnect) && reconnect) { 163f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber sp<AMessage> reply = new AMessage('conn', id()); 164f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber mConn->connect(mSessionURL.c_str(), reply); 165f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } else { 166f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber (new AMessage('quit', id()))->post(); 167f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } 1687a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 1697a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 1707a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 1717a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'desc': 1727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 1737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber int32_t result; 1747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findInt32("result", &result)); 1757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 1767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber LOG(INFO) << "DESCRIBE completed with result " 1777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber << result << " (" << strerror(-result) << ")"; 1787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 1797a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (result == OK) { 1807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<RefBase> obj; 1817a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findObject("response", &obj)); 1827a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<ARTSPResponse> response = 1837a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 1847a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 1857a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (response->mStatusCode == 302) { 1867a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber ssize_t i = response->mHeaders.indexOfKey("location"); 1877a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK_GE(i, 0); 1887a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 1897a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mSessionURL = response->mHeaders.valueAt(i); 1907a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 1917a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString request; 1927a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request = "DESCRIBE "; 1937a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(mSessionURL); 1947a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(" RTSP/1.0\r\n"); 1957a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("Accept: application/sdp\r\n"); 1967a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 1977a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 1987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('desc', id()); 1997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->sendRequest(request.c_str(), reply); 2007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 2017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 2027a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 2033a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (response->mStatusCode != 200) { 2043a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber result = UNKNOWN_ERROR; 2053a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } else { 2063a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mSessionDesc = new ASessionDescription; 2077a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 2083a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mSessionDesc->setTo( 2093a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber response->mContent->data(), 2103a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber response->mContent->size()); 2117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 212f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber if (!mSessionDesc->isValid()) { 213f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber result = ERROR_MALFORMED; 2147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } else { 215f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber ssize_t i = response->mHeaders.indexOfKey("content-base"); 2163a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (i >= 0) { 2173a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mBaseURL = response->mHeaders.valueAt(i); 2183a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } else { 219f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber i = response->mHeaders.indexOfKey("content-location"); 220f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber if (i >= 0) { 221f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber mBaseURL = response->mHeaders.valueAt(i); 222f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } else { 223f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber mBaseURL = mSessionURL; 224f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } 2253a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } 2263a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber 227f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber CHECK_GT(mSessionDesc->countTracks(), 1u); 228f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber setupTrack(1); 229f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } 2307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 2313a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } 2327a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 2333a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (result != OK) { 2347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 2357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->disconnect(reply); 2367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 2377a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 2387a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 2397a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 2407a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'setu': 2417a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 2427a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber size_t index; 2437a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findSize("index", &index)); 2447a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 24557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber TrackInfo *track = NULL; 2467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber size_t trackIndex; 24757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber if (msg->findSize("track-index", &trackIndex)) { 24857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber track = &mTracks.editItemAt(trackIndex); 24957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber } 2507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 2517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber int32_t result; 2527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findInt32("result", &result)); 2537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 2547a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber LOG(INFO) << "SETUP(" << index << ") completed with result " 2557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber << result << " (" << strerror(-result) << ")"; 2567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 2573a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (result == OK) { 25857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber CHECK(track != NULL); 2597a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 2607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<RefBase> obj; 2617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findObject("response", &obj)); 2627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<ARTSPResponse> response = 2637a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 2647a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 2653a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (response->mStatusCode != 200) { 2663a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber result = UNKNOWN_ERROR; 2673a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } else { 2683a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber ssize_t i = response->mHeaders.indexOfKey("session"); 2693a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber CHECK_GE(i, 0); 2707a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 2717a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mSessionID = response->mHeaders.valueAt(i); 2727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber i = mSessionID.find(";"); 2737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (i >= 0) { 2747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber // Remove options, i.e. ";timeout=90" 2757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mSessionID.erase(i, mSessionID.size() - i); 2767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 2777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 2783a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber sp<AMessage> notify = new AMessage('accu', id()); 2793a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber notify->setSize("track-index", trackIndex); 2807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 2813a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mRTPConn->addStream( 2823a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber track->mRTPSocket, track->mRTCPSocket, 2833a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mSessionDesc, index, 2843a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber notify, track->mUsingInterleavedTCP); 2857a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 2863a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mSetupTracksSuccessful = true; 2873a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } 2883a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } 2893a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber 2903a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (result != OK) { 2913a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (track) { 2923a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (!track->mUsingInterleavedTCP) { 2933a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber close(track->mRTPSocket); 2943a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber close(track->mRTCPSocket); 2953a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } 2963a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber 2973a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mTracks.removeItemsAt(trackIndex); 2983a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } 2997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 3007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 30157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber ++index; 30257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber if (index < mSessionDesc->countTracks()) { 30357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber setupTrack(index); 30457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber } else if (mSetupTracksSuccessful) { 3057a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString request = "PLAY "; 3067a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(mSessionURL); 3077a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(" RTSP/1.0\r\n"); 3087a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("Session: "); 3107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(mSessionID); 3117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 3127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3137a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 3147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3157a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('play', id()); 3167a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->sendRequest(request.c_str(), reply); 3177a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } else { 3187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 3197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->disconnect(reply); 3207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 3217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 3227a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 3237a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3247a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'play': 3257a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 3267a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber int32_t result; 3277a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findInt32("result", &result)); 3287a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3297a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber LOG(INFO) << "PLAY completed with result " 3307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber << result << " (" << strerror(-result) << ")"; 3317a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3327a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (result == OK) { 3337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<RefBase> obj; 3347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findObject("response", &obj)); 3357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<ARTSPResponse> response = 3367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 3377a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 338f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber if (response->mStatusCode != 200) { 339f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber result = UNKNOWN_ERROR; 340f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } else { 341f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber parsePlayResponse(response); 3427a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 343f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber sp<AMessage> timeout = new AMessage('tiou', id()); 344f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber timeout->post(kStartupTimeoutUs); 345f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } 346f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } 347eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 348f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber if (result != OK) { 3497a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 3507a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->disconnect(reply); 3517a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 3527a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3537a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 3547a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 3557a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3567a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'abor': 3577a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 3587a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 359f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber TrackInfo *info = &mTracks.editItemAt(i); 360f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 361f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber info->mPacketSource->signalEOS(ERROR_END_OF_STREAM); 362f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 363f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber if (!info->mUsingInterleavedTCP) { 364f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber mRTPConn->removeStream(info->mRTPSocket, info->mRTCPSocket); 365f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 366f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber close(info->mRTPSocket); 367f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber close(info->mRTCPSocket); 368f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } 3697a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 370f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber mTracks.clear(); 3713a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mSetupTracksSuccessful = false; 3723a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mSeekPending = false; 3733a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mFirstAccessUnit = true; 3743a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mFirstAccessUnitNTP = 0; 3753a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mNumAccessUnitsReceived = 0; 3763a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mReceivedFirstRTCPPacket = false; 3777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('tear', id()); 3797a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 380f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber int32_t reconnect; 381f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber if (msg->findInt32("reconnect", &reconnect) && reconnect) { 382f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber reply->setInt32("reconnect", true); 383f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } 384f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 3857a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString request; 3867a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request = "TEARDOWN "; 3877a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3887a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber // XXX should use aggregate url from SDP here... 3897a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(mSessionURL); 3907a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(" RTSP/1.0\r\n"); 3917a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3927a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("Session: "); 3937a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(mSessionID); 3947a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 3957a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3967a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 3977a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 3987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->sendRequest(request.c_str(), reply); 3997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 4007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 4017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 4027a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'tear': 4037a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 4047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber int32_t result; 4057a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findInt32("result", &result)); 4067a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 4077a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber LOG(INFO) << "TEARDOWN completed with result " 4087a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber << result << " (" << strerror(-result) << ")"; 4097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 4107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 411f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 412f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber int32_t reconnect; 413f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber if (msg->findInt32("reconnect", &reconnect) && reconnect) { 414f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber reply->setInt32("reconnect", true); 415f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } 416f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 4177a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->disconnect(reply); 4187a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 4197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 4207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 4217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'quit': 4227a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 4238370be11debc574b4a9fee62009009d999e29fa3Andreas Huber if (mDoneMsg != NULL) { 4248370be11debc574b4a9fee62009009d999e29fa3Andreas Huber mDoneMsg->setInt32("result", UNKNOWN_ERROR); 4258370be11debc574b4a9fee62009009d999e29fa3Andreas Huber mDoneMsg->post(); 4268370be11debc574b4a9fee62009009d999e29fa3Andreas Huber mDoneMsg = NULL; 4278370be11debc574b4a9fee62009009d999e29fa3Andreas Huber } 4287a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 4297a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 4307a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 431eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber case 'chek': 432eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber { 433eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (mNumAccessUnitsReceived == 0) { 434eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber LOG(INFO) << "stream ended? aborting."; 435eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber (new AMessage('abor', id()))->post(); 436eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber break; 437eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 438eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 439eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber mNumAccessUnitsReceived = 0; 440f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huber msg->post(kAccessUnitTimeoutUs); 441eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber break; 442eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 443eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 4447a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber case 'accu': 4457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber { 4463a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber int32_t firstRTCP; 4473a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (msg->findInt32("first-rtcp", &firstRTCP)) { 4483a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber mReceivedFirstRTCPPacket = true; 4493a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber break; 4503a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber } 4513a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber 452eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber ++mNumAccessUnitsReceived; 453eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 454eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (!mCheckPending) { 455eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber mCheckPending = true; 456eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber sp<AMessage> check = new AMessage('chek', id()); 457f6639c46e83a1ccab7b293192c208091d17c61beAndreas Huber check->post(kAccessUnitTimeoutUs); 458eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 459eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 4607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber size_t trackIndex; 4617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findSize("track-index", &trackIndex)); 4627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 463f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber if (trackIndex >= mTracks.size()) { 464f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber LOG(ERROR) << "late packets ignored."; 465f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber break; 466f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } 467f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 468eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 469eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 470af063a67b291c4622321a35af6966b8568d5a564Andreas Huber int32_t eos; 471af063a67b291c4622321a35af6966b8568d5a564Andreas Huber if (msg->findInt32("eos", &eos)) { 472af063a67b291c4622321a35af6966b8568d5a564Andreas Huber LOG(INFO) << "received BYE on track index " << trackIndex; 473af063a67b291c4622321a35af6966b8568d5a564Andreas Huber#if 0 474af063a67b291c4622321a35af6966b8568d5a564Andreas Huber track->mPacketSource->signalEOS(ERROR_END_OF_STREAM); 475af063a67b291c4622321a35af6966b8568d5a564Andreas Huber#endif 476af063a67b291c4622321a35af6966b8568d5a564Andreas Huber return; 477af063a67b291c4622321a35af6966b8568d5a564Andreas Huber } 478af063a67b291c4622321a35af6966b8568d5a564Andreas Huber 4797a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<RefBase> obj; 4807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(msg->findObject("access-unit", &obj)); 4817a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 4827a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<ABuffer> accessUnit = static_cast<ABuffer *>(obj.get()); 4837a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 484eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber uint32_t seqNum = (uint32_t)accessUnit->int32Data(); 485eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 486f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber if (mSeekPending) { 487f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber LOG(INFO) << "we're seeking, dropping stale packet."; 488f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber break; 489f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } 490f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber 491eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (seqNum < track->mFirstSeqNumInSegment) { 492eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber LOG(INFO) << "dropping stale access-unit " 493eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber << "(" << seqNum << " < " 494eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber << track->mFirstSeqNumInSegment << ")"; 495eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber break; 496eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 497eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 4987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber uint64_t ntpTime; 4997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(accessUnit->meta()->findInt64( 5007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber "ntp-time", (int64_t *)&ntpTime)); 5017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 502eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber uint32_t rtpTime; 503eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber CHECK(accessUnit->meta()->findInt32( 504eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber "rtp-time", (int32_t *)&rtpTime)); 505eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 506eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (track->mNewSegment) { 507eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber track->mNewSegment = false; 508eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 509eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber LOG(VERBOSE) << "first segment unit ntpTime=" 510eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber << StringPrintf("0x%016llx", ntpTime) 511eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber << " rtpTime=" << rtpTime 512eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber << " seq=" << seqNum; 513eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 514eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 515e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber if (mFirstAccessUnit) { 516f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber mDoneMsg->setInt32("result", OK); 517f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber mDoneMsg->post(); 518f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber mDoneMsg = NULL; 519f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 520e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber mFirstAccessUnit = false; 521e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber mFirstAccessUnitNTP = ntpTime; 522e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber } 523e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 524e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber if (ntpTime >= mFirstAccessUnitNTP) { 525e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber ntpTime -= mFirstAccessUnitNTP; 526e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber } else { 527e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber ntpTime = 0; 528e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber } 529e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 530e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber int64_t timeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32)); 531e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 532e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber accessUnit->meta()->setInt64("timeUs", timeUs); 5337a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 5344e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber#if 0 5354e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber int32_t damaged; 5364e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber if (accessUnit->meta()->findInt32("damaged", &damaged) 5374e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber && damaged != 0) { 5384e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber LOG(INFO) << "ignoring damaged AU"; 5394e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber } else 5404e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber#endif 5414e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber { 5424e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 5434e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber track->mPacketSource->queueAccessUnit(accessUnit); 5444e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber } 5457a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 5467a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 5477a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 548e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber case 'seek': 549e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber { 550e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber if (mSeekPending) { 551e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber break; 552e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber } 553e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 554e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber int64_t timeUs; 555e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber CHECK(msg->findInt64("time", &timeUs)); 556e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 557e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber mSeekPending = true; 558e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 559e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber AString request = "PAUSE "; 560e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append(mSessionURL); 561e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append(" RTSP/1.0\r\n"); 562e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 563e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append("Session: "); 564e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append(mSessionID); 565e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append("\r\n"); 566e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 567e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append("\r\n"); 568e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 569e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber sp<AMessage> reply = new AMessage('see1', id()); 570e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber reply->setInt64("time", timeUs); 571e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber mConn->sendRequest(request.c_str(), reply); 572e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber break; 573e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber } 574e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 575e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber case 'see1': 576e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber { 577eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber // Session is paused now. 578eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 579eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber mTracks.editItemAt(i).mPacketSource->flushQueue(); 580eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 581eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 582e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber int64_t timeUs; 583e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber CHECK(msg->findInt64("time", &timeUs)); 584e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 585e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber AString request = "PLAY "; 586e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append(mSessionURL); 587e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append(" RTSP/1.0\r\n"); 588e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 589e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append("Session: "); 590e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append(mSessionID); 591e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append("\r\n"); 592e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 593e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append( 594e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber StringPrintf( 595e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber "Range: npt=%lld-\r\n", timeUs / 1000000ll)); 596e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 597e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber request.append("\r\n"); 598e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 599e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber sp<AMessage> reply = new AMessage('see2', id()); 600e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber mConn->sendRequest(request.c_str(), reply); 601e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber break; 602e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber } 603e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 604e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber case 'see2': 605e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber { 606e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber CHECK(mSeekPending); 607e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 608e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber int32_t result; 609e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber CHECK(msg->findInt32("result", &result)); 610eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 611eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber LOG(INFO) << "PLAY completed with result " 612eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber << result << " (" << strerror(-result) << ")"; 613eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 614f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber if (result == OK) { 615f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber sp<RefBase> obj; 616f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber CHECK(msg->findObject("response", &obj)); 617f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber sp<ARTSPResponse> response = 618f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber static_cast<ARTSPResponse *>(obj.get()); 619e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 620f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber if (response->mStatusCode != 200) { 621f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber result = UNKNOWN_ERROR; 622f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } else { 623f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber parsePlayResponse(response); 624e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 625f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber LOG(INFO) << "seek completed."; 626f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } 627f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } 628e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 629f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber if (result != OK) { 630f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber LOG(ERROR) << "seek failed, aborting."; 631f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber (new AMessage('abor', id()))->post(); 632f3d2bdf73c36be549f1ddff4238e97b3629c480dAndreas Huber } 633eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 634eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber mSeekPending = false; 635e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber break; 636e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber } 637e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber 6380416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber case 'biny': 6390416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber { 6400416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber sp<RefBase> obj; 6410416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber CHECK(msg->findObject("buffer", &obj)); 6420416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); 6430416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber 6440416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber int32_t index; 6450416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber CHECK(buffer->meta()->findInt32("index", &index)); 6460416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber 6470416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber mRTPConn->injectPacket(index, buffer); 6480416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber break; 6490416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber } 6500416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber 6510416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber case 'tiou': 6520416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber { 6533a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber if (!mReceivedFirstRTCPPacket) { 654f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber if (mTryTCPInterleaving) { 655f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber LOG(WARNING) << "Never received any data, disconnecting."; 656f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber (new AMessage('abor', id()))->post(); 657f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } else { 658f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber LOG(WARNING) 659f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber << "Never received any data, switching transports."; 660f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 661f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber mTryTCPInterleaving = true; 662f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 663f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber sp<AMessage> msg = new AMessage('abor', id()); 664f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber msg->setInt32("reconnect", true); 665f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber msg->post(); 666f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } 6670416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber } 6680416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber break; 6690416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber } 6700416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber 6717a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber default: 6727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber TRESPASS(); 6737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber break; 6747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 6757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 6767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 677eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber static void SplitString( 678eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber const AString &s, const char *separator, List<AString> *items) { 679eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber items->clear(); 680eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber size_t start = 0; 681eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber while (start < s.size()) { 682eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber ssize_t offset = s.find(separator, start); 683eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 684eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (offset < 0) { 685eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber items->push_back(AString(s, start, s.size() - start)); 686eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber break; 687eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 688eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 689eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber items->push_back(AString(s, start, offset - start)); 690eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber start = offset + strlen(separator); 691eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 692eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 693eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 694eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber void parsePlayResponse(const sp<ARTSPResponse> &response) { 695eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber ssize_t i = response->mHeaders.indexOfKey("range"); 696eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (i < 0) { 697eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber // Server doesn't even tell use what range it is going to 698eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber // play, therefore we won't support seeking. 699eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber return; 700eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 701eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 702eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber AString range = response->mHeaders.valueAt(i); 703eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber LOG(VERBOSE) << "Range: " << range; 704eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 705eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber AString val; 706eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber CHECK(GetAttribute(range.c_str(), "npt", &val)); 707eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber float npt1, npt2; 708eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 709eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber if (val == "now-") { 710eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber // This is a live stream and therefore not seekable. 711eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber return; 712eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } else { 713eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber CHECK_EQ(sscanf(val.c_str(), "%f-%f", &npt1, &npt2), 2); 714eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 715eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 716eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber i = response->mHeaders.indexOfKey("rtp-info"); 717eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber CHECK_GE(i, 0); 718eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 719eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber AString rtpInfo = response->mHeaders.valueAt(i); 720eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber List<AString> streamInfos; 721eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber SplitString(rtpInfo, ",", &streamInfos); 722eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 723eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber int n = 1; 724eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber for (List<AString>::iterator it = streamInfos.begin(); 725eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber it != streamInfos.end(); ++it) { 726eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber (*it).trim(); 727eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber LOG(VERBOSE) << "streamInfo[" << n << "] = " << *it; 728eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 729eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber CHECK(GetAttribute((*it).c_str(), "url", &val)); 730eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 731eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber size_t trackIndex = 0; 732eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber while (trackIndex < mTracks.size() 733eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber && !(val == mTracks.editItemAt(trackIndex).mURL)) { 734eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber ++trackIndex; 735eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 736eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber CHECK_LT(trackIndex, mTracks.size()); 737eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 738eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber CHECK(GetAttribute((*it).c_str(), "seq", &val)); 739eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 740eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber char *end; 741eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber unsigned long seq = strtoul(val.c_str(), &end, 10); 742eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 743eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber TrackInfo *info = &mTracks.editItemAt(trackIndex); 744eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber info->mFirstSeqNumInSegment = seq; 745eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber info->mNewSegment = true; 746eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 747eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber CHECK(GetAttribute((*it).c_str(), "rtptime", &val)); 748eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 749eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber uint32_t rtpTime = strtoul(val.c_str(), &end, 10); 750eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 751eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber LOG(VERBOSE) << "track #" << n 752eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber << ": rtpTime=" << rtpTime << " <=> npt=" << npt1; 753eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 754eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber info->mPacketSource->setNormalPlayTimeMapping( 755eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber rtpTime, (int64_t)(npt1 * 1E6)); 756eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 757eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber ++n; 758eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 759eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber } 760eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 7617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<APacketSource> getPacketSource(size_t index) { 7627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK_GE(index, 0u); 7637a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK_LT(index, mTracks.size()); 7647a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 7657a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber return mTracks.editItemAt(index).mPacketSource; 7667a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 7677a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 7687a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber size_t countTracks() const { 7697a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber return mTracks.size(); 7707a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 7717a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 7727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huberprivate: 7737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<ALooper> mLooper; 7744e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber sp<ALooper> mNetLooper; 7757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<ARTSPConnection> mConn; 7767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<ARTPConnection> mRTPConn; 7777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<ASessionDescription> mSessionDesc; 7787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString mSessionURL; 7797a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString mBaseURL; 7807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString mSessionID; 7817a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber bool mSetupTracksSuccessful; 782e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber bool mSeekPending; 783e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber bool mFirstAccessUnit; 784e0dd7d396051942ccce0429d7a1fe968d63ac3f7Andreas Huber uint64_t mFirstAccessUnitNTP; 785eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber int64_t mNumAccessUnitsReceived; 786eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber bool mCheckPending; 787f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber bool mTryTCPInterleaving; 7883a48d4d7269a37308eee4affd021adfcab7629a1Andreas Huber bool mReceivedFirstRTCPPacket; 7897a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 7907a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber struct TrackInfo { 791eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber AString mURL; 7927a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber int mRTPSocket; 7937a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber int mRTCPSocket; 7940416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber bool mUsingInterleavedTCP; 795eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber uint32_t mFirstSeqNumInSegment; 796eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber bool mNewSegment; 7977a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 7987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<APacketSource> mPacketSource; 7997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber }; 8007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber Vector<TrackInfo> mTracks; 8017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 8028370be11debc574b4a9fee62009009d999e29fa3Andreas Huber sp<AMessage> mDoneMsg; 8038370be11debc574b4a9fee62009009d999e29fa3Andreas Huber 8047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber void setupTrack(size_t index) { 80557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber sp<APacketSource> source = 80657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber new APacketSource(mSessionDesc, index); 807f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 80857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber if (source->initCheck() != OK) { 80957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber LOG(WARNING) << "Unsupported format. Ignoring track #" 81057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber << index << "."; 81157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber 81257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber sp<AMessage> reply = new AMessage('setu', id()); 81357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber reply->setSize("index", index); 81457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber reply->setInt32("result", ERROR_UNSUPPORTED); 81557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber reply->post(); 81657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber return; 81757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber } 81857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber 8197a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString url; 8207a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(mSessionDesc->findAttribute(index, "a=control", &url)); 8217a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 8227a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString trackURL; 8237a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber CHECK(MakeURL(mBaseURL.c_str(), url.c_str(), &trackURL)); 8247a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 8257a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mTracks.push(TrackInfo()); 8267a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber TrackInfo *info = &mTracks.editItemAt(mTracks.size() - 1); 827eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber info->mURL = trackURL; 82857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber info->mPacketSource = source; 8290416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber info->mUsingInterleavedTCP = false; 830eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber info->mFirstSeqNumInSegment = 0; 831eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber info->mNewSegment = true; 832eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber 833eeb97d91b97f1fc0b26815f098515e9c06d219b8Andreas Huber LOG(VERBOSE) << "track #" << mTracks.size() << " URL=" << trackURL; 8347a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 8357a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber AString request = "SETUP "; 8367a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(trackURL); 8377a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(" RTSP/1.0\r\n"); 8387a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 839f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber if (mTryTCPInterleaving) { 840f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber size_t interleaveIndex = 2 * (mTracks.size() - 1); 841f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber info->mUsingInterleavedTCP = true; 842f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber info->mRTPSocket = interleaveIndex; 843f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber info->mRTCPSocket = interleaveIndex + 1; 844f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 845f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber request.append("Transport: RTP/AVP/TCP;interleaved="); 846f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber request.append(interleaveIndex); 847f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber request.append("-"); 848f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber request.append(interleaveIndex + 1); 849f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } else { 850f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber unsigned rtpPort; 851f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber ARTPConnection::MakePortPair( 852f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber &info->mRTPSocket, &info->mRTCPSocket, &rtpPort); 853f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber 854f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber request.append("Transport: RTP/AVP/UDP;unicast;client_port="); 855f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber request.append(rtpPort); 856f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber request.append("-"); 857f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber request.append(rtpPort + 1); 858f88ca7a0335c36732a5550c58c073e549c3cb0ddAndreas Huber } 8590416da73a0addfc7b3eddfea4a6a0a0215e1dd0bAndreas Huber 8607a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 8617a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 8627a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (index > 1) { 8637a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("Session: "); 8647a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append(mSessionID); 8657a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 8667a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 8677a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 8687a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber request.append("\r\n"); 8697a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 8707a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber sp<AMessage> reply = new AMessage('setu', id()); 8717a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber reply->setSize("index", index); 8727a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber reply->setSize("track-index", mTracks.size() - 1); 8737a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber mConn->sendRequest(request.c_str(), reply); 8747a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 8757a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 8767a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber static bool MakeURL(const char *baseURL, const char *url, AString *out) { 8777a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber out->clear(); 8787a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 8797a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (strncasecmp("rtsp://", baseURL, 7)) { 8807a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber // Base URL must be absolute 8817a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber return false; 8827a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 8837a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 8847a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (!strncasecmp("rtsp://", url, 7)) { 8857a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber // "url" is already an absolute URL, ignore base URL. 8867a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber out->setTo(url); 8877a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber return true; 8887a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 8897a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 8907a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber size_t n = strlen(baseURL); 8917a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (baseURL[n - 1] == '/') { 8927a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber out->setTo(baseURL); 8937a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber out->append(url); 8947a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } else { 8957a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber char *slashPos = strrchr(baseURL, '/'); 8967a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 8977a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber if (slashPos > &baseURL[6]) { 8987a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber out->setTo(baseURL, slashPos - baseURL); 8997a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } else { 9007a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber out->setTo(baseURL); 9017a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 9027a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 9037a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber out->append("/"); 9047a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber out->append(url); 9057a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 9067a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 9077a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber return true; 9087a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber } 9097a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 9107a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber DISALLOW_EVIL_CONSTRUCTORS(MyHandler); 9117a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber}; 9127a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 9137a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber} // namespace android 9147a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber 9157a747b8e0dadf909ea4ac0b67fd88fc14b4eb3f8Andreas Huber#endif // MY_HANDLER_H_ 916