1cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber/*
2cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Copyright (C) 2010 The Android Open Source Project
3cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber *
4cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * you may not use this file except in compliance with the License.
6cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * You may obtain a copy of the License at
7cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber *
8cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber *
10cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Unless required by applicable law or agreed to in writing, software
11cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * See the License for the specific language governing permissions and
14cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * limitations under the License.
15cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber */
16cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
176e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber//#define LOG_NDEBUG 0
186e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber#define LOG_TAG "ARTPConnection"
196e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber#include <utils/Log.h>
206e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber
213677437296fd1547d762b1b227a3de83dbc960d6Tareq A. Siraj#include "ARTPAssembler.h"
22cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ARTPConnection.h"
23cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
24cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ARTPSource.h"
25cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ASessionDescription.h"
26cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
27cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
28cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ADebug.h>
29cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/AMessage.h>
30cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/AString.h>
3139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include <media/stagefright/foundation/hexdump.h>
32cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
33cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <arpa/inet.h>
34cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <sys/socket.h>
35cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
36cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubernamespace android {
37cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
3839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberstatic const size_t kMaxUDPSize = 1500;
3939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
40cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatic uint16_t u16at(const uint8_t *data) {
41cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return data[0] << 8 | data[1];
42cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
43cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
44cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatic uint32_t u32at(const uint8_t *data) {
45cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return u16at(data) << 16 | u16at(&data[2]);
46cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
47cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
48cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatic uint64_t u64at(const uint8_t *data) {
49cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return (uint64_t)(u32at(data)) << 32 | u32at(&data[4]);
50cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
51cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
52cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber// static
53cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberconst int64_t ARTPConnection::kSelectTimeoutUs = 1000ll;
54cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
55cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstruct ARTPConnection::StreamInfo {
56cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int mRTPSocket;
57cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int mRTCPSocket;
58cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<ASessionDescription> mSessionDesc;
59cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    size_t mIndex;
60cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> mNotifyMsg;
6139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    KeyedVector<uint32_t, sp<ARTPSource> > mSources;
6239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
63f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber    int64_t mNumRTCPPacketsReceived;
64f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber    int64_t mNumRTPPacketsReceived;
6539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    struct sockaddr_in mRemoteRTCPAddr;
660792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
670792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    bool mIsInjected;
68cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber};
69cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
70f8ca90452ff3e252f20de38f1c3eee524c808c3eAndreas HuberARTPConnection::ARTPConnection(uint32_t flags)
71f8ca90452ff3e252f20de38f1c3eee524c808c3eAndreas Huber    : mFlags(flags),
72f8ca90452ff3e252f20de38f1c3eee524c808c3eAndreas Huber      mPollEventPending(false),
7339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber      mLastReceiverReportTimeUs(-1) {
74cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
75cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
76cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas HuberARTPConnection::~ARTPConnection() {
77cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
78cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
79cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTPConnection::addStream(
80cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        int rtpSocket, int rtcpSocket,
81cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        const sp<ASessionDescription> &sessionDesc,
82cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size_t index,
830792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        const sp<AMessage> &notify,
840792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        bool injected) {
851d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatAddStream, this);
86cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setInt32("rtp-socket", rtpSocket);
87cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setInt32("rtcp-socket", rtcpSocket);
88cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setObject("session-desc", sessionDesc);
89cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setSize("index", index);
90cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setMessage("notify", notify);
910792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    msg->setInt32("injected", injected);
92cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->post();
93cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
94cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
95cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTPConnection::removeStream(int rtpSocket, int rtcpSocket) {
961d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatRemoveStream, this);
97cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setInt32("rtp-socket", rtpSocket);
98cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setInt32("rtcp-socket", rtcpSocket);
99cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->post();
100cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
101cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
102cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatic void bumpSocketBufferSize(int s) {
103cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int size = 256 * 1024;
104cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK_EQ(setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)), 0);
105cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
106cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
107cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber// static
108cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTPConnection::MakePortPair(
109cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        int *rtpSocket, int *rtcpSocket, unsigned *rtpPort) {
110cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    *rtpSocket = socket(AF_INET, SOCK_DGRAM, 0);
111cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK_GE(*rtpSocket, 0);
112cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
113cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    bumpSocketBufferSize(*rtpSocket);
114cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
115cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    *rtcpSocket = socket(AF_INET, SOCK_DGRAM, 0);
116cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK_GE(*rtcpSocket, 0);
117cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
118cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    bumpSocketBufferSize(*rtcpSocket);
119cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1206cb3f224d7e2280f8834d361bba1a72682aaaad1Yajun Zeng    /* rand() * 1000 may overflow int type, use long long */
1216cb3f224d7e2280f8834d361bba1a72682aaaad1Yajun Zeng    unsigned start = (unsigned)((rand()* 1000ll)/RAND_MAX) + 15550;
122cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    start &= ~1;
123cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
124cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    for (unsigned port = start; port < 65536; port += 2) {
125cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        struct sockaddr_in addr;
126cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
127cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        addr.sin_family = AF_INET;
128dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber        addr.sin_addr.s_addr = htonl(INADDR_ANY);
129cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        addr.sin_port = htons(port);
130cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
131cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (bind(*rtpSocket,
132cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                 (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
133cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            continue;
134cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
135cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
136cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        addr.sin_port = htons(port + 1);
137cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
138cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (bind(*rtcpSocket,
139cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                 (const struct sockaddr *)&addr, sizeof(addr)) == 0) {
140cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            *rtpPort = port;
141cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return;
142cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
143cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
144cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
145cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    TRESPASS();
146cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
147cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
148cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTPConnection::onMessageReceived(const sp<AMessage> &msg) {
149cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    switch (msg->what()) {
150cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        case kWhatAddStream:
151cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        {
152cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            onAddStream(msg);
153cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
154cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
155cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
156cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        case kWhatRemoveStream:
157cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        {
158cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            onRemoveStream(msg);
159cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
160cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
161cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
162cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        case kWhatPollStreams:
163cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        {
164cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            onPollStreams();
165cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
166cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
167cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1680792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        case kWhatInjectPacket:
1690792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        {
1700792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            onInjectPacket(msg);
1710792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            break;
1720792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        }
1730792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
174cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        default:
175cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        {
176cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            TRESPASS();
177cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
178cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
179cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
180cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
181cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
182cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTPConnection::onAddStream(const sp<AMessage> &msg) {
183cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mStreams.push_back(StreamInfo());
184cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    StreamInfo *info = &*--mStreams.end();
185cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
186cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int32_t s;
187cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findInt32("rtp-socket", &s));
188cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    info->mRTPSocket = s;
189cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findInt32("rtcp-socket", &s));
190cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    info->mRTCPSocket = s;
191cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1920792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    int32_t injected;
1930792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    CHECK(msg->findInt32("injected", &injected));
1940792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
1950792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    info->mIsInjected = injected;
1960792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
197cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<RefBase> obj;
198cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findObject("session-desc", &obj));
199cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    info->mSessionDesc = static_cast<ASessionDescription *>(obj.get());
200cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
201cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findSize("index", &info->mIndex));
202cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findMessage("notify", &info->mNotifyMsg));
203cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
20439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    info->mNumRTCPPacketsReceived = 0;
205f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber    info->mNumRTPPacketsReceived = 0;
20639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    memset(&info->mRemoteRTCPAddr, 0, sizeof(info->mRemoteRTCPAddr));
20739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
2080792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    if (!injected) {
2090792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        postPollEvent();
2100792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    }
211cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
212cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
213cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTPConnection::onRemoveStream(const sp<AMessage> &msg) {
214cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int32_t rtpSocket, rtcpSocket;
215cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findInt32("rtp-socket", &rtpSocket));
216cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findInt32("rtcp-socket", &rtcpSocket));
217cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
218cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    List<StreamInfo>::iterator it = mStreams.begin();
219cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    while (it != mStreams.end()
220cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           && (it->mRTPSocket != rtpSocket || it->mRTCPSocket != rtcpSocket)) {
221cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        ++it;
222cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
223cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
224cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (it == mStreams.end()) {
2258c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber        return;
226cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
227cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
228cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mStreams.erase(it);
229cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
230cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
231cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTPConnection::postPollEvent() {
232cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (mPollEventPending) {
233cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return;
234cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
235cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
2361d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatPollStreams, this);
237cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->post();
238cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
239cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mPollEventPending = true;
240cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
241cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
242cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTPConnection::onPollStreams() {
243cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mPollEventPending = false;
244cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
245cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (mStreams.empty()) {
246cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return;
247cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
248cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
249cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    struct timeval tv;
250cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    tv.tv_sec = 0;
251cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    tv.tv_usec = kSelectTimeoutUs;
252cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
253cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    fd_set rs;
254cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    FD_ZERO(&rs);
255cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
256cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int maxSocket = -1;
257cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    for (List<StreamInfo>::iterator it = mStreams.begin();
258cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber         it != mStreams.end(); ++it) {
2590792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        if ((*it).mIsInjected) {
2600792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            continue;
2610792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        }
2620792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
263cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        FD_SET(it->mRTPSocket, &rs);
264cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        FD_SET(it->mRTCPSocket, &rs);
265cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
266cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (it->mRTPSocket > maxSocket) {
267cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            maxSocket = it->mRTPSocket;
268cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
269cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (it->mRTCPSocket > maxSocket) {
270cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            maxSocket = it->mRTCPSocket;
271cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
272cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
273cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
2747aef03379179c109c2547c33c410bfc93c8db576Andreas Huber    if (maxSocket == -1) {
2757aef03379179c109c2547c33c410bfc93c8db576Andreas Huber        return;
2767aef03379179c109c2547c33c410bfc93c8db576Andreas Huber    }
2777aef03379179c109c2547c33c410bfc93c8db576Andreas Huber
278cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int res = select(maxSocket + 1, &rs, NULL, NULL, &tv);
279cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
280cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (res > 0) {
2818c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber        List<StreamInfo>::iterator it = mStreams.begin();
2828c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber        while (it != mStreams.end()) {
2830792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            if ((*it).mIsInjected) {
2848c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                ++it;
2850792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber                continue;
2860792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            }
2870792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
2888c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber            status_t err = OK;
289cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            if (FD_ISSET(it->mRTPSocket, &rs)) {
2908c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                err = receive(&*it, true);
2918c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber            }
2928c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber            if (err == OK && FD_ISSET(it->mRTCPSocket, &rs)) {
2938c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                err = receive(&*it, false);
294cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
2958c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber
2968c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber            if (err == -ECONNRESET) {
2978c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                // socket failure, this stream is dead, Jim.
2988c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber
2995ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block                ALOGW("failed to receive RTP/RTCP datagram.");
3008c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                it = mStreams.erase(it);
3018c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                continue;
302cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
3038c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber
3048c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber            ++it;
305cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
306cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
307cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
30839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    int64_t nowUs = ALooper::GetNowUs();
30939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (mLastReceiverReportTimeUs <= 0
31039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            || mLastReceiverReportTimeUs + 5000000ll <= nowUs) {
31139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        sp<ABuffer> buffer = new ABuffer(kMaxUDPSize);
3128c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber        List<StreamInfo>::iterator it = mStreams.begin();
3138c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber        while (it != mStreams.end()) {
31439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            StreamInfo *s = &*it;
31539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
3167aef03379179c109c2547c33c410bfc93c8db576Andreas Huber            if (s->mIsInjected) {
3178c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                ++it;
3187aef03379179c109c2547c33c410bfc93c8db576Andreas Huber                continue;
3197aef03379179c109c2547c33c410bfc93c8db576Andreas Huber            }
3207aef03379179c109c2547c33c410bfc93c8db576Andreas Huber
32139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            if (s->mNumRTCPPacketsReceived == 0) {
32239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                // We have never received any RTCP packets on this stream,
32339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                // we don't even know where to send a report.
3248c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                ++it;
32539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                continue;
32639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            }
32739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
32839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            buffer->setRange(0, 0);
32939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
33039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            for (size_t i = 0; i < s->mSources.size(); ++i) {
33139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                sp<ARTPSource> source = s->mSources.valueAt(i);
33239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
33339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                source->addReceiverReport(buffer);
334f8ca90452ff3e252f20de38f1c3eee524c808c3eAndreas Huber
335f8ca90452ff3e252f20de38f1c3eee524c808c3eAndreas Huber                if (mFlags & kRegularlyRequestFIR) {
336f8ca90452ff3e252f20de38f1c3eee524c808c3eAndreas Huber                    source->addFIR(buffer);
337f8ca90452ff3e252f20de38f1c3eee524c808c3eAndreas Huber                }
33839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            }
33939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
34039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            if (buffer->size() > 0) {
3413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("Sending RR...");
34239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
3438c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                ssize_t n;
3448c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                do {
3458c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                    n = sendto(
34639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                        s->mRTCPSocket, buffer->data(), buffer->size(), 0,
34739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                        (const struct sockaddr *)&s->mRemoteRTCPAddr,
34839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                        sizeof(s->mRemoteRTCPAddr));
3498c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                } while (n < 0 && errno == EINTR);
3508c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber
3518c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                if (n <= 0) {
3525ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block                    ALOGW("failed to send RTCP receiver report (%s).",
3538c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                         n == 0 ? "connection gone" : strerror(errno));
3548c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber
3558c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                    it = mStreams.erase(it);
3568c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                    continue;
3578c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber                }
3588c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber
35939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                CHECK_EQ(n, (ssize_t)buffer->size());
36039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
36139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                mLastReceiverReportTimeUs = nowUs;
36239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            }
3638c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber
3648c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber            ++it;
36539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        }
36639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
3678c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber
3688c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber    if (!mStreams.empty()) {
3698c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber        postPollEvent();
3708c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber    }
371cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
372cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
373cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatus_t ARTPConnection::receive(StreamInfo *s, bool receiveRTP) {
3743856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("receiving %s", receiveRTP ? "RTP" : "RTCP");
375dc468c5f9d72ce54de0070493e9a23efb8907e06Andreas Huber
3760792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    CHECK(!s->mIsInjected);
3770792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
378cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<ABuffer> buffer = new ABuffer(65536);
379cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
38039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    socklen_t remoteAddrLen =
38139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        (!receiveRTP && s->mNumRTCPPacketsReceived == 0)
38239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            ? sizeof(s->mRemoteRTCPAddr) : 0;
383cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
3848c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber    ssize_t nbytes;
3858c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber    do {
3868c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber        nbytes = recvfrom(
387cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            receiveRTP ? s->mRTPSocket : s->mRTCPSocket,
388cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            buffer->data(),
389cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            buffer->capacity(),
390cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            0,
39139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            remoteAddrLen > 0 ? (struct sockaddr *)&s->mRemoteRTCPAddr : NULL,
39239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            remoteAddrLen > 0 ? &remoteAddrLen : NULL);
3938c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber    } while (nbytes < 0 && errno == EINTR);
394cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
3958c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber    if (nbytes <= 0) {
3968c308ffd781132c8417cebc3bf77c2e56a464e0bAndreas Huber        return -ECONNRESET;
397cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
398cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
399cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    buffer->setRange(0, nbytes);
400cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
401df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    // ALOGI("received %d bytes.", buffer->size());
40262cb04d23642a2ea7c005f050494c8ef3c370dd3Andreas Huber
403cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    status_t err;
404cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (receiveRTP) {
405cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        err = parseRTP(s, buffer);
406cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    } else {
407cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        err = parseRTCP(s, buffer);
408cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
409cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
410cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return err;
411cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
412cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
413cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatus_t ARTPConnection::parseRTP(StreamInfo *s, const sp<ABuffer> &buffer) {
414f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber    if (s->mNumRTPPacketsReceived++ == 0) {
415f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber        sp<AMessage> notify = s->mNotifyMsg->dup();
416f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber        notify->setInt32("first-rtp", true);
417f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber        notify->post();
418f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber    }
419f61551f4fc79e7da879802e3974afa9b03ffb5d0Andreas Huber
420cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    size_t size = buffer->size();
421cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
422cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (size < 12) {
423cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // Too short to be a valid RTP header.
424cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return -1;
425cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
426cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
427cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    const uint8_t *data = buffer->data();
428cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
429cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if ((data[0] >> 6) != 2) {
430cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // Unsupported version.
431cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return -1;
432cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
433cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
434cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (data[0] & 0x20) {
435cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // Padding present.
436cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
437cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size_t paddingLength = data[size - 1];
438cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
439cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (paddingLength + 12 > size) {
440cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // If we removed this much padding we'd end up with something
441cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // that's too short to be a valid RTP header.
442cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return -1;
443cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
444cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
445cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size -= paddingLength;
446cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
447cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
448cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int numCSRCs = data[0] & 0x0f;
449cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
450cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    size_t payloadOffset = 12 + 4 * numCSRCs;
451cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
452cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (size < payloadOffset) {
453cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // Not enough data to fit the basic header and all the CSRC entries.
454cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return -1;
455cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
456cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
457cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (data[0] & 0x10) {
458cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // Header eXtension present.
459cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
460cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (size < payloadOffset + 4) {
461cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // Not enough data to fit the basic header, all CSRC entries
462cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // and the first 4 bytes of the extension header.
463cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
464cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return -1;
465cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
466cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
467cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        const uint8_t *extensionData = &data[payloadOffset];
468cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
469cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size_t extensionLength =
470cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            4 * (extensionData[2] << 8 | extensionData[3]);
471cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
472cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (size < payloadOffset + 4 + extensionLength) {
473cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return -1;
474cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
475cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
476cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        payloadOffset += 4 + extensionLength;
477cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
478cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
479cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    uint32_t srcId = u32at(&data[8]);
480cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
48139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sp<ARTPSource> source = findSource(s, srcId);
482cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
483cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    uint32_t rtpTime = u32at(&data[4]);
484cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
485cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> meta = buffer->meta();
486cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    meta->setInt32("ssrc", srcId);
487cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    meta->setInt32("rtp-time", rtpTime);
488cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    meta->setInt32("PT", data[1] & 0x7f);
489cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    meta->setInt32("M", data[1] >> 7);
490cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
491cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    buffer->setInt32Data(u16at(&data[2]));
492cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    buffer->setRange(payloadOffset, size - payloadOffset);
493cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
494cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    source->processRTPPacket(buffer);
495cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
496cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return OK;
497cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
498cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
499cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatus_t ARTPConnection::parseRTCP(StreamInfo *s, const sp<ABuffer> &buffer) {
500e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber    if (s->mNumRTCPPacketsReceived++ == 0) {
501e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber        sp<AMessage> notify = s->mNotifyMsg->dup();
502e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber        notify->setInt32("first-rtcp", true);
503e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber        notify->post();
504e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber    }
505e7d3e90d8761f52a6acfdcd926f0392aca8ebb52Andreas Huber
506cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    const uint8_t *data = buffer->data();
507cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    size_t size = buffer->size();
508cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
509cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    while (size > 0) {
510cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (size < 8) {
511cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // Too short to be a valid RTCP header
512cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return -1;
513cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
514cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
515cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if ((data[0] >> 6) != 2) {
516cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // Unsupported version.
517cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return -1;
518cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
519cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
520cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (data[0] & 0x20) {
521cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // Padding present.
522cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
523cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            size_t paddingLength = data[size - 1];
524cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
525cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            if (paddingLength + 12 > size) {
526cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                // If we removed this much padding we'd end up with something
527cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                // that's too short to be a valid RTP header.
528cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                return -1;
529cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
530cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
531cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            size -= paddingLength;
532cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
533cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
534cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size_t headerLength = 4 * (data[2] << 8 | data[3]) + 4;
535cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
536cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (size < headerLength) {
537cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // Only received a partial packet?
538cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return -1;
539cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
540cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
541cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        switch (data[1]) {
542cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 200:
543cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
544cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                parseSR(s, data, headerLength);
545cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
546cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
547cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
54839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            case 201:  // RR
54939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            case 202:  // SDES
55039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            case 204:  // APP
55139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                break;
55239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
55339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            case 205:  // TSFB (transport layer specific feedback)
55439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            case 206:  // PSFB (payload specific feedback)
55539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                // hexdump(data, headerLength);
55639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                break;
55739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
55839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            case 203:
559cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
56039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                parseBYE(s, data, headerLength);
56139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                break;
56239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            }
563cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
56439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            default:
56539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber            {
566f6d0c1fd6d9e697bb3a891fae14c7e9d4b685de6Colin Cross                ALOGW("Unknown RTCP packet type %u of size %zu",
5676e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber                     (unsigned)data[1], headerLength);
568cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
569cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
570cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
571cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
572cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        data += headerLength;
573cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size -= headerLength;
574cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
575cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
576cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return OK;
577cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
578cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
57939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberstatus_t ARTPConnection::parseBYE(
58039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        StreamInfo *s, const uint8_t *data, size_t size) {
58139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    size_t SC = data[0] & 0x3f;
58239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
58339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    if (SC == 0 || size < (4 + SC * 4)) {
58439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        // Packet too short for the minimal BYE header.
58539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        return -1;
58639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    }
58739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
58839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    uint32_t id = u32at(&data[4]);
58939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
59039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sp<ARTPSource> source = findSource(s, id);
59139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
59239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    source->byeReceived();
59339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
59439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    return OK;
59539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
59639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
597cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatus_t ARTPConnection::parseSR(
598cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        StreamInfo *s, const uint8_t *data, size_t size) {
599cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    size_t RC = data[0] & 0x1f;
600cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
601cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (size < (7 + RC * 6) * 4) {
602cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // Packet too short for the minimal SR header.
603cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return -1;
604cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
605cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
606cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    uint32_t id = u32at(&data[4]);
607cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    uint64_t ntpTime = u64at(&data[8]);
608cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    uint32_t rtpTime = u32at(&data[16]);
609cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
61039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#if 0
611df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("XXX timeUpdate: ssrc=0x%08x, rtpTime %u == ntpTime %.3f",
6126e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber         id,
6136e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber         rtpTime,
6146e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber         (ntpTime >> 32) + (double)(ntpTime & 0xffffffff) / (1ll << 32));
61539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#endif
61639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
61739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    sp<ARTPSource> source = findSource(s, id);
61839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
619100a4408968b90e314526185d572c72ea4cc784aAndreas Huber    source->timeUpdate(rtpTime, ntpTime);
620cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
62139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    return 0;
62239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber}
62339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
62439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Hubersp<ARTPSource> ARTPConnection::findSource(StreamInfo *info, uint32_t srcId) {
625cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<ARTPSource> source;
62639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    ssize_t index = info->mSources.indexOfKey(srcId);
627cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (index < 0) {
62839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        index = info->mSources.size();
629cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
630cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        source = new ARTPSource(
63139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber                srcId, info->mSessionDesc, info->mIndex, info->mNotifyMsg);
63239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber
63339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        info->mSources.add(srcId, source);
634cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    } else {
63539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber        source = info->mSources.valueAt(index);
636cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
637cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
63839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber    return source;
639cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
640cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
6410792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Hubervoid ARTPConnection::injectPacket(int index, const sp<ABuffer> &buffer) {
6421d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatInjectPacket, this);
6430792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    msg->setInt32("index", index);
6442d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    msg->setBuffer("buffer", buffer);
6450792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    msg->post();
6460792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber}
6470792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6480792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Hubervoid ARTPConnection::onInjectPacket(const sp<AMessage> &msg) {
6490792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    int32_t index;
6500792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    CHECK(msg->findInt32("index", &index));
6510792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6522d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    sp<ABuffer> buffer;
6532d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber    CHECK(msg->findBuffer("buffer", &buffer));
6540792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6550792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    List<StreamInfo>::iterator it = mStreams.begin();
6560792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    while (it != mStreams.end()
6570792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber           && it->mRTPSocket != index && it->mRTCPSocket != index) {
6580792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        ++it;
6590792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    }
6600792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6610792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    if (it == mStreams.end()) {
6620792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        TRESPASS();
6630792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    }
6640792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6650792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    StreamInfo *s = &*it;
6660792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6670792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    if (it->mRTPSocket == index) {
668b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        parseRTP(s, buffer);
6690792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    } else {
670b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        parseRTCP(s, buffer);
6710792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    }
6720792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber}
6730792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
674cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}  // namespace android
675cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
676