1fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber/* 2fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * Copyright 2012, The Android Open Source Project 3fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * 4fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * you may not use this file except in compliance with the License. 6fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * You may obtain a copy of the License at 7fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * 8fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * 10fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * Unless required by applicable law or agreed to in writing, software 11fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * See the License for the specific language governing permissions and 14fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * limitations under the License. 15fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber */ 16fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 17fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber//#define LOG_NDEBUG 0 18fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#define LOG_TAG "WifiDisplaySink" 19fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <utils/Log.h> 20fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 21fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include "WifiDisplaySink.h" 22fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include "ParsedMessage.h" 23fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include "RTPSink.h" 24fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 25fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 26fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <media/stagefright/foundation/ADebug.h> 27fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <media/stagefright/foundation/AMessage.h> 28fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <media/stagefright/MediaErrors.h> 29fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 30fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubernamespace android { 31fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 32fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas HuberWifiDisplaySink::WifiDisplaySink( 33fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber const sp<ANetworkSession> &netSession, 34fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber const sp<ISurfaceTexture> &surfaceTex) 35fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber : mState(UNDEFINED), 36fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mNetSession(netSession), 37fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mSurfaceTex(surfaceTex), 38fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mSessionID(0), 39fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mNextCSeq(1) { 40fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 41fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 42fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas HuberWifiDisplaySink::~WifiDisplaySink() { 43fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 44fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 45fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid WifiDisplaySink::start(const char *sourceHost, int32_t sourcePort) { 46fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sp<AMessage> msg = new AMessage(kWhatStart, id()); 47fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber msg->setString("sourceHost", sourceHost); 48fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber msg->setInt32("sourcePort", sourcePort); 49fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber msg->post(); 50fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 51fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 52fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid WifiDisplaySink::start(const char *uri) { 53fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sp<AMessage> msg = new AMessage(kWhatStart, id()); 54fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber msg->setString("setupURI", uri); 55fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber msg->post(); 56fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 57fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 58fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber// static 59fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberbool WifiDisplaySink::ParseURL( 60fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber const char *url, AString *host, int32_t *port, AString *path, 61fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString *user, AString *pass) { 62fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber host->clear(); 63fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber *port = 0; 64fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber path->clear(); 65fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber user->clear(); 66fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber pass->clear(); 67fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 68fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (strncasecmp("rtsp://", url, 7)) { 69fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return false; 70fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 71fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 72fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber const char *slashPos = strchr(&url[7], '/'); 73fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 74fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (slashPos == NULL) { 75fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber host->setTo(&url[7]); 76fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber path->setTo("/"); 77fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } else { 78fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber host->setTo(&url[7], slashPos - &url[7]); 79fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber path->setTo(slashPos); 80fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 81fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 82fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ssize_t atPos = host->find("@"); 83fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 84fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (atPos >= 0) { 85fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber // Split of user:pass@ from hostname. 86fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 87fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString userPass(*host, 0, atPos); 88fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber host->erase(0, atPos + 1); 89fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 90fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ssize_t colonPos = userPass.find(":"); 91fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 92fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (colonPos < 0) { 93fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber *user = userPass; 94fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } else { 95fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber user->setTo(userPass, 0, colonPos); 96fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber pass->setTo(userPass, colonPos + 1, userPass.size() - colonPos - 1); 97fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 98fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 99fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 100fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber const char *colonPos = strchr(host->c_str(), ':'); 101fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 102fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (colonPos != NULL) { 103fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber char *end; 104fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber unsigned long x = strtoul(colonPos + 1, &end, 10); 105fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 106fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (end == colonPos + 1 || *end != '\0' || x >= 65536) { 107fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return false; 108fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 109fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 110fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber *port = x; 111fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 112fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber size_t colonOffset = colonPos - host->c_str(); 113fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber size_t trailing = host->size() - colonOffset; 114fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber host->erase(colonOffset, trailing); 115fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } else { 116fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber *port = 554; 117fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 118fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 119fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return true; 120fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 121fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 122fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid WifiDisplaySink::onMessageReceived(const sp<AMessage> &msg) { 123fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber switch (msg->what()) { 124fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber case kWhatStart: 125fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber { 126fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t sourcePort; 127fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 128fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (msg->findString("setupURI", &mSetupURI)) { 129fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString path, user, pass; 130fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK(ParseURL( 131fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mSetupURI.c_str(), 132fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber &mRTSPHost, &sourcePort, &path, &user, &pass) 133fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber && user.empty() && pass.empty()); 134fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } else { 135fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK(msg->findString("sourceHost", &mRTSPHost)); 136fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK(msg->findInt32("sourcePort", &sourcePort)); 137fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 138fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 139fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sp<AMessage> notify = new AMessage(kWhatRTSPNotify, id()); 140fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 141fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber status_t err = mNetSession->createRTSPClient( 142fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mRTSPHost.c_str(), sourcePort, notify, &mSessionID); 143fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK_EQ(err, (status_t)OK); 144fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 145fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mState = CONNECTING; 146fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber break; 147fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 148fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 149fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber case kWhatRTSPNotify: 150fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber { 151fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t reason; 152fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK(msg->findInt32("reason", &reason)); 153fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 154fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber switch (reason) { 155fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber case ANetworkSession::kWhatError: 156fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber { 157fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t sessionID; 158fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK(msg->findInt32("sessionID", &sessionID)); 159fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 160fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t err; 161fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK(msg->findInt32("err", &err)); 162fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 163fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString detail; 164fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK(msg->findString("detail", &detail)); 165fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 166fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ALOGE("An error occurred in session %d (%d, '%s/%s').", 167fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sessionID, 168fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber err, 169fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber detail.c_str(), 170fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber strerror(-err)); 171fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 172fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (sessionID == mSessionID) { 173fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ALOGI("Lost control connection."); 174fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 175fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber // The control connection is dead now. 176fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mNetSession->destroySession(mSessionID); 177fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mSessionID = 0; 178fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 179fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber looper()->stop(); 180fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 181fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber break; 182fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 183fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 184fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber case ANetworkSession::kWhatConnected: 185fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber { 186fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ALOGI("We're now connected."); 187fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mState = CONNECTED; 188fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 189fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (!mSetupURI.empty()) { 190fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber status_t err = 191fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sendDescribe(mSessionID, mSetupURI.c_str()); 192fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 193fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK_EQ(err, (status_t)OK); 194fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 195fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber break; 196fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 197fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 198fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber case ANetworkSession::kWhatData: 199fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber { 200fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber onReceiveClientData(msg); 201fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber break; 202fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 203fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 204fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber case ANetworkSession::kWhatBinaryData: 205fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber { 206fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK(sUseTCPInterleaving); 207fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 208fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t channel; 209fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK(msg->findInt32("channel", &channel)); 210fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 211fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sp<ABuffer> data; 212fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK(msg->findBuffer("data", &data)); 213fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 214fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mRTPSink->injectPacket(channel == 0 /* isRTP */, data); 215fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber break; 216fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 217fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 218fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber default: 219fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber TRESPASS(); 220fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 221fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber break; 222fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 223fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 224fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber case kWhatStop: 225fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber { 226fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber looper()->stop(); 227fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber break; 228fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 229fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 230fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber default: 231fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber TRESPASS(); 232fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 233fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 234fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 235fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid WifiDisplaySink::registerResponseHandler( 236fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func) { 237fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ResponseID id; 238fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber id.mSessionID = sessionID; 239fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber id.mCSeq = cseq; 240fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mResponseHandlers.add(id, func); 241fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 242fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 243fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstatus_t WifiDisplaySink::sendM2(int32_t sessionID) { 244fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString request = "OPTIONS * RTSP/1.0\r\n"; 245fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AppendCommonResponse(&request, mNextCSeq); 246fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 247fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber request.append( 248fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber "Require: org.wfa.wfd1.0\r\n" 249fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber "\r\n"); 250fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 251fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber status_t err = 252fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 253fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 254fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (err != OK) { 255fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return err; 256fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 257fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 258fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber registerResponseHandler( 259fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sessionID, mNextCSeq, &WifiDisplaySink::onReceiveM2Response); 260fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 261fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ++mNextCSeq; 262fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 263fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return OK; 264fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 265fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 266fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstatus_t WifiDisplaySink::onReceiveM2Response( 267fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t sessionID, const sp<ParsedMessage> &msg) { 268fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t statusCode; 269fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (!msg->getStatusCode(&statusCode)) { 270fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return ERROR_MALFORMED; 271fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 272fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 273fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (statusCode != 200) { 274fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return ERROR_UNSUPPORTED; 275fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 276fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 277fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return OK; 278fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 279fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 280fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstatus_t WifiDisplaySink::onReceiveDescribeResponse( 281fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t sessionID, const sp<ParsedMessage> &msg) { 282fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t statusCode; 283fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (!msg->getStatusCode(&statusCode)) { 284fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return ERROR_MALFORMED; 285fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 286fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 287fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (statusCode != 200) { 288fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return ERROR_UNSUPPORTED; 289fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 290fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 291fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return sendSetup(sessionID, mSetupURI.c_str()); 292fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 293fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 294fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstatus_t WifiDisplaySink::onReceiveSetupResponse( 295fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t sessionID, const sp<ParsedMessage> &msg) { 296fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t statusCode; 297fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (!msg->getStatusCode(&statusCode)) { 298fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return ERROR_MALFORMED; 299fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 300fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 301fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (statusCode != 200) { 302fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return ERROR_UNSUPPORTED; 303fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 304fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 305fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (!msg->findString("session", &mPlaybackSessionID)) { 306fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return ERROR_MALFORMED; 307fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 308fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 309fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (!ParsedMessage::GetInt32Attribute( 310fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mPlaybackSessionID.c_str(), 311fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber "timeout", 312fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber &mPlaybackSessionTimeoutSecs)) { 313fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mPlaybackSessionTimeoutSecs = -1; 314fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 315fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 316fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ssize_t colonPos = mPlaybackSessionID.find(";"); 317fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (colonPos >= 0) { 318fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber // Strip any options from the returned session id. 319fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mPlaybackSessionID.erase( 320fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber colonPos, mPlaybackSessionID.size() - colonPos); 321fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 322fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 323fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber status_t err = configureTransport(msg); 324fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 325fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (err != OK) { 326fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return err; 327fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 328fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 329fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mState = PAUSED; 330fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 331fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return sendPlay( 332fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sessionID, 333fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber !mSetupURI.empty() 334fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ? mSetupURI.c_str() : "rtsp://x.x.x.x:x/wfd1.0/streamid=0"); 335fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 336fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 337fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstatus_t WifiDisplaySink::configureTransport(const sp<ParsedMessage> &msg) { 338fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (sUseTCPInterleaving) { 339fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return OK; 340fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 341fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 342fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString transport; 343fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (!msg->findString("transport", &transport)) { 344fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ALOGE("Missing 'transport' field in SETUP response."); 345fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return ERROR_MALFORMED; 346fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 347fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 348fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString sourceHost; 349fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (!ParsedMessage::GetAttribute( 350fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber transport.c_str(), "source", &sourceHost)) { 351fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sourceHost = mRTSPHost; 352fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 353fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 354fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString serverPortStr; 355fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (!ParsedMessage::GetAttribute( 356fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber transport.c_str(), "server_port", &serverPortStr)) { 357fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ALOGE("Missing 'server_port' in Transport field."); 358fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return ERROR_MALFORMED; 359fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 360fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 361fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int rtpPort, rtcpPort; 362fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (sscanf(serverPortStr.c_str(), "%d-%d", &rtpPort, &rtcpPort) != 2 363fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber || rtpPort <= 0 || rtpPort > 65535 364fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber || rtcpPort <=0 || rtcpPort > 65535 365fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber || rtcpPort != rtpPort + 1) { 366fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ALOGE("Invalid server_port description '%s'.", 367fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber serverPortStr.c_str()); 368fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 369fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return ERROR_MALFORMED; 370fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 371fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 372fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (rtpPort & 1) { 373fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ALOGW("Server picked an odd numbered RTP port."); 374fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 375fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 376fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return mRTPSink->connect(sourceHost.c_str(), rtpPort, rtcpPort); 377fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 378fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 379fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstatus_t WifiDisplaySink::onReceivePlayResponse( 380fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t sessionID, const sp<ParsedMessage> &msg) { 381fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t statusCode; 382fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (!msg->getStatusCode(&statusCode)) { 383fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return ERROR_MALFORMED; 384fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 385fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 386fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (statusCode != 200) { 387fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return ERROR_UNSUPPORTED; 388fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 389fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 390fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mState = PLAYING; 391fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 392fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return OK; 393fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 394fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 395fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid WifiDisplaySink::onReceiveClientData(const sp<AMessage> &msg) { 396fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t sessionID; 397fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK(msg->findInt32("sessionID", &sessionID)); 398fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 399fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sp<RefBase> obj; 400fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK(msg->findObject("data", &obj)); 401fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 402fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sp<ParsedMessage> data = 403fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber static_cast<ParsedMessage *>(obj.get()); 404fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 405fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ALOGV("session %d received '%s'", 406fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sessionID, data->debugString().c_str()); 407fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 408fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString method; 409fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString uri; 410fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber data->getRequestField(0, &method); 411fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 412fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t cseq; 413fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (!data->findInt32("cseq", &cseq)) { 414fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sendErrorResponse(sessionID, "400 Bad Request", -1 /* cseq */); 415fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return; 416fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 417fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 418fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (method.startsWith("RTSP/")) { 419fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber // This is a response. 420fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 421fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ResponseID id; 422fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber id.mSessionID = sessionID; 423fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber id.mCSeq = cseq; 424fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 425fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ssize_t index = mResponseHandlers.indexOfKey(id); 426fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 427fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (index < 0) { 428fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ALOGW("Received unsolicited server response, cseq %d", cseq); 429fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return; 430fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 431fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 432fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber HandleRTSPResponseFunc func = mResponseHandlers.valueAt(index); 433fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mResponseHandlers.removeItemsAt(index); 434fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 435fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber status_t err = (this->*func)(sessionID, data); 436fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK_EQ(err, (status_t)OK); 437fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } else { 438fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString version; 439fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber data->getRequestField(2, &version); 440fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (!(version == AString("RTSP/1.0"))) { 441fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sendErrorResponse(sessionID, "505 RTSP Version not supported", cseq); 442fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return; 443fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 444fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 445fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (method == "OPTIONS") { 446fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber onOptionsRequest(sessionID, cseq, data); 447fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } else if (method == "GET_PARAMETER") { 448fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber onGetParameterRequest(sessionID, cseq, data); 449fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } else if (method == "SET_PARAMETER") { 450fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber onSetParameterRequest(sessionID, cseq, data); 451fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } else { 452fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sendErrorResponse(sessionID, "405 Method Not Allowed", cseq); 453fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 454fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 455fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 456fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 457fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid WifiDisplaySink::onOptionsRequest( 458fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t sessionID, 459fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t cseq, 460fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber const sp<ParsedMessage> &data) { 461fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString response = "RTSP/1.0 200 OK\r\n"; 462fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AppendCommonResponse(&response, cseq); 463fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber response.append("Public: org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER\r\n"); 464fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber response.append("\r\n"); 465fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 466fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 467fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK_EQ(err, (status_t)OK); 468fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 469fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber err = sendM2(sessionID); 470fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK_EQ(err, (status_t)OK); 471fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 472fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 473fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid WifiDisplaySink::onGetParameterRequest( 474fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t sessionID, 475fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t cseq, 476fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber const sp<ParsedMessage> &data) { 477fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString body = 478fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber "wfd_video_formats: xxx\r\n" 479fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber "wfd_audio_codecs: xxx\r\n" 480fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber "wfd_client_rtp_ports: RTP/AVP/UDP;unicast xxx 0 mode=play\r\n"; 481fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 482fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString response = "RTSP/1.0 200 OK\r\n"; 483fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AppendCommonResponse(&response, cseq); 484fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber response.append("Content-Type: text/parameters\r\n"); 485fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber response.append(StringPrintf("Content-Length: %d\r\n", body.size())); 486fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber response.append("\r\n"); 487fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber response.append(body); 488fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 489fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 490fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK_EQ(err, (status_t)OK); 491fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 492fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 493fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstatus_t WifiDisplaySink::sendDescribe(int32_t sessionID, const char *uri) { 494fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber uri = "rtsp://xwgntvx.is.livestream-api.com/livestreamiphone/wgntv"; 495fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber uri = "rtsp://v2.cache6.c.youtube.com/video.3gp?cid=e101d4bf280055f9&fmt=18"; 496fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 497fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString request = StringPrintf("DESCRIBE %s RTSP/1.0\r\n", uri); 498fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AppendCommonResponse(&request, mNextCSeq); 499fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 500fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber request.append("Accept: application/sdp\r\n"); 501fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber request.append("\r\n"); 502fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 503fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber status_t err = mNetSession->sendRequest( 504fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sessionID, request.c_str(), request.size()); 505fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 506fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (err != OK) { 507fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return err; 508fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 509fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 510fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber registerResponseHandler( 511fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sessionID, mNextCSeq, &WifiDisplaySink::onReceiveDescribeResponse); 512fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 513fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ++mNextCSeq; 514fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 515fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return OK; 516fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 517fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 518fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstatus_t WifiDisplaySink::sendSetup(int32_t sessionID, const char *uri) { 519fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mRTPSink = new RTPSink(mNetSession, mSurfaceTex); 520fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber looper()->registerHandler(mRTPSink); 521fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 522fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber status_t err = mRTPSink->init(sUseTCPInterleaving); 523fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 524fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (err != OK) { 525fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber looper()->unregisterHandler(mRTPSink->id()); 526fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mRTPSink.clear(); 527fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return err; 528fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 529fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 530fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString request = StringPrintf("SETUP %s RTSP/1.0\r\n", uri); 531fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 532fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AppendCommonResponse(&request, mNextCSeq); 533fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 534fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (sUseTCPInterleaving) { 535fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber request.append("Transport: RTP/AVP/TCP;interleaved=0-1\r\n"); 536fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } else { 537fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t rtpPort = mRTPSink->getRTPPort(); 538fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 539fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber request.append( 540fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber StringPrintf( 541fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber "Transport: RTP/AVP/UDP;unicast;client_port=%d-%d\r\n", 542fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber rtpPort, rtpPort + 1)); 543fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 544fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 545fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber request.append("\r\n"); 546fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 547fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ALOGV("request = '%s'", request.c_str()); 548fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 549fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber err = mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 550fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 551fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (err != OK) { 552fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return err; 553fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 554fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 555fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber registerResponseHandler( 556fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sessionID, mNextCSeq, &WifiDisplaySink::onReceiveSetupResponse); 557fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 558fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ++mNextCSeq; 559fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 560fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return OK; 561fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 562fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 563fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstatus_t WifiDisplaySink::sendPlay(int32_t sessionID, const char *uri) { 564fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString request = StringPrintf("PLAY %s RTSP/1.0\r\n", uri); 565fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 566fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AppendCommonResponse(&request, mNextCSeq); 567fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 568fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber request.append(StringPrintf("Session: %s\r\n", mPlaybackSessionID.c_str())); 569fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber request.append("\r\n"); 570fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 571fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber status_t err = 572fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 573fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 574fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (err != OK) { 575fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return err; 576fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 577fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 578fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber registerResponseHandler( 579fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sessionID, mNextCSeq, &WifiDisplaySink::onReceivePlayResponse); 580fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 581fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber ++mNextCSeq; 582fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 583fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber return OK; 584fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 585fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 586fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid WifiDisplaySink::onSetParameterRequest( 587fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t sessionID, 588fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t cseq, 589fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber const sp<ParsedMessage> &data) { 590fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber const char *content = data->getContent(); 591fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 592fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (strstr(content, "wfd_trigger_method: SETUP\r\n") != NULL) { 593fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber status_t err = 594fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sendSetup( 595fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber sessionID, 596fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber "rtsp://x.x.x.x:x/wfd1.0/streamid=0"); 597fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 598fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK_EQ(err, (status_t)OK); 599fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 600fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 601fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString response = "RTSP/1.0 200 OK\r\n"; 602fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AppendCommonResponse(&response, cseq); 603fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber response.append("\r\n"); 604fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 605fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 606fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK_EQ(err, (status_t)OK); 607fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 608fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 609fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid WifiDisplaySink::sendErrorResponse( 610fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t sessionID, 611fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber const char *errorDetail, 612fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber int32_t cseq) { 613fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AString response; 614fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber response.append("RTSP/1.0 "); 615fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber response.append(errorDetail); 616fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber response.append("\r\n"); 617fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 618fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber AppendCommonResponse(&response, cseq); 619fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 620fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber response.append("\r\n"); 621fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 622fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 623fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber CHECK_EQ(err, (status_t)OK); 624fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 625fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 626fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber// static 627fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid WifiDisplaySink::AppendCommonResponse(AString *response, int32_t cseq) { 628fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber time_t now = time(NULL); 629fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber struct tm *now2 = gmtime(&now); 630fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber char buf[128]; 631fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z", now2); 632fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 633fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber response->append("Date: "); 634fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber response->append(buf); 635fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber response->append("\r\n"); 636fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 637fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber response->append("User-Agent: stagefright/1.1 (Linux;Android 4.1)\r\n"); 638fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 639fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber if (cseq >= 0) { 640fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber response->append(StringPrintf("CSeq: %d\r\n", cseq)); 641fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber } 642fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} 643fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber 644fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber} // namespace android 645