16e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber/*
26e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber * Copyright (C) 2010 The Android Open Source Project
36e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber *
46e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
56e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber * you may not use this file except in compliance with the License.
66e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber * You may obtain a copy of the License at
76e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber *
86e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
96e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber *
106e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber * Unless required by applicable law or agreed to in writing, software
116e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
126e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber * See the License for the specific language governing permissions and
146e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber * limitations under the License.
156e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber */
166e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber
176e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber//#define LOG_NDEBUG 0
186e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber#define LOG_TAG "ARTPWriter"
196e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber#include <utils/Log.h>
206e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber
2139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include "ARTPWriter.h"
2239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
2339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <fcntl.h>
2439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
2539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
2639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/foundation/ADebug.h>
2739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/foundation/AMessage.h>
2839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/foundation/hexdump.h>
2939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/MediaBuffer.h>
3039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/MediaDefs.h>
3139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/MediaSource.h>
3239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/MetaData.h>
3339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <utils/ByteOrder.h>
3439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
3539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#define PT      97
3639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#define PT_STR  "97"
3739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
3839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubernamespace android {
3939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
4039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber// static const size_t kMaxPacketSize = 65507;  // maximum payload in UDP over IP
4139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberstatic const size_t kMaxPacketSize = 1500;
4239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
4339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberstatic int UniformRand(int limit) {
4439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    return ((double)rand() * limit) / RAND_MAX;
4539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
4639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
4739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas HuberARTPWriter::ARTPWriter(int fd)
4839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    : mFlags(0),
49674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong      mFd(dup(fd)),
5039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber      mLooper(new ALooper),
5139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber      mReflector(new AHandlerReflector<ARTPWriter>(this)) {
5239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_GE(fd, 0);
5339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
54a814c1fdc2acf0ed2ee3b175110f6039be7c4873Andreas Huber    mLooper->setName("rtp writer");
5539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mLooper->registerHandler(mReflector);
5639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mLooper->start();
5739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
5839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mSocket = socket(AF_INET, SOCK_DGRAM, 0);
5939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_GE(mSocket, 0);
6039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
6139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    memset(mRTPAddr.sin_zero, 0, sizeof(mRTPAddr.sin_zero));
6239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mRTPAddr.sin_family = AF_INET;
6339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
6439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#if 1
6539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mRTPAddr.sin_addr.s_addr = INADDR_ANY;
6639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#else
67a6238a1e5b603ca2ccf3b2297c9bc8a141cf8559Andreas Huber    mRTPAddr.sin_addr.s_addr = inet_addr("172.19.18.246");
6839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#endif
6939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
7039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mRTPAddr.sin_port = htons(5634);
7139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_EQ(0, ntohs(mRTPAddr.sin_port) & 1);
7239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
7339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mRTCPAddr = mRTPAddr;
7439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mRTCPAddr.sin_port = htons(ntohs(mRTPAddr.sin_port) | 1);
7539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
7639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#if LOG_TO_FILES
7739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mRTPFd = open(
7839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            "/data/misc/rtpout.bin",
7939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            O_WRONLY | O_CREAT | O_TRUNC,
8039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            0644);
8139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_GE(mRTPFd, 0);
8239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
8339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mRTCPFd = open(
8439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            "/data/misc/rtcpout.bin",
8539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            O_WRONLY | O_CREAT | O_TRUNC,
8639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            0644);
8739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_GE(mRTCPFd, 0);
8839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#endif
8939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
9039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
9139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas HuberARTPWriter::~ARTPWriter() {
9239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#if LOG_TO_FILES
9339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    close(mRTCPFd);
9439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mRTCPFd = -1;
9539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
9639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    close(mRTPFd);
9739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mRTPFd = -1;
9839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#endif
9939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
10039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    close(mSocket);
10139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mSocket = -1;
10239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
10339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    close(mFd);
10439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mFd = -1;
10539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
10639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
10739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberstatus_t ARTPWriter::addSource(const sp<MediaSource> &source) {
10839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mSource = source;
10939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    return OK;
11039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
11139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
11239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberbool ARTPWriter::reachedEOS() {
11339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    Mutex::Autolock autoLock(mLock);
11439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    return (mFlags & kFlagEOS) != 0;
11539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
11639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
11739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberstatus_t ARTPWriter::start(MetaData *params) {
11839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    Mutex::Autolock autoLock(mLock);
11939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (mFlags & kFlagStarted) {
12039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        return INVALID_OPERATION;
12139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
12239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
12339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mFlags &= ~kFlagEOS;
12439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mSourceID = rand();
12539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mSeqNo = UniformRand(65536);
12639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mRTPTimeBase = rand();
12739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mNumRTPSent = 0;
12839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mNumRTPOctetsSent = 0;
12939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mLastRTPTime = 0;
13039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mLastNTPTime = 0;
13139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mNumSRsSent = 0;
13239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
13339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    const char *mime;
13439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
13539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
13639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mMode = INVALID;
13739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
13839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        mMode = H264;
13939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_H263)) {
14039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        mMode = H263;
14139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
14239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        mMode = AMR_NB;
14339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
14439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        mMode = AMR_WB;
14539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    } else {
14639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        TRESPASS();
14739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
14839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
14939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    (new AMessage(kWhatStart, mReflector->id()))->post();
15039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
15139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    while (!(mFlags & kFlagStarted)) {
15239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        mCondition.wait(mLock);
15339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
15439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
15539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    return OK;
15639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
15739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
15837187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t ARTPWriter::stop() {
15939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    Mutex::Autolock autoLock(mLock);
16039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (!(mFlags & kFlagStarted)) {
16137187916a486504acaf83bea30147eb5fbf46ae5James Dong        return OK;
16239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
16339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
16439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    (new AMessage(kWhatStop, mReflector->id()))->post();
16539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
16639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    while (mFlags & kFlagStarted) {
16739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        mCondition.wait(mLock);
16839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
16937187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
17039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
17139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
17237187916a486504acaf83bea30147eb5fbf46ae5James Dongstatus_t ARTPWriter::pause() {
17337187916a486504acaf83bea30147eb5fbf46ae5James Dong    return OK;
17439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
17539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
17639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberstatic void StripStartcode(MediaBuffer *buffer) {
17739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (buffer->range_length() < 4) {
17839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        return;
17939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
18039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
18139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    const uint8_t *ptr =
18239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
18339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
18439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
18539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        buffer->set_range(
18639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                buffer->range_offset() + 4, buffer->range_length() - 4);
18739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
18839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
18939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
19039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubervoid ARTPWriter::onMessageReceived(const sp<AMessage> &msg) {
19139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    switch (msg->what()) {
19239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        case kWhatStart:
19339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        {
19439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            CHECK_EQ(mSource->start(), (status_t)OK);
19539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
19639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#if 0
19739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            if (mMode == H264) {
19839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                MediaBuffer *buffer;
19939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                CHECK_EQ(mSource->read(&buffer), (status_t)OK);
20039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
20139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                StripStartcode(buffer);
20239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                makeH264SPropParamSets(buffer);
20339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                buffer->release();
20439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                buffer = NULL;
20539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            }
20639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
20739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            dumpSessionDesc();
20839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#endif
20939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
21039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            {
21139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                Mutex::Autolock autoLock(mLock);
21239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                mFlags |= kFlagStarted;
21339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                mCondition.signal();
21439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            }
21539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
21639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            (new AMessage(kWhatRead, mReflector->id()))->post();
21739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            (new AMessage(kWhatSendSR, mReflector->id()))->post();
21839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            break;
21939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        }
22039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
22139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        case kWhatStop:
22239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        {
22339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            CHECK_EQ(mSource->stop(), (status_t)OK);
22439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
22539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            sendBye();
22639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
22739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            {
22839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                Mutex::Autolock autoLock(mLock);
22939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                mFlags &= ~kFlagStarted;
23039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                mCondition.signal();
23139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            }
23239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            break;
23339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        }
23439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
23539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        case kWhatRead:
23639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        {
23739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            {
23839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                Mutex::Autolock autoLock(mLock);
23939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                if (!(mFlags & kFlagStarted)) {
24039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                    break;
24139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                }
24239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            }
24339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
24439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            onRead(msg);
24539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            break;
24639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        }
24739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
24839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        case kWhatSendSR:
24939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        {
25039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            {
25139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                Mutex::Autolock autoLock(mLock);
25239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                if (!(mFlags & kFlagStarted)) {
25339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                    break;
25439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                }
25539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            }
25639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
25739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            onSendSR(msg);
25839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            break;
25939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        }
26039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
26139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        default:
26239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            TRESPASS();
26339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            break;
26439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
26539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
26639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
26739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubervoid ARTPWriter::onRead(const sp<AMessage> &msg) {
26839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    MediaBuffer *mediaBuf;
26939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    status_t err = mSource->read(&mediaBuf);
27039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
27139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (err != OK) {
272df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("reached EOS.");
27339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
27439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        Mutex::Autolock autoLock(mLock);
27539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        mFlags |= kFlagEOS;
27639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        return;
27739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
27839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
27939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (mediaBuf->range_length() > 0) {
2803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("read buffer of size %d", mediaBuf->range_length());
28139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
28239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        if (mMode == H264) {
28339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            StripStartcode(mediaBuf);
28439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            sendAVCData(mediaBuf);
28539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        } else if (mMode == H263) {
28639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            sendH263Data(mediaBuf);
28739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        } else if (mMode == AMR_NB || mMode == AMR_WB) {
28839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            sendAMRData(mediaBuf);
28939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        }
29039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
29139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
29239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mediaBuf->release();
29339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mediaBuf = NULL;
29439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
29539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    msg->post();
29639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
29739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
29839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubervoid ARTPWriter::onSendSR(const sp<AMessage> &msg) {
29939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sp<ABuffer> buffer = new ABuffer(65536);
30039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    buffer->setRange(0, 0);
30139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
30239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    addSR(buffer);
30339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    addSDES(buffer);
30439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
30539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    send(buffer, true /* isRTCP */);
30639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
30739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    ++mNumSRsSent;
30839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    msg->post(3000000);
30939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
31039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
31139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubervoid ARTPWriter::send(const sp<ABuffer> &buffer, bool isRTCP) {
31239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    ssize_t n = sendto(
31339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            mSocket, buffer->data(), buffer->size(), 0,
31439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            (const struct sockaddr *)(isRTCP ? &mRTCPAddr : &mRTPAddr),
31539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            sizeof(mRTCPAddr));
31639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
31739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_EQ(n, (ssize_t)buffer->size());
31839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
31939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#if LOG_TO_FILES
32039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    int fd = isRTCP ? mRTCPFd : mRTPFd;
32139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
32239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint32_t ms = tolel(ALooper::GetNowUs() / 1000ll);
32339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint32_t length = tolel(buffer->size());
32439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    write(fd, &ms, sizeof(ms));
32539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    write(fd, &length, sizeof(length));
32639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    write(fd, buffer->data(), buffer->size());
32739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#endif
32839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
32939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
33039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubervoid ARTPWriter::addSR(const sp<ABuffer> &buffer) {
33139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint8_t *data = buffer->data() + buffer->size();
33239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
33339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[0] = 0x80 | 0;
33439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[1] = 200;  // SR
33539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[2] = 0;
33639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[3] = 6;
33739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[4] = mSourceID >> 24;
33839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[5] = (mSourceID >> 16) & 0xff;
33939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[6] = (mSourceID >> 8) & 0xff;
34039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[7] = mSourceID & 0xff;
34139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
34239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[8] = mLastNTPTime >> (64 - 8);
34339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[9] = (mLastNTPTime >> (64 - 16)) & 0xff;
34439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[10] = (mLastNTPTime >> (64 - 24)) & 0xff;
34539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[11] = (mLastNTPTime >> 32) & 0xff;
34639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[12] = (mLastNTPTime >> 24) & 0xff;
34739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[13] = (mLastNTPTime >> 16) & 0xff;
34839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[14] = (mLastNTPTime >> 8) & 0xff;
34939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[15] = mLastNTPTime & 0xff;
35039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
35139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[16] = (mLastRTPTime >> 24) & 0xff;
35239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[17] = (mLastRTPTime >> 16) & 0xff;
35339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[18] = (mLastRTPTime >> 8) & 0xff;
35439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[19] = mLastRTPTime & 0xff;
35539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
35639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[20] = mNumRTPSent >> 24;
35739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[21] = (mNumRTPSent >> 16) & 0xff;
35839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[22] = (mNumRTPSent >> 8) & 0xff;
35939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[23] = mNumRTPSent & 0xff;
36039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
36139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[24] = mNumRTPOctetsSent >> 24;
36239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[25] = (mNumRTPOctetsSent >> 16) & 0xff;
36339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[26] = (mNumRTPOctetsSent >> 8) & 0xff;
36439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[27] = mNumRTPOctetsSent & 0xff;
36539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
36639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    buffer->setRange(buffer->offset(), buffer->size() + 28);
36739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
36839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
36939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubervoid ARTPWriter::addSDES(const sp<ABuffer> &buffer) {
37039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint8_t *data = buffer->data() + buffer->size();
37139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[0] = 0x80 | 1;
37239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[1] = 202;  // SDES
37339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[4] = mSourceID >> 24;
37439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[5] = (mSourceID >> 16) & 0xff;
37539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[6] = (mSourceID >> 8) & 0xff;
37639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[7] = mSourceID & 0xff;
37739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
37839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    size_t offset = 8;
37939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
38039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[offset++] = 1;  // CNAME
38139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
38239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    static const char *kCNAME = "someone@somewhere";
38339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[offset++] = strlen(kCNAME);
38439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
38539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    memcpy(&data[offset], kCNAME, strlen(kCNAME));
38639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    offset += strlen(kCNAME);
38739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
38839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[offset++] = 7;  // NOTE
38939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
39039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    static const char *kNOTE = "Hell's frozen over.";
39139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[offset++] = strlen(kNOTE);
39239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
39339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    memcpy(&data[offset], kNOTE, strlen(kNOTE));
39439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    offset += strlen(kNOTE);
39539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
39639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[offset++] = 0;
39739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
39839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if ((offset % 4) > 0) {
39939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        size_t count = 4 - (offset % 4);
40039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        switch (count) {
40139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            case 3:
40239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                data[offset++] = 0;
40339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            case 2:
40439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                data[offset++] = 0;
40539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            case 1:
40639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                data[offset++] = 0;
40739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        }
40839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
40939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
41039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    size_t numWords = (offset / 4) - 1;
41139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[2] = numWords >> 8;
41239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[3] = numWords & 0xff;
41339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
41439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    buffer->setRange(buffer->offset(), buffer->size() + offset);
41539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
41639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
41739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber// static
41839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberuint64_t ARTPWriter::GetNowNTP() {
41939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint64_t nowUs = ALooper::GetNowUs();
42039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
42139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
42239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
42339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint64_t hi = nowUs / 1000000ll;
42439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll;
42539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
42639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    return (hi << 32) | lo;
42739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
42839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
42939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubervoid ARTPWriter::dumpSessionDesc() {
43039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    AString sdp;
43139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sdp = "v=0\r\n";
43239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
43339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sdp.append("o=- ");
43439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
43539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint64_t ntp = GetNowNTP();
43639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sdp.append(ntp);
43739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sdp.append(" ");
43839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sdp.append(ntp);
43939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sdp.append(" IN IP4 127.0.0.0\r\n");
44039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
44139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sdp.append(
44239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber          "s=Sample\r\n"
44339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber          "i=Playing around\r\n"
44439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber          "c=IN IP4 ");
44539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
44639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    struct in_addr addr;
44739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    addr.s_addr = ntohl(INADDR_LOOPBACK);
44839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
44939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sdp.append(inet_ntoa(addr));
45039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
45139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sdp.append(
45239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber          "\r\n"
45339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber          "t=0 0\r\n"
45439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber          "a=range:npt=now-\r\n");
45539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
45639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sp<MetaData> meta = mSource->getFormat();
45739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
45839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (mMode == H264 || mMode == H263) {
45939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append("m=video ");
46039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    } else {
46139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append("m=audio ");
46239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
46339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
46439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sdp.append(StringPrintf("%d", ntohs(mRTPAddr.sin_port)));
46539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sdp.append(
46639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber          " RTP/AVP " PT_STR "\r\n"
46739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber          "b=AS 320000\r\n"
46839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber          "a=rtpmap:" PT_STR " ");
46939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
47039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (mMode == H264) {
47139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append("H264/90000");
47239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    } else if (mMode == H263) {
47339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append("H263-1998/90000");
47439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    } else if (mMode == AMR_NB || mMode == AMR_WB) {
47539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        int32_t sampleRate, numChannels;
47639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        CHECK(mSource->getFormat()->findInt32(kKeySampleRate, &sampleRate));
47739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        CHECK(mSource->getFormat()->findInt32(kKeyChannelCount, &numChannels));
47839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
47939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        CHECK_EQ(numChannels, 1);
48039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        CHECK_EQ(sampleRate, (mMode == AMR_NB) ? 8000 : 16000);
48139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
48239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append(mMode == AMR_NB ? "AMR" : "AMR-WB");
48339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append(StringPrintf("/%d/%d", sampleRate, numChannels));
48439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    } else {
48539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        TRESPASS();
48639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
48739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
48839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sdp.append("\r\n");
48939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
49039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (mMode == H264 || mMode == H263) {
49139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        int32_t width, height;
49239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        CHECK(meta->findInt32(kKeyWidth, &width));
49339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        CHECK(meta->findInt32(kKeyHeight, &height));
49439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
49539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append("a=cliprect 0,0,");
49639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append(height);
49739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append(",");
49839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append(width);
49939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append("\r\n");
50039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
50139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append(
50239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber              "a=framesize:" PT_STR " ");
50339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append(width);
50439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append("-");
50539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append(height);
50639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append("\r\n");
50739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
50839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
50939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (mMode == H264) {
51039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append(
51139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber              "a=fmtp:" PT_STR " profile-level-id=");
51239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append(mProfileLevel);
51339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append(";sprop-parameter-sets=");
51439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
51539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append(mSeqParamSet);
51639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append(",");
51739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append(mPicParamSet);
51839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append(";packetization-mode=1\r\n");
51939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    } else if (mMode == AMR_NB || mMode == AMR_WB) {
52039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sdp.append("a=fmtp:" PT_STR " octed-align\r\n");
52139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
52239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
523df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("%s", sdp.c_str());
52439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
52539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
52639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubervoid ARTPWriter::makeH264SPropParamSets(MediaBuffer *buffer) {
52739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    static const char kStartCode[] = "\x00\x00\x00\x01";
52839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
52939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    const uint8_t *data =
53039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        (const uint8_t *)buffer->data() + buffer->range_offset();
53139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    size_t size = buffer->range_length();
53239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
53339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_GE(size, 0u);
53439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
53539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    size_t startCodePos = 0;
53639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    while (startCodePos + 3 < size
53739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            && memcmp(kStartCode, &data[startCodePos], 4)) {
53839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        ++startCodePos;
53939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
54039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
54139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_LT(startCodePos + 3, size);
54239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
54339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_EQ((unsigned)data[0], 0x67u);
54439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
54539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mProfileLevel =
54639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        StringPrintf("%02X%02X%02X", data[1], data[2], data[3]);
54739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
54839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    encodeBase64(data, startCodePos, &mSeqParamSet);
54939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
55039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    encodeBase64(&data[startCodePos + 4], size - startCodePos - 4,
55139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                 &mPicParamSet);
55239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
55339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
55439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubervoid ARTPWriter::sendBye() {
55539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sp<ABuffer> buffer = new ABuffer(8);
55639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint8_t *data = buffer->data();
55739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    *data++ = (2 << 6) | 1;
55839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    *data++ = 203;
55939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    *data++ = 0;
56039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    *data++ = 1;
56139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    *data++ = mSourceID >> 24;
56239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    *data++ = (mSourceID >> 16) & 0xff;
56339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    *data++ = (mSourceID >> 8) & 0xff;
56439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    *data++ = mSourceID & 0xff;
56539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    buffer->setRange(0, 8);
56639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
56739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    send(buffer, true /* isRTCP */);
56839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
56939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
57039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubervoid ARTPWriter::sendAVCData(MediaBuffer *mediaBuf) {
57139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    // 12 bytes RTP header + 2 bytes for the FU-indicator and FU-header.
57239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_GE(kMaxPacketSize, 12u + 2u);
57339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
57439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    int64_t timeUs;
57539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs));
57639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
57739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
57839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
57939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    const uint8_t *mediaData =
58039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
58139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
58239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
58339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (mediaBuf->range_length() + 12 <= buffer->capacity()) {
58439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        // The data fits into a single packet
58539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        uint8_t *data = buffer->data();
58639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[0] = 0x80;
58739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[1] = (1 << 7) | PT;  // M-bit
58839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[2] = (mSeqNo >> 8) & 0xff;
58939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[3] = mSeqNo & 0xff;
59039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[4] = rtpTime >> 24;
59139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[5] = (rtpTime >> 16) & 0xff;
59239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[6] = (rtpTime >> 8) & 0xff;
59339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[7] = rtpTime & 0xff;
59439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[8] = mSourceID >> 24;
59539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[9] = (mSourceID >> 16) & 0xff;
59639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[10] = (mSourceID >> 8) & 0xff;
59739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[11] = mSourceID & 0xff;
59839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
59939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        memcpy(&data[12],
60039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber               mediaData, mediaBuf->range_length());
60139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
60239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        buffer->setRange(0, mediaBuf->range_length() + 12);
60339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
60439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        send(buffer, false /* isRTCP */);
60539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
60639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        ++mSeqNo;
60739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        ++mNumRTPSent;
60839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        mNumRTPOctetsSent += buffer->size() - 12;
60939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    } else {
61039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        // FU-A
61139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
61239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        unsigned nalType = mediaData[0];
61339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        size_t offset = 1;
61439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
61539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        bool firstPacket = true;
61639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        while (offset < mediaBuf->range_length()) {
61739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            size_t size = mediaBuf->range_length() - offset;
61839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            bool lastPacket = true;
61939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            if (size + 12 + 2 > buffer->capacity()) {
62039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                lastPacket = false;
62139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                size = buffer->capacity() - 12 - 2;
62239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            }
62339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
62439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            uint8_t *data = buffer->data();
62539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            data[0] = 0x80;
62639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            data[1] = (lastPacket ? (1 << 7) : 0x00) | PT;  // M-bit
62739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            data[2] = (mSeqNo >> 8) & 0xff;
62839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            data[3] = mSeqNo & 0xff;
62939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            data[4] = rtpTime >> 24;
63039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            data[5] = (rtpTime >> 16) & 0xff;
63139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            data[6] = (rtpTime >> 8) & 0xff;
63239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            data[7] = rtpTime & 0xff;
63339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            data[8] = mSourceID >> 24;
63439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            data[9] = (mSourceID >> 16) & 0xff;
63539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            data[10] = (mSourceID >> 8) & 0xff;
63639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            data[11] = mSourceID & 0xff;
63739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
63839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            data[12] = 28 | (nalType & 0xe0);
63939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
64039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            CHECK(!firstPacket || !lastPacket);
64139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
64239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            data[13] =
64339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                (firstPacket ? 0x80 : 0x00)
64439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                | (lastPacket ? 0x40 : 0x00)
64539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                | (nalType & 0x1f);
64639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
64739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            memcpy(&data[14], &mediaData[offset], size);
64839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
64939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            buffer->setRange(0, 14 + size);
65039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
65139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            send(buffer, false /* isRTCP */);
65239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
65339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            ++mSeqNo;
65439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            ++mNumRTPSent;
65539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            mNumRTPOctetsSent += buffer->size() - 12;
65639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
65739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            firstPacket = false;
65839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            offset += size;
65939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        }
66039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
66139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
66239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mLastRTPTime = rtpTime;
66339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mLastNTPTime = GetNowNTP();
66439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
66539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
66639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubervoid ARTPWriter::sendH263Data(MediaBuffer *mediaBuf) {
66739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_GE(kMaxPacketSize, 12u + 2u);
66839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
66939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    int64_t timeUs;
67039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs));
67139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
67239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
67339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
67439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    const uint8_t *mediaData =
67539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
67639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
67739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    // hexdump(mediaData, mediaBuf->range_length());
67839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
67939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_EQ((unsigned)mediaData[0], 0u);
68039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_EQ((unsigned)mediaData[1], 0u);
68139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
68239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    size_t offset = 2;
68339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    size_t size = mediaBuf->range_length();
68439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
68539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    while (offset < size) {
68639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
68739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        // CHECK_LE(mediaBuf->range_length() -2 + 14, buffer->capacity());
68839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
68939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        size_t remaining = size - offset;
69039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        bool lastPacket = (remaining + 14 <= buffer->capacity());
69139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        if (!lastPacket) {
69239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            remaining = buffer->capacity() - 14;
69339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        }
69439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
69539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        uint8_t *data = buffer->data();
69639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[0] = 0x80;
69739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[1] = (lastPacket ? 0x80 : 0x00) | PT;  // M-bit
69839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[2] = (mSeqNo >> 8) & 0xff;
69939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[3] = mSeqNo & 0xff;
70039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[4] = rtpTime >> 24;
70139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[5] = (rtpTime >> 16) & 0xff;
70239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[6] = (rtpTime >> 8) & 0xff;
70339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[7] = rtpTime & 0xff;
70439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[8] = mSourceID >> 24;
70539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[9] = (mSourceID >> 16) & 0xff;
70639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[10] = (mSourceID >> 8) & 0xff;
70739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[11] = mSourceID & 0xff;
70839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
70939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[12] = (offset == 2) ? 0x04 : 0x00;  // P=?, V=0
71039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[13] = 0x00;  // PLEN = PEBIT = 0
71139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
71239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        memcpy(&data[14], &mediaData[offset], remaining);
71339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        offset += remaining;
71439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
71539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        buffer->setRange(0, remaining + 14);
71639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
71739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        send(buffer, false /* isRTCP */);
71839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
71939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        ++mSeqNo;
72039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        ++mNumRTPSent;
72139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        mNumRTPOctetsSent += buffer->size() - 12;
72239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
72339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
72439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mLastRTPTime = rtpTime;
72539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mLastNTPTime = GetNowNTP();
72639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
72739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
72839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberstatic size_t getFrameSize(bool isWide, unsigned FT) {
72939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    static const size_t kFrameSizeNB[8] = {
73039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        95, 103, 118, 134, 148, 159, 204, 244
73139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    };
73239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    static const size_t kFrameSizeWB[9] = {
73339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        132, 177, 253, 285, 317, 365, 397, 461, 477
73439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    };
73539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
73639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT];
73739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
73839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    // Round up bits to bytes and add 1 for the header byte.
73939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    frameSize = (frameSize + 7) / 8 + 1;
74039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
74139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    return frameSize;
74239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
74339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
74439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubervoid ARTPWriter::sendAMRData(MediaBuffer *mediaBuf) {
74539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    const uint8_t *mediaData =
74639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
74739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
74839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    size_t mediaLength = mediaBuf->range_length();
74939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
75039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_GE(kMaxPacketSize, 12u + 1u + mediaLength);
75139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
75239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    const bool isWide = (mMode == AMR_WB);
75339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
75439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    int64_t timeUs;
75539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs));
75639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint32_t rtpTime = mRTPTimeBase + (timeUs / (isWide ? 250 : 125));
75739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
75839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    // hexdump(mediaData, mediaLength);
75939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
76039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    Vector<uint8_t> tableOfContents;
76139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    size_t srcOffset = 0;
76239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    while (srcOffset < mediaLength) {
76339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        uint8_t toc = mediaData[srcOffset];
76439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
76539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        unsigned FT = (toc >> 3) & 0x0f;
76639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        CHECK((isWide && FT <= 8) || (!isWide && FT <= 7));
76739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
76839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        tableOfContents.push(toc);
76939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        srcOffset += getFrameSize(isWide, FT);
77039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
77139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_EQ(srcOffset, mediaLength);
77239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
77339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
77439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    CHECK_LE(mediaLength + 12 + 1, buffer->capacity());
77539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
77639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    // The data fits into a single packet
77739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint8_t *data = buffer->data();
77839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[0] = 0x80;
77939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[1] = PT;
78039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (mNumRTPSent == 0) {
78139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        // Signal start of talk-spurt.
78239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[1] |= 0x80;  // M-bit
78339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
78439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[2] = (mSeqNo >> 8) & 0xff;
78539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[3] = mSeqNo & 0xff;
78639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[4] = rtpTime >> 24;
78739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[5] = (rtpTime >> 16) & 0xff;
78839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[6] = (rtpTime >> 8) & 0xff;
78939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[7] = rtpTime & 0xff;
79039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[8] = mSourceID >> 24;
79139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[9] = (mSourceID >> 16) & 0xff;
79239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[10] = (mSourceID >> 8) & 0xff;
79339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[11] = mSourceID & 0xff;
79439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
79539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    data[12] = 0xf0;  // CMR=15, RR=0
79639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
79739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    size_t dstOffset = 13;
79839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
79939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    for (size_t i = 0; i < tableOfContents.size(); ++i) {
80039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        uint8_t toc = tableOfContents[i];
80139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
80239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        if (i + 1 < tableOfContents.size()) {
80339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            toc |= 0x80;
80439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        } else {
80539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            toc &= ~0x80;
80639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        }
80739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
80839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        data[dstOffset++] = toc;
80939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
81039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
81139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    srcOffset = 0;
81239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    for (size_t i = 0; i < tableOfContents.size(); ++i) {
81339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        uint8_t toc = tableOfContents[i];
81439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        unsigned FT = (toc >> 3) & 0x0f;
81539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        size_t frameSize = getFrameSize(isWide, FT);
81639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
81739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        ++srcOffset;  // skip toc
81839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        memcpy(&data[dstOffset], &mediaData[srcOffset], frameSize - 1);
81939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        srcOffset += frameSize - 1;
82039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        dstOffset += frameSize - 1;
82139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
82239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
82339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    buffer->setRange(0, dstOffset);
82439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
82539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    send(buffer, false /* isRTCP */);
82639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
82739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    ++mSeqNo;
82839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    ++mNumRTPSent;
82939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mNumRTPOctetsSent += buffer->size() - 12;
83039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
83139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mLastRTPTime = rtpTime;
83239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    mLastNTPTime = GetNowNTP();
83339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
83439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
83539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}  // namespace android
83639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
837