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