ARTPWriter.cpp revision a814c1fdc2acf0ed2ee3b175110f6039be7c4873
1#include "ARTPWriter.h" 2 3#include <fcntl.h> 4 5#include <media/stagefright/foundation/ABuffer.h> 6#include <media/stagefright/foundation/ADebug.h> 7#include <media/stagefright/foundation/AMessage.h> 8#include <media/stagefright/foundation/hexdump.h> 9#include <media/stagefright/MediaBuffer.h> 10#include <media/stagefright/MediaDefs.h> 11#include <media/stagefright/MediaSource.h> 12#include <media/stagefright/MetaData.h> 13#include <utils/ByteOrder.h> 14 15#define PT 97 16#define PT_STR "97" 17 18namespace android { 19 20// static const size_t kMaxPacketSize = 65507; // maximum payload in UDP over IP 21static const size_t kMaxPacketSize = 1500; 22 23static int UniformRand(int limit) { 24 return ((double)rand() * limit) / RAND_MAX; 25} 26 27ARTPWriter::ARTPWriter(int fd) 28 : mFlags(0), 29 mFd(fd), 30 mLooper(new ALooper), 31 mReflector(new AHandlerReflector<ARTPWriter>(this)) { 32 CHECK_GE(fd, 0); 33 34 mLooper->setName("rtp writer"); 35 mLooper->registerHandler(mReflector); 36 mLooper->start(); 37 38 mSocket = socket(AF_INET, SOCK_DGRAM, 0); 39 CHECK_GE(mSocket, 0); 40 41 memset(mRTPAddr.sin_zero, 0, sizeof(mRTPAddr.sin_zero)); 42 mRTPAddr.sin_family = AF_INET; 43 44#if 1 45 mRTPAddr.sin_addr.s_addr = INADDR_ANY; 46#else 47 mRTPAddr.sin_addr.s_addr = inet_addr("172.19.18.246"); 48#endif 49 50 mRTPAddr.sin_port = htons(5634); 51 CHECK_EQ(0, ntohs(mRTPAddr.sin_port) & 1); 52 53 mRTCPAddr = mRTPAddr; 54 mRTCPAddr.sin_port = htons(ntohs(mRTPAddr.sin_port) | 1); 55 56#if LOG_TO_FILES 57 mRTPFd = open( 58 "/data/misc/rtpout.bin", 59 O_WRONLY | O_CREAT | O_TRUNC, 60 0644); 61 CHECK_GE(mRTPFd, 0); 62 63 mRTCPFd = open( 64 "/data/misc/rtcpout.bin", 65 O_WRONLY | O_CREAT | O_TRUNC, 66 0644); 67 CHECK_GE(mRTCPFd, 0); 68#endif 69} 70 71ARTPWriter::~ARTPWriter() { 72#if LOG_TO_FILES 73 close(mRTCPFd); 74 mRTCPFd = -1; 75 76 close(mRTPFd); 77 mRTPFd = -1; 78#endif 79 80 close(mSocket); 81 mSocket = -1; 82 83 close(mFd); 84 mFd = -1; 85} 86 87status_t ARTPWriter::addSource(const sp<MediaSource> &source) { 88 mSource = source; 89 return OK; 90} 91 92bool ARTPWriter::reachedEOS() { 93 Mutex::Autolock autoLock(mLock); 94 return (mFlags & kFlagEOS) != 0; 95} 96 97status_t ARTPWriter::start(MetaData *params) { 98 Mutex::Autolock autoLock(mLock); 99 if (mFlags & kFlagStarted) { 100 return INVALID_OPERATION; 101 } 102 103 mFlags &= ~kFlagEOS; 104 mSourceID = rand(); 105 mSeqNo = UniformRand(65536); 106 mRTPTimeBase = rand(); 107 mNumRTPSent = 0; 108 mNumRTPOctetsSent = 0; 109 mLastRTPTime = 0; 110 mLastNTPTime = 0; 111 mNumSRsSent = 0; 112 113 const char *mime; 114 CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime)); 115 116 mMode = INVALID; 117 if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 118 mMode = H264; 119 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_H263)) { 120 mMode = H263; 121 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { 122 mMode = AMR_NB; 123 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { 124 mMode = AMR_WB; 125 } else { 126 TRESPASS(); 127 } 128 129 (new AMessage(kWhatStart, mReflector->id()))->post(); 130 131 while (!(mFlags & kFlagStarted)) { 132 mCondition.wait(mLock); 133 } 134 135 return OK; 136} 137 138status_t ARTPWriter::stop() { 139 Mutex::Autolock autoLock(mLock); 140 if (!(mFlags & kFlagStarted)) { 141 return OK; 142 } 143 144 (new AMessage(kWhatStop, mReflector->id()))->post(); 145 146 while (mFlags & kFlagStarted) { 147 mCondition.wait(mLock); 148 } 149 return OK; 150} 151 152status_t ARTPWriter::pause() { 153 return OK; 154} 155 156static void StripStartcode(MediaBuffer *buffer) { 157 if (buffer->range_length() < 4) { 158 return; 159 } 160 161 const uint8_t *ptr = 162 (const uint8_t *)buffer->data() + buffer->range_offset(); 163 164 if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) { 165 buffer->set_range( 166 buffer->range_offset() + 4, buffer->range_length() - 4); 167 } 168} 169 170void ARTPWriter::onMessageReceived(const sp<AMessage> &msg) { 171 switch (msg->what()) { 172 case kWhatStart: 173 { 174 CHECK_EQ(mSource->start(), (status_t)OK); 175 176#if 0 177 if (mMode == H264) { 178 MediaBuffer *buffer; 179 CHECK_EQ(mSource->read(&buffer), (status_t)OK); 180 181 StripStartcode(buffer); 182 makeH264SPropParamSets(buffer); 183 buffer->release(); 184 buffer = NULL; 185 } 186 187 dumpSessionDesc(); 188#endif 189 190 { 191 Mutex::Autolock autoLock(mLock); 192 mFlags |= kFlagStarted; 193 mCondition.signal(); 194 } 195 196 (new AMessage(kWhatRead, mReflector->id()))->post(); 197 (new AMessage(kWhatSendSR, mReflector->id()))->post(); 198 break; 199 } 200 201 case kWhatStop: 202 { 203 CHECK_EQ(mSource->stop(), (status_t)OK); 204 205 sendBye(); 206 207 { 208 Mutex::Autolock autoLock(mLock); 209 mFlags &= ~kFlagStarted; 210 mCondition.signal(); 211 } 212 break; 213 } 214 215 case kWhatRead: 216 { 217 { 218 Mutex::Autolock autoLock(mLock); 219 if (!(mFlags & kFlagStarted)) { 220 break; 221 } 222 } 223 224 onRead(msg); 225 break; 226 } 227 228 case kWhatSendSR: 229 { 230 { 231 Mutex::Autolock autoLock(mLock); 232 if (!(mFlags & kFlagStarted)) { 233 break; 234 } 235 } 236 237 onSendSR(msg); 238 break; 239 } 240 241 default: 242 TRESPASS(); 243 break; 244 } 245} 246 247void ARTPWriter::onRead(const sp<AMessage> &msg) { 248 MediaBuffer *mediaBuf; 249 status_t err = mSource->read(&mediaBuf); 250 251 if (err != OK) { 252 LOG(INFO) << "reached EOS."; 253 254 Mutex::Autolock autoLock(mLock); 255 mFlags |= kFlagEOS; 256 return; 257 } 258 259 if (mediaBuf->range_length() > 0) { 260 LOG(VERBOSE) << "read buffer of size " << mediaBuf->range_length(); 261 262 if (mMode == H264) { 263 StripStartcode(mediaBuf); 264 sendAVCData(mediaBuf); 265 } else if (mMode == H263) { 266 sendH263Data(mediaBuf); 267 } else if (mMode == AMR_NB || mMode == AMR_WB) { 268 sendAMRData(mediaBuf); 269 } 270 } 271 272 mediaBuf->release(); 273 mediaBuf = NULL; 274 275 msg->post(); 276} 277 278void ARTPWriter::onSendSR(const sp<AMessage> &msg) { 279 sp<ABuffer> buffer = new ABuffer(65536); 280 buffer->setRange(0, 0); 281 282 addSR(buffer); 283 addSDES(buffer); 284 285 send(buffer, true /* isRTCP */); 286 287 ++mNumSRsSent; 288 msg->post(3000000); 289} 290 291void ARTPWriter::send(const sp<ABuffer> &buffer, bool isRTCP) { 292 ssize_t n = sendto( 293 mSocket, buffer->data(), buffer->size(), 0, 294 (const struct sockaddr *)(isRTCP ? &mRTCPAddr : &mRTPAddr), 295 sizeof(mRTCPAddr)); 296 297 CHECK_EQ(n, (ssize_t)buffer->size()); 298 299#if LOG_TO_FILES 300 int fd = isRTCP ? mRTCPFd : mRTPFd; 301 302 uint32_t ms = tolel(ALooper::GetNowUs() / 1000ll); 303 uint32_t length = tolel(buffer->size()); 304 write(fd, &ms, sizeof(ms)); 305 write(fd, &length, sizeof(length)); 306 write(fd, buffer->data(), buffer->size()); 307#endif 308} 309 310void ARTPWriter::addSR(const sp<ABuffer> &buffer) { 311 uint8_t *data = buffer->data() + buffer->size(); 312 313 data[0] = 0x80 | 0; 314 data[1] = 200; // SR 315 data[2] = 0; 316 data[3] = 6; 317 data[4] = mSourceID >> 24; 318 data[5] = (mSourceID >> 16) & 0xff; 319 data[6] = (mSourceID >> 8) & 0xff; 320 data[7] = mSourceID & 0xff; 321 322 data[8] = mLastNTPTime >> (64 - 8); 323 data[9] = (mLastNTPTime >> (64 - 16)) & 0xff; 324 data[10] = (mLastNTPTime >> (64 - 24)) & 0xff; 325 data[11] = (mLastNTPTime >> 32) & 0xff; 326 data[12] = (mLastNTPTime >> 24) & 0xff; 327 data[13] = (mLastNTPTime >> 16) & 0xff; 328 data[14] = (mLastNTPTime >> 8) & 0xff; 329 data[15] = mLastNTPTime & 0xff; 330 331 data[16] = (mLastRTPTime >> 24) & 0xff; 332 data[17] = (mLastRTPTime >> 16) & 0xff; 333 data[18] = (mLastRTPTime >> 8) & 0xff; 334 data[19] = mLastRTPTime & 0xff; 335 336 data[20] = mNumRTPSent >> 24; 337 data[21] = (mNumRTPSent >> 16) & 0xff; 338 data[22] = (mNumRTPSent >> 8) & 0xff; 339 data[23] = mNumRTPSent & 0xff; 340 341 data[24] = mNumRTPOctetsSent >> 24; 342 data[25] = (mNumRTPOctetsSent >> 16) & 0xff; 343 data[26] = (mNumRTPOctetsSent >> 8) & 0xff; 344 data[27] = mNumRTPOctetsSent & 0xff; 345 346 buffer->setRange(buffer->offset(), buffer->size() + 28); 347} 348 349void ARTPWriter::addSDES(const sp<ABuffer> &buffer) { 350 uint8_t *data = buffer->data() + buffer->size(); 351 data[0] = 0x80 | 1; 352 data[1] = 202; // SDES 353 data[4] = mSourceID >> 24; 354 data[5] = (mSourceID >> 16) & 0xff; 355 data[6] = (mSourceID >> 8) & 0xff; 356 data[7] = mSourceID & 0xff; 357 358 size_t offset = 8; 359 360 data[offset++] = 1; // CNAME 361 362 static const char *kCNAME = "someone@somewhere"; 363 data[offset++] = strlen(kCNAME); 364 365 memcpy(&data[offset], kCNAME, strlen(kCNAME)); 366 offset += strlen(kCNAME); 367 368 data[offset++] = 7; // NOTE 369 370 static const char *kNOTE = "Hell's frozen over."; 371 data[offset++] = strlen(kNOTE); 372 373 memcpy(&data[offset], kNOTE, strlen(kNOTE)); 374 offset += strlen(kNOTE); 375 376 data[offset++] = 0; 377 378 if ((offset % 4) > 0) { 379 size_t count = 4 - (offset % 4); 380 switch (count) { 381 case 3: 382 data[offset++] = 0; 383 case 2: 384 data[offset++] = 0; 385 case 1: 386 data[offset++] = 0; 387 } 388 } 389 390 size_t numWords = (offset / 4) - 1; 391 data[2] = numWords >> 8; 392 data[3] = numWords & 0xff; 393 394 buffer->setRange(buffer->offset(), buffer->size() + offset); 395} 396 397// static 398uint64_t ARTPWriter::GetNowNTP() { 399 uint64_t nowUs = ALooper::GetNowUs(); 400 401 nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll; 402 403 uint64_t hi = nowUs / 1000000ll; 404 uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll; 405 406 return (hi << 32) | lo; 407} 408 409void ARTPWriter::dumpSessionDesc() { 410 AString sdp; 411 sdp = "v=0\r\n"; 412 413 sdp.append("o=- "); 414 415 uint64_t ntp = GetNowNTP(); 416 sdp.append(ntp); 417 sdp.append(" "); 418 sdp.append(ntp); 419 sdp.append(" IN IP4 127.0.0.0\r\n"); 420 421 sdp.append( 422 "s=Sample\r\n" 423 "i=Playing around\r\n" 424 "c=IN IP4 "); 425 426 struct in_addr addr; 427 addr.s_addr = ntohl(INADDR_LOOPBACK); 428 429 sdp.append(inet_ntoa(addr)); 430 431 sdp.append( 432 "\r\n" 433 "t=0 0\r\n" 434 "a=range:npt=now-\r\n"); 435 436 sp<MetaData> meta = mSource->getFormat(); 437 438 if (mMode == H264 || mMode == H263) { 439 sdp.append("m=video "); 440 } else { 441 sdp.append("m=audio "); 442 } 443 444 sdp.append(StringPrintf("%d", ntohs(mRTPAddr.sin_port))); 445 sdp.append( 446 " RTP/AVP " PT_STR "\r\n" 447 "b=AS 320000\r\n" 448 "a=rtpmap:" PT_STR " "); 449 450 if (mMode == H264) { 451 sdp.append("H264/90000"); 452 } else if (mMode == H263) { 453 sdp.append("H263-1998/90000"); 454 } else if (mMode == AMR_NB || mMode == AMR_WB) { 455 int32_t sampleRate, numChannels; 456 CHECK(mSource->getFormat()->findInt32(kKeySampleRate, &sampleRate)); 457 CHECK(mSource->getFormat()->findInt32(kKeyChannelCount, &numChannels)); 458 459 CHECK_EQ(numChannels, 1); 460 CHECK_EQ(sampleRate, (mMode == AMR_NB) ? 8000 : 16000); 461 462 sdp.append(mMode == AMR_NB ? "AMR" : "AMR-WB"); 463 sdp.append(StringPrintf("/%d/%d", sampleRate, numChannels)); 464 } else { 465 TRESPASS(); 466 } 467 468 sdp.append("\r\n"); 469 470 if (mMode == H264 || mMode == H263) { 471 int32_t width, height; 472 CHECK(meta->findInt32(kKeyWidth, &width)); 473 CHECK(meta->findInt32(kKeyHeight, &height)); 474 475 sdp.append("a=cliprect 0,0,"); 476 sdp.append(height); 477 sdp.append(","); 478 sdp.append(width); 479 sdp.append("\r\n"); 480 481 sdp.append( 482 "a=framesize:" PT_STR " "); 483 sdp.append(width); 484 sdp.append("-"); 485 sdp.append(height); 486 sdp.append("\r\n"); 487 } 488 489 if (mMode == H264) { 490 sdp.append( 491 "a=fmtp:" PT_STR " profile-level-id="); 492 sdp.append(mProfileLevel); 493 sdp.append(";sprop-parameter-sets="); 494 495 sdp.append(mSeqParamSet); 496 sdp.append(","); 497 sdp.append(mPicParamSet); 498 sdp.append(";packetization-mode=1\r\n"); 499 } else if (mMode == AMR_NB || mMode == AMR_WB) { 500 sdp.append("a=fmtp:" PT_STR " octed-align\r\n"); 501 } 502 503 LOG(INFO) << sdp; 504} 505 506void ARTPWriter::makeH264SPropParamSets(MediaBuffer *buffer) { 507 static const char kStartCode[] = "\x00\x00\x00\x01"; 508 509 const uint8_t *data = 510 (const uint8_t *)buffer->data() + buffer->range_offset(); 511 size_t size = buffer->range_length(); 512 513 CHECK_GE(size, 0u); 514 515 size_t startCodePos = 0; 516 while (startCodePos + 3 < size 517 && memcmp(kStartCode, &data[startCodePos], 4)) { 518 ++startCodePos; 519 } 520 521 CHECK_LT(startCodePos + 3, size); 522 523 CHECK_EQ((unsigned)data[0], 0x67u); 524 525 mProfileLevel = 526 StringPrintf("%02X%02X%02X", data[1], data[2], data[3]); 527 528 encodeBase64(data, startCodePos, &mSeqParamSet); 529 530 encodeBase64(&data[startCodePos + 4], size - startCodePos - 4, 531 &mPicParamSet); 532} 533 534void ARTPWriter::sendBye() { 535 sp<ABuffer> buffer = new ABuffer(8); 536 uint8_t *data = buffer->data(); 537 *data++ = (2 << 6) | 1; 538 *data++ = 203; 539 *data++ = 0; 540 *data++ = 1; 541 *data++ = mSourceID >> 24; 542 *data++ = (mSourceID >> 16) & 0xff; 543 *data++ = (mSourceID >> 8) & 0xff; 544 *data++ = mSourceID & 0xff; 545 buffer->setRange(0, 8); 546 547 send(buffer, true /* isRTCP */); 548} 549 550void ARTPWriter::sendAVCData(MediaBuffer *mediaBuf) { 551 // 12 bytes RTP header + 2 bytes for the FU-indicator and FU-header. 552 CHECK_GE(kMaxPacketSize, 12u + 2u); 553 554 int64_t timeUs; 555 CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs)); 556 557 uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll); 558 559 const uint8_t *mediaData = 560 (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset(); 561 562 sp<ABuffer> buffer = new ABuffer(kMaxPacketSize); 563 if (mediaBuf->range_length() + 12 <= buffer->capacity()) { 564 // The data fits into a single packet 565 uint8_t *data = buffer->data(); 566 data[0] = 0x80; 567 data[1] = (1 << 7) | PT; // M-bit 568 data[2] = (mSeqNo >> 8) & 0xff; 569 data[3] = mSeqNo & 0xff; 570 data[4] = rtpTime >> 24; 571 data[5] = (rtpTime >> 16) & 0xff; 572 data[6] = (rtpTime >> 8) & 0xff; 573 data[7] = rtpTime & 0xff; 574 data[8] = mSourceID >> 24; 575 data[9] = (mSourceID >> 16) & 0xff; 576 data[10] = (mSourceID >> 8) & 0xff; 577 data[11] = mSourceID & 0xff; 578 579 memcpy(&data[12], 580 mediaData, mediaBuf->range_length()); 581 582 buffer->setRange(0, mediaBuf->range_length() + 12); 583 584 send(buffer, false /* isRTCP */); 585 586 ++mSeqNo; 587 ++mNumRTPSent; 588 mNumRTPOctetsSent += buffer->size() - 12; 589 } else { 590 // FU-A 591 592 unsigned nalType = mediaData[0]; 593 size_t offset = 1; 594 595 bool firstPacket = true; 596 while (offset < mediaBuf->range_length()) { 597 size_t size = mediaBuf->range_length() - offset; 598 bool lastPacket = true; 599 if (size + 12 + 2 > buffer->capacity()) { 600 lastPacket = false; 601 size = buffer->capacity() - 12 - 2; 602 } 603 604 uint8_t *data = buffer->data(); 605 data[0] = 0x80; 606 data[1] = (lastPacket ? (1 << 7) : 0x00) | PT; // M-bit 607 data[2] = (mSeqNo >> 8) & 0xff; 608 data[3] = mSeqNo & 0xff; 609 data[4] = rtpTime >> 24; 610 data[5] = (rtpTime >> 16) & 0xff; 611 data[6] = (rtpTime >> 8) & 0xff; 612 data[7] = rtpTime & 0xff; 613 data[8] = mSourceID >> 24; 614 data[9] = (mSourceID >> 16) & 0xff; 615 data[10] = (mSourceID >> 8) & 0xff; 616 data[11] = mSourceID & 0xff; 617 618 data[12] = 28 | (nalType & 0xe0); 619 620 CHECK(!firstPacket || !lastPacket); 621 622 data[13] = 623 (firstPacket ? 0x80 : 0x00) 624 | (lastPacket ? 0x40 : 0x00) 625 | (nalType & 0x1f); 626 627 memcpy(&data[14], &mediaData[offset], size); 628 629 buffer->setRange(0, 14 + size); 630 631 send(buffer, false /* isRTCP */); 632 633 ++mSeqNo; 634 ++mNumRTPSent; 635 mNumRTPOctetsSent += buffer->size() - 12; 636 637 firstPacket = false; 638 offset += size; 639 } 640 } 641 642 mLastRTPTime = rtpTime; 643 mLastNTPTime = GetNowNTP(); 644} 645 646void ARTPWriter::sendH263Data(MediaBuffer *mediaBuf) { 647 CHECK_GE(kMaxPacketSize, 12u + 2u); 648 649 int64_t timeUs; 650 CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs)); 651 652 uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll); 653 654 const uint8_t *mediaData = 655 (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset(); 656 657 // hexdump(mediaData, mediaBuf->range_length()); 658 659 CHECK_EQ((unsigned)mediaData[0], 0u); 660 CHECK_EQ((unsigned)mediaData[1], 0u); 661 662 size_t offset = 2; 663 size_t size = mediaBuf->range_length(); 664 665 while (offset < size) { 666 sp<ABuffer> buffer = new ABuffer(kMaxPacketSize); 667 // CHECK_LE(mediaBuf->range_length() -2 + 14, buffer->capacity()); 668 669 size_t remaining = size - offset; 670 bool lastPacket = (remaining + 14 <= buffer->capacity()); 671 if (!lastPacket) { 672 remaining = buffer->capacity() - 14; 673 } 674 675 uint8_t *data = buffer->data(); 676 data[0] = 0x80; 677 data[1] = (lastPacket ? 0x80 : 0x00) | PT; // M-bit 678 data[2] = (mSeqNo >> 8) & 0xff; 679 data[3] = mSeqNo & 0xff; 680 data[4] = rtpTime >> 24; 681 data[5] = (rtpTime >> 16) & 0xff; 682 data[6] = (rtpTime >> 8) & 0xff; 683 data[7] = rtpTime & 0xff; 684 data[8] = mSourceID >> 24; 685 data[9] = (mSourceID >> 16) & 0xff; 686 data[10] = (mSourceID >> 8) & 0xff; 687 data[11] = mSourceID & 0xff; 688 689 data[12] = (offset == 2) ? 0x04 : 0x00; // P=?, V=0 690 data[13] = 0x00; // PLEN = PEBIT = 0 691 692 memcpy(&data[14], &mediaData[offset], remaining); 693 offset += remaining; 694 695 buffer->setRange(0, remaining + 14); 696 697 send(buffer, false /* isRTCP */); 698 699 ++mSeqNo; 700 ++mNumRTPSent; 701 mNumRTPOctetsSent += buffer->size() - 12; 702 } 703 704 mLastRTPTime = rtpTime; 705 mLastNTPTime = GetNowNTP(); 706} 707 708static size_t getFrameSize(bool isWide, unsigned FT) { 709 static const size_t kFrameSizeNB[8] = { 710 95, 103, 118, 134, 148, 159, 204, 244 711 }; 712 static const size_t kFrameSizeWB[9] = { 713 132, 177, 253, 285, 317, 365, 397, 461, 477 714 }; 715 716 size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT]; 717 718 // Round up bits to bytes and add 1 for the header byte. 719 frameSize = (frameSize + 7) / 8 + 1; 720 721 return frameSize; 722} 723 724void ARTPWriter::sendAMRData(MediaBuffer *mediaBuf) { 725 const uint8_t *mediaData = 726 (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset(); 727 728 size_t mediaLength = mediaBuf->range_length(); 729 730 CHECK_GE(kMaxPacketSize, 12u + 1u + mediaLength); 731 732 const bool isWide = (mMode == AMR_WB); 733 734 int64_t timeUs; 735 CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs)); 736 uint32_t rtpTime = mRTPTimeBase + (timeUs / (isWide ? 250 : 125)); 737 738 // hexdump(mediaData, mediaLength); 739 740 Vector<uint8_t> tableOfContents; 741 size_t srcOffset = 0; 742 while (srcOffset < mediaLength) { 743 uint8_t toc = mediaData[srcOffset]; 744 745 unsigned FT = (toc >> 3) & 0x0f; 746 CHECK((isWide && FT <= 8) || (!isWide && FT <= 7)); 747 748 tableOfContents.push(toc); 749 srcOffset += getFrameSize(isWide, FT); 750 } 751 CHECK_EQ(srcOffset, mediaLength); 752 753 sp<ABuffer> buffer = new ABuffer(kMaxPacketSize); 754 CHECK_LE(mediaLength + 12 + 1, buffer->capacity()); 755 756 // The data fits into a single packet 757 uint8_t *data = buffer->data(); 758 data[0] = 0x80; 759 data[1] = PT; 760 if (mNumRTPSent == 0) { 761 // Signal start of talk-spurt. 762 data[1] |= 0x80; // M-bit 763 } 764 data[2] = (mSeqNo >> 8) & 0xff; 765 data[3] = mSeqNo & 0xff; 766 data[4] = rtpTime >> 24; 767 data[5] = (rtpTime >> 16) & 0xff; 768 data[6] = (rtpTime >> 8) & 0xff; 769 data[7] = rtpTime & 0xff; 770 data[8] = mSourceID >> 24; 771 data[9] = (mSourceID >> 16) & 0xff; 772 data[10] = (mSourceID >> 8) & 0xff; 773 data[11] = mSourceID & 0xff; 774 775 data[12] = 0xf0; // CMR=15, RR=0 776 777 size_t dstOffset = 13; 778 779 for (size_t i = 0; i < tableOfContents.size(); ++i) { 780 uint8_t toc = tableOfContents[i]; 781 782 if (i + 1 < tableOfContents.size()) { 783 toc |= 0x80; 784 } else { 785 toc &= ~0x80; 786 } 787 788 data[dstOffset++] = toc; 789 } 790 791 srcOffset = 0; 792 for (size_t i = 0; i < tableOfContents.size(); ++i) { 793 uint8_t toc = tableOfContents[i]; 794 unsigned FT = (toc >> 3) & 0x0f; 795 size_t frameSize = getFrameSize(isWide, FT); 796 797 ++srcOffset; // skip toc 798 memcpy(&data[dstOffset], &mediaData[srcOffset], frameSize - 1); 799 srcOffset += frameSize - 1; 800 dstOffset += frameSize - 1; 801 } 802 803 buffer->setRange(0, dstOffset); 804 805 send(buffer, false /* isRTCP */); 806 807 ++mSeqNo; 808 ++mNumRTPSent; 809 mNumRTPOctetsSent += buffer->size() - 12; 810 811 mLastRTPTime = rtpTime; 812 mLastNTPTime = GetNowNTP(); 813} 814 815} // namespace android 816 817