diff options
Diffstat (limited to 'media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp')
-rw-r--r-- | media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp | 917 |
1 files changed, 0 insertions, 917 deletions
diff --git a/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp b/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp deleted file mode 100644 index 5db2099..0000000 --- a/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp +++ /dev/null @@ -1,917 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "WifiDisplaySink" -#include <utils/Log.h> - -#include "WifiDisplaySink.h" - -#include "DirectRenderer.h" -#include "MediaReceiver.h" -#include "ParsedMessage.h" -#include "TimeSyncer.h" - -#include <cutils/properties.h> -#include <media/stagefright/foundation/ABuffer.h> -#include <media/stagefright/foundation/ADebug.h> -#include <media/stagefright/foundation/AMessage.h> -#include <media/stagefright/MediaErrors.h> -#include <media/stagefright/Utils.h> - -namespace android { - -// static -const AString WifiDisplaySink::sUserAgent = MakeUserAgent(); - -WifiDisplaySink::WifiDisplaySink( - uint32_t flags, - const sp<ANetworkSession> &netSession, - const sp<IGraphicBufferProducer> &bufferProducer, - const sp<AMessage> ¬ify) - : mState(UNDEFINED), - mFlags(flags), - mNetSession(netSession), - mSurfaceTex(bufferProducer), - mNotify(notify), - mUsingTCPTransport(false), - mUsingTCPInterleaving(false), - mSessionID(0), - mNextCSeq(1), - mIDRFrameRequestPending(false), - mTimeOffsetUs(0ll), - mTimeOffsetValid(false), - mSetupDeferred(false), - mLatencyCount(0), - mLatencySumUs(0ll), - mLatencyMaxUs(0ll), - mMaxDelayMs(-1ll) { - // We support any and all resolutions, but prefer 720p30 - mSinkSupportedVideoFormats.setNativeResolution( - VideoFormats::RESOLUTION_CEA, 5); // 1280 x 720 p30 - - mSinkSupportedVideoFormats.enableAll(); -} - -WifiDisplaySink::~WifiDisplaySink() { -} - -void WifiDisplaySink::start(const char *sourceHost, int32_t sourcePort) { - sp<AMessage> msg = new AMessage(kWhatStart, id()); - msg->setString("sourceHost", sourceHost); - msg->setInt32("sourcePort", sourcePort); - msg->post(); -} - -void WifiDisplaySink::start(const char *uri) { - sp<AMessage> msg = new AMessage(kWhatStart, id()); - msg->setString("setupURI", uri); - msg->post(); -} - -// static -bool WifiDisplaySink::ParseURL( - const char *url, AString *host, int32_t *port, AString *path, - AString *user, AString *pass) { - host->clear(); - *port = 0; - path->clear(); - user->clear(); - pass->clear(); - - if (strncasecmp("rtsp://", url, 7)) { - return false; - } - - const char *slashPos = strchr(&url[7], '/'); - - if (slashPos == NULL) { - host->setTo(&url[7]); - path->setTo("/"); - } else { - host->setTo(&url[7], slashPos - &url[7]); - path->setTo(slashPos); - } - - ssize_t atPos = host->find("@"); - - if (atPos >= 0) { - // Split of user:pass@ from hostname. - - AString userPass(*host, 0, atPos); - host->erase(0, atPos + 1); - - ssize_t colonPos = userPass.find(":"); - - if (colonPos < 0) { - *user = userPass; - } else { - user->setTo(userPass, 0, colonPos); - pass->setTo(userPass, colonPos + 1, userPass.size() - colonPos - 1); - } - } - - const char *colonPos = strchr(host->c_str(), ':'); - - if (colonPos != NULL) { - char *end; - unsigned long x = strtoul(colonPos + 1, &end, 10); - - if (end == colonPos + 1 || *end != '\0' || x >= 65536) { - return false; - } - - *port = x; - - size_t colonOffset = colonPos - host->c_str(); - size_t trailing = host->size() - colonOffset; - host->erase(colonOffset, trailing); - } else { - *port = 554; - } - - return true; -} - -void WifiDisplaySink::onMessageReceived(const sp<AMessage> &msg) { - switch (msg->what()) { - case kWhatStart: - { - sleep(2); // XXX - - int32_t sourcePort; - CHECK(msg->findString("sourceHost", &mRTSPHost)); - CHECK(msg->findInt32("sourcePort", &sourcePort)); - - sp<AMessage> notify = new AMessage(kWhatRTSPNotify, id()); - - status_t err = mNetSession->createRTSPClient( - mRTSPHost.c_str(), sourcePort, notify, &mSessionID); - CHECK_EQ(err, (status_t)OK); - - mState = CONNECTING; - break; - } - - case kWhatRTSPNotify: - { - int32_t reason; - CHECK(msg->findInt32("reason", &reason)); - - switch (reason) { - case ANetworkSession::kWhatError: - { - int32_t sessionID; - CHECK(msg->findInt32("sessionID", &sessionID)); - - int32_t err; - CHECK(msg->findInt32("err", &err)); - - AString detail; - CHECK(msg->findString("detail", &detail)); - - ALOGE("An error occurred in session %d (%d, '%s/%s').", - sessionID, - err, - detail.c_str(), - strerror(-err)); - - if (sessionID == mSessionID) { - ALOGI("Lost control connection."); - - // The control connection is dead now. - mNetSession->destroySession(mSessionID); - mSessionID = 0; - - if (mNotify == NULL) { - looper()->stop(); - } else { - sp<AMessage> notify = mNotify->dup(); - notify->setInt32("what", kWhatDisconnected); - notify->post(); - } - } - break; - } - - case ANetworkSession::kWhatConnected: - { - ALOGI("We're now connected."); - mState = CONNECTED; - - if (mFlags & FLAG_SPECIAL_MODE) { - sp<AMessage> notify = new AMessage( - kWhatTimeSyncerNotify, id()); - - mTimeSyncer = new TimeSyncer(mNetSession, notify); - looper()->registerHandler(mTimeSyncer); - - mTimeSyncer->startClient(mRTSPHost.c_str(), 8123); - } - break; - } - - case ANetworkSession::kWhatData: - { - onReceiveClientData(msg); - break; - } - - default: - TRESPASS(); - } - break; - } - - case kWhatStop: - { - looper()->stop(); - break; - } - - case kWhatMediaReceiverNotify: - { - onMediaReceiverNotify(msg); - break; - } - - case kWhatTimeSyncerNotify: - { - int32_t what; - CHECK(msg->findInt32("what", &what)); - - if (what == TimeSyncer::kWhatTimeOffset) { - CHECK(msg->findInt64("offset", &mTimeOffsetUs)); - mTimeOffsetValid = true; - - if (mSetupDeferred) { - CHECK_EQ((status_t)OK, - sendSetup( - mSessionID, - "rtsp://x.x.x.x:x/wfd1.0/streamid=0")); - - mSetupDeferred = false; - } - } - break; - } - - case kWhatReportLateness: - { - if (mLatencyCount > 0) { - int64_t avgLatencyUs = mLatencySumUs / mLatencyCount; - - ALOGV("avg. latency = %lld ms (max %lld ms)", - avgLatencyUs / 1000ll, - mLatencyMaxUs / 1000ll); - - sp<AMessage> params = new AMessage; - params->setInt64("avgLatencyUs", avgLatencyUs); - params->setInt64("maxLatencyUs", mLatencyMaxUs); - mMediaReceiver->informSender(0 /* trackIndex */, params); - } - - mLatencyCount = 0; - mLatencySumUs = 0ll; - mLatencyMaxUs = 0ll; - - msg->post(kReportLatenessEveryUs); - break; - } - - default: - TRESPASS(); - } -} - -void WifiDisplaySink::dumpDelay(size_t trackIndex, int64_t timeUs) { - int64_t delayMs = (ALooper::GetNowUs() - timeUs) / 1000ll; - - if (delayMs > mMaxDelayMs) { - mMaxDelayMs = delayMs; - } - - static const int64_t kMinDelayMs = 0; - static const int64_t kMaxDelayMs = 300; - - const char *kPattern = "########################################"; - size_t kPatternSize = strlen(kPattern); - - int n = (kPatternSize * (delayMs - kMinDelayMs)) - / (kMaxDelayMs - kMinDelayMs); - - if (n < 0) { - n = 0; - } else if ((size_t)n > kPatternSize) { - n = kPatternSize; - } - - ALOGI("[%lld]: (%4lld ms / %4lld ms) %s", - timeUs / 1000, - delayMs, - mMaxDelayMs, - kPattern + kPatternSize - n); -} - -void WifiDisplaySink::onMediaReceiverNotify(const sp<AMessage> &msg) { - int32_t what; - CHECK(msg->findInt32("what", &what)); - - switch (what) { - case MediaReceiver::kWhatInitDone: - { - status_t err; - CHECK(msg->findInt32("err", &err)); - - ALOGI("MediaReceiver initialization completed w/ err %d", err); - break; - } - - case MediaReceiver::kWhatError: - { - status_t err; - CHECK(msg->findInt32("err", &err)); - - ALOGE("MediaReceiver signaled error %d", err); - break; - } - - case MediaReceiver::kWhatAccessUnit: - { - if (mRenderer == NULL) { - mRenderer = new DirectRenderer(mSurfaceTex); - looper()->registerHandler(mRenderer); - } - - sp<ABuffer> accessUnit; - CHECK(msg->findBuffer("accessUnit", &accessUnit)); - - int64_t timeUs; - CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); - - if (!mTimeOffsetValid && !(mFlags & FLAG_SPECIAL_MODE)) { - mTimeOffsetUs = timeUs - ALooper::GetNowUs(); - mTimeOffsetValid = true; - } - - CHECK(mTimeOffsetValid); - - // We are the timesync _client_, - // client time = server time - time offset. - timeUs -= mTimeOffsetUs; - - size_t trackIndex; - CHECK(msg->findSize("trackIndex", &trackIndex)); - - int64_t nowUs = ALooper::GetNowUs(); - int64_t delayUs = nowUs - timeUs; - - mLatencySumUs += delayUs; - if (mLatencyCount == 0 || delayUs > mLatencyMaxUs) { - mLatencyMaxUs = delayUs; - } - ++mLatencyCount; - - // dumpDelay(trackIndex, timeUs); - - timeUs += 220000ll; // Assume 220 ms of latency - accessUnit->meta()->setInt64("timeUs", timeUs); - - sp<AMessage> format; - if (msg->findMessage("format", &format)) { - mRenderer->setFormat(trackIndex, format); - } - - mRenderer->queueAccessUnit(trackIndex, accessUnit); - break; - } - - case MediaReceiver::kWhatPacketLost: - { -#if 0 - if (!mIDRFrameRequestPending) { - ALOGI("requesting IDR frame"); - - sendIDRFrameRequest(mSessionID); - } -#endif - break; - } - - default: - TRESPASS(); - } -} - -void WifiDisplaySink::registerResponseHandler( - int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func) { - ResponseID id; - id.mSessionID = sessionID; - id.mCSeq = cseq; - mResponseHandlers.add(id, func); -} - -status_t WifiDisplaySink::sendM2(int32_t sessionID) { - AString request = "OPTIONS * RTSP/1.0\r\n"; - AppendCommonResponse(&request, mNextCSeq); - - request.append( - "Require: org.wfa.wfd1.0\r\n" - "\r\n"); - - status_t err = - mNetSession->sendRequest(sessionID, request.c_str(), request.size()); - - if (err != OK) { - return err; - } - - registerResponseHandler( - sessionID, mNextCSeq, &WifiDisplaySink::onReceiveM2Response); - - ++mNextCSeq; - - return OK; -} - -status_t WifiDisplaySink::onReceiveM2Response( - int32_t sessionID, const sp<ParsedMessage> &msg) { - int32_t statusCode; - if (!msg->getStatusCode(&statusCode)) { - return ERROR_MALFORMED; - } - - if (statusCode != 200) { - return ERROR_UNSUPPORTED; - } - - return OK; -} - -status_t WifiDisplaySink::onReceiveSetupResponse( - int32_t sessionID, const sp<ParsedMessage> &msg) { - int32_t statusCode; - if (!msg->getStatusCode(&statusCode)) { - return ERROR_MALFORMED; - } - - if (statusCode != 200) { - return ERROR_UNSUPPORTED; - } - - if (!msg->findString("session", &mPlaybackSessionID)) { - return ERROR_MALFORMED; - } - - if (!ParsedMessage::GetInt32Attribute( - mPlaybackSessionID.c_str(), - "timeout", - &mPlaybackSessionTimeoutSecs)) { - mPlaybackSessionTimeoutSecs = -1; - } - - ssize_t colonPos = mPlaybackSessionID.find(";"); - if (colonPos >= 0) { - // Strip any options from the returned session id. - mPlaybackSessionID.erase( - colonPos, mPlaybackSessionID.size() - colonPos); - } - - status_t err = configureTransport(msg); - - if (err != OK) { - return err; - } - - mState = PAUSED; - - return sendPlay( - sessionID, - "rtsp://x.x.x.x:x/wfd1.0/streamid=0"); -} - -status_t WifiDisplaySink::configureTransport(const sp<ParsedMessage> &msg) { - if (mUsingTCPTransport && !(mFlags & FLAG_SPECIAL_MODE)) { - // In "special" mode we still use a UDP RTCP back-channel that - // needs connecting. - return OK; - } - - AString transport; - if (!msg->findString("transport", &transport)) { - ALOGE("Missing 'transport' field in SETUP response."); - return ERROR_MALFORMED; - } - - AString sourceHost; - if (!ParsedMessage::GetAttribute( - transport.c_str(), "source", &sourceHost)) { - sourceHost = mRTSPHost; - } - - AString serverPortStr; - if (!ParsedMessage::GetAttribute( - transport.c_str(), "server_port", &serverPortStr)) { - ALOGE("Missing 'server_port' in Transport field."); - return ERROR_MALFORMED; - } - - int rtpPort, rtcpPort; - if (sscanf(serverPortStr.c_str(), "%d-%d", &rtpPort, &rtcpPort) != 2 - || rtpPort <= 0 || rtpPort > 65535 - || rtcpPort <=0 || rtcpPort > 65535 - || rtcpPort != rtpPort + 1) { - ALOGE("Invalid server_port description '%s'.", - serverPortStr.c_str()); - - return ERROR_MALFORMED; - } - - if (rtpPort & 1) { - ALOGW("Server picked an odd numbered RTP port."); - } - - return mMediaReceiver->connectTrack( - 0 /* trackIndex */, sourceHost.c_str(), rtpPort, rtcpPort); -} - -status_t WifiDisplaySink::onReceivePlayResponse( - int32_t sessionID, const sp<ParsedMessage> &msg) { - int32_t statusCode; - if (!msg->getStatusCode(&statusCode)) { - return ERROR_MALFORMED; - } - - if (statusCode != 200) { - return ERROR_UNSUPPORTED; - } - - mState = PLAYING; - - (new AMessage(kWhatReportLateness, id()))->post(kReportLatenessEveryUs); - - return OK; -} - -status_t WifiDisplaySink::onReceiveIDRFrameRequestResponse( - int32_t sessionID, const sp<ParsedMessage> &msg) { - CHECK(mIDRFrameRequestPending); - mIDRFrameRequestPending = false; - - return OK; -} - -void WifiDisplaySink::onReceiveClientData(const sp<AMessage> &msg) { - int32_t sessionID; - CHECK(msg->findInt32("sessionID", &sessionID)); - - sp<RefBase> obj; - CHECK(msg->findObject("data", &obj)); - - sp<ParsedMessage> data = - static_cast<ParsedMessage *>(obj.get()); - - ALOGV("session %d received '%s'", - sessionID, data->debugString().c_str()); - - AString method; - AString uri; - data->getRequestField(0, &method); - - int32_t cseq; - if (!data->findInt32("cseq", &cseq)) { - sendErrorResponse(sessionID, "400 Bad Request", -1 /* cseq */); - return; - } - - if (method.startsWith("RTSP/")) { - // This is a response. - - ResponseID id; - id.mSessionID = sessionID; - id.mCSeq = cseq; - - ssize_t index = mResponseHandlers.indexOfKey(id); - - if (index < 0) { - ALOGW("Received unsolicited server response, cseq %d", cseq); - return; - } - - HandleRTSPResponseFunc func = mResponseHandlers.valueAt(index); - mResponseHandlers.removeItemsAt(index); - - status_t err = (this->*func)(sessionID, data); - CHECK_EQ(err, (status_t)OK); - } else { - AString version; - data->getRequestField(2, &version); - if (!(version == AString("RTSP/1.0"))) { - sendErrorResponse(sessionID, "505 RTSP Version not supported", cseq); - return; - } - - if (method == "OPTIONS") { - onOptionsRequest(sessionID, cseq, data); - } else if (method == "GET_PARAMETER") { - onGetParameterRequest(sessionID, cseq, data); - } else if (method == "SET_PARAMETER") { - onSetParameterRequest(sessionID, cseq, data); - } else { - sendErrorResponse(sessionID, "405 Method Not Allowed", cseq); - } - } -} - -void WifiDisplaySink::onOptionsRequest( - int32_t sessionID, - int32_t cseq, - const sp<ParsedMessage> &data) { - AString response = "RTSP/1.0 200 OK\r\n"; - AppendCommonResponse(&response, cseq); - response.append("Public: org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER\r\n"); - response.append("\r\n"); - - status_t err = mNetSession->sendRequest(sessionID, response.c_str()); - CHECK_EQ(err, (status_t)OK); - - err = sendM2(sessionID); - CHECK_EQ(err, (status_t)OK); -} - -void WifiDisplaySink::onGetParameterRequest( - int32_t sessionID, - int32_t cseq, - const sp<ParsedMessage> &data) { - AString body; - - if (mState == CONNECTED) { - mUsingTCPTransport = false; - mUsingTCPInterleaving = false; - - char val[PROPERTY_VALUE_MAX]; - if (property_get("media.wfd-sink.tcp-mode", val, NULL)) { - if (!strcasecmp("true", val) || !strcmp("1", val)) { - ALOGI("Using TCP unicast transport."); - mUsingTCPTransport = true; - mUsingTCPInterleaving = false; - } else if (!strcasecmp("interleaved", val)) { - ALOGI("Using TCP interleaved transport."); - mUsingTCPTransport = true; - mUsingTCPInterleaving = true; - } - } else if (mFlags & FLAG_SPECIAL_MODE) { - mUsingTCPTransport = true; - } - - body = "wfd_video_formats: "; - body.append(mSinkSupportedVideoFormats.getFormatSpec()); - - body.append( - "\r\nwfd_audio_codecs: AAC 0000000F 00\r\n" - "wfd_client_rtp_ports: RTP/AVP/"); - - if (mUsingTCPTransport) { - body.append("TCP;"); - if (mUsingTCPInterleaving) { - body.append("interleaved"); - } else { - body.append("unicast 19000 0"); - } - } else { - body.append("UDP;unicast 19000 0"); - } - - body.append(" mode=play\r\n"); - } - - AString response = "RTSP/1.0 200 OK\r\n"; - AppendCommonResponse(&response, cseq); - response.append("Content-Type: text/parameters\r\n"); - response.append(StringPrintf("Content-Length: %d\r\n", body.size())); - response.append("\r\n"); - response.append(body); - - status_t err = mNetSession->sendRequest(sessionID, response.c_str()); - CHECK_EQ(err, (status_t)OK); -} - -status_t WifiDisplaySink::sendSetup(int32_t sessionID, const char *uri) { - sp<AMessage> notify = new AMessage(kWhatMediaReceiverNotify, id()); - - mMediaReceiverLooper = new ALooper; - mMediaReceiverLooper->setName("media_receiver"); - - mMediaReceiverLooper->start( - false /* runOnCallingThread */, - false /* canCallJava */, - PRIORITY_AUDIO); - - mMediaReceiver = new MediaReceiver(mNetSession, notify); - mMediaReceiverLooper->registerHandler(mMediaReceiver); - - RTPReceiver::TransportMode rtpMode = RTPReceiver::TRANSPORT_UDP; - if (mUsingTCPTransport) { - if (mUsingTCPInterleaving) { - rtpMode = RTPReceiver::TRANSPORT_TCP_INTERLEAVED; - } else { - rtpMode = RTPReceiver::TRANSPORT_TCP; - } - } - - int32_t localRTPPort; - status_t err = mMediaReceiver->addTrack( - rtpMode, RTPReceiver::TRANSPORT_UDP /* rtcpMode */, &localRTPPort); - - if (err == OK) { - err = mMediaReceiver->initAsync(MediaReceiver::MODE_TRANSPORT_STREAM); - } - - if (err != OK) { - mMediaReceiverLooper->unregisterHandler(mMediaReceiver->id()); - mMediaReceiver.clear(); - - mMediaReceiverLooper->stop(); - mMediaReceiverLooper.clear(); - - return err; - } - - AString request = StringPrintf("SETUP %s RTSP/1.0\r\n", uri); - - AppendCommonResponse(&request, mNextCSeq); - - if (rtpMode == RTPReceiver::TRANSPORT_TCP_INTERLEAVED) { - request.append("Transport: RTP/AVP/TCP;interleaved=0-1\r\n"); - } else if (rtpMode == RTPReceiver::TRANSPORT_TCP) { - if (mFlags & FLAG_SPECIAL_MODE) { - // This isn't quite true, since the RTP connection is through TCP - // and the RTCP connection through UDP... - request.append( - StringPrintf( - "Transport: RTP/AVP/TCP;unicast;client_port=%d-%d\r\n", - localRTPPort, localRTPPort + 1)); - } else { - request.append( - StringPrintf( - "Transport: RTP/AVP/TCP;unicast;client_port=%d\r\n", - localRTPPort)); - } - } else { - request.append( - StringPrintf( - "Transport: RTP/AVP/UDP;unicast;client_port=%d-%d\r\n", - localRTPPort, - localRTPPort + 1)); - } - - request.append("\r\n"); - - ALOGV("request = '%s'", request.c_str()); - - err = mNetSession->sendRequest(sessionID, request.c_str(), request.size()); - - if (err != OK) { - return err; - } - - registerResponseHandler( - sessionID, mNextCSeq, &WifiDisplaySink::onReceiveSetupResponse); - - ++mNextCSeq; - - return OK; -} - -status_t WifiDisplaySink::sendPlay(int32_t sessionID, const char *uri) { - AString request = StringPrintf("PLAY %s RTSP/1.0\r\n", uri); - - AppendCommonResponse(&request, mNextCSeq); - - request.append(StringPrintf("Session: %s\r\n", mPlaybackSessionID.c_str())); - request.append("\r\n"); - - status_t err = - mNetSession->sendRequest(sessionID, request.c_str(), request.size()); - - if (err != OK) { - return err; - } - - registerResponseHandler( - sessionID, mNextCSeq, &WifiDisplaySink::onReceivePlayResponse); - - ++mNextCSeq; - - return OK; -} - -status_t WifiDisplaySink::sendIDRFrameRequest(int32_t sessionID) { - CHECK(!mIDRFrameRequestPending); - - AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; - - AppendCommonResponse(&request, mNextCSeq); - - AString content = "wfd_idr_request\r\n"; - - request.append(StringPrintf("Session: %s\r\n", mPlaybackSessionID.c_str())); - request.append(StringPrintf("Content-Length: %d\r\n", content.size())); - request.append("\r\n"); - request.append(content); - - status_t err = - mNetSession->sendRequest(sessionID, request.c_str(), request.size()); - - if (err != OK) { - return err; - } - - registerResponseHandler( - sessionID, - mNextCSeq, - &WifiDisplaySink::onReceiveIDRFrameRequestResponse); - - ++mNextCSeq; - - mIDRFrameRequestPending = true; - - return OK; -} - -void WifiDisplaySink::onSetParameterRequest( - int32_t sessionID, - int32_t cseq, - const sp<ParsedMessage> &data) { - const char *content = data->getContent(); - - if (strstr(content, "wfd_trigger_method: SETUP\r\n") != NULL) { - if ((mFlags & FLAG_SPECIAL_MODE) && !mTimeOffsetValid) { - mSetupDeferred = true; - } else { - status_t err = - sendSetup( - sessionID, - "rtsp://x.x.x.x:x/wfd1.0/streamid=0"); - - CHECK_EQ(err, (status_t)OK); - } - } - - AString response = "RTSP/1.0 200 OK\r\n"; - AppendCommonResponse(&response, cseq); - response.append("\r\n"); - - status_t err = mNetSession->sendRequest(sessionID, response.c_str()); - CHECK_EQ(err, (status_t)OK); -} - -void WifiDisplaySink::sendErrorResponse( - int32_t sessionID, - const char *errorDetail, - int32_t cseq) { - AString response; - response.append("RTSP/1.0 "); - response.append(errorDetail); - response.append("\r\n"); - - AppendCommonResponse(&response, cseq); - - response.append("\r\n"); - - status_t err = mNetSession->sendRequest(sessionID, response.c_str()); - CHECK_EQ(err, (status_t)OK); -} - -// static -void WifiDisplaySink::AppendCommonResponse(AString *response, int32_t cseq) { - time_t now = time(NULL); - struct tm *now2 = gmtime(&now); - char buf[128]; - strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z", now2); - - response->append("Date: "); - response->append(buf); - response->append("\r\n"); - - response->append(StringPrintf("User-Agent: %s\r\n", sUserAgent.c_str())); - - if (cseq >= 0) { - response->append(StringPrintf("CSeq: %d\r\n", cseq)); - } -} - -} // namespace android |