MyHandler.h revision cf7b9c7aae758ac0b99833915053c63c2ac46e09
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 26cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 27cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ADebug.h> 28cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ALooper.h> 29cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/AMessage.h> 30cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/MediaErrors.h> 31cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 32cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubernamespace android { 33cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 34cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstruct MyHandler : public AHandler { 35cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber MyHandler(const char *url, const sp<ALooper> &looper) 36cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber : mLooper(looper), 37cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn(new ARTSPConnection), 38cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRTPConn(new ARTPConnection), 39cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionURL(url), 40cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSetupTracksSuccessful(false), 41cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mFirstAccessUnit(true), 42cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mFirstAccessUnitNTP(-1) { 43cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLooper->registerHandler(this); 44cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLooper->registerHandler(mConn); 45cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLooper->registerHandler(mRTPConn); 46cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('conn', id()); 47cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->connect(mSessionURL.c_str(), reply); 48cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 49cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 50cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber virtual void onMessageReceived(const sp<AMessage> &msg) { 51cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber switch (msg->what()) { 52cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'conn': 53cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 54cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 55cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 56cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 57cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "connection request completed with result " 58cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 59cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 60cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 61cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 62cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request = "DESCRIBE "; 63cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 64cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 65cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Accept: application/sdp\r\n"); 66cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 67cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 68cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('desc', id()); 69cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 70cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 71cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 72cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 73cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 74cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'disc': 75cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 76cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "disconnect completed"; 77cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 78cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber (new AMessage('quit', id()))->post(); 79cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 80cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 81cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 82cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'desc': 83cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 84cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 85cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 86cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 87cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "DESCRIBE completed with result " 88cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 89cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 90cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 91cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 92cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 93cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response = 94cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 95cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 96cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (response->mStatusCode == 302) { 97cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ssize_t i = response->mHeaders.indexOfKey("location"); 98cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(i, 0); 99cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 100cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionURL = response->mHeaders.valueAt(i); 101cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 102cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 103cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request = "DESCRIBE "; 104cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 105cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 106cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Accept: application/sdp\r\n"); 107cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 108cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 109cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('desc', id()); 110cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 111cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 112cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 113cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 114cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_EQ(response->mStatusCode, 200u); 115cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 116cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionDesc = new ASessionDescription; 117cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 118cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionDesc->setTo( 119cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber response->mContent->data(), 120cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber response->mContent->size()); 121cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 122cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(mSessionDesc->isValid()); 123cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 124cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ssize_t i = response->mHeaders.indexOfKey("content-base"); 125cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (i >= 0) { 126cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mBaseURL = response->mHeaders.valueAt(i); 127cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 128cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber i = response->mHeaders.indexOfKey("content-location"); 129cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (i >= 0) { 130cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mBaseURL = response->mHeaders.valueAt(i); 131cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 132cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mBaseURL = mSessionURL; 133cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 134cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 135cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 136cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GT(mSessionDesc->countTracks(), 1u); 137cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber setupTrack(1); 138cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 139cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 140cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 141cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 142cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 143cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 144cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 145cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'setu': 146cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 147cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t index; 148cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findSize("index", &index)); 149cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 150cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t trackIndex; 151cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findSize("track-index", &trackIndex)); 152cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 153cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 154cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 155cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 156cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "SETUP(" << index << ") completed with result " 157cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 158cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 159cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 160cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 161cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 162cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 163cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 164cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response = 165cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 166cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 167cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_EQ(response->mStatusCode, 200u); 168cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 169cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ssize_t i = response->mHeaders.indexOfKey("session"); 170cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(i, 0); 171cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 172cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (index == 1) { 173cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionID = response->mHeaders.valueAt(i); 174cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber i = mSessionID.find(";"); 175cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (i >= 0) { 176cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // Remove options, i.e. ";timeout=90" 177cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionID.erase(i, mSessionID.size() - i); 178cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 179cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 180cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 181cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> notify = new AMessage('accu', id()); 182cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber notify->setSize("track-index", trackIndex); 183cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 184cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mRTPConn->addStream( 185cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber track->mRTPSocket, track->mRTCPSocket, 186cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSessionDesc, index, 187cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber notify); 188cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 189cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber track->mPacketSource = 190cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber new APacketSource(mSessionDesc, index); 191cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 192cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mSetupTracksSuccessful = true; 193cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 194cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ++index; 195cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (index < mSessionDesc->countTracks()) { 196cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber setupTrack(index); 197cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 198cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 199cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 200cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber close(track->mRTPSocket); 201cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber close(track->mRTCPSocket); 202cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 203cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mTracks.removeItemsAt(mTracks.size() - 1); 204cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 205cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 206cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (mSetupTracksSuccessful) { 207cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request = "PLAY "; 208cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 209cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 210cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 211cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 212cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 213cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 214cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 215cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 216cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 217cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('play', id()); 218cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 219cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 220cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 221cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 222cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 223cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 224cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 225cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 226cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'play': 227cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 228cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 229cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 230cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 231cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "PLAY completed with result " 232cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 233cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 234cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (result == OK) { 235cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 236cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("response", &obj)); 237cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPResponse> response = 238cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static_cast<ARTSPResponse *>(obj.get()); 239cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 240cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_EQ(response->mStatusCode, 200u); 241cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 242cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> msg = new AMessage('abor', id()); 243cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber msg->post(60000000ll); 244cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 245cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 246cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 247cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 248cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 249cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 250cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 251cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 252cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'abor': 253cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 254cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 255cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mTracks.editItemAt(i).mPacketSource->signalEOS( 256cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ERROR_END_OF_STREAM); 257cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 258cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 259cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('tear', id()); 260cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 261cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request; 262cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request = "TEARDOWN "; 263cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 264cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // XXX should use aggregate url from SDP here... 265cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionURL); 266cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 267cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 268cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 269cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 270cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 271cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 272cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 273cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 274cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 275cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 276cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 277cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 278cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'tear': 279cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 280cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int32_t result; 281cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findInt32("result", &result)); 282cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 283cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber LOG(INFO) << "TEARDOWN completed with result " 284cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber << result << " (" << strerror(-result) << ")"; 285cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 286cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('disc', id()); 287cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->disconnect(reply); 288cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 289cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 290cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 291cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'quit': 292cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 293cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mLooper->stop(); 294cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 295cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 296cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 297cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber case 'accu': 298cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber { 299cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t trackIndex; 300cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findSize("track-index", &trackIndex)); 301cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 302cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<RefBase> obj; 303cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(msg->findObject("access-unit", &obj)); 304cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 305cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ABuffer> accessUnit = static_cast<ABuffer *>(obj.get()); 306cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 307cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint64_t ntpTime; 308cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(accessUnit->meta()->findInt64( 309cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber "ntp-time", (int64_t *)&ntpTime)); 310cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 311cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (mFirstAccessUnit) { 312cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mFirstAccessUnit = false; 313cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mFirstAccessUnitNTP = ntpTime; 314cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 315cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (ntpTime > mFirstAccessUnitNTP) { 316cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ntpTime -= mFirstAccessUnitNTP; 317cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 318cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ntpTime = 0; 319cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 320cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 321cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber accessUnit->meta()->setInt64("ntp-time", ntpTime); 322cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 323cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber TrackInfo *track = &mTracks.editItemAt(trackIndex); 324cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber track->mPacketSource->queueAccessUnit(accessUnit); 325cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 326cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 327cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 328cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber default: 329cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber TRESPASS(); 330cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber break; 331cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 332cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 333cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 334cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<APacketSource> getPacketSource(size_t index) { 335cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_GE(index, 0u); 336cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK_LT(index, mTracks.size()); 337cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 338cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return mTracks.editItemAt(index).mPacketSource; 339cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 340cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 341cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t countTracks() const { 342cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return mTracks.size(); 343cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 344cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 345cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberprivate: 346cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ALooper> mLooper; 347cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTSPConnection> mConn; 348cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ARTPConnection> mRTPConn; 349cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<ASessionDescription> mSessionDesc; 350cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mSessionURL; 351cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mBaseURL; 352cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString mSessionID; 353cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber bool mSetupTracksSuccessful; 354cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber bool mFirstAccessUnit; 355cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber uint64_t mFirstAccessUnitNTP; 356cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 357cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber struct TrackInfo { 358cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int mRTPSocket; 359cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber int mRTCPSocket; 360cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 361cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<APacketSource> mPacketSource; 362cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber }; 363cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber Vector<TrackInfo> mTracks; 364cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 365cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber void setupTrack(size_t index) { 366cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString url; 367cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(mSessionDesc->findAttribute(index, "a=control", &url)); 368cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 369cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString trackURL; 370cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber CHECK(MakeURL(mBaseURL.c_str(), url.c_str(), &trackURL)); 371cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 372cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mTracks.push(TrackInfo()); 373cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber TrackInfo *info = &mTracks.editItemAt(mTracks.size() - 1); 374cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 375cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber unsigned rtpPort; 376cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber ARTPConnection::MakePortPair( 377cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber &info->mRTPSocket, &info->mRTCPSocket, &rtpPort); 378cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 379cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber AString request = "SETUP "; 380cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(trackURL); 381cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(" RTSP/1.0\r\n"); 382cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 383cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Transport: RTP/AVP/UDP;unicast;client_port="); 384cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(rtpPort); 385cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("-"); 386cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(rtpPort + 1); 387cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 388cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 389cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (index > 1) { 390cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("Session: "); 391cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append(mSessionID); 392cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 393cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 394cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 395cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber request.append("\r\n"); 396cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 397cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber sp<AMessage> reply = new AMessage('setu', id()); 398cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber reply->setSize("index", index); 399cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber reply->setSize("track-index", mTracks.size() - 1); 400cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber mConn->sendRequest(request.c_str(), reply); 401cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 402cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 403cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber static bool MakeURL(const char *baseURL, const char *url, AString *out) { 404cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->clear(); 405cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 406cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (strncasecmp("rtsp://", baseURL, 7)) { 407cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // Base URL must be absolute 408cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return false; 409cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 410cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 411cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (!strncasecmp("rtsp://", url, 7)) { 412cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber // "url" is already an absolute URL, ignore base URL. 413cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(url); 414cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return true; 415cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 416cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 417cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber size_t n = strlen(baseURL); 418cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (baseURL[n - 1] == '/') { 419cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(baseURL); 420cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append(url); 421cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 422cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber char *slashPos = strrchr(baseURL, '/'); 423cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 424cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber if (slashPos > &baseURL[6]) { 425cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(baseURL, slashPos - baseURL); 426cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } else { 427cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->setTo(baseURL); 428cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 429cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 430cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append("/"); 431cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber out->append(url); 432cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 433cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 434cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber return true; 435cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber } 436cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 437cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber DISALLOW_EVIL_CONSTRUCTORS(MyHandler); 438cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}; 439cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 440cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber} // namespace android 441cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber 442cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif // MY_HANDLER_H_ 443