1 /* 2 * Copyright (C) 2010 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 #ifndef MY_TRANSMITTER_H_ 18 19 #define MY_TRANSMITTER_H_ 20 21 #include "ARTPConnection.h" 22 23 #include <arpa/inet.h> 24 #include <sys/socket.h> 25 26 #include <openssl/md5.h> 27 28 #include <media/stagefright/foundation/ADebug.h> 29 #include <media/stagefright/foundation/base64.h> 30 #include <media/stagefright/foundation/hexdump.h> 31 32 #ifdef ANDROID 33 #include "VideoSource.h" 34 #include <media/stagefright/foundation/ABuffer.h> 35 #include <media/stagefright/foundation/ALooper.h> 36 #include <media/stagefright/foundation/AMessage.h> 37 #include <media/stagefright/MediaCodecSource.h> 38 #endif 39 40 namespace android { 41 42 #define TRACK_SUFFIX "trackid=1" 43 #define PT 96 44 #define PT_STR "96" 45 46 #define USERNAME "bcast" 47 #define PASSWORD "test" 48 49 static int uniformRand(int limit) { 50 return ((double)rand() * limit) / RAND_MAX; 51 } 52 53 static bool GetAttribute(const char *s, const char *key, AString *value) { 54 value->clear(); 55 56 size_t keyLen = strlen(key); 57 58 for (;;) { 59 const char *colonPos = strchr(s, ';'); 60 61 size_t len = 62 (colonPos == NULL) ? strlen(s) : colonPos - s; 63 64 if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) { 65 value->setTo(&s[keyLen + 1], len - keyLen - 1); 66 return true; 67 } 68 69 if (colonPos == NULL) { 70 return false; 71 } 72 73 s = colonPos + 1; 74 } 75 } 76 77 struct MyTransmitter : public AHandler { 78 MyTransmitter(const char *url, const sp<ALooper> &looper) 79 : mServerURL(url), 80 mLooper(looper), 81 mConn(new ARTSPConnection), 82 mConnected(false), 83 mAuthType(NONE), 84 mRTPSocket(-1), 85 mRTCPSocket(-1), 86 mSourceID(rand()), 87 mSeqNo(uniformRand(65536)), 88 mRTPTimeBase(rand()), 89 mNumSamplesSent(0), 90 mNumRTPSent(0), 91 mNumRTPOctetsSent(0), 92 mLastRTPTime(0), 93 mLastNTPTime(0) { 94 mStreamURL = mServerURL; 95 mStreamURL.append("/bazong.sdp"); 96 97 mTrackURL = mStreamURL; 98 mTrackURL.append("/"); 99 mTrackURL.append(TRACK_SUFFIX); 100 101 mLooper->registerHandler(this); 102 mLooper->registerHandler(mConn); 103 104 sp<AMessage> reply = new AMessage('conn', this); 105 mConn->connect(mServerURL.c_str(), reply); 106 107 #ifdef ANDROID 108 int width = 640; 109 int height = 480; 110 111 sp<MediaSource> source = new VideoSource(width, height); 112 113 sp<AMessage> encMeta = new AMessage; 114 encMeta->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC); 115 encMeta->setInt32("width", width); 116 encMeta->setInt32("height", height); 117 encMeta->setInt32("frame-rate", 30); 118 encMeta->setInt32("bitrate", 256000); 119 encMeta->setInt32("i-frame-interval", 10); 120 121 sp<ALooper> encLooper = new ALooper; 122 encLooper->setName("rtsp_transmitter"); 123 encLooper->start(); 124 125 mEncoder = MediaCodecSource::Create(encLooper, encMeta, source); 126 127 mEncoder->start(); 128 129 MediaBuffer *buffer; 130 CHECK_EQ(mEncoder->read(&buffer), (status_t)OK); 131 CHECK(buffer != NULL); 132 133 makeH264SPropParamSets(buffer); 134 135 buffer->release(); 136 buffer = NULL; 137 #endif 138 } 139 140 uint64_t ntpTime() { 141 struct timeval tv; 142 gettimeofday(&tv, NULL); 143 144 uint64_t nowUs = tv.tv_sec * 1000000ll + tv.tv_usec; 145 146 nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll; 147 148 uint64_t hi = nowUs / 1000000ll; 149 uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll; 150 151 return (hi << 32) | lo; 152 } 153 154 void issueAnnounce() { 155 AString sdp; 156 sdp = "v=0\r\n"; 157 158 sdp.append("o=- "); 159 160 uint64_t ntp = ntpTime(); 161 sdp.append(ntp); 162 sdp.append(" "); 163 sdp.append(ntp); 164 sdp.append(" IN IP4 127.0.0.0\r\n"); 165 166 sdp.append( 167 "s=Sample\r\n" 168 "i=Playing around with ANNOUNCE\r\n" 169 "c=IN IP4 "); 170 171 struct in_addr addr; 172 addr.s_addr = htonl(mServerIP); 173 174 sdp.append(inet_ntoa(addr)); 175 176 sdp.append( 177 "\r\n" 178 "t=0 0\r\n" 179 "a=range:npt=now-\r\n"); 180 181 #ifdef ANDROID 182 sp<MetaData> meta = mEncoder->getFormat(); 183 int32_t width, height; 184 CHECK(meta->findInt32(kKeyWidth, &width)); 185 CHECK(meta->findInt32(kKeyHeight, &height)); 186 187 sdp.append( 188 "m=video 0 RTP/AVP " PT_STR "\r\n" 189 "b=AS 320000\r\n" 190 "a=rtpmap:" PT_STR " H264/90000\r\n"); 191 192 sdp.append("a=cliprect 0,0,"); 193 sdp.append(height); 194 sdp.append(","); 195 sdp.append(width); 196 sdp.append("\r\n"); 197 198 sdp.append( 199 "a=framesize:" PT_STR " "); 200 sdp.append(width); 201 sdp.append("-"); 202 sdp.append(height); 203 sdp.append("\r\n"); 204 205 sdp.append( 206 "a=fmtp:" PT_STR " profile-level-id=42C015;sprop-parameter-sets="); 207 208 sdp.append(mSeqParamSet); 209 sdp.append(","); 210 sdp.append(mPicParamSet); 211 sdp.append(";packetization-mode=1\r\n"); 212 #else 213 sdp.append( 214 "m=audio 0 RTP/AVP " PT_STR "\r\n" 215 "a=rtpmap:" PT_STR " L8/8000/1\r\n"); 216 #endif 217 218 sdp.append("a=control:" TRACK_SUFFIX "\r\n"); 219 220 AString request; 221 request.append("ANNOUNCE "); 222 request.append(mStreamURL); 223 request.append(" RTSP/1.0\r\n"); 224 225 addAuthentication(&request, "ANNOUNCE", mStreamURL.c_str()); 226 227 request.append("Content-Type: application/sdp\r\n"); 228 request.append("Content-Length: "); 229 request.append(sdp.size()); 230 request.append("\r\n"); 231 232 request.append("\r\n"); 233 request.append(sdp); 234 235 sp<AMessage> reply = new AMessage('anno', this); 236 mConn->sendRequest(request.c_str(), reply); 237 } 238 239 void H(const AString &s, AString *out) { 240 out->clear(); 241 242 MD5_CTX m; 243 MD5_Init(&m); 244 MD5_Update(&m, s.c_str(), s.size()); 245 246 uint8_t key[16]; 247 MD5_Final(key, &m); 248 249 for (size_t i = 0; i < 16; ++i) { 250 char nibble = key[i] >> 4; 251 if (nibble <= 9) { 252 nibble += '0'; 253 } else { 254 nibble += 'a' - 10; 255 } 256 out->append(&nibble, 1); 257 258 nibble = key[i] & 0x0f; 259 if (nibble <= 9) { 260 nibble += '0'; 261 } else { 262 nibble += 'a' - 10; 263 } 264 out->append(&nibble, 1); 265 } 266 } 267 268 void authenticate(const sp<ARTSPResponse> &response) { 269 ssize_t i = response->mHeaders.indexOfKey("www-authenticate"); 270 CHECK_GE(i, 0); 271 272 AString value = response->mHeaders.valueAt(i); 273 274 if (!strncmp(value.c_str(), "Basic", 5)) { 275 mAuthType = BASIC; 276 } else { 277 CHECK(!strncmp(value.c_str(), "Digest", 6)); 278 mAuthType = DIGEST; 279 280 i = value.find("nonce="); 281 CHECK_GE(i, 0); 282 CHECK_EQ(value.c_str()[i + 6], '\"'); 283 ssize_t j = value.find("\"", i + 7); 284 CHECK_GE(j, 0); 285 286 mNonce.setTo(value, i + 7, j - i - 7); 287 } 288 289 issueAnnounce(); 290 } 291 292 void addAuthentication( 293 AString *request, const char *method, const char *url) { 294 if (mAuthType == NONE) { 295 return; 296 } 297 298 if (mAuthType == BASIC) { 299 request->append("Authorization: Basic YmNhc3Q6dGVzdAo=\r\n"); 300 return; 301 } 302 303 CHECK_EQ((int)mAuthType, (int)DIGEST); 304 305 AString A1; 306 A1.append(USERNAME); 307 A1.append(":"); 308 A1.append("Streaming Server"); 309 A1.append(":"); 310 A1.append(PASSWORD); 311 312 AString A2; 313 A2.append(method); 314 A2.append(":"); 315 A2.append(url); 316 317 AString HA1, HA2; 318 H(A1, &HA1); 319 H(A2, &HA2); 320 321 AString tmp; 322 tmp.append(HA1); 323 tmp.append(":"); 324 tmp.append(mNonce); 325 tmp.append(":"); 326 tmp.append(HA2); 327 328 AString digest; 329 H(tmp, &digest); 330 331 request->append("Authorization: Digest "); 332 request->append("nonce=\""); 333 request->append(mNonce); 334 request->append("\", "); 335 request->append("username=\"" USERNAME "\", "); 336 request->append("uri=\""); 337 request->append(url); 338 request->append("\", "); 339 request->append("response=\""); 340 request->append(digest); 341 request->append("\""); 342 request->append("\r\n"); 343 } 344 345 virtual void onMessageReceived(const sp<AMessage> &msg) { 346 switch (msg->what()) { 347 case 'conn': 348 { 349 int32_t result; 350 CHECK(msg->findInt32("result", &result)); 351 352 LOG(INFO) << "connection request completed with result " 353 << result << " (" << strerror(-result) << ")"; 354 355 if (result != OK) { 356 (new AMessage('quit', this))->post(); 357 break; 358 } 359 360 mConnected = true; 361 362 CHECK(msg->findInt32("server-ip", (int32_t *)&mServerIP)); 363 364 issueAnnounce(); 365 break; 366 } 367 368 case 'anno': 369 { 370 int32_t result; 371 CHECK(msg->findInt32("result", &result)); 372 373 LOG(INFO) << "ANNOUNCE completed with result " 374 << result << " (" << strerror(-result) << ")"; 375 376 sp<RefBase> obj; 377 CHECK(msg->findObject("response", &obj)); 378 sp<ARTSPResponse> response; 379 380 if (result == OK) { 381 response = static_cast<ARTSPResponse *>(obj.get()); 382 CHECK(response != NULL); 383 384 if (response->mStatusCode == 401) { 385 if (mAuthType != NONE) { 386 LOG(INFO) << "FAILED to authenticate"; 387 (new AMessage('quit', this))->post(); 388 break; 389 } 390 391 authenticate(response); 392 break; 393 } 394 } 395 396 if (result != OK || response->mStatusCode != 200) { 397 (new AMessage('quit', this))->post(); 398 break; 399 } 400 401 unsigned rtpPort; 402 ARTPConnection::MakePortPair(&mRTPSocket, &mRTCPSocket, &rtpPort); 403 404 // (new AMessage('poll', this))->post(); 405 406 AString request; 407 request.append("SETUP "); 408 request.append(mTrackURL); 409 request.append(" RTSP/1.0\r\n"); 410 411 addAuthentication(&request, "SETUP", mTrackURL.c_str()); 412 413 request.append("Transport: RTP/AVP;unicast;client_port="); 414 request.append(rtpPort); 415 request.append("-"); 416 request.append(rtpPort + 1); 417 request.append(";mode=record\r\n"); 418 request.append("\r\n"); 419 420 sp<AMessage> reply = new AMessage('setu', this); 421 mConn->sendRequest(request.c_str(), reply); 422 break; 423 } 424 425 #if 0 426 case 'poll': 427 { 428 fd_set rs; 429 FD_ZERO(&rs); 430 FD_SET(mRTCPSocket, &rs); 431 432 struct timeval tv; 433 tv.tv_sec = 0; 434 tv.tv_usec = 0; 435 436 int res = select(mRTCPSocket + 1, &rs, NULL, NULL, &tv); 437 438 if (res == 1) { 439 sp<ABuffer> buffer = new ABuffer(65536); 440 ssize_t n = recv(mRTCPSocket, buffer->data(), buffer->size(), 0); 441 442 if (n <= 0) { 443 LOG(ERROR) << "recv returned " << n; 444 } else { 445 LOG(INFO) << "recv returned " << n << " bytes of data."; 446 447 hexdump(buffer->data(), n); 448 } 449 } 450 451 msg->post(50000); 452 break; 453 } 454 #endif 455 456 case 'setu': 457 { 458 int32_t result; 459 CHECK(msg->findInt32("result", &result)); 460 461 LOG(INFO) << "SETUP completed with result " 462 << result << " (" << strerror(-result) << ")"; 463 464 sp<RefBase> obj; 465 CHECK(msg->findObject("response", &obj)); 466 sp<ARTSPResponse> response; 467 468 if (result == OK) { 469 response = static_cast<ARTSPResponse *>(obj.get()); 470 CHECK(response != NULL); 471 } 472 473 if (result != OK || response->mStatusCode != 200) { 474 (new AMessage('quit', this))->post(); 475 break; 476 } 477 478 ssize_t i = response->mHeaders.indexOfKey("session"); 479 CHECK_GE(i, 0); 480 mSessionID = response->mHeaders.valueAt(i); 481 i = mSessionID.find(";"); 482 if (i >= 0) { 483 // Remove options, i.e. ";timeout=90" 484 mSessionID.erase(i, mSessionID.size() - i); 485 } 486 487 i = response->mHeaders.indexOfKey("transport"); 488 CHECK_GE(i, 0); 489 AString transport = response->mHeaders.valueAt(i); 490 491 LOG(INFO) << "transport = '" << transport << "'"; 492 493 AString value; 494 CHECK(GetAttribute(transport.c_str(), "server_port", &value)); 495 496 unsigned rtpPort, rtcpPort; 497 CHECK_EQ(sscanf(value.c_str(), "%u-%u", &rtpPort, &rtcpPort), 2); 498 499 CHECK(GetAttribute(transport.c_str(), "source", &value)); 500 501 memset(mRemoteAddr.sin_zero, 0, sizeof(mRemoteAddr.sin_zero)); 502 mRemoteAddr.sin_family = AF_INET; 503 mRemoteAddr.sin_addr.s_addr = inet_addr(value.c_str()); 504 mRemoteAddr.sin_port = htons(rtpPort); 505 506 mRemoteRTCPAddr = mRemoteAddr; 507 mRemoteRTCPAddr.sin_port = htons(rtpPort + 1); 508 509 CHECK_EQ(0, connect(mRTPSocket, 510 (const struct sockaddr *)&mRemoteAddr, 511 sizeof(mRemoteAddr))); 512 513 CHECK_EQ(0, connect(mRTCPSocket, 514 (const struct sockaddr *)&mRemoteRTCPAddr, 515 sizeof(mRemoteRTCPAddr))); 516 517 uint32_t x = ntohl(mRemoteAddr.sin_addr.s_addr); 518 LOG(INFO) << "sending data to " 519 << (x >> 24) 520 << "." 521 << ((x >> 16) & 0xff) 522 << "." 523 << ((x >> 8) & 0xff) 524 << "." 525 << (x & 0xff) 526 << ":" 527 << rtpPort; 528 529 AString request; 530 request.append("RECORD "); 531 request.append(mStreamURL); 532 request.append(" RTSP/1.0\r\n"); 533 534 addAuthentication(&request, "RECORD", mStreamURL.c_str()); 535 536 request.append("Session: "); 537 request.append(mSessionID); 538 request.append("\r\n"); 539 request.append("\r\n"); 540 541 sp<AMessage> reply = new AMessage('reco', this); 542 mConn->sendRequest(request.c_str(), reply); 543 break; 544 } 545 546 case 'reco': 547 { 548 int32_t result; 549 CHECK(msg->findInt32("result", &result)); 550 551 LOG(INFO) << "RECORD completed with result " 552 << result << " (" << strerror(-result) << ")"; 553 554 sp<RefBase> obj; 555 CHECK(msg->findObject("response", &obj)); 556 sp<ARTSPResponse> response; 557 558 if (result == OK) { 559 response = static_cast<ARTSPResponse *>(obj.get()); 560 CHECK(response != NULL); 561 } 562 563 if (result != OK) { 564 (new AMessage('quit', this))->post(); 565 break; 566 } 567 568 (new AMessage('more', this))->post(); 569 (new AMessage('sr ', this))->post(); 570 (new AMessage('aliv', this))->post(30000000ll); 571 break; 572 } 573 574 case 'aliv': 575 { 576 if (!mConnected) { 577 break; 578 } 579 580 AString request; 581 request.append("OPTIONS "); 582 request.append(mStreamURL); 583 request.append(" RTSP/1.0\r\n"); 584 585 addAuthentication(&request, "RECORD", mStreamURL.c_str()); 586 587 request.append("Session: "); 588 request.append(mSessionID); 589 request.append("\r\n"); 590 request.append("\r\n"); 591 592 sp<AMessage> reply = new AMessage('opts', this); 593 mConn->sendRequest(request.c_str(), reply); 594 break; 595 } 596 597 case 'opts': 598 { 599 int32_t result; 600 CHECK(msg->findInt32("result", &result)); 601 602 LOG(INFO) << "OPTIONS completed with result " 603 << result << " (" << strerror(-result) << ")"; 604 605 if (!mConnected) { 606 break; 607 } 608 609 (new AMessage('aliv', this))->post(30000000ll); 610 break; 611 } 612 613 case 'more': 614 { 615 if (!mConnected) { 616 break; 617 } 618 619 sp<ABuffer> buffer = new ABuffer(65536); 620 uint8_t *data = buffer->data(); 621 data[0] = 0x80; 622 data[1] = (1 << 7) | PT; // M-bit 623 data[2] = (mSeqNo >> 8) & 0xff; 624 data[3] = mSeqNo & 0xff; 625 data[8] = mSourceID >> 24; 626 data[9] = (mSourceID >> 16) & 0xff; 627 data[10] = (mSourceID >> 8) & 0xff; 628 data[11] = mSourceID & 0xff; 629 630 #ifdef ANDROID 631 MediaBuffer *mediaBuf = NULL; 632 for (;;) { 633 CHECK_EQ(mEncoder->read(&mediaBuf), (status_t)OK); 634 if (mediaBuf->range_length() > 0) { 635 break; 636 } 637 mediaBuf->release(); 638 mediaBuf = NULL; 639 } 640 641 int64_t timeUs; 642 CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs)); 643 644 uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll); 645 646 const uint8_t *mediaData = 647 (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset(); 648 649 CHECK(!memcmp("\x00\x00\x00\x01", mediaData, 4)); 650 651 CHECK_LE(mediaBuf->range_length() - 4 + 12, buffer->size()); 652 653 memcpy(&data[12], 654 mediaData + 4, mediaBuf->range_length() - 4); 655 656 buffer->setRange(0, mediaBuf->range_length() - 4 + 12); 657 658 mediaBuf->release(); 659 mediaBuf = NULL; 660 #else 661 uint32_t rtpTime = mRTPTimeBase + mNumRTPSent * 128; 662 memset(&data[12], 0, 128); 663 buffer->setRange(0, 12 + 128); 664 #endif 665 666 data[4] = rtpTime >> 24; 667 data[5] = (rtpTime >> 16) & 0xff; 668 data[6] = (rtpTime >> 8) & 0xff; 669 data[7] = rtpTime & 0xff; 670 671 ssize_t n = send( 672 mRTPSocket, data, buffer->size(), 0); 673 if (n < 0) { 674 LOG(ERROR) << "send failed (" << strerror(errno) << ")"; 675 } 676 CHECK_EQ(n, (ssize_t)buffer->size()); 677 678 ++mSeqNo; 679 680 ++mNumRTPSent; 681 mNumRTPOctetsSent += buffer->size() - 12; 682 683 mLastRTPTime = rtpTime; 684 mLastNTPTime = ntpTime(); 685 686 #ifdef ANDROID 687 if (mNumRTPSent < 60 * 25) { // 60 secs worth 688 msg->post(40000); 689 #else 690 if (mNumRTPOctetsSent < 8000 * 60) { 691 msg->post(1000000ll * 128 / 8000); 692 #endif 693 } else { 694 LOG(INFO) << "That's enough, pausing."; 695 696 AString request; 697 request.append("PAUSE "); 698 request.append(mStreamURL); 699 request.append(" RTSP/1.0\r\n"); 700 701 addAuthentication(&request, "PAUSE", mStreamURL.c_str()); 702 703 request.append("Session: "); 704 request.append(mSessionID); 705 request.append("\r\n"); 706 request.append("\r\n"); 707 708 sp<AMessage> reply = new AMessage('paus', this); 709 mConn->sendRequest(request.c_str(), reply); 710 } 711 break; 712 } 713 714 case 'sr ': 715 { 716 if (!mConnected) { 717 break; 718 } 719 720 sp<ABuffer> buffer = new ABuffer(65536); 721 buffer->setRange(0, 0); 722 723 addSR(buffer); 724 addSDES(buffer); 725 726 uint8_t *data = buffer->data(); 727 ssize_t n = send( 728 mRTCPSocket, data, buffer->size(), 0); 729 CHECK_EQ(n, (ssize_t)buffer->size()); 730 731 msg->post(3000000); 732 break; 733 } 734 735 case 'paus': 736 { 737 int32_t result; 738 CHECK(msg->findInt32("result", &result)); 739 740 LOG(INFO) << "PAUSE completed with result " 741 << result << " (" << strerror(-result) << ")"; 742 743 sp<RefBase> obj; 744 CHECK(msg->findObject("response", &obj)); 745 sp<ARTSPResponse> response; 746 747 AString request; 748 request.append("TEARDOWN "); 749 request.append(mStreamURL); 750 request.append(" RTSP/1.0\r\n"); 751 752 addAuthentication(&request, "TEARDOWN", mStreamURL.c_str()); 753 754 request.append("Session: "); 755 request.append(mSessionID); 756 request.append("\r\n"); 757 request.append("\r\n"); 758 759 sp<AMessage> reply = new AMessage('tear', this); 760 mConn->sendRequest(request.c_str(), reply); 761 break; 762 } 763 764 case 'tear': 765 { 766 int32_t result; 767 CHECK(msg->findInt32("result", &result)); 768 769 LOG(INFO) << "TEARDOWN completed with result " 770 << result << " (" << strerror(-result) << ")"; 771 772 sp<RefBase> obj; 773 CHECK(msg->findObject("response", &obj)); 774 sp<ARTSPResponse> response; 775 776 if (result == OK) { 777 response = static_cast<ARTSPResponse *>(obj.get()); 778 CHECK(response != NULL); 779 } 780 781 (new AMessage('quit', this))->post(); 782 break; 783 } 784 785 case 'disc': 786 { 787 LOG(INFO) << "disconnect completed"; 788 789 mConnected = false; 790 (new AMessage('quit', this))->post(); 791 break; 792 } 793 794 case 'quit': 795 { 796 if (mConnected) { 797 mConn->disconnect(new AMessage('disc', this)); 798 break; 799 } 800 801 if (mRTPSocket >= 0) { 802 close(mRTPSocket); 803 mRTPSocket = -1; 804 } 805 806 if (mRTCPSocket >= 0) { 807 close(mRTCPSocket); 808 mRTCPSocket = -1; 809 } 810 811 #ifdef ANDROID 812 mEncoder->stop(); 813 mEncoder.clear(); 814 #endif 815 816 mLooper->stop(); 817 break; 818 } 819 820 default: 821 TRESPASS(); 822 } 823 } 824 825 protected: 826 virtual ~MyTransmitter() { 827 } 828 829 private: 830 enum AuthType { 831 NONE, 832 BASIC, 833 DIGEST 834 }; 835 836 AString mServerURL; 837 AString mTrackURL; 838 AString mStreamURL; 839 840 sp<ALooper> mLooper; 841 sp<ARTSPConnection> mConn; 842 bool mConnected; 843 uint32_t mServerIP; 844 AuthType mAuthType; 845 AString mNonce; 846 AString mSessionID; 847 int mRTPSocket, mRTCPSocket; 848 uint32_t mSourceID; 849 uint32_t mSeqNo; 850 uint32_t mRTPTimeBase; 851 struct sockaddr_in mRemoteAddr; 852 struct sockaddr_in mRemoteRTCPAddr; 853 size_t mNumSamplesSent; 854 uint32_t mNumRTPSent; 855 uint32_t mNumRTPOctetsSent; 856 uint32_t mLastRTPTime; 857 uint64_t mLastNTPTime; 858 859 #ifdef ANDROID 860 sp<MediaSource> mEncoder; 861 AString mSeqParamSet; 862 AString mPicParamSet; 863 864 void makeH264SPropParamSets(MediaBuffer *buffer) { 865 static const char kStartCode[] = "\x00\x00\x00\x01"; 866 867 const uint8_t *data = 868 (const uint8_t *)buffer->data() + buffer->range_offset(); 869 size_t size = buffer->range_length(); 870 871 CHECK_GE(size, 0u); 872 CHECK(!memcmp(kStartCode, data, 4)); 873 874 data += 4; 875 size -= 4; 876 877 size_t startCodePos = 0; 878 while (startCodePos + 3 < size 879 && memcmp(kStartCode, &data[startCodePos], 4)) { 880 ++startCodePos; 881 } 882 883 CHECK_LT(startCodePos + 3, size); 884 885 encodeBase64(data, startCodePos, &mSeqParamSet); 886 887 encodeBase64(&data[startCodePos + 4], size - startCodePos - 4, 888 &mPicParamSet); 889 } 890 #endif 891 892 void addSR(const sp<ABuffer> &buffer) { 893 uint8_t *data = buffer->data() + buffer->size(); 894 895 data[0] = 0x80 | 0; 896 data[1] = 200; // SR 897 data[2] = 0; 898 data[3] = 6; 899 data[4] = mSourceID >> 24; 900 data[5] = (mSourceID >> 16) & 0xff; 901 data[6] = (mSourceID >> 8) & 0xff; 902 data[7] = mSourceID & 0xff; 903 904 data[8] = mLastNTPTime >> (64 - 8); 905 data[9] = (mLastNTPTime >> (64 - 16)) & 0xff; 906 data[10] = (mLastNTPTime >> (64 - 24)) & 0xff; 907 data[11] = (mLastNTPTime >> 32) & 0xff; 908 data[12] = (mLastNTPTime >> 24) & 0xff; 909 data[13] = (mLastNTPTime >> 16) & 0xff; 910 data[14] = (mLastNTPTime >> 8) & 0xff; 911 data[15] = mLastNTPTime & 0xff; 912 913 data[16] = (mLastRTPTime >> 24) & 0xff; 914 data[17] = (mLastRTPTime >> 16) & 0xff; 915 data[18] = (mLastRTPTime >> 8) & 0xff; 916 data[19] = mLastRTPTime & 0xff; 917 918 data[20] = mNumRTPSent >> 24; 919 data[21] = (mNumRTPSent >> 16) & 0xff; 920 data[22] = (mNumRTPSent >> 8) & 0xff; 921 data[23] = mNumRTPSent & 0xff; 922 923 data[24] = mNumRTPOctetsSent >> 24; 924 data[25] = (mNumRTPOctetsSent >> 16) & 0xff; 925 data[26] = (mNumRTPOctetsSent >> 8) & 0xff; 926 data[27] = mNumRTPOctetsSent & 0xff; 927 928 buffer->setRange(buffer->offset(), buffer->size() + 28); 929 } 930 931 void addSDES(const sp<ABuffer> &buffer) { 932 uint8_t *data = buffer->data() + buffer->size(); 933 data[0] = 0x80 | 1; 934 data[1] = 202; // SDES 935 data[4] = mSourceID >> 24; 936 data[5] = (mSourceID >> 16) & 0xff; 937 data[6] = (mSourceID >> 8) & 0xff; 938 data[7] = mSourceID & 0xff; 939 940 size_t offset = 8; 941 942 data[offset++] = 1; // CNAME 943 944 static const char *kCNAME = "andih@laptop"; 945 data[offset++] = strlen(kCNAME); 946 947 memcpy(&data[offset], kCNAME, strlen(kCNAME)); 948 offset += strlen(kCNAME); 949 950 data[offset++] = 7; // NOTE 951 952 static const char *kNOTE = "Hell's frozen over."; 953 data[offset++] = strlen(kNOTE); 954 955 memcpy(&data[offset], kNOTE, strlen(kNOTE)); 956 offset += strlen(kNOTE); 957 958 data[offset++] = 0; 959 960 if ((offset % 4) > 0) { 961 size_t count = 4 - (offset % 4); 962 switch (count) { 963 case 3: 964 data[offset++] = 0; 965 case 2: 966 data[offset++] = 0; 967 case 1: 968 data[offset++] = 0; 969 } 970 } 971 972 size_t numWords = (offset / 4) - 1; 973 data[2] = numWords >> 8; 974 data[3] = numWords & 0xff; 975 976 buffer->setRange(buffer->offset(), buffer->size() + offset); 977 } 978 979 DISALLOW_EVIL_CONSTRUCTORS(MyTransmitter); 980 }; 981 982 } // namespace android 983 984 #endif // MY_TRANSMITTER_H_ 985