WifiDisplaySource.cpp revision 496238cc7551d414067dcbbb4fe3bd801f205f95
1/* 2 * Copyright 2012, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "WifiDisplaySource" 19#include <utils/Log.h> 20 21#include "WifiDisplaySource.h" 22#include "PlaybackSession.h" 23#include "ParsedMessage.h" 24 25#include <gui/ISurfaceTexture.h> 26 27#include <media/IRemoteDisplayClient.h> 28#include <media/stagefright/foundation/ABuffer.h> 29#include <media/stagefright/foundation/ADebug.h> 30#include <media/stagefright/foundation/AMessage.h> 31#include <media/stagefright/MediaErrors.h> 32 33#include <arpa/inet.h> 34#include <netinet/in.h> 35 36namespace android { 37 38WifiDisplaySource::WifiDisplaySource( 39 const sp<ANetworkSession> &netSession, 40 const sp<IRemoteDisplayClient> &client) 41 : mNetSession(netSession), 42 mClient(client), 43 mSessionID(0), 44 mReaperPending(false), 45 mNextCSeq(1) { 46} 47 48WifiDisplaySource::~WifiDisplaySource() { 49} 50 51status_t WifiDisplaySource::start(const char *iface) { 52 sp<AMessage> msg = new AMessage(kWhatStart, id()); 53 msg->setString("iface", iface); 54 55 sp<AMessage> response; 56 status_t err = msg->postAndAwaitResponse(&response); 57 58 if (err != OK) { 59 return err; 60 } 61 62 if (!response->findInt32("err", &err)) { 63 err = OK; 64 } 65 66 return err; 67} 68 69status_t WifiDisplaySource::stop() { 70 sp<AMessage> msg = new AMessage(kWhatStop, id()); 71 72 sp<AMessage> response; 73 status_t err = msg->postAndAwaitResponse(&response); 74 75 if (err != OK) { 76 return err; 77 } 78 79 if (!response->findInt32("err", &err)) { 80 err = OK; 81 } 82 83 return err; 84} 85 86void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) { 87 switch (msg->what()) { 88 case kWhatStart: 89 { 90 uint32_t replyID; 91 CHECK(msg->senderAwaitsResponse(&replyID)); 92 93 AString iface; 94 CHECK(msg->findString("iface", &iface)); 95 96 status_t err = OK; 97 98 ssize_t colonPos = iface.find(":"); 99 100 unsigned long port; 101 102 if (colonPos >= 0) { 103 const char *s = iface.c_str() + colonPos + 1; 104 105 char *end; 106 port = strtoul(s, &end, 10); 107 108 if (end == s || *end != '\0' || port > 65535) { 109 err = -EINVAL; 110 } else { 111 iface.erase(colonPos, iface.size() - colonPos); 112 } 113 } else { 114 port = kWifiDisplayDefaultPort; 115 } 116 117 struct in_addr addr; 118 119 if (err == OK) { 120 if (inet_aton(iface.c_str(), &addr) != 0) { 121 sp<AMessage> notify = new AMessage(kWhatRTSPNotify, id()); 122 123 err = mNetSession->createRTSPServer( 124 addr, port, notify, &mSessionID); 125 } else { 126 err = -EINVAL; 127 } 128 } 129 130 sp<AMessage> response = new AMessage; 131 response->setInt32("err", err); 132 response->postReply(replyID); 133 break; 134 } 135 136 case kWhatRTSPNotify: 137 { 138 int32_t reason; 139 CHECK(msg->findInt32("reason", &reason)); 140 141 switch (reason) { 142 case ANetworkSession::kWhatError: 143 { 144 int32_t sessionID; 145 CHECK(msg->findInt32("sessionID", &sessionID)); 146 147 int32_t err; 148 CHECK(msg->findInt32("err", &err)); 149 150 AString detail; 151 CHECK(msg->findString("detail", &detail)); 152 153 ALOGE("An error occurred in session %d (%d, '%s/%s').", 154 sessionID, 155 err, 156 detail.c_str(), 157 strerror(-err)); 158 159 mNetSession->destroySession(sessionID); 160 161 mClientInfos.removeItem(sessionID); 162 break; 163 } 164 165 case ANetworkSession::kWhatClientConnected: 166 { 167 int32_t sessionID; 168 CHECK(msg->findInt32("sessionID", &sessionID)); 169 170 ClientInfo info; 171 CHECK(msg->findString("client-ip", &info.mRemoteIP)); 172 CHECK(msg->findString("server-ip", &info.mLocalIP)); 173 CHECK(msg->findInt32("server-port", &info.mLocalPort)); 174 info.mPlaybackSessionID = -1; 175 176 ALOGI("We now have a client (%d) connected.", sessionID); 177 178 mClientInfos.add(sessionID, info); 179 180 status_t err = sendM1(sessionID); 181 CHECK_EQ(err, (status_t)OK); 182 break; 183 } 184 185 case ANetworkSession::kWhatData: 186 { 187 onReceiveClientData(msg); 188 break; 189 } 190 191 default: 192 TRESPASS(); 193 } 194 break; 195 } 196 197 case kWhatStop: 198 { 199 uint32_t replyID; 200 CHECK(msg->senderAwaitsResponse(&replyID)); 201 202 for (size_t i = mPlaybackSessions.size(); i-- > 0;) { 203 sp<PlaybackSession> playbackSession = 204 mPlaybackSessions.valueAt(i); 205 206 mPlaybackSessions.removeItemsAt(i); 207 208 playbackSession->destroy(); 209 looper()->unregisterHandler(playbackSession->id()); 210 playbackSession.clear(); 211 } 212 213 if (mClient != NULL) { 214 mClient->onDisplayDisconnected(); 215 } 216 217 status_t err = OK; 218 219 sp<AMessage> response = new AMessage; 220 response->setInt32("err", err); 221 response->postReply(replyID); 222 break; 223 } 224 225 case kWhatReapDeadClients: 226 { 227 mReaperPending = false; 228 229 for (size_t i = mPlaybackSessions.size(); i-- > 0;) { 230 const sp<PlaybackSession> &playbackSession = 231 mPlaybackSessions.valueAt(i); 232 233 if (playbackSession->getLastLifesignUs() 234 + kPlaybackSessionTimeoutUs < ALooper::GetNowUs()) { 235 ALOGI("playback session %d timed out, reaping.", 236 mPlaybackSessions.keyAt(i)); 237 238 looper()->unregisterHandler(playbackSession->id()); 239 mPlaybackSessions.removeItemsAt(i); 240 } 241 } 242 243 if (!mPlaybackSessions.isEmpty()) { 244 scheduleReaper(); 245 } 246 break; 247 } 248 249 case kWhatPlaybackSessionNotify: 250 { 251 int32_t playbackSessionID; 252 CHECK(msg->findInt32("playbackSessionID", &playbackSessionID)); 253 254 int32_t what; 255 CHECK(msg->findInt32("what", &what)); 256 257 ssize_t index = mPlaybackSessions.indexOfKey(playbackSessionID); 258 if (index >= 0) { 259 const sp<PlaybackSession> &playbackSession = 260 mPlaybackSessions.valueAt(index); 261 262 if (what == PlaybackSession::kWhatSessionDead) { 263 ALOGI("playback sessions %d wants to quit.", 264 playbackSessionID); 265 266 looper()->unregisterHandler(playbackSession->id()); 267 mPlaybackSessions.removeItemsAt(index); 268 } else { 269 CHECK_EQ(what, PlaybackSession::kWhatBinaryData); 270 271 int32_t channel; 272 CHECK(msg->findInt32("channel", &channel)); 273 274 sp<ABuffer> data; 275 CHECK(msg->findBuffer("data", &data)); 276 277 CHECK_LE(channel, 0xffu); 278 CHECK_LE(data->size(), 0xffffu); 279 280 int32_t sessionID; 281 CHECK(msg->findInt32("sessionID", &sessionID)); 282 283 char header[4]; 284 header[0] = '$'; 285 header[1] = channel; 286 header[2] = data->size() >> 8; 287 header[3] = data->size() & 0xff; 288 289 mNetSession->sendRequest( 290 sessionID, header, sizeof(header)); 291 292 mNetSession->sendRequest( 293 sessionID, data->data(), data->size()); 294 } 295 } 296 break; 297 } 298 299 case kWhatKeepAlive: 300 { 301 int32_t sessionID; 302 CHECK(msg->findInt32("sessionID", &sessionID)); 303 304 if (mClientInfos.indexOfKey(sessionID) < 0) { 305 // Obsolete event, client is already gone. 306 break; 307 } 308 309 sendM16(sessionID); 310 break; 311 } 312 313 default: 314 TRESPASS(); 315 } 316} 317 318void WifiDisplaySource::registerResponseHandler( 319 int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func) { 320 ResponseID id; 321 id.mSessionID = sessionID; 322 id.mCSeq = cseq; 323 mResponseHandlers.add(id, func); 324} 325 326status_t WifiDisplaySource::sendM1(int32_t sessionID) { 327 AString request = "OPTIONS * RTSP/1.0\r\n"; 328 AppendCommonResponse(&request, mNextCSeq); 329 330 request.append( 331 "Require: org.wfa.wfd1.0\r\n" 332 "\r\n"); 333 334 status_t err = 335 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 336 337 if (err != OK) { 338 return err; 339 } 340 341 registerResponseHandler( 342 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM1Response); 343 344 ++mNextCSeq; 345 346 return OK; 347} 348 349status_t WifiDisplaySource::sendM3(int32_t sessionID) { 350 AString body = 351 "wfd_video_formats\r\n" 352 "wfd_audio_codecs\r\n" 353 "wfd_client_rtp_ports\r\n"; 354 355 AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 356 AppendCommonResponse(&request, mNextCSeq); 357 358 request.append("Content-Type: text/parameters\r\n"); 359 request.append(StringPrintf("Content-Length: %d\r\n", body.size())); 360 request.append("\r\n"); 361 request.append(body); 362 363 status_t err = 364 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 365 366 if (err != OK) { 367 return err; 368 } 369 370 registerResponseHandler( 371 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM3Response); 372 373 ++mNextCSeq; 374 375 return OK; 376} 377 378status_t WifiDisplaySource::sendM4(int32_t sessionID) { 379 // wfd_video_formats: 380 // 1 byte "native" 381 // 1 byte "preferred-display-mode-supported" 0 or 1 382 // one or more avc codec structures 383 // 1 byte profile 384 // 1 byte level 385 // 4 byte CEA mask 386 // 4 byte VESA mask 387 // 4 byte HH mask 388 // 1 byte latency 389 // 2 byte min-slice-slice 390 // 2 byte slice-enc-params 391 // 1 byte framerate-control-support 392 // max-hres (none or 2 byte) 393 // max-vres (none or 2 byte) 394 395 const ClientInfo &info = mClientInfos.valueFor(sessionID); 396 397 AString body = StringPrintf( 398 "wfd_video_formats: " 399 "30 00 02 02 00000040 00000000 00000000 00 0000 0000 00 none none\r\n" 400 "wfd_audio_codecs: AAC 00000001 00\r\n" // 2 ch AAC 48kHz 401 "wfd_presentation_URL: rtsp://%s:%d/wfd1.0/streamid=0 none\r\n" 402 "wfd_client_rtp_ports: RTP/AVP/UDP;unicast 19000 0 mode=play\r\n", 403 info.mLocalIP.c_str(), info.mLocalPort); 404 405 AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 406 AppendCommonResponse(&request, mNextCSeq); 407 408 request.append("Content-Type: text/parameters\r\n"); 409 request.append(StringPrintf("Content-Length: %d\r\n", body.size())); 410 request.append("\r\n"); 411 request.append(body); 412 413 status_t err = 414 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 415 416 if (err != OK) { 417 return err; 418 } 419 420 registerResponseHandler( 421 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM4Response); 422 423 ++mNextCSeq; 424 425 return OK; 426} 427 428status_t WifiDisplaySource::sendM5(int32_t sessionID) { 429 AString body = "wfd_trigger_method: SETUP\r\n"; 430 431 AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 432 AppendCommonResponse(&request, mNextCSeq); 433 434 request.append("Content-Type: text/parameters\r\n"); 435 request.append(StringPrintf("Content-Length: %d\r\n", body.size())); 436 request.append("\r\n"); 437 request.append(body); 438 439 status_t err = 440 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 441 442 if (err != OK) { 443 return err; 444 } 445 446 registerResponseHandler( 447 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM5Response); 448 449 ++mNextCSeq; 450 451 return OK; 452} 453 454status_t WifiDisplaySource::sendM16(int32_t sessionID) { 455 AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 456 AppendCommonResponse(&request, mNextCSeq); 457 458 const ClientInfo &info = mClientInfos.valueFor(sessionID); 459 request.append(StringPrintf("Session: %d\r\n", info.mPlaybackSessionID)); 460 request.append("\r\n"); // Empty body 461 462 status_t err = 463 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 464 465 if (err != OK) { 466 return err; 467 } 468 469 registerResponseHandler( 470 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM16Response); 471 472 ++mNextCSeq; 473 474 return OK; 475} 476 477status_t WifiDisplaySource::onReceiveM1Response( 478 int32_t sessionID, const sp<ParsedMessage> &msg) { 479 int32_t statusCode; 480 if (!msg->getStatusCode(&statusCode)) { 481 return ERROR_MALFORMED; 482 } 483 484 if (statusCode != 200) { 485 return ERROR_UNSUPPORTED; 486 } 487 488 return OK; 489} 490 491status_t WifiDisplaySource::onReceiveM3Response( 492 int32_t sessionID, const sp<ParsedMessage> &msg) { 493 int32_t statusCode; 494 if (!msg->getStatusCode(&statusCode)) { 495 return ERROR_MALFORMED; 496 } 497 498 if (statusCode != 200) { 499 return ERROR_UNSUPPORTED; 500 } 501 502 return sendM4(sessionID); 503} 504 505status_t WifiDisplaySource::onReceiveM4Response( 506 int32_t sessionID, const sp<ParsedMessage> &msg) { 507 int32_t statusCode; 508 if (!msg->getStatusCode(&statusCode)) { 509 return ERROR_MALFORMED; 510 } 511 512 if (statusCode != 200) { 513 return ERROR_UNSUPPORTED; 514 } 515 516 return sendM5(sessionID); 517} 518 519status_t WifiDisplaySource::onReceiveM5Response( 520 int32_t sessionID, const sp<ParsedMessage> &msg) { 521 int32_t statusCode; 522 if (!msg->getStatusCode(&statusCode)) { 523 return ERROR_MALFORMED; 524 } 525 526 if (statusCode != 200) { 527 return ERROR_UNSUPPORTED; 528 } 529 530 return OK; 531} 532 533status_t WifiDisplaySource::onReceiveM16Response( 534 int32_t sessionID, const sp<ParsedMessage> &msg) { 535 // If only the response was required to include a "Session:" header... 536 537 const ClientInfo &info = mClientInfos.valueFor(sessionID); 538 539 ssize_t index = mPlaybackSessions.indexOfKey(info.mPlaybackSessionID); 540 if (index >= 0) { 541 mPlaybackSessions.valueAt(index)->updateLiveness(); 542 543 scheduleKeepAlive(sessionID); 544 } 545 546 return OK; 547} 548 549void WifiDisplaySource::scheduleReaper() { 550 if (mReaperPending) { 551 return; 552 } 553 554 mReaperPending = true; 555 (new AMessage(kWhatReapDeadClients, id()))->post(kReaperIntervalUs); 556} 557 558void WifiDisplaySource::scheduleKeepAlive(int32_t sessionID) { 559 // We need to send updates at least 5 secs before the timeout is set to 560 // expire, make sure the timeout is greater than 5 secs to begin with. 561 CHECK_GT(kPlaybackSessionTimeoutUs, 5000000ll); 562 563 sp<AMessage> msg = new AMessage(kWhatKeepAlive, id()); 564 msg->setInt32("sessionID", sessionID); 565 msg->post(kPlaybackSessionTimeoutUs - 5000000ll); 566} 567 568void WifiDisplaySource::onReceiveClientData(const sp<AMessage> &msg) { 569 int32_t sessionID; 570 CHECK(msg->findInt32("sessionID", &sessionID)); 571 572 sp<RefBase> obj; 573 CHECK(msg->findObject("data", &obj)); 574 575 sp<ParsedMessage> data = 576 static_cast<ParsedMessage *>(obj.get()); 577 578 ALOGV("session %d received '%s'", 579 sessionID, data->debugString().c_str()); 580 581 AString method; 582 AString uri; 583 data->getRequestField(0, &method); 584 585 int32_t cseq; 586 if (!data->findInt32("cseq", &cseq)) { 587 sendErrorResponse(sessionID, "400 Bad Request", -1 /* cseq */); 588 return; 589 } 590 591 if (method.startsWith("RTSP/")) { 592 // This is a response. 593 594 ResponseID id; 595 id.mSessionID = sessionID; 596 id.mCSeq = cseq; 597 598 ssize_t index = mResponseHandlers.indexOfKey(id); 599 600 if (index < 0) { 601 ALOGW("Received unsolicited server response, cseq %d", cseq); 602 return; 603 } 604 605 HandleRTSPResponseFunc func = mResponseHandlers.valueAt(index); 606 mResponseHandlers.removeItemsAt(index); 607 608 status_t err = (this->*func)(sessionID, data); 609 610 if (err != OK) { 611 ALOGW("Response handler for session %d, cseq %d returned " 612 "err %d (%s)", 613 sessionID, cseq, err, strerror(-err)); 614 } 615 } else { 616 AString version; 617 data->getRequestField(2, &version); 618 if (!(version == AString("RTSP/1.0"))) { 619 sendErrorResponse(sessionID, "505 RTSP Version not supported", cseq); 620 return; 621 } 622 623 if (method == "DESCRIBE") { 624 onDescribeRequest(sessionID, cseq, data); 625 } else if (method == "OPTIONS") { 626 onOptionsRequest(sessionID, cseq, data); 627 } else if (method == "SETUP") { 628 onSetupRequest(sessionID, cseq, data); 629 } else if (method == "PLAY") { 630 onPlayRequest(sessionID, cseq, data); 631 } else if (method == "PAUSE") { 632 onPauseRequest(sessionID, cseq, data); 633 } else if (method == "TEARDOWN") { 634 onTeardownRequest(sessionID, cseq, data); 635 } else if (method == "GET_PARAMETER") { 636 onGetParameterRequest(sessionID, cseq, data); 637 } else if (method == "SET_PARAMETER") { 638 onSetParameterRequest(sessionID, cseq, data); 639 } else { 640 sendErrorResponse(sessionID, "405 Method Not Allowed", cseq); 641 } 642 } 643} 644 645void WifiDisplaySource::onDescribeRequest( 646 int32_t sessionID, 647 int32_t cseq, 648 const sp<ParsedMessage> &data) { 649 int64_t nowUs = ALooper::GetNowUs(); 650 651 AString sdp; 652 sdp.append("v=0\r\n"); 653 654 sdp.append(StringPrintf( 655 "o=- %lld %lld IN IP4 0.0.0.0\r\n", nowUs, nowUs)); 656 657 sdp.append( 658 "o=- 0 0 IN IP4 127.0.0.0\r\n" 659 "s=Sample\r\n" 660 "c=IN IP4 0.0.0.0\r\n" 661 "b=AS:502\r\n" 662 "t=0 0\r\n" 663 "a=control:*\r\n" 664 "a=range:npt=now-\r\n" 665 "m=video 0 RTP/AVP 33\r\n" 666 "a=rtpmap:33 MP2T/90000\r\n" 667 "a=control:\r\n"); 668 669 AString response = "RTSP/1.0 200 OK\r\n"; 670 AppendCommonResponse(&response, cseq); 671 672 response.append("Content-Type: application/sdp\r\n"); 673 674 // response.append("Content-Base: rtsp://0.0.0.0:7236\r\n"); 675 response.append(StringPrintf("Content-Length: %d\r\n", sdp.size())); 676 response.append("\r\n"); 677 response.append(sdp); 678 679 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 680 CHECK_EQ(err, (status_t)OK); 681} 682 683void WifiDisplaySource::onOptionsRequest( 684 int32_t sessionID, 685 int32_t cseq, 686 const sp<ParsedMessage> &data) { 687 int32_t playbackSessionID; 688 sp<PlaybackSession> playbackSession = 689 findPlaybackSession(data, &playbackSessionID); 690 691 if (playbackSession != NULL) { 692 playbackSession->updateLiveness(); 693 } 694 695 AString response = "RTSP/1.0 200 OK\r\n"; 696 AppendCommonResponse(&response, cseq); 697 698 response.append( 699 "Public: org.wfa.wfd1.0, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, " 700 "GET_PARAMETER, SET_PARAMETER\r\n"); 701 702 response.append("\r\n"); 703 704 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 705 CHECK_EQ(err, (status_t)OK); 706 707 err = sendM3(sessionID); 708 CHECK_EQ(err, (status_t)OK); 709} 710 711void WifiDisplaySource::onSetupRequest( 712 int32_t sessionID, 713 int32_t cseq, 714 const sp<ParsedMessage> &data) { 715 ClientInfo *info = &mClientInfos.editValueFor(sessionID); 716 if (info->mPlaybackSessionID != -1) { 717 // We only support a single playback session per client. 718 // This is due to the reversed keep-alive design in the wfd specs... 719 sendErrorResponse(sessionID, "400 Bad Request", cseq); 720 return; 721 } 722 723 AString transport; 724 if (!data->findString("transport", &transport)) { 725 sendErrorResponse(sessionID, "400 Bad Request", cseq); 726 return; 727 } 728 729 bool useInterleavedTCP = false; 730 731 int clientRtp, clientRtcp; 732 if (transport.startsWith("RTP/AVP/TCP;")) { 733 AString interleaved; 734 if (!ParsedMessage::GetAttribute( 735 transport.c_str(), "interleaved", &interleaved) 736 || sscanf(interleaved.c_str(), "%d-%d", 737 &clientRtp, &clientRtcp) != 2) { 738 sendErrorResponse(sessionID, "400 Bad Request", cseq); 739 return; 740 } 741 742 useInterleavedTCP = true; 743 } else if (transport.startsWith("RTP/AVP;unicast;") 744 || transport.startsWith("RTP/AVP/UDP;unicast;")) { 745 bool badRequest = false; 746 747 AString clientPort; 748 if (!ParsedMessage::GetAttribute( 749 transport.c_str(), "client_port", &clientPort)) { 750 badRequest = true; 751 } else if (sscanf(clientPort.c_str(), "%d-%d", 752 &clientRtp, &clientRtcp) == 2) { 753 } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) { 754 // No RTCP. 755 clientRtcp = -1; 756 } else { 757 badRequest = true; 758 } 759 760 if (badRequest) { 761 sendErrorResponse(sessionID, "400 Bad Request", cseq); 762 return; 763 } 764#if 1 765 // The older LG dongles doesn't specify client_port=xxx apparently. 766 } else if (transport == "RTP/AVP/UDP;unicast") { 767 clientRtp = 19000; 768 clientRtcp = clientRtp + 1; 769#endif 770 } else { 771 sendErrorResponse(sessionID, "461 Unsupported Transport", cseq); 772 return; 773 } 774 775 int32_t playbackSessionID = makeUniquePlaybackSessionID(); 776 777 sp<AMessage> notify = new AMessage(kWhatPlaybackSessionNotify, id()); 778 notify->setInt32("playbackSessionID", playbackSessionID); 779 notify->setInt32("sessionID", sessionID); 780 781 sp<PlaybackSession> playbackSession = 782 new PlaybackSession( 783 mNetSession, notify, mClient == NULL /* legacyMode */); 784 785 looper()->registerHandler(playbackSession); 786 787 AString uri; 788 data->getRequestField(1, &uri); 789 790 if (strncasecmp("rtsp://", uri.c_str(), 7)) { 791 sendErrorResponse(sessionID, "400 Bad Request", cseq); 792 return; 793 } 794 795 if (!(uri.startsWith("rtsp://") && uri.endsWith("/wfd1.0/streamid=0"))) { 796 sendErrorResponse(sessionID, "404 Not found", cseq); 797 return; 798 } 799 800 status_t err = playbackSession->init( 801 info->mRemoteIP.c_str(), 802 clientRtp, 803 clientRtcp, 804 useInterleavedTCP); 805 806 if (err != OK) { 807 looper()->unregisterHandler(playbackSession->id()); 808 playbackSession.clear(); 809 } 810 811 switch (err) { 812 case OK: 813 break; 814 case -ENOENT: 815 sendErrorResponse(sessionID, "404 Not Found", cseq); 816 return; 817 default: 818 sendErrorResponse(sessionID, "403 Forbidden", cseq); 819 return; 820 } 821 822 mPlaybackSessions.add(playbackSessionID, playbackSession); 823 824 info->mPlaybackSessionID = playbackSessionID; 825 826 AString response = "RTSP/1.0 200 OK\r\n"; 827 AppendCommonResponse(&response, cseq, playbackSessionID); 828 829 if (useInterleavedTCP) { 830 response.append( 831 StringPrintf( 832 "Transport: RTP/AVP/TCP;interleaved=%d-%d;", 833 clientRtp, clientRtcp)); 834 } else { 835 int32_t serverRtp = playbackSession->getRTPPort(); 836 837 if (clientRtcp >= 0) { 838 response.append( 839 StringPrintf( 840 "Transport: RTP/AVP;unicast;client_port=%d-%d;" 841 "server_port=%d-%d\r\n", 842 clientRtp, clientRtcp, serverRtp, serverRtp + 1)); 843 } else { 844 response.append( 845 StringPrintf( 846 "Transport: RTP/AVP;unicast;client_port=%d;" 847 "server_port=%d\r\n", 848 clientRtp, serverRtp)); 849 } 850 } 851 852 response.append("\r\n"); 853 854 err = mNetSession->sendRequest(sessionID, response.c_str()); 855 CHECK_EQ(err, (status_t)OK); 856 857 scheduleReaper(); 858 scheduleKeepAlive(sessionID); 859} 860 861void WifiDisplaySource::onPlayRequest( 862 int32_t sessionID, 863 int32_t cseq, 864 const sp<ParsedMessage> &data) { 865 int32_t playbackSessionID; 866 sp<PlaybackSession> playbackSession = 867 findPlaybackSession(data, &playbackSessionID); 868 869 if (playbackSession == NULL) { 870 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 871 return; 872 } 873 874 status_t err = playbackSession->play(); 875 CHECK_EQ(err, (status_t)OK); 876 877 AString response = "RTSP/1.0 200 OK\r\n"; 878 AppendCommonResponse(&response, cseq, playbackSessionID); 879 response.append("Range: npt=now-\r\n"); 880 response.append("\r\n"); 881 882 err = mNetSession->sendRequest(sessionID, response.c_str()); 883 CHECK_EQ(err, (status_t)OK); 884 885 if (mClient != NULL) { 886 mClient->onDisplayConnected( 887 playbackSession->getSurfaceTexture(), 888 playbackSession->width(), 889 playbackSession->height(), 890 0 /* flags */); 891 } 892} 893 894void WifiDisplaySource::onPauseRequest( 895 int32_t sessionID, 896 int32_t cseq, 897 const sp<ParsedMessage> &data) { 898 int32_t playbackSessionID; 899 sp<PlaybackSession> playbackSession = 900 findPlaybackSession(data, &playbackSessionID); 901 902 if (playbackSession == NULL) { 903 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 904 return; 905 } 906 907 status_t err = playbackSession->pause(); 908 CHECK_EQ(err, (status_t)OK); 909 910 AString response = "RTSP/1.0 200 OK\r\n"; 911 AppendCommonResponse(&response, cseq, playbackSessionID); 912 response.append("\r\n"); 913 914 err = mNetSession->sendRequest(sessionID, response.c_str()); 915 CHECK_EQ(err, (status_t)OK); 916} 917 918void WifiDisplaySource::onTeardownRequest( 919 int32_t sessionID, 920 int32_t cseq, 921 const sp<ParsedMessage> &data) { 922 int32_t playbackSessionID; 923 sp<PlaybackSession> playbackSession = 924 findPlaybackSession(data, &playbackSessionID); 925 926 if (playbackSession == NULL) { 927 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 928 return; 929 } 930 931 looper()->unregisterHandler(playbackSession->id()); 932 mPlaybackSessions.removeItem(playbackSessionID); 933 934 AString response = "RTSP/1.0 200 OK\r\n"; 935 AppendCommonResponse(&response, cseq, playbackSessionID); 936 response.append("\r\n"); 937 938 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 939 CHECK_EQ(err, (status_t)OK); 940} 941 942void WifiDisplaySource::onGetParameterRequest( 943 int32_t sessionID, 944 int32_t cseq, 945 const sp<ParsedMessage> &data) { 946 int32_t playbackSessionID; 947 sp<PlaybackSession> playbackSession = 948 findPlaybackSession(data, &playbackSessionID); 949 950 if (playbackSession == NULL) { 951 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 952 return; 953 } 954 955 playbackSession->updateLiveness(); 956 957 AString response = "RTSP/1.0 200 OK\r\n"; 958 AppendCommonResponse(&response, cseq, playbackSessionID); 959 response.append("\r\n"); 960 961 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 962 CHECK_EQ(err, (status_t)OK); 963} 964 965void WifiDisplaySource::onSetParameterRequest( 966 int32_t sessionID, 967 int32_t cseq, 968 const sp<ParsedMessage> &data) { 969 int32_t playbackSessionID; 970 sp<PlaybackSession> playbackSession = 971 findPlaybackSession(data, &playbackSessionID); 972 973#if 1 974 // XXX the older dongles do not include a "Session:" header in this request. 975 if (playbackSession == NULL) { 976 CHECK_EQ(mPlaybackSessions.size(), 1u); 977 playbackSessionID = mPlaybackSessions.keyAt(0); 978 playbackSession = mPlaybackSessions.valueAt(0); 979 } 980#else 981 if (playbackSession == NULL) { 982 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 983 return; 984 } 985#endif 986 987 // XXX check that the parameter is about that. 988 playbackSession->requestIDRFrame(); 989 990 playbackSession->updateLiveness(); 991 992 AString response = "RTSP/1.0 200 OK\r\n"; 993 AppendCommonResponse(&response, cseq, playbackSessionID); 994 response.append("\r\n"); 995 996 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 997 CHECK_EQ(err, (status_t)OK); 998} 999 1000// static 1001void WifiDisplaySource::AppendCommonResponse( 1002 AString *response, int32_t cseq, int32_t playbackSessionID) { 1003 time_t now = time(NULL); 1004 struct tm *now2 = gmtime(&now); 1005 char buf[128]; 1006 strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z", now2); 1007 1008 response->append("Date: "); 1009 response->append(buf); 1010 response->append("\r\n"); 1011 1012 response->append("Server: Mine/1.0\r\n"); 1013 1014 if (cseq >= 0) { 1015 response->append(StringPrintf("CSeq: %d\r\n", cseq)); 1016 } 1017 1018 if (playbackSessionID >= 0ll) { 1019 response->append( 1020 StringPrintf( 1021 "Session: %d;timeout=%lld\r\n", 1022 playbackSessionID, kPlaybackSessionTimeoutSecs)); 1023 } 1024} 1025 1026void WifiDisplaySource::sendErrorResponse( 1027 int32_t sessionID, 1028 const char *errorDetail, 1029 int32_t cseq) { 1030 AString response; 1031 response.append("RTSP/1.0 "); 1032 response.append(errorDetail); 1033 response.append("\r\n"); 1034 1035 AppendCommonResponse(&response, cseq); 1036 1037 response.append("\r\n"); 1038 1039 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 1040 CHECK_EQ(err, (status_t)OK); 1041} 1042 1043int32_t WifiDisplaySource::makeUniquePlaybackSessionID() const { 1044 for (;;) { 1045 int32_t playbackSessionID = rand(); 1046 1047 if (playbackSessionID == -1) { 1048 // reserved. 1049 continue; 1050 } 1051 1052 for (size_t i = 0; i < mPlaybackSessions.size(); ++i) { 1053 if (mPlaybackSessions.keyAt(i) == playbackSessionID) { 1054 continue; 1055 } 1056 } 1057 1058 return playbackSessionID; 1059 } 1060} 1061 1062sp<WifiDisplaySource::PlaybackSession> WifiDisplaySource::findPlaybackSession( 1063 const sp<ParsedMessage> &data, int32_t *playbackSessionID) const { 1064 if (!data->findInt32("session", playbackSessionID)) { 1065 *playbackSessionID = 0; 1066 return NULL; 1067 } 1068 1069 ssize_t index = mPlaybackSessions.indexOfKey(*playbackSessionID); 1070 if (index < 0) { 1071 return NULL; 1072 } 1073 1074 return mPlaybackSessions.valueAt(index); 1075} 1076 1077} // namespace android 1078 1079