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