ARTPWriter.cpp revision b4a7a2df4c28c3f32b5d877b54831d2cc5d78f81
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//#define LOG_NDEBUG 0
18#define LOG_TAG "ARTPWriter"
19#include <utils/Log.h>
20
21#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),
49      mFd(dup(fd)),
50      mLooper(new ALooper),
51      mReflector(new AHandlerReflector<ARTPWriter>(this)) {
52    CHECK_GE(fd, 0);
53
54    mLooper->setName("rtp writer");
55    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
67    mRTPAddr.sin_addr.s_addr = inet_addr("172.19.18.246");
68#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
158status_t ARTPWriter::stop() {
159    Mutex::Autolock autoLock(mLock);
160    if (!(mFlags & kFlagStarted)) {
161        return OK;
162    }
163
164    (new AMessage(kWhatStop, mReflector->id()))->post();
165
166    while (mFlags & kFlagStarted) {
167        mCondition.wait(mLock);
168    }
169    return OK;
170}
171
172status_t ARTPWriter::pause() {
173    return OK;
174}
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) {
272        ALOGI("reached EOS.");
273
274        Mutex::Autolock autoLock(mLock);
275        mFlags |= kFlagEOS;
276        return;
277    }
278
279    if (mediaBuf->range_length() > 0) {
280        ALOGV("read buffer of size %zu", mediaBuf->range_length());
281
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
523    ALOGI("%s", sdp.c_str());
524}
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
837