RTPSink.cpp revision fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96
1fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber/*
2fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * Copyright 2012, The Android Open Source Project
3fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber *
4fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * you may not use this file except in compliance with the License.
6fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * You may obtain a copy of the License at
7fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber *
8fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber *     http://www.apache.org/licenses/LICENSE-2.0
9fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber *
10fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * Unless required by applicable law or agreed to in writing, software
11fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * See the License for the specific language governing permissions and
14fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * limitations under the License.
15fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber */
16fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
17fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber//#define LOG_NDEBUG 0
18fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#define LOG_TAG "RTPSink"
19fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <utils/Log.h>
20fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
21fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include "RTPSink.h"
22fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
23fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include "ANetworkSession.h"
24fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include "TunnelRenderer.h"
25fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
26fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
27fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <media/stagefright/foundation/ADebug.h>
28fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <media/stagefright/foundation/AMessage.h>
29fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <media/stagefright/foundation/hexdump.h>
30fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <media/stagefright/MediaErrors.h>
31fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <media/stagefright/Utils.h>
32fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
33fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubernamespace android {
34fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
35fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstruct RTPSink::Source : public RefBase {
36fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    Source(uint16_t seq, const sp<ABuffer> &buffer,
37fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber           const sp<AMessage> queueBufferMsg);
38fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
39fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    bool updateSeq(uint16_t seq, const sp<ABuffer> &buffer);
40fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
41fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    void addReportBlock(uint32_t ssrc, const sp<ABuffer> &buf);
42fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
43fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberprotected:
44fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    virtual ~Source();
45fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
46fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberprivate:
47fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    static const uint32_t kMinSequential = 2;
48fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    static const uint32_t kMaxDropout = 3000;
49fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    static const uint32_t kMaxMisorder = 100;
50fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    static const uint32_t kRTPSeqMod = 1u << 16;
51fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
52fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    sp<AMessage> mQueueBufferMsg;
53fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
54fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint16_t mMaxSeq;
55fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t mCycles;
56fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t mBaseSeq;
57fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t mBadSeq;
58fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t mProbation;
59fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t mReceived;
60fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t mExpectedPrior;
61fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t mReceivedPrior;
62fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
63fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    void initSeq(uint16_t seq);
64fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    void queuePacket(const sp<ABuffer> &buffer);
65fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
66fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(Source);
67fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber};
68fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
69fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber////////////////////////////////////////////////////////////////////////////////
70fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
71fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas HuberRTPSink::Source::Source(
72fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        uint16_t seq, const sp<ABuffer> &buffer,
73fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        const sp<AMessage> queueBufferMsg)
74fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    : mQueueBufferMsg(queueBufferMsg),
75fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber      mProbation(kMinSequential) {
76fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    initSeq(seq);
77fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mMaxSeq = seq - 1;
78fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
79fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    buffer->setInt32Data(mCycles | seq);
80fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    queuePacket(buffer);
81fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
82fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
83fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas HuberRTPSink::Source::~Source() {
84fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
85fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
86fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid RTPSink::Source::initSeq(uint16_t seq) {
87fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mMaxSeq = seq;
88fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mCycles = 0;
89fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mBaseSeq = seq;
90fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mBadSeq = kRTPSeqMod + 1;
91fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mReceived = 0;
92fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mExpectedPrior = 0;
93fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mReceivedPrior = 0;
94fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
95fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
96fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberbool RTPSink::Source::updateSeq(uint16_t seq, const sp<ABuffer> &buffer) {
97fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint16_t udelta = seq - mMaxSeq;
98fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
99fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (mProbation) {
100fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        // Startup phase
101fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
102fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (seq == mMaxSeq + 1) {
103fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            buffer->setInt32Data(mCycles | seq);
104fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            queuePacket(buffer);
105fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
106fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            --mProbation;
107fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mMaxSeq = seq;
108fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            if (mProbation == 0) {
109fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                initSeq(seq);
110fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                ++mReceived;
111fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
112fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                return true;
113fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            }
114fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        } else {
115fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // Packet out of sequence, restart startup phase
116fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
117fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mProbation = kMinSequential - 1;
118fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mMaxSeq = seq;
119fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
120fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#if 0
121fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mPackets.clear();
122fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mTotalBytesQueued = 0;
123fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            ALOGI("XXX cleared packets");
124fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#endif
125fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
126fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            buffer->setInt32Data(mCycles | seq);
127fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            queuePacket(buffer);
128fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
129fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
130fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        return false;
131fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
132fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
133fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (udelta < kMaxDropout) {
134fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        // In order, with permissible gap.
135fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
136fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (seq < mMaxSeq) {
137fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // Sequence number wrapped - count another 64K cycle
138fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mCycles += kRTPSeqMod;
139fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
140fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
141fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mMaxSeq = seq;
142fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    } else if (udelta <= kRTPSeqMod - kMaxMisorder) {
143fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        // The sequence number made a very large jump
144fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
145fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (seq == mBadSeq) {
146fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // Two sequential packets -- assume that the other side
147fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // restarted without telling us so just re-sync
148fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // (i.e. pretend this was the first packet)
149fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
150fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            initSeq(seq);
151fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        } else {
152fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mBadSeq = (seq + 1) & (kRTPSeqMod - 1);
153fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
154fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            return false;
155fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
156fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    } else {
157fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        // Duplicate or reordered packet.
158fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
159fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
160fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ++mReceived;
161fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
162fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    buffer->setInt32Data(mCycles | seq);
163fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    queuePacket(buffer);
164fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
165fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    return true;
166fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
167fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
168fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid RTPSink::Source::queuePacket(const sp<ABuffer> &buffer) {
169fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    sp<AMessage> msg = mQueueBufferMsg->dup();
170fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    msg->setBuffer("buffer", buffer);
171fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    msg->post();
172fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
173fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
174fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid RTPSink::Source::addReportBlock(
175fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        uint32_t ssrc, const sp<ABuffer> &buf) {
176fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t extMaxSeq = mMaxSeq | mCycles;
177fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t expected = extMaxSeq - mBaseSeq + 1;
178fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
179fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    int64_t lost = (int64_t)expected - (int64_t)mReceived;
180fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (lost > 0x7fffff) {
181fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        lost = 0x7fffff;
182fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    } else if (lost < -0x800000) {
183fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        lost = -0x800000;
184fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
185fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
186fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t expectedInterval = expected - mExpectedPrior;
187fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mExpectedPrior = expected;
188fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
189fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t receivedInterval = mReceived - mReceivedPrior;
190fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mReceivedPrior = mReceived;
191fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
192fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    int64_t lostInterval = expectedInterval - receivedInterval;
193fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
194fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint8_t fractionLost;
195fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (expectedInterval == 0 || lostInterval <=0) {
196fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        fractionLost = 0;
197fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    } else {
198fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        fractionLost = (lostInterval << 8) / expectedInterval;
199fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
200fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
201fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint8_t *ptr = buf->data() + buf->size();
202fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
203fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[0] = ssrc >> 24;
204fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[1] = (ssrc >> 16) & 0xff;
205fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[2] = (ssrc >> 8) & 0xff;
206fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[3] = ssrc & 0xff;
207fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
208fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[4] = fractionLost;
209fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
210fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[5] = (lost >> 16) & 0xff;
211fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[6] = (lost >> 8) & 0xff;
212fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[7] = lost & 0xff;
213fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
214fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[8] = extMaxSeq >> 24;
215fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[9] = (extMaxSeq >> 16) & 0xff;
216fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[10] = (extMaxSeq >> 8) & 0xff;
217fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[11] = extMaxSeq & 0xff;
218fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
219fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    // XXX TODO:
220fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
221fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[12] = 0x00;  // interarrival jitter
222fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[13] = 0x00;
223fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[14] = 0x00;
224fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[15] = 0x00;
225fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
226fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[16] = 0x00;  // last SR
227fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[17] = 0x00;
228fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[18] = 0x00;
229fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[19] = 0x00;
230fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
231fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[20] = 0x00;  // delay since last SR
232fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[21] = 0x00;
233fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[22] = 0x00;
234fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[23] = 0x00;
235fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
236fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
237fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber////////////////////////////////////////////////////////////////////////////////
238fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
239fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas HuberRTPSink::RTPSink(
240fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        const sp<ANetworkSession> &netSession,
241fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        const sp<ISurfaceTexture> &surfaceTex)
242fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    : mNetSession(netSession),
243fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber      mSurfaceTex(surfaceTex),
244fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber      mRTPPort(0),
245fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber      mRTPSessionID(0),
246fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber      mRTCPSessionID(0),
247fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber      mFirstArrivalTimeUs(-1ll),
248fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber      mNumPacketsReceived(0ll),
249fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber      mRegression(1000),
250fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber      mMaxDelayMs(-1ll) {
251fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
252fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
253fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas HuberRTPSink::~RTPSink() {
254fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (mRTCPSessionID != 0) {
255fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mNetSession->destroySession(mRTCPSessionID);
256fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
257fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
258fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (mRTPSessionID != 0) {
259fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mNetSession->destroySession(mRTPSessionID);
260fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
261fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
262fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
263fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstatus_t RTPSink::init(bool useTCPInterleaving) {
264fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (useTCPInterleaving) {
265fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        return OK;
266fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
267fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
268fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    int clientRtp;
269fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
270fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, id());
271fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    sp<AMessage> rtcpNotify = new AMessage(kWhatRTCPNotify, id());
272fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    for (clientRtp = 15550;; clientRtp += 2) {
273fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        int32_t rtpSession;
274fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        status_t err = mNetSession->createUDPSession(
275fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    clientRtp, rtpNotify, &rtpSession);
276fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
277fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (err != OK) {
278fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            ALOGI("failed to create RTP socket on port %d", clientRtp);
279fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            continue;
280fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
281fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
282fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        int32_t rtcpSession;
283fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        err = mNetSession->createUDPSession(
284fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                clientRtp + 1, rtcpNotify, &rtcpSession);
285fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
286fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (err == OK) {
287fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mRTPPort = clientRtp;
288fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mRTPSessionID = rtpSession;
289fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mRTCPSessionID = rtcpSession;
290fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            break;
291fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
292fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
293fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        ALOGI("failed to create RTCP socket on port %d", clientRtp + 1);
294fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mNetSession->destroySession(rtpSession);
295fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
296fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
297fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (mRTPPort == 0) {
298fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        return UNKNOWN_ERROR;
299fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
300fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
301fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    return OK;
302fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
303fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
304fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberint32_t RTPSink::getRTPPort() const {
305fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    return mRTPPort;
306fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
307fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
308fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid RTPSink::onMessageReceived(const sp<AMessage> &msg) {
309fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    switch (msg->what()) {
310fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        case kWhatRTPNotify:
311fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        case kWhatRTCPNotify:
312fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        {
313fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            int32_t reason;
314fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            CHECK(msg->findInt32("reason", &reason));
315fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
316fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            switch (reason) {
317fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                case ANetworkSession::kWhatError:
318fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                {
319fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    int32_t sessionID;
320fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    CHECK(msg->findInt32("sessionID", &sessionID));
321fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
322fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    int32_t err;
323fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    CHECK(msg->findInt32("err", &err));
324fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
325fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    AString detail;
326fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    CHECK(msg->findString("detail", &detail));
327fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
328fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    ALOGE("An error occurred in session %d (%d, '%s/%s').",
329fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                          sessionID,
330fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                          err,
331fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                          detail.c_str(),
332fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                          strerror(-err));
333fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
334fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    mNetSession->destroySession(sessionID);
335fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
336fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    if (sessionID == mRTPSessionID) {
337fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                        mRTPSessionID = 0;
338fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    } else if (sessionID == mRTCPSessionID) {
339fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                        mRTCPSessionID = 0;
340fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    }
341fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    break;
342fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                }
343fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
344fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                case ANetworkSession::kWhatDatagram:
345fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                {
346fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    int32_t sessionID;
347fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    CHECK(msg->findInt32("sessionID", &sessionID));
348fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
349fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    sp<ABuffer> data;
350fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    CHECK(msg->findBuffer("data", &data));
351fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
352fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    status_t err;
353fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    if (msg->what() == kWhatRTPNotify) {
354fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                        err = parseRTP(data);
355fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    } else {
356fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                        err = parseRTCP(data);
357fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    }
358fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    break;
359fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                }
360fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
361fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                default:
362fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    TRESPASS();
363fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            }
364fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            break;
365fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
366fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
367fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        case kWhatSendRR:
368fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        {
369fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            onSendRR();
370fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            break;
371fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
372fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
373fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        case kWhatPacketLost:
374fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        {
375fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            onPacketLost(msg);
376fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            break;
377fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
378fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
379fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        case kWhatInject:
380fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        {
381fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            int32_t isRTP;
382fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            CHECK(msg->findInt32("isRTP", &isRTP));
383fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
384fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            sp<ABuffer> buffer;
385fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            CHECK(msg->findBuffer("buffer", &buffer));
386fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
387fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            status_t err;
388fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            if (isRTP) {
389fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                err = parseRTP(buffer);
390fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            } else {
391fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                err = parseRTCP(buffer);
392fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            }
393fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            break;
394fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
395fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
396fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        default:
397fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            TRESPASS();
398fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
399fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
400fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
401fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstatus_t RTPSink::injectPacket(bool isRTP, const sp<ABuffer> &buffer) {
402fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    sp<AMessage> msg = new AMessage(kWhatInject, id());
403fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    msg->setInt32("isRTP", isRTP);
404fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    msg->setBuffer("buffer", buffer);
405fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    msg->post();
406fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
407fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    return OK;
408fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
409fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
410fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstatus_t RTPSink::parseRTP(const sp<ABuffer> &buffer) {
411fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    size_t size = buffer->size();
412fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (size < 12) {
413fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        // Too short to be a valid RTP header.
414fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        return ERROR_MALFORMED;
415fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
416fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
417fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    const uint8_t *data = buffer->data();
418fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
419fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if ((data[0] >> 6) != 2) {
420fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        // Unsupported version.
421fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        return ERROR_UNSUPPORTED;
422fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
423fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
424fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (data[0] & 0x20) {
425fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        // Padding present.
426fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
427fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        size_t paddingLength = data[size - 1];
428fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
429fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (paddingLength + 12 > size) {
430fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // If we removed this much padding we'd end up with something
431fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // that's too short to be a valid RTP header.
432fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            return ERROR_MALFORMED;
433fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
434fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
435fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        size -= paddingLength;
436fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
437fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
438fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    int numCSRCs = data[0] & 0x0f;
439fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
440fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    size_t payloadOffset = 12 + 4 * numCSRCs;
441fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
442fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (size < payloadOffset) {
443fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        // Not enough data to fit the basic header and all the CSRC entries.
444fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        return ERROR_MALFORMED;
445fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
446fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
447fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (data[0] & 0x10) {
448fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        // Header eXtension present.
449fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
450fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (size < payloadOffset + 4) {
451fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // Not enough data to fit the basic header, all CSRC entries
452fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // and the first 4 bytes of the extension header.
453fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
454fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            return ERROR_MALFORMED;
455fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
456fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
457fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        const uint8_t *extensionData = &data[payloadOffset];
458fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
459fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        size_t extensionLength =
460fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            4 * (extensionData[2] << 8 | extensionData[3]);
461fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
462fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (size < payloadOffset + 4 + extensionLength) {
463fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            return ERROR_MALFORMED;
464fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
465fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
466fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        payloadOffset += 4 + extensionLength;
467fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
468fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
469fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t srcId = U32_AT(&data[8]);
470fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t rtpTime = U32_AT(&data[4]);
471fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint16_t seqNo = U16_AT(&data[2]);
472fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
473fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    int64_t arrivalTimeUs;
474fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    CHECK(buffer->meta()->findInt64("arrivalTimeUs", &arrivalTimeUs));
475fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
476fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (mFirstArrivalTimeUs < 0ll) {
477fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mFirstArrivalTimeUs = arrivalTimeUs;
478fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
479fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    arrivalTimeUs -= mFirstArrivalTimeUs;
480fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
481fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    int64_t arrivalTimeMedia = (arrivalTimeUs * 9ll) / 100ll;
482fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
483fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ALOGV("seqNo: %d, SSRC 0x%08x, diff %lld",
484fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            seqNo, srcId, rtpTime - arrivalTimeMedia);
485fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
486fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mRegression.addPoint((float)rtpTime, (float)arrivalTimeMedia);
487fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
488fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ++mNumPacketsReceived;
489fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
490fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    float n1, n2, b;
491fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (mRegression.approxLine(&n1, &n2, &b)) {
492fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        ALOGV("Line %lld: %.2f %.2f %.2f, slope %.2f",
493fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber              mNumPacketsReceived, n1, n2, b, -n1 / n2);
494fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
495fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        float expectedArrivalTimeMedia = (b - n1 * (float)rtpTime) / n2;
496fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        float latenessMs = (arrivalTimeMedia - expectedArrivalTimeMedia) / 90.0;
497fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
498fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (mMaxDelayMs < 0ll || latenessMs > mMaxDelayMs) {
499fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mMaxDelayMs = latenessMs;
500fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            ALOGI("packet was %.2f ms late", latenessMs);
501fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
502fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
503fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
504fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    sp<AMessage> meta = buffer->meta();
505fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    meta->setInt32("ssrc", srcId);
506fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    meta->setInt32("rtp-time", rtpTime);
507fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    meta->setInt32("PT", data[1] & 0x7f);
508fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    meta->setInt32("M", data[1] >> 7);
509fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
510fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    buffer->setRange(payloadOffset, size - payloadOffset);
511fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
512fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ssize_t index = mSources.indexOfKey(srcId);
513fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (index < 0) {
514fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (mRenderer == NULL) {
515fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            sp<AMessage> notifyLost = new AMessage(kWhatPacketLost, id());
516fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            notifyLost->setInt32("ssrc", srcId);
517fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
518fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mRenderer = new TunnelRenderer(notifyLost, mSurfaceTex);
519fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            looper()->registerHandler(mRenderer);
520fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
521fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
522fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        sp<AMessage> queueBufferMsg =
523fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            new AMessage(TunnelRenderer::kWhatQueueBuffer, mRenderer->id());
524fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
525fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        sp<Source> source = new Source(seqNo, buffer, queueBufferMsg);
526fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mSources.add(srcId, source);
527fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    } else {
528fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mSources.valueAt(index)->updateSeq(seqNo, buffer);
529fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
530fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
531fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    return OK;
532fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
533fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
534fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstatus_t RTPSink::parseRTCP(const sp<ABuffer> &buffer) {
535fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    const uint8_t *data = buffer->data();
536fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    size_t size = buffer->size();
537fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
538fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    while (size > 0) {
539fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (size < 8) {
540fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // Too short to be a valid RTCP header
541fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            return ERROR_MALFORMED;
542fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
543fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
544fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if ((data[0] >> 6) != 2) {
545fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // Unsupported version.
546fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            return ERROR_UNSUPPORTED;
547fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
548fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
549fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (data[0] & 0x20) {
550fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // Padding present.
551fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
552fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            size_t paddingLength = data[size - 1];
553fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
554fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            if (paddingLength + 12 > size) {
555fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                // If we removed this much padding we'd end up with something
556fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                // that's too short to be a valid RTP header.
557fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                return ERROR_MALFORMED;
558fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            }
559fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
560fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            size -= paddingLength;
561fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
562fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
563fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        size_t headerLength = 4 * (data[2] << 8 | data[3]) + 4;
564fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
565fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (size < headerLength) {
566fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // Only received a partial packet?
567fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            return ERROR_MALFORMED;
568fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
569fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
570fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        switch (data[1]) {
571fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            case 200:
572fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            {
573fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                parseSR(data, headerLength);
574fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                break;
575fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            }
576fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
577fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            case 201:  // RR
578fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            case 202:  // SDES
579fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            case 204:  // APP
580fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                break;
581fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
582fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            case 205:  // TSFB (transport layer specific feedback)
583fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            case 206:  // PSFB (payload specific feedback)
584fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                // hexdump(data, headerLength);
585fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                break;
586fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
587fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            case 203:
588fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            {
589fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                parseBYE(data, headerLength);
590fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                break;
591fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            }
592fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
593fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            default:
594fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            {
595fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                ALOGW("Unknown RTCP packet type %u of size %d",
596fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                     (unsigned)data[1], headerLength);
597fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                break;
598fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            }
599fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
600fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
601fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        data += headerLength;
602fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        size -= headerLength;
603fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
604fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
605fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    return OK;
606fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
607fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
608fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstatus_t RTPSink::parseBYE(const uint8_t *data, size_t size) {
609fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    size_t SC = data[0] & 0x3f;
610fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
611fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (SC == 0 || size < (4 + SC * 4)) {
612fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        // Packet too short for the minimal BYE header.
613fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        return ERROR_MALFORMED;
614fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
615fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
616fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t id = U32_AT(&data[4]);
617fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
618fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    return OK;
619fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
620fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
621fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstatus_t RTPSink::parseSR(const uint8_t *data, size_t size) {
622fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    size_t RC = data[0] & 0x1f;
623fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
624fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (size < (7 + RC * 6) * 4) {
625fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        // Packet too short for the minimal SR header.
626fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        return ERROR_MALFORMED;
627fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
628fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
629fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t id = U32_AT(&data[4]);
630fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint64_t ntpTime = U64_AT(&data[8]);
631fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t rtpTime = U32_AT(&data[16]);
632fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
633fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ALOGV("SR: ssrc 0x%08x, ntpTime 0x%016llx, rtpTime 0x%08x",
634fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber          id, ntpTime, rtpTime);
635fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
636fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    return OK;
637fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
638fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
639fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstatus_t RTPSink::connect(
640fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        const char *host, int32_t remoteRtpPort, int32_t remoteRtcpPort) {
641fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ALOGI("connecting RTP/RTCP sockets to %s:{%d,%d}",
642fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber          host, remoteRtpPort, remoteRtcpPort);
643fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
644fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    status_t err =
645fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mNetSession->connectUDPSession(mRTPSessionID, host, remoteRtpPort);
646fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
647fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (err != OK) {
648fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        return err;
649fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
650fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
651fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    err = mNetSession->connectUDPSession(mRTCPSessionID, host, remoteRtcpPort);
652fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
653fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (err != OK) {
654fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        return err;
655fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
656fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
657fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#if 0
658fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    sp<ABuffer> buf = new ABuffer(1500);
659fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    memset(buf->data(), 0, buf->size());
660fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
661fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mNetSession->sendRequest(
662fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mRTPSessionID, buf->data(), buf->size());
663fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
664fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mNetSession->sendRequest(
665fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mRTCPSessionID, buf->data(), buf->size());
666fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#endif
667fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
668fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    scheduleSendRR();
669fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
670fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    return OK;
671fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
672fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
673fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid RTPSink::scheduleSendRR() {
674fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    (new AMessage(kWhatSendRR, id()))->post(2000000ll);
675fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
676fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
677fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid RTPSink::addSDES(const sp<ABuffer> &buffer) {
678fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint8_t *data = buffer->data() + buffer->size();
679fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    data[0] = 0x80 | 1;
680fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    data[1] = 202;  // SDES
681fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    data[4] = 0xde;  // SSRC
682fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    data[5] = 0xad;
683fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    data[6] = 0xbe;
684fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    data[7] = 0xef;
685fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
686fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    size_t offset = 8;
687fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
688fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    data[offset++] = 1;  // CNAME
689fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
690fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    AString cname = "stagefright@somewhere";
691fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    data[offset++] = cname.size();
692fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
693fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    memcpy(&data[offset], cname.c_str(), cname.size());
694fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    offset += cname.size();
695fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
696fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    data[offset++] = 6;  // TOOL
697fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
698fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    AString tool = "stagefright/1.0";
699fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    data[offset++] = tool.size();
700fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
701fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    memcpy(&data[offset], tool.c_str(), tool.size());
702fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    offset += tool.size();
703fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
704fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    data[offset++] = 0;
705fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
706fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if ((offset % 4) > 0) {
707fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        size_t count = 4 - (offset % 4);
708fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        switch (count) {
709fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            case 3:
710fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                data[offset++] = 0;
711fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            case 2:
712fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                data[offset++] = 0;
713fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            case 1:
714fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                data[offset++] = 0;
715fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
716fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
717fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
718fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    size_t numWords = (offset / 4) - 1;
719fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    data[2] = numWords >> 8;
720fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    data[3] = numWords & 0xff;
721fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
722fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    buffer->setRange(buffer->offset(), buffer->size() + offset);
723fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
724fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
725fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid RTPSink::onSendRR() {
726fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    sp<ABuffer> buf = new ABuffer(1500);
727fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    buf->setRange(0, 0);
728fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
729fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint8_t *ptr = buf->data();
730fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[0] = 0x80 | 0;
731fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[1] = 201;  // RR
732fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[2] = 0;
733fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[3] = 1;
734fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[4] = 0xde;  // SSRC
735fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[5] = 0xad;
736fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[6] = 0xbe;
737fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[7] = 0xef;
738fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
739fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    buf->setRange(0, 8);
740fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
741fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    size_t numReportBlocks = 0;
742fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    for (size_t i = 0; i < mSources.size(); ++i) {
743fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        uint32_t ssrc = mSources.keyAt(i);
744fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        sp<Source> source = mSources.valueAt(i);
745fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
746fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (numReportBlocks > 31 || buf->size() + 24 > buf->capacity()) {
747fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // Cannot fit another report block.
748fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            break;
749fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
750fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
751fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        source->addReportBlock(ssrc, buf);
752fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        ++numReportBlocks;
753fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
754fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
755fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[0] |= numReportBlocks;  // 5 bit
756fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
757fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    size_t sizeInWordsMinus1 = 1 + 6 * numReportBlocks;
758fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[2] = sizeInWordsMinus1 >> 8;
759fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[3] = sizeInWordsMinus1 & 0xff;
760fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
761fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    buf->setRange(0, (sizeInWordsMinus1 + 1) * 4);
762fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
763fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    addSDES(buf);
764fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
765fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mNetSession->sendRequest(mRTCPSessionID, buf->data(), buf->size());
766fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
767fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    scheduleSendRR();
768fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
769fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
770fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid RTPSink::onPacketLost(const sp<AMessage> &msg) {
771fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint32_t srcId;
772fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    CHECK(msg->findInt32("ssrc", (int32_t *)&srcId));
773fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
774fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    int32_t seqNo;
775fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    CHECK(msg->findInt32("seqNo", &seqNo));
776fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
777fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    int32_t blp = 0;
778fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
779fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    sp<ABuffer> buf = new ABuffer(1500);
780fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    buf->setRange(0, 0);
781fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
782fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    uint8_t *ptr = buf->data();
783fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[0] = 0x80 | 1;  // generic NACK
784fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[1] = 205;  // RTPFB
785fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[2] = 0;
786fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[3] = 3;
787fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[4] = 0xde;  // sender SSRC
788fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[5] = 0xad;
789fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[6] = 0xbe;
790fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[7] = 0xef;
791fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[8] = (srcId >> 24) & 0xff;
792fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[9] = (srcId >> 16) & 0xff;
793fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[10] = (srcId >> 8) & 0xff;
794fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[11] = (srcId & 0xff);
795fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[12] = (seqNo >> 8) & 0xff;
796fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[13] = (seqNo & 0xff);
797fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[14] = (blp >> 8) & 0xff;
798fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ptr[15] = (blp & 0xff);
799fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
800fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    buf->setRange(0, 16);
801fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
802fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mNetSession->sendRequest(mRTCPSessionID, buf->data(), buf->size());
803fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
804fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
805fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}  // namespace android
806fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
807