MyHandler.h revision e56121bc4cb29c91d736eab181b1f51c4f125e78
1cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber/* 2cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Copyright (C) 2010 The Android Open Source Project 3cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * 4cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * you may not use this file except in compliance with the License. 6cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * You may obtain a copy of the License at 7cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * 8cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * 10cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Unless required by applicable law or agreed to in writing, software 11cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * See the License for the specific language governing permissions and 14cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * limitations under the License. 15cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber */ 16cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 17cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#ifndef MY_HANDLER_H_ 18cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 19cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#define MY_HANDLER_H_ 20cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 21cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "APacketSource.h" 22cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ARTPConnection.h" 23cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ARTSPConnection.h" 24cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ASessionDescription.h" 25cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 268d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber#include <ctype.h> 278d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 28cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 29cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ADebug.h> 30cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ALooper.h> 31cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/AMessage.h> 32cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/MediaErrors.h> 33cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 340792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber#define USE_TCP_INTERLEAVED 0 350792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 36e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// If no access units are received within 3 secs, assume that the rtp 37e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// stream has ended and signal end of stream. 38e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huberstatic int64_t kAccessUnitTimeoutUs = 3000000ll; 39e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber 40e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// If no access units arrive for the first 10 secs after starting the 41e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber// stream, assume none ever will and signal EOS or switch transports. 42e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huberstatic int64_t kStartupTimeoutUs = 10000000ll; 43e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber 44cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubernamespace android { 45cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 468d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huberstatic bool GetAttribute(const char *s, const char *key, AString *value) { 478d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber value->clear(); 488d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 498d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber size_t keyLen = strlen(key); 508d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 518d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber for (;;) { 528d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber while (isspace(*s)) { 538d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ++s; 548d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 558d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 568d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber const char *colonPos = strchr(s, ';'); 578d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 588d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber size_t len = 598d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber (colonPos == NULL) ? strlen(s) : colonPos - s; 608d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 618d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) { 628d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber value->setTo(&s[keyLen + 1], len - keyLen - 1); 638d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return true; 648d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 658d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 668d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (colonPos == NULL) { 678d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return false; 688d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 698d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 708d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber s = colonPos + 1; 718d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 728d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber} 738d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 74cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstruct MyHandler : public AHandler { 75cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber MyHandler(const char *url, const sp<ALooper> &looper) 76cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber : mLooper(looper), 77348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber mNetLooper(new ALooper), 78cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn(new ARTSPConnection), 79cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRTPConn(new ARTPConnection), 80cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionURL(url), 81cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mSetupTracksSuccessful(false), 82cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mSeekPending(false), 83cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mFirstAccessUnit(true), 848d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mFirstAccessUnitNTP(0), 858d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mNumAccessUnitsReceived(0), 868d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mCheckPending(false) { 87a814c1fdc2acf0ed2ee3b175110f6039be7c4873Andreas Huber mNetLooper->setName("rtsp net"); 88348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber mNetLooper->start(false /* runOnCallingThread */, 89348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber false /* canCallJava */, 90348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber PRIORITY_HIGHEST); 91348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber } 92348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber 931b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber void connect(const sp<AMessage> &doneMsg) { 941b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg = doneMsg; 951b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber 96cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLooper->registerHandler(this); 97cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLooper->registerHandler(mConn); 98348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber (1 ? mNetLooper : mLooper)->registerHandler(mRTPConn); 99348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber 1000792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber sp<AMessage> notify = new AMessage('biny', id()); 1010792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber mConn->observeBinaryData(notify); 1020792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 1031b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber sp<AMessage> reply = new AMessage('conn', id()); 104cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->connect(mSessionURL.c_str(), reply); 105cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 106cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 1071b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber void disconnect(const sp<AMessage> &doneMsg) { 1081b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg = doneMsg; 1091b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber 1101b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber (new AMessage('abor', id()))->post(); 111348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber } 112348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber 113cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber void seek(int64_t timeUs) { 114cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber sp<AMessage> msg = new AMessage('seek', id()); 115cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber msg->setInt64("time", timeUs); 116cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber msg->post(); 117cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 118cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 1198d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int64_t getNormalPlayTimeUs() { 1208d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int64_t maxTimeUs = 0; 1218d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 1228d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int64_t timeUs = mTracks.editItemAt(i).mPacketSource 1238d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ->getNormalPlayTimeUs(); 1248d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 1258d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (i == 0 || timeUs > maxTimeUs) { 1268d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber maxTimeUs = timeUs; 1278d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 1288d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 1298d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 1308d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return maxTimeUs; 1318d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 1328d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 133cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber virtual void onMessageReceived(const sp<AMessage> &msg) { 134cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber switch (msg->what()) { 135cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'conn': 136cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 137cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 138cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 139cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 140cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "connection request completed with result " 141cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 142cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 143cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 144cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 145cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request = "DESCRIBE "; 146cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 147cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 148cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Accept: application/sdp\r\n"); 149cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 150cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 151cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('desc', id()); 152cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 1530792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } else { 1540792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber (new AMessage('disc', id()))->post(); 155cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 156cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 157cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 158cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 159cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'disc': 160cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 161cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (new AMessage('quit', id()))->post(); 162cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 163cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 164cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 165cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'desc': 166cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 167cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 168cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 169cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 170cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "DESCRIBE completed with result " 171cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 172cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 173cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 174cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 175cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 176cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response = 177cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 178cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 179cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (response->mStatusCode == 302) { 180cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ssize_t i = response->mHeaders.indexOfKey("location"); 181cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(i, 0); 182cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 183cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionURL = response->mHeaders.valueAt(i); 184cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 185cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 186cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request = "DESCRIBE "; 187cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 188cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 189cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Accept: application/sdp\r\n"); 190cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 191cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 192cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('desc', id()); 193cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 194cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 195cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 196cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 197cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_EQ(response->mStatusCode, 200u); 198cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 199cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionDesc = new ASessionDescription; 200cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 201cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionDesc->setTo( 202cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber response->mContent->data(), 203cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber response->mContent->size()); 204cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 205cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(mSessionDesc->isValid()); 206cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 207cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ssize_t i = response->mHeaders.indexOfKey("content-base"); 208cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (i >= 0) { 209cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mBaseURL = response->mHeaders.valueAt(i); 210cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 211cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber i = response->mHeaders.indexOfKey("content-location"); 212cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (i >= 0) { 213cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mBaseURL = response->mHeaders.valueAt(i); 214cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 215cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mBaseURL = mSessionURL; 216cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 217cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 218cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 219cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GT(mSessionDesc->countTracks(), 1u); 220cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber setupTrack(1); 221cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 222cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 223cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 224cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 225cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 226cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 227cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 228cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'setu': 229cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 230cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t index; 231cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findSize("index", &index)); 232cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 23339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber TrackInfo *track = NULL; 234cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t trackIndex; 23539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (msg->findSize("track-index", &trackIndex)) { 23639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber track = &mTracks.editItemAt(trackIndex); 23739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 238cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 239cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 240cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 241cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 242cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "SETUP(" << index << ") completed with result " 243cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 244cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 24539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (result != OK) { 24639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (track) { 2470792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber if (!track->mUsingInterleavedTCP) { 2480792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber close(track->mRTPSocket); 2490792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber close(track->mRTCPSocket); 2500792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } 25139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 25239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber mTracks.removeItemsAt(trackIndex); 25339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 25439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } else { 25539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK(track != NULL); 256cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 257cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 258cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 259cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response = 260cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 261cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 262cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_EQ(response->mStatusCode, 200u); 263cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 264cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ssize_t i = response->mHeaders.indexOfKey("session"); 265cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(i, 0); 266cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 267cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (index == 1) { 268cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionID = response->mHeaders.valueAt(i); 269cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber i = mSessionID.find(";"); 270cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (i >= 0) { 271cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // Remove options, i.e. ";timeout=90" 272cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionID.erase(i, mSessionID.size() - i); 273cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 274cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 275cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 276cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> notify = new AMessage('accu', id()); 277cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber notify->setSize("track-index", trackIndex); 278cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 279cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRTPConn->addStream( 280cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber track->mRTPSocket, track->mRTCPSocket, 281cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionDesc, index, 2820792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber notify, track->mUsingInterleavedTCP); 283cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 284cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSetupTracksSuccessful = true; 285cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 286cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 28739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber ++index; 28839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (index < mSessionDesc->countTracks()) { 28939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber setupTrack(index); 29039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } else if (mSetupTracksSuccessful) { 291cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request = "PLAY "; 292cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 293cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 294cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 295cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 296cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 297cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 298cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 299cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 300cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 301cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('play', id()); 302cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 303cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 304cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 305cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 306cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 307cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 308cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 309cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 310cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'play': 311cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 312cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 313cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 314cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 315cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "PLAY completed with result " 316cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 317cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 318cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 319cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 320cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 321cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response = 322cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 323cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 324cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_EQ(response->mStatusCode, 200u); 325cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 3268d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber parsePlayResponse(response); 3278d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 3281b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg->setInt32("result", OK); 3291b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg->post(); 3301b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg = NULL; 3310792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 3320792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber sp<AMessage> timeout = new AMessage('tiou', id()); 333e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber timeout->post(kStartupTimeoutUs); 334cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 335cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 336cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 337cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 338cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 339cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 340cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 341cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 342cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'abor': 343cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 344cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 345cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mTracks.editItemAt(i).mPacketSource->signalEOS( 346cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ERROR_END_OF_STREAM); 347cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 348cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 349cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('tear', id()); 350cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 351cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 352cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request = "TEARDOWN "; 353cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 354cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // XXX should use aggregate url from SDP here... 355cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 356cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 357cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 358cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 359cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 360cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 361cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 362cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 363cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 364cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 365cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 366cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 367cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 368cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'tear': 369cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 370cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 371cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 372cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 373cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "TEARDOWN completed with result " 374cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 375cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 376cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 377cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 378cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 379cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 380cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 381cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'quit': 382cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 3831b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber if (mDoneMsg != NULL) { 3841b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg->setInt32("result", UNKNOWN_ERROR); 3851b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg->post(); 3861b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber mDoneMsg = NULL; 3871b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber } 388cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 389cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 390cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 3918d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber case 'chek': 3928d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber { 3938d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (mNumAccessUnitsReceived == 0) { 3948d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber LOG(INFO) << "stream ended? aborting."; 3958d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber (new AMessage('abor', id()))->post(); 3968d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber break; 3978d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 3988d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 3998d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mNumAccessUnitsReceived = 0; 400e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber msg->post(kAccessUnitTimeoutUs); 4018d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber break; 4028d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 4038d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 404cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'accu': 405cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 4068d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ++mNumAccessUnitsReceived; 4078d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 4088d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (!mCheckPending) { 4098d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mCheckPending = true; 4108d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber sp<AMessage> check = new AMessage('chek', id()); 411e56121bc4cb29c91d736eab181b1f51c4f125e78Andreas Huber check->post(kAccessUnitTimeoutUs); 4128d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 4138d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 414cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t trackIndex; 415cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findSize("track-index", &trackIndex)); 416cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 4178d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 4188d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 419ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber int32_t eos; 420ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber if (msg->findInt32("eos", &eos)) { 421ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber LOG(INFO) << "received BYE on track index " << trackIndex; 422ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber#if 0 423ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber track->mPacketSource->signalEOS(ERROR_END_OF_STREAM); 424ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber#endif 425ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber return; 426ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber } 427ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber 428cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 429cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("access-unit", &obj)); 430cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 431cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ABuffer> accessUnit = static_cast<ABuffer *>(obj.get()); 432cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 4338d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber uint32_t seqNum = (uint32_t)accessUnit->int32Data(); 4348d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 4358d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (seqNum < track->mFirstSeqNumInSegment) { 4368d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber LOG(INFO) << "dropping stale access-unit " 4378d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber << "(" << seqNum << " < " 4388d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber << track->mFirstSeqNumInSegment << ")"; 4398d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber break; 4408d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 4418d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 442cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint64_t ntpTime; 443cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(accessUnit->meta()->findInt64( 444cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber "ntp-time", (int64_t *)&ntpTime)); 445cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 4468d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber uint32_t rtpTime; 4478d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(accessUnit->meta()->findInt32( 4488d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber "rtp-time", (int32_t *)&rtpTime)); 4498d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 4508d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (track->mNewSegment) { 4518d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber track->mNewSegment = false; 4528d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 4538d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber LOG(VERBOSE) << "first segment unit ntpTime=" 4548d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber << StringPrintf("0x%016llx", ntpTime) 4558d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber << " rtpTime=" << rtpTime 4568d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber << " seq=" << seqNum; 4578d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 4588d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 459cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber if (mFirstAccessUnit) { 460cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mFirstAccessUnit = false; 461cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mFirstAccessUnitNTP = ntpTime; 462cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 463cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 464cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber if (ntpTime >= mFirstAccessUnitNTP) { 465cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber ntpTime -= mFirstAccessUnitNTP; 466cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } else { 467cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber ntpTime = 0; 468cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 469cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 470cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber int64_t timeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32)); 471cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 472cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber accessUnit->meta()->setInt64("timeUs", timeUs); 473cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 474348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber#if 0 475348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber int32_t damaged; 476348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber if (accessUnit->meta()->findInt32("damaged", &damaged) 477348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber && damaged != 0) { 478348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber LOG(INFO) << "ignoring damaged AU"; 479348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber } else 480348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber#endif 481348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber { 482348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 483348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber track->mPacketSource->queueAccessUnit(accessUnit); 484348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber } 485cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 486cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 487cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 488cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber case 'seek': 489cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber { 490cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber if (mSeekPending) { 491cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber break; 492cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 493cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 494cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber int64_t timeUs; 495cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(msg->findInt64("time", &timeUs)); 496cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 497cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mSeekPending = true; 498cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 499cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber AString request = "PAUSE "; 500cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(mSessionURL); 501cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(" RTSP/1.0\r\n"); 502cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 503cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("Session: "); 504cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(mSessionID); 505cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("\r\n"); 506cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 507cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("\r\n"); 508cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 509cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber sp<AMessage> reply = new AMessage('see1', id()); 510cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber reply->setInt64("time", timeUs); 511cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mConn->sendRequest(request.c_str(), reply); 512cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber break; 513cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 514cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 515cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber case 'see1': 516cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber { 5178d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // Session is paused now. 5188d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 5198d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mTracks.editItemAt(i).mPacketSource->flushQueue(); 5208d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 5218d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 522cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber int64_t timeUs; 523cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(msg->findInt64("time", &timeUs)); 524cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 525cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber AString request = "PLAY "; 526cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(mSessionURL); 527cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(" RTSP/1.0\r\n"); 528cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 529cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("Session: "); 530cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append(mSessionID); 531cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("\r\n"); 532cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 533cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append( 534cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber StringPrintf( 535cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber "Range: npt=%lld-\r\n", timeUs / 1000000ll)); 536cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 537cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber request.append("\r\n"); 538cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 539cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber sp<AMessage> reply = new AMessage('see2', id()); 540cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber mConn->sendRequest(request.c_str(), reply); 541cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber break; 542cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 543cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 544cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber case 'see2': 545cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber { 546cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(mSeekPending); 547cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 548cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber int32_t result; 549cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(msg->findInt32("result", &result)); 5508d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 5518d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber LOG(INFO) << "PLAY completed with result " 5528d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber << result << " (" << strerror(-result) << ")"; 5538d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 5548d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK_EQ(result, (status_t)OK); 555cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 556cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber sp<RefBase> obj; 557cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK(msg->findObject("response", &obj)); 558cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber sp<ARTSPResponse> response = 559cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 560cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 561cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber CHECK_EQ(response->mStatusCode, 200u); 562cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 5638d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber parsePlayResponse(response); 5648d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 5658d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber LOG(INFO) << "seek completed."; 5668d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber mSeekPending = false; 567cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber break; 568cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber } 569cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber 5700792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber case 'biny': 5710792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber { 5720792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber sp<RefBase> obj; 5730792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber CHECK(msg->findObject("buffer", &obj)); 5740792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); 5750792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 5760792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber int32_t index; 5770792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber CHECK(buffer->meta()->findInt32("index", &index)); 5780792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 5790792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber mRTPConn->injectPacket(index, buffer); 5800792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber break; 5810792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } 5820792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 5830792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber case 'tiou': 5840792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber { 5850792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber if (mFirstAccessUnit) { 5860792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber LOG(WARNING) << "Never received any data, disconnecting."; 587cc6adf524c1bb3bfaa5be464b50b8bcca899761cAndreas Huber (new AMessage('abor', id()))->post(); 5880792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } 5890792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber break; 5900792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber } 5910792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 592cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber default: 593cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber TRESPASS(); 594cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 595cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 596cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 597cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 5988d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber static void SplitString( 5998d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber const AString &s, const char *separator, List<AString> *items) { 6008d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber items->clear(); 6018d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber size_t start = 0; 6028d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber while (start < s.size()) { 6038d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ssize_t offset = s.find(separator, start); 6048d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6058d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (offset < 0) { 6068d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber items->push_back(AString(s, start, s.size() - start)); 6078d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber break; 6088d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 6098d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6108d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber items->push_back(AString(s, start, offset - start)); 6118d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber start = offset + strlen(separator); 6128d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 6138d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 6148d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6158d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber void parsePlayResponse(const sp<ARTSPResponse> &response) { 6168d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ssize_t i = response->mHeaders.indexOfKey("range"); 6178d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (i < 0) { 6188d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // Server doesn't even tell use what range it is going to 6198d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // play, therefore we won't support seeking. 6208d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return; 6218d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 6228d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6238d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber AString range = response->mHeaders.valueAt(i); 6248d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber LOG(VERBOSE) << "Range: " << range; 6258d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6268d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber AString val; 6278d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(GetAttribute(range.c_str(), "npt", &val)); 6288d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber float npt1, npt2; 6298d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6308d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber if (val == "now-") { 6318d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber // This is a live stream and therefore not seekable. 6328d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber return; 6338d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } else { 6348d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK_EQ(sscanf(val.c_str(), "%f-%f", &npt1, &npt2), 2); 6358d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 6368d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6378d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber i = response->mHeaders.indexOfKey("rtp-info"); 6388d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK_GE(i, 0); 6398d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6408d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber AString rtpInfo = response->mHeaders.valueAt(i); 6418d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber List<AString> streamInfos; 6428d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber SplitString(rtpInfo, ",", &streamInfos); 6438d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6448d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int n = 1; 6458d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber for (List<AString>::iterator it = streamInfos.begin(); 6468d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber it != streamInfos.end(); ++it) { 6478d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber (*it).trim(); 6488d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber LOG(VERBOSE) << "streamInfo[" << n << "] = " << *it; 6498d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6508d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(GetAttribute((*it).c_str(), "url", &val)); 6518d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6528d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber size_t trackIndex = 0; 6538d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber while (trackIndex < mTracks.size() 6548d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber && !(val == mTracks.editItemAt(trackIndex).mURL)) { 6558d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ++trackIndex; 6568d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 6578d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK_LT(trackIndex, mTracks.size()); 6588d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6598d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(GetAttribute((*it).c_str(), "seq", &val)); 6608d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6618d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber char *end; 6628d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber unsigned long seq = strtoul(val.c_str(), &end, 10); 6638d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6648d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber TrackInfo *info = &mTracks.editItemAt(trackIndex); 6658d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mFirstSeqNumInSegment = seq; 6668d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mNewSegment = true; 6678d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6688d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber CHECK(GetAttribute((*it).c_str(), "rtptime", &val)); 6698d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6708d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber uint32_t rtpTime = strtoul(val.c_str(), &end, 10); 6718d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6728d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber LOG(VERBOSE) << "track #" << n 6738d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber << ": rtpTime=" << rtpTime << " <=> npt=" << npt1; 6748d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6758d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mPacketSource->setNormalPlayTimeMapping( 6768d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber rtpTime, (int64_t)(npt1 * 1E6)); 6778d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 6788d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber ++n; 6798d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 6808d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber } 6818d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 682cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<APacketSource> getPacketSource(size_t index) { 683cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(index, 0u); 684cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_LT(index, mTracks.size()); 685cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 686cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return mTracks.editItemAt(index).mPacketSource; 687cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 688cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 689cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t countTracks() const { 690cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return mTracks.size(); 691cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 692cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 693cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberprivate: 694cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ALooper> mLooper; 695348a8eab84f4bba76c04ca83b2f5418467aa1a48Andreas Huber sp<ALooper> mNetLooper; 696cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPConnection> mConn; 697cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTPConnection> mRTPConn; 698cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ASessionDescription> mSessionDesc; 699cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mSessionURL; 700cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mBaseURL; 701cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mSessionID; 702cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber bool mSetupTracksSuccessful; 703cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber bool mSeekPending; 704cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber bool mFirstAccessUnit; 705cce326fe43411855aca2f719e505b051bc4b61b3Andreas Huber uint64_t mFirstAccessUnitNTP; 7068d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber int64_t mNumAccessUnitsReceived; 7078d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber bool mCheckPending; 708cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 709cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber struct TrackInfo { 7108d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber AString mURL; 711cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int mRTPSocket; 712cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int mRTCPSocket; 7130792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber bool mUsingInterleavedTCP; 7148d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber uint32_t mFirstSeqNumInSegment; 7158d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber bool mNewSegment; 716cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 717cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<APacketSource> mPacketSource; 718cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber }; 719cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber Vector<TrackInfo> mTracks; 720cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 7211b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber sp<AMessage> mDoneMsg; 7221b543242102ef3c28145c6ad50ee8e8ce2fb26d3Andreas Huber 723cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber void setupTrack(size_t index) { 72439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber sp<APacketSource> source = 72539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber new APacketSource(mSessionDesc, index); 72639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (source->initCheck() != OK) { 72739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber LOG(WARNING) << "Unsupported format. Ignoring track #" 72839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber << index << "."; 72939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 73039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber sp<AMessage> reply = new AMessage('setu', id()); 73139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber reply->setSize("index", index); 73239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber reply->setInt32("result", ERROR_UNSUPPORTED); 73339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber reply->post(); 73439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return; 73539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 73639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 737cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString url; 738cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(mSessionDesc->findAttribute(index, "a=control", &url)); 739cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 740cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString trackURL; 741cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(MakeURL(mBaseURL.c_str(), url.c_str(), &trackURL)); 742cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 743cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mTracks.push(TrackInfo()); 744cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber TrackInfo *info = &mTracks.editItemAt(mTracks.size() - 1); 7458d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mURL = trackURL; 74639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber info->mPacketSource = source; 7470792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber info->mUsingInterleavedTCP = false; 7488d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mFirstSeqNumInSegment = 0; 7498d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber info->mNewSegment = true; 7508d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber 7518d342970108926c4ea355c90d26a2a353ec0fd47Andreas Huber LOG(VERBOSE) << "track #" << mTracks.size() << " URL=" << trackURL; 752cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 753cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request = "SETUP "; 754cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(trackURL); 755cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 756cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 7570792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber#if USE_TCP_INTERLEAVED 7580792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber size_t interleaveIndex = 2 * (mTracks.size() - 1); 7590792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber info->mUsingInterleavedTCP = true; 7600792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber info->mRTPSocket = interleaveIndex; 7610792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber info->mRTCPSocket = interleaveIndex + 1; 7620792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 7630792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber request.append("Transport: RTP/AVP/TCP;interleaved="); 7640792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber request.append(interleaveIndex); 7650792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber request.append("-"); 7660792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber request.append(interleaveIndex + 1); 7670792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber#else 7680792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber unsigned rtpPort; 7690792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber ARTPConnection::MakePortPair( 7700792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber &info->mRTPSocket, &info->mRTCPSocket, &rtpPort); 7710792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 772cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Transport: RTP/AVP/UDP;unicast;client_port="); 773cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(rtpPort); 774cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("-"); 775cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(rtpPort + 1); 7760792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber#endif 7770792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber 778cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 779cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 780cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (index > 1) { 781cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 782cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 783cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 784cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 785cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 786cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 787cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 788cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('setu', id()); 789cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber reply->setSize("index", index); 790cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber reply->setSize("track-index", mTracks.size() - 1); 791cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 792cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 793cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 794cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static bool MakeURL(const char *baseURL, const char *url, AString *out) { 795cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->clear(); 796cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 797cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (strncasecmp("rtsp://", baseURL, 7)) { 798cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // Base URL must be absolute 799cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return false; 800cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 801cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 802cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (!strncasecmp("rtsp://", url, 7)) { 803cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // "url" is already an absolute URL, ignore base URL. 804cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(url); 805cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return true; 806cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 807cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 808cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t n = strlen(baseURL); 809cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (baseURL[n - 1] == '/') { 810cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(baseURL); 811cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append(url); 812cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 813cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber char *slashPos = strrchr(baseURL, '/'); 814cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 815cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (slashPos > &baseURL[6]) { 816cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(baseURL, slashPos - baseURL); 817cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 818cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(baseURL); 819cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 820cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 821cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append("/"); 822cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append(url); 823cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 824cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 825cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return true; 826cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 827cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 828cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber DISALLOW_EVIL_CONSTRUCTORS(MyHandler); 829cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}; 830cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 831cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber} // namespace android 832cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 833cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif // MY_HANDLER_H_ 834