ARTPWriter.cpp revision 57648e4eec7dd2593af467877bc7cce4aa654759
157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#include "ARTPWriter.h"
257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#include <fcntl.h>
457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#include <media/stagefright/foundation/ADebug.h>
757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#include <media/stagefright/foundation/AMessage.h>
857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#include <media/stagefright/foundation/hexdump.h>
957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#include <media/stagefright/MediaBuffer.h>
1057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#include <media/stagefright/MediaDefs.h>
1157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#include <media/stagefright/MediaSource.h>
1257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#include <media/stagefright/MetaData.h>
1357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#include <utils/ByteOrder.h>
1457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
1557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#define PT      97
1657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#define PT_STR  "97"
1757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
1857648e4eec7dd2593af467877bc7cce4aa654759Andreas Hubernamespace android {
1957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
2057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber// static const size_t kMaxPacketSize = 65507;  // maximum payload in UDP over IP
2157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huberstatic const size_t kMaxPacketSize = 1500;
2257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
2357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huberstatic int UniformRand(int limit) {
2457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    return ((double)rand() * limit) / RAND_MAX;
2557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
2657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
2757648e4eec7dd2593af467877bc7cce4aa654759Andreas HuberARTPWriter::ARTPWriter(int fd)
2857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    : mFlags(0),
2957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber      mFd(fd),
3057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber      mLooper(new ALooper),
3157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber      mReflector(new AHandlerReflector<ARTPWriter>(this)) {
3257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK_GE(fd, 0);
3357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
3457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mLooper->registerHandler(mReflector);
3557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mLooper->start();
3657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
3757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mSocket = socket(AF_INET, SOCK_DGRAM, 0);
3857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK_GE(mSocket, 0);
3957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
4057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    memset(mRTPAddr.sin_zero, 0, sizeof(mRTPAddr.sin_zero));
4157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mRTPAddr.sin_family = AF_INET;
4257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
4357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#if 1
4457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mRTPAddr.sin_addr.s_addr = INADDR_ANY;
4557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#else
4657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mRTPAddr.sin_addr.s_addr = inet_addr("172.19.19.74");
4757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#endif
4857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
4957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mRTPAddr.sin_port = htons(5634);
5057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK_EQ(0, ntohs(mRTPAddr.sin_port) & 1);
5157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
5257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mRTCPAddr = mRTPAddr;
5357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mRTCPAddr.sin_port = htons(ntohs(mRTPAddr.sin_port) | 1);
5457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
5557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#if LOG_TO_FILES
5657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mRTPFd = open(
5757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            "/data/misc/rtpout.bin",
5857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            O_WRONLY | O_CREAT | O_TRUNC,
5957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            0644);
6057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK_GE(mRTPFd, 0);
6157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
6257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mRTCPFd = open(
6357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            "/data/misc/rtcpout.bin",
6457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            O_WRONLY | O_CREAT | O_TRUNC,
6557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            0644);
6657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK_GE(mRTCPFd, 0);
6757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#endif
6857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
6957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
7057648e4eec7dd2593af467877bc7cce4aa654759Andreas HuberARTPWriter::~ARTPWriter() {
7157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#if LOG_TO_FILES
7257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    close(mRTCPFd);
7357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mRTCPFd = -1;
7457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
7557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    close(mRTPFd);
7657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mRTPFd = -1;
7757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#endif
7857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
7957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    close(mSocket);
8057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mSocket = -1;
8157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
8257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    close(mFd);
8357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mFd = -1;
8457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
8557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
8657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huberstatus_t ARTPWriter::addSource(const sp<MediaSource> &source) {
8757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mSource = source;
8857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    return OK;
8957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
9057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
9157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huberbool ARTPWriter::reachedEOS() {
9257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    Mutex::Autolock autoLock(mLock);
9357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    return (mFlags & kFlagEOS) != 0;
9457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
9557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
9657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huberstatus_t ARTPWriter::start(MetaData *params) {
9757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    Mutex::Autolock autoLock(mLock);
9857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    if (mFlags & kFlagStarted) {
9957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        return INVALID_OPERATION;
10057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
10157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
10257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mFlags &= ~kFlagEOS;
10357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mSourceID = rand();
10457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mSeqNo = UniformRand(65536);
10557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mRTPTimeBase = rand();
10657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mNumRTPSent = 0;
10757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mNumRTPOctetsSent = 0;
10857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mLastRTPTime = 0;
10957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mLastNTPTime = 0;
11057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mNumSRsSent = 0;
11157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
11257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    const char *mime;
11357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
11457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
11557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mMode = INVALID;
11657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
11757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        mMode = H264;
11857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_H263)) {
11957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        mMode = H263;
12057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
12157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        mMode = AMR_NB;
12257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
12357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        mMode = AMR_WB;
12457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    } else {
12557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        TRESPASS();
12657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
12757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
12857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    (new AMessage(kWhatStart, mReflector->id()))->post();
12957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
13057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    while (!(mFlags & kFlagStarted)) {
13157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        mCondition.wait(mLock);
13257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
13357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
13457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    return OK;
13557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
13657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
13757648e4eec7dd2593af467877bc7cce4aa654759Andreas Hubervoid ARTPWriter::stop() {
13857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    Mutex::Autolock autoLock(mLock);
13957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    if (!(mFlags & kFlagStarted)) {
14057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        return;
14157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
14257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
14357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    (new AMessage(kWhatStop, mReflector->id()))->post();
14457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
14557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    while (mFlags & kFlagStarted) {
14657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        mCondition.wait(mLock);
14757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
14857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
14957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
15057648e4eec7dd2593af467877bc7cce4aa654759Andreas Hubervoid ARTPWriter::pause() {
15157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
15257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
15357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
15457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    if (buffer->range_length() < 4) {
15557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        return;
15657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
15757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
15857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    const uint8_t *ptr =
15957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
16057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
16157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
16257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        buffer->set_range(
16357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
16457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
16557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
16657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
16757648e4eec7dd2593af467877bc7cce4aa654759Andreas Hubervoid ARTPWriter::onMessageReceived(const sp<AMessage> &msg) {
16857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    switch (msg->what()) {
16957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        case kWhatStart:
17057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        {
17157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            CHECK_EQ(mSource->start(), (status_t)OK);
17257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
17357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#if 0
17457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            if (mMode == H264) {
17557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                MediaBuffer *buffer;
17657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                CHECK_EQ(mSource->read(&buffer), (status_t)OK);
17757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
17857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                StripStartcode(buffer);
17957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                makeH264SPropParamSets(buffer);
18057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                buffer->release();
18157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                buffer = NULL;
18257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            }
18357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
18457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            dumpSessionDesc();
18557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#endif
18657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
18757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            {
18857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                Mutex::Autolock autoLock(mLock);
18957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                mFlags |= kFlagStarted;
19057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                mCondition.signal();
19157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            }
19257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
19357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            (new AMessage(kWhatRead, mReflector->id()))->post();
19457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            (new AMessage(kWhatSendSR, mReflector->id()))->post();
19557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            break;
19657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        }
19757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
19857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        case kWhatStop:
19957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        {
20057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            CHECK_EQ(mSource->stop(), (status_t)OK);
20157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
20257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            sendBye();
20357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
20457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            {
20557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                Mutex::Autolock autoLock(mLock);
20657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                mFlags &= ~kFlagStarted;
20757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                mCondition.signal();
20857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            }
20957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            break;
21057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        }
21157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
21257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        case kWhatRead:
21357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        {
21457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            {
21557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                Mutex::Autolock autoLock(mLock);
21657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                if (!(mFlags & kFlagStarted)) {
21757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                    break;
21857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                }
21957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            }
22057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
22157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            onRead(msg);
22257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            break;
22357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        }
22457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
22557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        case kWhatSendSR:
22657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        {
22757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            {
22857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                Mutex::Autolock autoLock(mLock);
22957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                if (!(mFlags & kFlagStarted)) {
23057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                    break;
23157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                }
23257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            }
23357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
23457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            onSendSR(msg);
23557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            break;
23657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        }
23757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
23857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        default:
23957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            TRESPASS();
24057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            break;
24157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
24257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
24357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
24457648e4eec7dd2593af467877bc7cce4aa654759Andreas Hubervoid ARTPWriter::onRead(const sp<AMessage> &msg) {
24557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    MediaBuffer *mediaBuf;
24657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    status_t err = mSource->read(&mediaBuf);
24757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
24857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    if (err != OK) {
24957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        LOG(INFO) << "reached EOS.";
25057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
25157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        Mutex::Autolock autoLock(mLock);
25257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        mFlags |= kFlagEOS;
25357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        return;
25457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
25557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
25657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    if (mediaBuf->range_length() > 0) {
25757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        LOG(VERBOSE) << "read buffer of size " << mediaBuf->range_length();
25857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
25957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        if (mMode == H264) {
26057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            StripStartcode(mediaBuf);
26157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            sendAVCData(mediaBuf);
26257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        } else if (mMode == H263) {
26357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            sendH263Data(mediaBuf);
26457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        } else if (mMode == AMR_NB || mMode == AMR_WB) {
26557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            sendAMRData(mediaBuf);
26657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        }
26757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
26857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
26957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mediaBuf->release();
27057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mediaBuf = NULL;
27157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
27257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    msg->post();
27357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
27457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
27557648e4eec7dd2593af467877bc7cce4aa654759Andreas Hubervoid ARTPWriter::onSendSR(const sp<AMessage> &msg) {
27657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sp<ABuffer> buffer = new ABuffer(65536);
27757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    buffer->setRange(0, 0);
27857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
27957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    addSR(buffer);
28057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    addSDES(buffer);
28157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
28257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    send(buffer, true /* isRTCP */);
28357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
28457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    ++mNumSRsSent;
28557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    msg->post(3000000);
28657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
28757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
28857648e4eec7dd2593af467877bc7cce4aa654759Andreas Hubervoid ARTPWriter::send(const sp<ABuffer> &buffer, bool isRTCP) {
28957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    ssize_t n = sendto(
29057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            mSocket, buffer->data(), buffer->size(), 0,
29157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            (const struct sockaddr *)(isRTCP ? &mRTCPAddr : &mRTPAddr),
29257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            sizeof(mRTCPAddr));
29357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
29457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK_EQ(n, (ssize_t)buffer->size());
29557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
29657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#if LOG_TO_FILES
29757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    int fd = isRTCP ? mRTCPFd : mRTPFd;
29857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
29957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    uint32_t ms = tolel(ALooper::GetNowUs() / 1000ll);
30057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    uint32_t length = tolel(buffer->size());
30157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    write(fd, &ms, sizeof(ms));
30257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    write(fd, &length, sizeof(length));
30357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    write(fd, buffer->data(), buffer->size());
30457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber#endif
30557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
30657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
30757648e4eec7dd2593af467877bc7cce4aa654759Andreas Hubervoid ARTPWriter::addSR(const sp<ABuffer> &buffer) {
30857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    uint8_t *data = buffer->data() + buffer->size();
30957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
31057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[0] = 0x80 | 0;
31157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[1] = 200;  // SR
31257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[2] = 0;
31357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[3] = 6;
31457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[4] = mSourceID >> 24;
31557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[5] = (mSourceID >> 16) & 0xff;
31657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[6] = (mSourceID >> 8) & 0xff;
31757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[7] = mSourceID & 0xff;
31857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
31957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[8] = mLastNTPTime >> (64 - 8);
32057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[9] = (mLastNTPTime >> (64 - 16)) & 0xff;
32157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[10] = (mLastNTPTime >> (64 - 24)) & 0xff;
32257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[11] = (mLastNTPTime >> 32) & 0xff;
32357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[12] = (mLastNTPTime >> 24) & 0xff;
32457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[13] = (mLastNTPTime >> 16) & 0xff;
32557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[14] = (mLastNTPTime >> 8) & 0xff;
32657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[15] = mLastNTPTime & 0xff;
32757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
32857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[16] = (mLastRTPTime >> 24) & 0xff;
32957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[17] = (mLastRTPTime >> 16) & 0xff;
33057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[18] = (mLastRTPTime >> 8) & 0xff;
33157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[19] = mLastRTPTime & 0xff;
33257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
33357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[20] = mNumRTPSent >> 24;
33457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[21] = (mNumRTPSent >> 16) & 0xff;
33557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[22] = (mNumRTPSent >> 8) & 0xff;
33657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[23] = mNumRTPSent & 0xff;
33757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
33857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[24] = mNumRTPOctetsSent >> 24;
33957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[25] = (mNumRTPOctetsSent >> 16) & 0xff;
34057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[26] = (mNumRTPOctetsSent >> 8) & 0xff;
34157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[27] = mNumRTPOctetsSent & 0xff;
34257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
34357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    buffer->setRange(buffer->offset(), buffer->size() + 28);
34457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
34557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
34657648e4eec7dd2593af467877bc7cce4aa654759Andreas Hubervoid ARTPWriter::addSDES(const sp<ABuffer> &buffer) {
34757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    uint8_t *data = buffer->data() + buffer->size();
34857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[0] = 0x80 | 1;
34957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[1] = 202;  // SDES
35057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[4] = mSourceID >> 24;
35157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[5] = (mSourceID >> 16) & 0xff;
35257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[6] = (mSourceID >> 8) & 0xff;
35357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[7] = mSourceID & 0xff;
35457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
35557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    size_t offset = 8;
35657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
35757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[offset++] = 1;  // CNAME
35857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
35957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    static const char *kCNAME = "someone@somewhere";
36057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[offset++] = strlen(kCNAME);
36157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
36257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    memcpy(&data[offset], kCNAME, strlen(kCNAME));
36357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    offset += strlen(kCNAME);
36457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
36557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[offset++] = 7;  // NOTE
36657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
36757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    static const char *kNOTE = "Hell's frozen over.";
36857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[offset++] = strlen(kNOTE);
36957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
37057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    memcpy(&data[offset], kNOTE, strlen(kNOTE));
37157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    offset += strlen(kNOTE);
37257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
37357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[offset++] = 0;
37457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
37557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    if ((offset % 4) > 0) {
37657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        size_t count = 4 - (offset % 4);
37757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        switch (count) {
37857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            case 3:
37957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                data[offset++] = 0;
38057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            case 2:
38157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                data[offset++] = 0;
38257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            case 1:
38357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                data[offset++] = 0;
38457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        }
38557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
38657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
38757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    size_t numWords = (offset / 4) - 1;
38857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[2] = numWords >> 8;
38957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[3] = numWords & 0xff;
39057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
39157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    buffer->setRange(buffer->offset(), buffer->size() + offset);
39257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
39357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
39457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber// static
39557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huberuint64_t ARTPWriter::GetNowNTP() {
39657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    uint64_t nowUs = ALooper::GetNowUs();
39757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
39857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
39957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
40057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    uint64_t hi = nowUs / 1000000ll;
40157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll;
40257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
40357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    return (hi << 32) | lo;
40457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
40557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
40657648e4eec7dd2593af467877bc7cce4aa654759Andreas Hubervoid ARTPWriter::dumpSessionDesc() {
40757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    AString sdp;
40857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sdp = "v=0\r\n";
40957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
41057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sdp.append("o=- ");
41157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
41257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    uint64_t ntp = GetNowNTP();
41357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sdp.append(ntp);
41457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sdp.append(" ");
41557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sdp.append(ntp);
41657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sdp.append(" IN IP4 127.0.0.0\r\n");
41757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
41857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sdp.append(
41957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber          "s=Sample\r\n"
42057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber          "i=Playing around\r\n"
42157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber          "c=IN IP4 ");
42257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
42357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    struct in_addr addr;
42457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    addr.s_addr = ntohl(INADDR_LOOPBACK);
42557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
42657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sdp.append(inet_ntoa(addr));
42757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
42857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sdp.append(
42957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber          "\r\n"
43057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber          "t=0 0\r\n"
43157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber          "a=range:npt=now-\r\n");
43257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
43357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sp<MetaData> meta = mSource->getFormat();
43457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
43557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    if (mMode == H264 || mMode == H263) {
43657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append("m=video ");
43757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    } else {
43857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append("m=audio ");
43957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
44057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
44157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sdp.append(StringPrintf("%d", ntohs(mRTPAddr.sin_port)));
44257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sdp.append(
44357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber          " RTP/AVP " PT_STR "\r\n"
44457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber          "b=AS 320000\r\n"
44557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber          "a=rtpmap:" PT_STR " ");
44657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
44757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    if (mMode == H264) {
44857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append("H264/90000");
44957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    } else if (mMode == H263) {
45057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append("H263-1998/90000");
45157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    } else if (mMode == AMR_NB || mMode == AMR_WB) {
45257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        int32_t sampleRate, numChannels;
45357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        CHECK(mSource->getFormat()->findInt32(kKeySampleRate, &sampleRate));
45457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        CHECK(mSource->getFormat()->findInt32(kKeyChannelCount, &numChannels));
45557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
45657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        CHECK_EQ(numChannels, 1);
45757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        CHECK_EQ(sampleRate, (mMode == AMR_NB) ? 8000 : 16000);
45857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
45957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append(mMode == AMR_NB ? "AMR" : "AMR-WB");
46057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append(StringPrintf("/%d/%d", sampleRate, numChannels));
46157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    } else {
46257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        TRESPASS();
46357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
46457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
46557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sdp.append("\r\n");
46657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
46757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    if (mMode == H264 || mMode == H263) {
46857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        int32_t width, height;
46957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        CHECK(meta->findInt32(kKeyWidth, &width));
47057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        CHECK(meta->findInt32(kKeyHeight, &height));
47157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
47257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append("a=cliprect 0,0,");
47357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append(height);
47457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append(",");
47557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append(width);
47657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append("\r\n");
47757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
47857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append(
47957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber              "a=framesize:" PT_STR " ");
48057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append(width);
48157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append("-");
48257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append(height);
48357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append("\r\n");
48457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
48557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
48657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    if (mMode == H264) {
48757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append(
48857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber              "a=fmtp:" PT_STR " profile-level-id=");
48957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append(mProfileLevel);
49057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append(";sprop-parameter-sets=");
49157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
49257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append(mSeqParamSet);
49357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append(",");
49457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append(mPicParamSet);
49557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append(";packetization-mode=1\r\n");
49657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    } else if (mMode == AMR_NB || mMode == AMR_WB) {
49757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sdp.append("a=fmtp:" PT_STR " octed-align\r\n");
49857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
49957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
50057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    LOG(INFO) << sdp;
50157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
50257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
50357648e4eec7dd2593af467877bc7cce4aa654759Andreas Hubervoid ARTPWriter::makeH264SPropParamSets(MediaBuffer *buffer) {
50457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    static const char kStartCode[] = "\x00\x00\x00\x01";
50557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
50657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    const uint8_t *data =
50757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
50857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    size_t size = buffer->range_length();
50957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
51057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK_GE(size, 0u);
51157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
51257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    size_t startCodePos = 0;
51357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    while (startCodePos + 3 < size
51457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            && memcmp(kStartCode, &data[startCodePos], 4)) {
51557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        ++startCodePos;
51657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
51757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
51857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK_LT(startCodePos + 3, size);
51957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
52057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK_EQ((unsigned)data[0], 0x67u);
52157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
52257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mProfileLevel =
52357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        StringPrintf("%02X%02X%02X", data[1], data[2], data[3]);
52457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
52557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    encodeBase64(data, startCodePos, &mSeqParamSet);
52657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
52757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    encodeBase64(&data[startCodePos + 4], size - startCodePos - 4,
52857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                 &mPicParamSet);
52957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
53057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
53157648e4eec7dd2593af467877bc7cce4aa654759Andreas Hubervoid ARTPWriter::sendBye() {
53257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sp<ABuffer> buffer = new ABuffer(8);
53357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    uint8_t *data = buffer->data();
53457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    *data++ = (2 << 6) | 1;
53557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    *data++ = 203;
53657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    *data++ = 0;
53757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    *data++ = 1;
53857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    *data++ = mSourceID >> 24;
53957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    *data++ = (mSourceID >> 16) & 0xff;
54057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    *data++ = (mSourceID >> 8) & 0xff;
54157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    *data++ = mSourceID & 0xff;
54257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    buffer->setRange(0, 8);
54357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
54457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    send(buffer, true /* isRTCP */);
54557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
54657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
54757648e4eec7dd2593af467877bc7cce4aa654759Andreas Hubervoid ARTPWriter::sendAVCData(MediaBuffer *mediaBuf) {
54857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    // 12 bytes RTP header + 2 bytes for the FU-indicator and FU-header.
54957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK_GE(kMaxPacketSize, 12u + 2u);
55057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
55157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    int64_t timeUs;
55257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs));
55357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
55457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
55557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
55657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    const uint8_t *mediaData =
55757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
55857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
55957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
56057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    if (mediaBuf->range_length() + 12 <= buffer->capacity()) {
56157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        // The data fits into a single packet
56257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        uint8_t *data = buffer->data();
56357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[0] = 0x80;
56457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[1] = (1 << 7) | PT;  // M-bit
56557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[2] = (mSeqNo >> 8) & 0xff;
56657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[3] = mSeqNo & 0xff;
56757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[4] = rtpTime >> 24;
56857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[5] = (rtpTime >> 16) & 0xff;
56957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[6] = (rtpTime >> 8) & 0xff;
57057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[7] = rtpTime & 0xff;
57157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[8] = mSourceID >> 24;
57257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[9] = (mSourceID >> 16) & 0xff;
57357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[10] = (mSourceID >> 8) & 0xff;
57457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[11] = mSourceID & 0xff;
57557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
57657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        memcpy(&data[12],
57757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber               mediaData, mediaBuf->range_length());
57857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
57957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        buffer->setRange(0, mediaBuf->range_length() + 12);
58057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
58157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        send(buffer, false /* isRTCP */);
58257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
58357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        ++mSeqNo;
58457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        ++mNumRTPSent;
58557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        mNumRTPOctetsSent += buffer->size() - 12;
58657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    } else {
58757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        // FU-A
58857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
58957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        unsigned nalType = mediaData[0];
59057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        size_t offset = 1;
59157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
59257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        bool firstPacket = true;
59357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        while (offset < mediaBuf->range_length()) {
59457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            size_t size = mediaBuf->range_length() - offset;
59557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            bool lastPacket = true;
59657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            if (size + 12 + 2 > buffer->capacity()) {
59757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                lastPacket = false;
59857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                size = buffer->capacity() - 12 - 2;
59957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            }
60057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
60157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            uint8_t *data = buffer->data();
60257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            data[0] = 0x80;
60357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            data[1] = (lastPacket ? (1 << 7) : 0x00) | PT;  // M-bit
60457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            data[2] = (mSeqNo >> 8) & 0xff;
60557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            data[3] = mSeqNo & 0xff;
60657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            data[4] = rtpTime >> 24;
60757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            data[5] = (rtpTime >> 16) & 0xff;
60857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            data[6] = (rtpTime >> 8) & 0xff;
60957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            data[7] = rtpTime & 0xff;
61057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            data[8] = mSourceID >> 24;
61157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            data[9] = (mSourceID >> 16) & 0xff;
61257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            data[10] = (mSourceID >> 8) & 0xff;
61357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            data[11] = mSourceID & 0xff;
61457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
61557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            data[12] = 28 | (nalType & 0xe0);
61657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
61757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            CHECK(!firstPacket || !lastPacket);
61857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
61957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            data[13] =
62057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                (firstPacket ? 0x80 : 0x00)
62157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                | (lastPacket ? 0x40 : 0x00)
62257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber                | (nalType & 0x1f);
62357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
62457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            memcpy(&data[14], &mediaData[offset], size);
62557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
62657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            buffer->setRange(0, 14 + size);
62757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
62857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            send(buffer, false /* isRTCP */);
62957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
63057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            ++mSeqNo;
63157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            ++mNumRTPSent;
63257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            mNumRTPOctetsSent += buffer->size() - 12;
63357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
63457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            firstPacket = false;
63557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            offset += size;
63657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        }
63757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
63857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
63957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mLastRTPTime = rtpTime;
64057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mLastNTPTime = GetNowNTP();
64157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
64257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
64357648e4eec7dd2593af467877bc7cce4aa654759Andreas Hubervoid ARTPWriter::sendH263Data(MediaBuffer *mediaBuf) {
64457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK_GE(kMaxPacketSize, 12u + 2u);
64557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
64657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    int64_t timeUs;
64757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs));
64857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
64957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
65057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
65157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    const uint8_t *mediaData =
65257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
65357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
65457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    // hexdump(mediaData, mediaBuf->range_length());
65557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
65657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK_EQ((unsigned)mediaData[0], 0u);
65757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK_EQ((unsigned)mediaData[1], 0u);
65857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
65957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    size_t offset = 2;
66057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    size_t size = mediaBuf->range_length();
66157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
66257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    while (offset < size) {
66357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
66457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        // CHECK_LE(mediaBuf->range_length() -2 + 14, buffer->capacity());
66557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
66657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        size_t remaining = size - offset;
66757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        bool lastPacket = (remaining + 14 <= buffer->capacity());
66857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        if (!lastPacket) {
66957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            remaining = buffer->capacity() - 14;
67057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        }
67157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
67257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        uint8_t *data = buffer->data();
67357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[0] = 0x80;
67457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[1] = (lastPacket ? 0x80 : 0x00) | PT;  // M-bit
67557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[2] = (mSeqNo >> 8) & 0xff;
67657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[3] = mSeqNo & 0xff;
67757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[4] = rtpTime >> 24;
67857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[5] = (rtpTime >> 16) & 0xff;
67957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[6] = (rtpTime >> 8) & 0xff;
68057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[7] = rtpTime & 0xff;
68157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[8] = mSourceID >> 24;
68257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[9] = (mSourceID >> 16) & 0xff;
68357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[10] = (mSourceID >> 8) & 0xff;
68457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[11] = mSourceID & 0xff;
68557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
68657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[12] = (offset == 2) ? 0x04 : 0x00;  // P=?, V=0
68757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[13] = 0x00;  // PLEN = PEBIT = 0
68857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
68957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        memcpy(&data[14], &mediaData[offset], remaining);
69057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        offset += remaining;
69157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
69257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        buffer->setRange(0, remaining + 14);
69357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
69457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        send(buffer, false /* isRTCP */);
69557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
69657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        ++mSeqNo;
69757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        ++mNumRTPSent;
69857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        mNumRTPOctetsSent += buffer->size() - 12;
69957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
70057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
70157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mLastRTPTime = rtpTime;
70257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mLastNTPTime = GetNowNTP();
70357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
70457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
70557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huberstatic size_t getFrameSize(bool isWide, unsigned FT) {
70657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    static const size_t kFrameSizeNB[8] = {
70757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        95, 103, 118, 134, 148, 159, 204, 244
70857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    };
70957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    static const size_t kFrameSizeWB[9] = {
71057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        132, 177, 253, 285, 317, 365, 397, 461, 477
71157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    };
71257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
71357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT];
71457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
71557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    // Round up bits to bytes and add 1 for the header byte.
71657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    frameSize = (frameSize + 7) / 8 + 1;
71757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
71857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    return frameSize;
71957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
72057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
72157648e4eec7dd2593af467877bc7cce4aa654759Andreas Hubervoid ARTPWriter::sendAMRData(MediaBuffer *mediaBuf) {
72257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    const uint8_t *mediaData =
72357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
72457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
72557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    size_t mediaLength = mediaBuf->range_length();
72657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
72757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK_GE(kMaxPacketSize, 12u + 1u + mediaLength);
72857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
72957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    const bool isWide = (mMode == AMR_WB);
73057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
73157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    int64_t timeUs;
73257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs));
73357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    uint32_t rtpTime = mRTPTimeBase + (timeUs / (isWide ? 250 : 125));
73457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
73557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    // hexdump(mediaData, mediaLength);
73657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
73757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    Vector<uint8_t> tableOfContents;
73857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    size_t srcOffset = 0;
73957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    while (srcOffset < mediaLength) {
74057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        uint8_t toc = mediaData[srcOffset];
74157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
74257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        unsigned FT = (toc >> 3) & 0x0f;
74357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        CHECK((isWide && FT <= 8) || (!isWide && FT <= 7));
74457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
74557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        tableOfContents.push(toc);
74657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        srcOffset += getFrameSize(isWide, FT);
74757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
74857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK_EQ(srcOffset, mediaLength);
74957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
75057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
75157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    CHECK_LE(mediaLength + 12 + 1, buffer->capacity());
75257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
75357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    // The data fits into a single packet
75457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    uint8_t *data = buffer->data();
75557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[0] = 0x80;
75657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[1] = PT;
75757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    if (mNumRTPSent == 0) {
75857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        // Signal start of talk-spurt.
75957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[1] |= 0x80;  // M-bit
76057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
76157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[2] = (mSeqNo >> 8) & 0xff;
76257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[3] = mSeqNo & 0xff;
76357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[4] = rtpTime >> 24;
76457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[5] = (rtpTime >> 16) & 0xff;
76557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[6] = (rtpTime >> 8) & 0xff;
76657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[7] = rtpTime & 0xff;
76757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[8] = mSourceID >> 24;
76857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[9] = (mSourceID >> 16) & 0xff;
76957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[10] = (mSourceID >> 8) & 0xff;
77057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[11] = mSourceID & 0xff;
77157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
77257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    data[12] = 0xf0;  // CMR=15, RR=0
77357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
77457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    size_t dstOffset = 13;
77557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
77657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    for (size_t i = 0; i < tableOfContents.size(); ++i) {
77757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        uint8_t toc = tableOfContents[i];
77857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
77957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        if (i + 1 < tableOfContents.size()) {
78057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            toc |= 0x80;
78157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        } else {
78257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber            toc &= ~0x80;
78357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        }
78457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
78557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        data[dstOffset++] = toc;
78657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
78757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
78857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    srcOffset = 0;
78957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    for (size_t i = 0; i < tableOfContents.size(); ++i) {
79057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        uint8_t toc = tableOfContents[i];
79157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        unsigned FT = (toc >> 3) & 0x0f;
79257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        size_t frameSize = getFrameSize(isWide, FT);
79357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
79457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        ++srcOffset;  // skip toc
79557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        memcpy(&data[dstOffset], &mediaData[srcOffset], frameSize - 1);
79657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        srcOffset += frameSize - 1;
79757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber        dstOffset += frameSize - 1;
79857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    }
79957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
80057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    buffer->setRange(0, dstOffset);
80157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
80257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    send(buffer, false /* isRTCP */);
80357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
80457648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    ++mSeqNo;
80557648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    ++mNumRTPSent;
80657648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mNumRTPOctetsSent += buffer->size() - 12;
80757648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
80857648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mLastRTPTime = rtpTime;
80957648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber    mLastNTPTime = GetNowNTP();
81057648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}
81157648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
81257648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber}  // namespace android
81357648e4eec7dd2593af467877bc7cce4aa654759Andreas Huber
814