WifiDisplaySource.cpp revision 72f6aea5afba3ff8ab7e8eab49552d65ee3bb97b
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 const sp<PlaybackSession> &playbackSession = 204 mPlaybackSessions.valueAt(i); 205 206 looper()->unregisterHandler(playbackSession->id()); 207 mPlaybackSessions.removeItemsAt(i); 208 } 209 210 if (mClient != NULL) { 211 mClient->onDisplayDisconnected(); 212 } 213 214 status_t err = OK; 215 216 sp<AMessage> response = new AMessage; 217 response->setInt32("err", err); 218 response->postReply(replyID); 219 break; 220 } 221 222 case kWhatReapDeadClients: 223 { 224 mReaperPending = false; 225 226 for (size_t i = mPlaybackSessions.size(); i-- > 0;) { 227 const sp<PlaybackSession> &playbackSession = 228 mPlaybackSessions.valueAt(i); 229 230 if (playbackSession->getLastLifesignUs() 231 + kPlaybackSessionTimeoutUs < ALooper::GetNowUs()) { 232 ALOGI("playback session %d timed out, reaping.", 233 mPlaybackSessions.keyAt(i)); 234 235 looper()->unregisterHandler(playbackSession->id()); 236 mPlaybackSessions.removeItemsAt(i); 237 } 238 } 239 240 if (!mPlaybackSessions.isEmpty()) { 241 scheduleReaper(); 242 } 243 break; 244 } 245 246 case kWhatPlaybackSessionNotify: 247 { 248 int32_t playbackSessionID; 249 CHECK(msg->findInt32("playbackSessionID", &playbackSessionID)); 250 251 int32_t what; 252 CHECK(msg->findInt32("what", &what)); 253 254 ssize_t index = mPlaybackSessions.indexOfKey(playbackSessionID); 255 if (index >= 0) { 256 const sp<PlaybackSession> &playbackSession = 257 mPlaybackSessions.valueAt(index); 258 259 if (what == PlaybackSession::kWhatSessionDead) { 260 ALOGI("playback sessions %d wants to quit.", 261 playbackSessionID); 262 263 looper()->unregisterHandler(playbackSession->id()); 264 mPlaybackSessions.removeItemsAt(index); 265 } else { 266 CHECK_EQ(what, PlaybackSession::kWhatBinaryData); 267 268 int32_t channel; 269 CHECK(msg->findInt32("channel", &channel)); 270 271 sp<ABuffer> data; 272 CHECK(msg->findBuffer("data", &data)); 273 274 CHECK_LE(channel, 0xffu); 275 CHECK_LE(data->size(), 0xffffu); 276 277 int32_t sessionID; 278 CHECK(msg->findInt32("sessionID", &sessionID)); 279 280 char header[4]; 281 header[0] = '$'; 282 header[1] = channel; 283 header[2] = data->size() >> 8; 284 header[3] = data->size() & 0xff; 285 286 mNetSession->sendRequest( 287 sessionID, header, sizeof(header)); 288 289 mNetSession->sendRequest( 290 sessionID, data->data(), data->size()); 291 } 292 } 293 break; 294 } 295 296 case kWhatKeepAlive: 297 { 298 int32_t sessionID; 299 CHECK(msg->findInt32("sessionID", &sessionID)); 300 301 if (mClientInfos.indexOfKey(sessionID) < 0) { 302 // Obsolete event, client is already gone. 303 break; 304 } 305 306 sendM16(sessionID); 307 break; 308 } 309 310 default: 311 TRESPASS(); 312 } 313} 314 315void WifiDisplaySource::registerResponseHandler( 316 int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func) { 317 ResponseID id; 318 id.mSessionID = sessionID; 319 id.mCSeq = cseq; 320 mResponseHandlers.add(id, func); 321} 322 323status_t WifiDisplaySource::sendM1(int32_t sessionID) { 324 AString request = "OPTIONS * RTSP/1.0\r\n"; 325 AppendCommonResponse(&request, mNextCSeq); 326 327 request.append( 328 "Require: org.wfa.wfd1.0\r\n" 329 "\r\n"); 330 331 status_t err = 332 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 333 334 if (err != OK) { 335 return err; 336 } 337 338 registerResponseHandler( 339 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM1Response); 340 341 ++mNextCSeq; 342 343 return OK; 344} 345 346status_t WifiDisplaySource::sendM3(int32_t sessionID) { 347 AString body = 348 "wfd_video_formats\r\n" 349 "wfd_audio_codecs\r\n" 350 "wfd_client_rtp_ports\r\n"; 351 352 AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 353 AppendCommonResponse(&request, mNextCSeq); 354 355 request.append("Content-Type: text/parameters\r\n"); 356 request.append(StringPrintf("Content-Length: %d\r\n", body.size())); 357 request.append("\r\n"); 358 request.append(body); 359 360 status_t err = 361 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 362 363 if (err != OK) { 364 return err; 365 } 366 367 registerResponseHandler( 368 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM3Response); 369 370 ++mNextCSeq; 371 372 return OK; 373} 374 375status_t WifiDisplaySource::sendM4(int32_t sessionID) { 376 // wfd_video_formats: 377 // 1 byte "native" 378 // 1 byte "preferred-display-mode-supported" 0 or 1 379 // one or more avc codec structures 380 // 1 byte profile 381 // 1 byte level 382 // 4 byte CEA mask 383 // 4 byte VESA mask 384 // 4 byte HH mask 385 // 1 byte latency 386 // 2 byte min-slice-slice 387 // 2 byte slice-enc-params 388 // 1 byte framerate-control-support 389 // max-hres (none or 2 byte) 390 // max-vres (none or 2 byte) 391 392 const ClientInfo &info = mClientInfos.valueFor(sessionID); 393 394 AString body = StringPrintf( 395 "wfd_video_formats: " 396 "30 00 02 02 00000040 00000000 00000000 00 0000 0000 00 none none\r\n" 397 "wfd_audio_codecs: AAC 00000001 00\r\n" // 2 ch AAC 48kHz 398 "wfd_presentation_URL: rtsp://%s:%d/wfd1.0/streamid=0 none\r\n" 399 "wfd_client_rtp_ports: RTP/AVP/UDP;unicast 19000 0 mode=play\r\n", 400 info.mLocalIP.c_str(), info.mLocalPort); 401 402 AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 403 AppendCommonResponse(&request, mNextCSeq); 404 405 request.append("Content-Type: text/parameters\r\n"); 406 request.append(StringPrintf("Content-Length: %d\r\n", body.size())); 407 request.append("\r\n"); 408 request.append(body); 409 410 status_t err = 411 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 412 413 if (err != OK) { 414 return err; 415 } 416 417 registerResponseHandler( 418 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM4Response); 419 420 ++mNextCSeq; 421 422 return OK; 423} 424 425status_t WifiDisplaySource::sendM5(int32_t sessionID) { 426 AString body = "wfd_trigger_method: SETUP\r\n"; 427 428 AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 429 AppendCommonResponse(&request, mNextCSeq); 430 431 request.append("Content-Type: text/parameters\r\n"); 432 request.append(StringPrintf("Content-Length: %d\r\n", body.size())); 433 request.append("\r\n"); 434 request.append(body); 435 436 status_t err = 437 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 438 439 if (err != OK) { 440 return err; 441 } 442 443 registerResponseHandler( 444 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM5Response); 445 446 ++mNextCSeq; 447 448 return OK; 449} 450 451status_t WifiDisplaySource::sendM16(int32_t sessionID) { 452 AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 453 AppendCommonResponse(&request, mNextCSeq); 454 455 const ClientInfo &info = mClientInfos.valueFor(sessionID); 456 request.append(StringPrintf("Session: %d\r\n", info.mPlaybackSessionID)); 457 458 request.append("Content-Length: 0\r\n"); 459 request.append("\r\n"); 460 461 status_t err = 462 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 463 464 if (err != OK) { 465 return err; 466 } 467 468 registerResponseHandler( 469 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM16Response); 470 471 ++mNextCSeq; 472 473 return OK; 474} 475 476status_t WifiDisplaySource::onReceiveM1Response( 477 int32_t sessionID, const sp<ParsedMessage> &msg) { 478 int32_t statusCode; 479 if (!msg->getStatusCode(&statusCode)) { 480 return ERROR_MALFORMED; 481 } 482 483 if (statusCode != 200) { 484 return ERROR_UNSUPPORTED; 485 } 486 487 return OK; 488} 489 490status_t WifiDisplaySource::onReceiveM3Response( 491 int32_t sessionID, const sp<ParsedMessage> &msg) { 492 int32_t statusCode; 493 if (!msg->getStatusCode(&statusCode)) { 494 return ERROR_MALFORMED; 495 } 496 497 if (statusCode != 200) { 498 return ERROR_UNSUPPORTED; 499 } 500 501 return sendM4(sessionID); 502} 503 504status_t WifiDisplaySource::onReceiveM4Response( 505 int32_t sessionID, const sp<ParsedMessage> &msg) { 506 int32_t statusCode; 507 if (!msg->getStatusCode(&statusCode)) { 508 return ERROR_MALFORMED; 509 } 510 511 if (statusCode != 200) { 512 return ERROR_UNSUPPORTED; 513 } 514 515 return sendM5(sessionID); 516} 517 518status_t WifiDisplaySource::onReceiveM5Response( 519 int32_t sessionID, const sp<ParsedMessage> &msg) { 520 int32_t statusCode; 521 if (!msg->getStatusCode(&statusCode)) { 522 return ERROR_MALFORMED; 523 } 524 525 if (statusCode != 200) { 526 return ERROR_UNSUPPORTED; 527 } 528 529 return OK; 530} 531 532status_t WifiDisplaySource::onReceiveM16Response( 533 int32_t sessionID, const sp<ParsedMessage> &msg) { 534 // If only the response was required to include a "Session:" header... 535 536 const ClientInfo &info = mClientInfos.valueFor(sessionID); 537 538 ssize_t index = mPlaybackSessions.indexOfKey(info.mPlaybackSessionID); 539 if (index >= 0) { 540 mPlaybackSessions.valueAt(index)->updateLiveness(); 541 542 scheduleKeepAlive(sessionID); 543 } 544 545 return OK; 546} 547 548void WifiDisplaySource::scheduleReaper() { 549 if (mReaperPending) { 550 return; 551 } 552 553 mReaperPending = true; 554 (new AMessage(kWhatReapDeadClients, id()))->post(kReaperIntervalUs); 555} 556 557void WifiDisplaySource::scheduleKeepAlive(int32_t sessionID) { 558 // We need to send updates at least 5 secs before the timeout is set to 559 // expire, make sure the timeout is greater than 5 secs to begin with. 560 CHECK_GT(kPlaybackSessionTimeoutUs, 5000000ll); 561 562 sp<AMessage> msg = new AMessage(kWhatKeepAlive, id()); 563 msg->setInt32("sessionID", sessionID); 564 msg->post(kPlaybackSessionTimeoutUs - 5000000ll); 565} 566 567void WifiDisplaySource::onReceiveClientData(const sp<AMessage> &msg) { 568 int32_t sessionID; 569 CHECK(msg->findInt32("sessionID", &sessionID)); 570 571 sp<RefBase> obj; 572 CHECK(msg->findObject("data", &obj)); 573 574 sp<ParsedMessage> data = 575 static_cast<ParsedMessage *>(obj.get()); 576 577 ALOGV("session %d received '%s'", 578 sessionID, data->debugString().c_str()); 579 580 AString method; 581 AString uri; 582 data->getRequestField(0, &method); 583 584 int32_t cseq; 585 if (!data->findInt32("cseq", &cseq)) { 586 sendErrorResponse(sessionID, "400 Bad Request", -1 /* cseq */); 587 return; 588 } 589 590 if (method.startsWith("RTSP/")) { 591 // This is a response. 592 593 ResponseID id; 594 id.mSessionID = sessionID; 595 id.mCSeq = cseq; 596 597 ssize_t index = mResponseHandlers.indexOfKey(id); 598 599 if (index < 0) { 600 ALOGW("Received unsolicited server response, cseq %d", cseq); 601 return; 602 } 603 604 HandleRTSPResponseFunc func = mResponseHandlers.valueAt(index); 605 mResponseHandlers.removeItemsAt(index); 606 607 status_t err = (this->*func)(sessionID, data); 608 609 if (err != OK) { 610 ALOGW("Response handler for session %d, cseq %d returned " 611 "err %d (%s)", 612 sessionID, cseq, err, strerror(-err)); 613 } 614 } else { 615 AString version; 616 data->getRequestField(2, &version); 617 if (!(version == AString("RTSP/1.0"))) { 618 sendErrorResponse(sessionID, "505 RTSP Version not supported", cseq); 619 return; 620 } 621 622 if (method == "DESCRIBE") { 623 onDescribeRequest(sessionID, cseq, data); 624 } else if (method == "OPTIONS") { 625 onOptionsRequest(sessionID, cseq, data); 626 } else if (method == "SETUP") { 627 onSetupRequest(sessionID, cseq, data); 628 } else if (method == "PLAY") { 629 onPlayRequest(sessionID, cseq, data); 630 } else if (method == "PAUSE") { 631 onPauseRequest(sessionID, cseq, data); 632 } else if (method == "TEARDOWN") { 633 onTeardownRequest(sessionID, cseq, data); 634 } else if (method == "GET_PARAMETER") { 635 onGetParameterRequest(sessionID, cseq, data); 636 } else if (method == "SET_PARAMETER") { 637 onSetParameterRequest(sessionID, cseq, data); 638 } else { 639 sendErrorResponse(sessionID, "405 Method Not Allowed", cseq); 640 } 641 } 642} 643 644void WifiDisplaySource::onDescribeRequest( 645 int32_t sessionID, 646 int32_t cseq, 647 const sp<ParsedMessage> &data) { 648 int64_t nowUs = ALooper::GetNowUs(); 649 650 AString sdp; 651 sdp.append("v=0\r\n"); 652 653 sdp.append(StringPrintf( 654 "o=- %lld %lld IN IP4 0.0.0.0\r\n", nowUs, nowUs)); 655 656 sdp.append( 657 "o=- 0 0 IN IP4 127.0.0.0\r\n" 658 "s=Sample\r\n" 659 "c=IN IP4 0.0.0.0\r\n" 660 "b=AS:502\r\n" 661 "t=0 0\r\n" 662 "a=control:*\r\n" 663 "a=range:npt=now-\r\n" 664 "m=video 0 RTP/AVP 33\r\n" 665 "a=rtpmap:33 MP2T/90000\r\n" 666 "a=control:\r\n"); 667 668 AString response = "RTSP/1.0 200 OK\r\n"; 669 AppendCommonResponse(&response, cseq); 670 671 response.append("Content-Type: application/sdp\r\n"); 672 673 // response.append("Content-Base: rtsp://0.0.0.0:7236\r\n"); 674 response.append(StringPrintf("Content-Length: %d\r\n", sdp.size())); 675 response.append("\r\n"); 676 response.append(sdp); 677 678 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 679 CHECK_EQ(err, (status_t)OK); 680} 681 682void WifiDisplaySource::onOptionsRequest( 683 int32_t sessionID, 684 int32_t cseq, 685 const sp<ParsedMessage> &data) { 686 int32_t playbackSessionID; 687 sp<PlaybackSession> playbackSession = 688 findPlaybackSession(data, &playbackSessionID); 689 690 if (playbackSession != NULL) { 691 playbackSession->updateLiveness(); 692 } 693 694 AString response = "RTSP/1.0 200 OK\r\n"; 695 AppendCommonResponse(&response, cseq); 696 697 response.append( 698 "Public: org.wfa.wfd1.0, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, " 699 "GET_PARAMETER, SET_PARAMETER\r\n"); 700 701 response.append("\r\n"); 702 703 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 704 CHECK_EQ(err, (status_t)OK); 705 706 err = sendM3(sessionID); 707 CHECK_EQ(err, (status_t)OK); 708} 709 710void WifiDisplaySource::onSetupRequest( 711 int32_t sessionID, 712 int32_t cseq, 713 const sp<ParsedMessage> &data) { 714 ClientInfo *info = &mClientInfos.editValueFor(sessionID); 715 if (info->mPlaybackSessionID != -1) { 716 // We only support a single playback session per client. 717 // This is due to the reversed keep-alive design in the wfd specs... 718 sendErrorResponse(sessionID, "400 Bad Request", cseq); 719 return; 720 } 721 722 AString transport; 723 if (!data->findString("transport", &transport)) { 724 sendErrorResponse(sessionID, "400 Bad Request", cseq); 725 return; 726 } 727 728 bool useInterleavedTCP = false; 729 730 int clientRtp, clientRtcp; 731 if (transport.startsWith("RTP/AVP/TCP;")) { 732 AString interleaved; 733 if (!ParsedMessage::GetAttribute( 734 transport.c_str(), "interleaved", &interleaved) 735 || sscanf(interleaved.c_str(), "%d-%d", 736 &clientRtp, &clientRtcp) != 2) { 737 sendErrorResponse(sessionID, "400 Bad Request", cseq); 738 return; 739 } 740 741 useInterleavedTCP = true; 742 } else if (transport.startsWith("RTP/AVP;unicast;") 743 || transport.startsWith("RTP/AVP/UDP;unicast;")) { 744 bool badRequest = false; 745 746 AString clientPort; 747 if (!ParsedMessage::GetAttribute( 748 transport.c_str(), "client_port", &clientPort)) { 749 badRequest = true; 750 } else if (sscanf(clientPort.c_str(), "%d-%d", 751 &clientRtp, &clientRtcp) == 2) { 752 } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) { 753 // No RTCP. 754 clientRtcp = -1; 755 } else { 756 badRequest = true; 757 } 758 759 if (badRequest) { 760 sendErrorResponse(sessionID, "400 Bad Request", cseq); 761 return; 762 } 763#if 1 764 // The LG dongle doesn't specify client_port=xxx apparently. 765 } else if (transport == "RTP/AVP/UDP;unicast") { 766 clientRtp = 19000; 767 clientRtcp = clientRtp + 1; 768#endif 769 } else { 770 sendErrorResponse(sessionID, "461 Unsupported Transport", cseq); 771 return; 772 } 773 774 int32_t playbackSessionID = makeUniquePlaybackSessionID(); 775 776 sp<AMessage> notify = new AMessage(kWhatPlaybackSessionNotify, id()); 777 notify->setInt32("playbackSessionID", playbackSessionID); 778 notify->setInt32("sessionID", sessionID); 779 780 sp<PlaybackSession> playbackSession = 781 new PlaybackSession( 782 mNetSession, notify, mClient == NULL /* legacyMode */); 783 784 looper()->registerHandler(playbackSession); 785 786 AString uri; 787 data->getRequestField(1, &uri); 788 789 if (strncasecmp("rtsp://", uri.c_str(), 7)) { 790 sendErrorResponse(sessionID, "400 Bad Request", cseq); 791 return; 792 } 793 794 if (!(uri.startsWith("rtsp://") && uri.endsWith("/wfd1.0/streamid=0"))) { 795 sendErrorResponse(sessionID, "404 Not found", cseq); 796 return; 797 } 798 799 status_t err = playbackSession->init( 800 info->mRemoteIP.c_str(), 801 clientRtp, 802 clientRtcp, 803 useInterleavedTCP); 804 805 if (err != OK) { 806 looper()->unregisterHandler(playbackSession->id()); 807 playbackSession.clear(); 808 } 809 810 switch (err) { 811 case OK: 812 break; 813 case -ENOENT: 814 sendErrorResponse(sessionID, "404 Not Found", cseq); 815 return; 816 default: 817 sendErrorResponse(sessionID, "403 Forbidden", cseq); 818 return; 819 } 820 821 mPlaybackSessions.add(playbackSessionID, playbackSession); 822 823 info->mPlaybackSessionID = playbackSessionID; 824 825 AString response = "RTSP/1.0 200 OK\r\n"; 826 AppendCommonResponse(&response, cseq, playbackSessionID); 827 828 if (useInterleavedTCP) { 829 response.append( 830 StringPrintf( 831 "Transport: RTP/AVP/TCP;interleaved=%d-%d;", 832 clientRtp, clientRtcp)); 833 } else { 834 int32_t serverRtp = playbackSession->getRTPPort(); 835 836 if (clientRtcp >= 0) { 837 response.append( 838 StringPrintf( 839 "Transport: RTP/AVP;unicast;client_port=%d-%d;" 840 "server_port=%d-%d\r\n", 841 clientRtp, clientRtcp, serverRtp, serverRtp + 1)); 842 } else { 843 response.append( 844 StringPrintf( 845 "Transport: RTP/AVP;unicast;client_port=%d;" 846 "server_port=%d\r\n", 847 clientRtp, serverRtp)); 848 } 849 } 850 851 response.append("\r\n"); 852 853 err = mNetSession->sendRequest(sessionID, response.c_str()); 854 CHECK_EQ(err, (status_t)OK); 855 856 scheduleReaper(); 857 scheduleKeepAlive(sessionID); 858} 859 860void WifiDisplaySource::onPlayRequest( 861 int32_t sessionID, 862 int32_t cseq, 863 const sp<ParsedMessage> &data) { 864 int32_t playbackSessionID; 865 sp<PlaybackSession> playbackSession = 866 findPlaybackSession(data, &playbackSessionID); 867 868 if (playbackSession == NULL) { 869 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 870 return; 871 } 872 873 status_t err = playbackSession->play(); 874 CHECK_EQ(err, (status_t)OK); 875 876 AString response = "RTSP/1.0 200 OK\r\n"; 877 AppendCommonResponse(&response, cseq, playbackSessionID); 878 response.append("Range: npt=now-\r\n"); 879 response.append("\r\n"); 880 881 err = mNetSession->sendRequest(sessionID, response.c_str()); 882 CHECK_EQ(err, (status_t)OK); 883 884 if (mClient != NULL) { 885 mClient->onDisplayConnected( 886 playbackSession->getSurfaceTexture(), 887 playbackSession->width(), 888 playbackSession->height(), 889 0 /* flags */); 890 } 891} 892 893void WifiDisplaySource::onPauseRequest( 894 int32_t sessionID, 895 int32_t cseq, 896 const sp<ParsedMessage> &data) { 897 int32_t playbackSessionID; 898 sp<PlaybackSession> playbackSession = 899 findPlaybackSession(data, &playbackSessionID); 900 901 if (playbackSession == NULL) { 902 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 903 return; 904 } 905 906 status_t err = playbackSession->pause(); 907 CHECK_EQ(err, (status_t)OK); 908 909 AString response = "RTSP/1.0 200 OK\r\n"; 910 AppendCommonResponse(&response, cseq, playbackSessionID); 911 response.append("\r\n"); 912 913 err = mNetSession->sendRequest(sessionID, response.c_str()); 914 CHECK_EQ(err, (status_t)OK); 915} 916 917void WifiDisplaySource::onTeardownRequest( 918 int32_t sessionID, 919 int32_t cseq, 920 const sp<ParsedMessage> &data) { 921 int32_t playbackSessionID; 922 sp<PlaybackSession> playbackSession = 923 findPlaybackSession(data, &playbackSessionID); 924 925 if (playbackSession == NULL) { 926 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 927 return; 928 } 929 930 looper()->unregisterHandler(playbackSession->id()); 931 mPlaybackSessions.removeItem(playbackSessionID); 932 933 AString response = "RTSP/1.0 200 OK\r\n"; 934 AppendCommonResponse(&response, cseq, playbackSessionID); 935 response.append("\r\n"); 936 937 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 938 CHECK_EQ(err, (status_t)OK); 939} 940 941void WifiDisplaySource::onGetParameterRequest( 942 int32_t sessionID, 943 int32_t cseq, 944 const sp<ParsedMessage> &data) { 945 int32_t playbackSessionID; 946 sp<PlaybackSession> playbackSession = 947 findPlaybackSession(data, &playbackSessionID); 948 949 if (playbackSession == NULL) { 950 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 951 return; 952 } 953 954 playbackSession->updateLiveness(); 955 956 AString response = "RTSP/1.0 200 OK\r\n"; 957 AppendCommonResponse(&response, cseq, playbackSessionID); 958 response.append("\r\n"); 959 960 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 961 CHECK_EQ(err, (status_t)OK); 962} 963 964void WifiDisplaySource::onSetParameterRequest( 965 int32_t sessionID, 966 int32_t cseq, 967 const sp<ParsedMessage> &data) { 968 int32_t playbackSessionID; 969#if 0 970 // XXX the dongle does not include a "Session:" header in this request. 971 sp<PlaybackSession> playbackSession = 972 findPlaybackSession(data, &playbackSessionID); 973 974 if (playbackSession == NULL) { 975 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 976 return; 977 } 978#else 979 CHECK_EQ(mPlaybackSessions.size(), 1u); 980 playbackSessionID = mPlaybackSessions.keyAt(0); 981 sp<PlaybackSession> playbackSession = mPlaybackSessions.valueAt(0); 982#endif 983 984 playbackSession->updateLiveness(); 985 986 AString response = "RTSP/1.0 200 OK\r\n"; 987 AppendCommonResponse(&response, cseq, playbackSessionID); 988 response.append("\r\n"); 989 990 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 991 CHECK_EQ(err, (status_t)OK); 992} 993 994// static 995void WifiDisplaySource::AppendCommonResponse( 996 AString *response, int32_t cseq, int32_t playbackSessionID) { 997 time_t now = time(NULL); 998 struct tm *now2 = gmtime(&now); 999 char buf[128]; 1000 strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z", now2); 1001 1002 response->append("Date: "); 1003 response->append(buf); 1004 response->append("\r\n"); 1005 1006 response->append("Server: Mine/1.0\r\n"); 1007 1008 if (cseq >= 0) { 1009 response->append(StringPrintf("CSeq: %d\r\n", cseq)); 1010 } 1011 1012 if (playbackSessionID >= 0ll) { 1013 response->append( 1014 StringPrintf( 1015 "Session: %d;timeout=%lld\r\n", 1016 playbackSessionID, kPlaybackSessionTimeoutSecs)); 1017 } 1018} 1019 1020void WifiDisplaySource::sendErrorResponse( 1021 int32_t sessionID, 1022 const char *errorDetail, 1023 int32_t cseq) { 1024 AString response; 1025 response.append("RTSP/1.0 "); 1026 response.append(errorDetail); 1027 response.append("\r\n"); 1028 1029 AppendCommonResponse(&response, cseq); 1030 1031 response.append("\r\n"); 1032 1033 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 1034 CHECK_EQ(err, (status_t)OK); 1035} 1036 1037int32_t WifiDisplaySource::makeUniquePlaybackSessionID() const { 1038 for (;;) { 1039 int32_t playbackSessionID = rand(); 1040 1041 if (playbackSessionID == -1) { 1042 // reserved. 1043 continue; 1044 } 1045 1046 for (size_t i = 0; i < mPlaybackSessions.size(); ++i) { 1047 if (mPlaybackSessions.keyAt(i) == playbackSessionID) { 1048 continue; 1049 } 1050 } 1051 1052 return playbackSessionID; 1053 } 1054} 1055 1056sp<WifiDisplaySource::PlaybackSession> WifiDisplaySource::findPlaybackSession( 1057 const sp<ParsedMessage> &data, int32_t *playbackSessionID) const { 1058 if (!data->findInt32("session", playbackSessionID)) { 1059 *playbackSessionID = 0; 1060 return NULL; 1061 } 1062 1063 ssize_t index = mPlaybackSessions.indexOfKey(*playbackSessionID); 1064 if (index < 0) { 1065 return NULL; 1066 } 1067 1068 return mPlaybackSessions.valueAt(index); 1069} 1070 1071} // namespace android 1072 1073