ARTPConnection.cpp revision cf7b9c7aae758ac0b99833915053c63c2ac46e09
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
17cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ARTPConnection.h"
18cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
19cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ARTPSource.h"
20cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ASessionDescription.h"
21cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
22cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
23cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ADebug.h>
24cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/AMessage.h>
25cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/AString.h>
26cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
27cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <arpa/inet.h>
28cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <sys/socket.h>
29cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
30cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#define VERBOSE         0
31cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
32cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#if VERBOSE
33cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "hexdump.h"
34cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif
35cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
36cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubernamespace android {
37cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
38cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatic uint16_t u16at(const uint8_t *data) {
39cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return data[0] << 8 | data[1];
40cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
41cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
42cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatic uint32_t u32at(const uint8_t *data) {
43cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return u16at(data) << 16 | u16at(&data[2]);
44cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
45cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
46cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatic uint64_t u64at(const uint8_t *data) {
47cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return (uint64_t)(u32at(data)) << 32 | u32at(&data[4]);
48cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
49cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
50cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber// static
51cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberconst int64_t ARTPConnection::kSelectTimeoutUs = 1000ll;
52cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
53cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstruct ARTPConnection::StreamInfo {
54cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int mRTPSocket;
55cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int mRTCPSocket;
56cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<ASessionDescription> mSessionDesc;
57cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    size_t mIndex;
58cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> mNotifyMsg;
59cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber};
60cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
61cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas HuberARTPConnection::ARTPConnection()
62cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    : mPollEventPending(false) {
63cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
64cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
65cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas HuberARTPConnection::~ARTPConnection() {
66cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
67cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
68cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTPConnection::addStream(
69cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        int rtpSocket, int rtcpSocket,
70cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        const sp<ASessionDescription> &sessionDesc,
71cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size_t index,
72cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        const sp<AMessage> &notify) {
73cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> msg = new AMessage(kWhatAddStream, id());
74cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setInt32("rtp-socket", rtpSocket);
75cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setInt32("rtcp-socket", rtcpSocket);
76cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setObject("session-desc", sessionDesc);
77cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setSize("index", index);
78cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setMessage("notify", notify);
79cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->post();
80cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
81cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
82cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTPConnection::removeStream(int rtpSocket, int rtcpSocket) {
83cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> msg = new AMessage(kWhatRemoveStream, id());
84cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setInt32("rtp-socket", rtpSocket);
85cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setInt32("rtcp-socket", rtcpSocket);
86cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->post();
87cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
88cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
89cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatic void bumpSocketBufferSize(int s) {
90cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int size = 256 * 1024;
91cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK_EQ(setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)), 0);
92cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
93cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
94cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber// static
95cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTPConnection::MakePortPair(
96cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        int *rtpSocket, int *rtcpSocket, unsigned *rtpPort) {
97cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    *rtpSocket = socket(AF_INET, SOCK_DGRAM, 0);
98cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK_GE(*rtpSocket, 0);
99cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
100cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    bumpSocketBufferSize(*rtpSocket);
101cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
102cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    *rtcpSocket = socket(AF_INET, SOCK_DGRAM, 0);
103cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK_GE(*rtcpSocket, 0);
104cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
105cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    bumpSocketBufferSize(*rtcpSocket);
106cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
107cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    unsigned start = (rand() * 1000)/ RAND_MAX + 15550;
108cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    start &= ~1;
109cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
110cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    for (unsigned port = start; port < 65536; port += 2) {
111cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        struct sockaddr_in addr;
112cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
113cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        addr.sin_family = AF_INET;
114cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        addr.sin_addr.s_addr = INADDR_ANY;
115cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        addr.sin_port = htons(port);
116cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
117cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (bind(*rtpSocket,
118cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                 (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
119cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            continue;
120cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
121cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
122cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        addr.sin_port = htons(port + 1);
123cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
124cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (bind(*rtcpSocket,
125cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                 (const struct sockaddr *)&addr, sizeof(addr)) == 0) {
126cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            *rtpPort = port;
127cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return;
128cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
129cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
130cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
131cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    TRESPASS();
132cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
133cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
134cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTPConnection::onMessageReceived(const sp<AMessage> &msg) {
135cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    switch (msg->what()) {
136cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        case kWhatAddStream:
137cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        {
138cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            onAddStream(msg);
139cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
140cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
141cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
142cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        case kWhatRemoveStream:
143cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        {
144cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            onRemoveStream(msg);
145cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
146cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
147cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
148cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        case kWhatPollStreams:
149cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        {
150cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            onPollStreams();
151cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
152cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
153cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
154cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        default:
155cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        {
156cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            TRESPASS();
157cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
158cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
159cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
160cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
161cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
162cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTPConnection::onAddStream(const sp<AMessage> &msg) {
163cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mStreams.push_back(StreamInfo());
164cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    StreamInfo *info = &*--mStreams.end();
165cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
166cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int32_t s;
167cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findInt32("rtp-socket", &s));
168cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    info->mRTPSocket = s;
169cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findInt32("rtcp-socket", &s));
170cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    info->mRTCPSocket = s;
171cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
172cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<RefBase> obj;
173cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findObject("session-desc", &obj));
174cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    info->mSessionDesc = static_cast<ASessionDescription *>(obj.get());
175cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
176cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findSize("index", &info->mIndex));
177cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findMessage("notify", &info->mNotifyMsg));
178cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
179cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    postPollEvent();
180cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
181cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
182cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTPConnection::onRemoveStream(const sp<AMessage> &msg) {
183cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int32_t rtpSocket, rtcpSocket;
184cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findInt32("rtp-socket", &rtpSocket));
185cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findInt32("rtcp-socket", &rtcpSocket));
186cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
187cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    List<StreamInfo>::iterator it = mStreams.begin();
188cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    while (it != mStreams.end()
189cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           && (it->mRTPSocket != rtpSocket || it->mRTCPSocket != rtcpSocket)) {
190cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        ++it;
191cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
192cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
193cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (it == mStreams.end()) {
194cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        TRESPASS();
195cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
196cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
197cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mStreams.erase(it);
198cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
199cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
200cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTPConnection::postPollEvent() {
201cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (mPollEventPending) {
202cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return;
203cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
204cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
205cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> msg = new AMessage(kWhatPollStreams, id());
206cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->post();
207cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
208cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mPollEventPending = true;
209cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
210cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
211cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTPConnection::onPollStreams() {
212cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mPollEventPending = false;
213cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
214cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (mStreams.empty()) {
215cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return;
216cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
217cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
218cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    struct timeval tv;
219cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    tv.tv_sec = 0;
220cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    tv.tv_usec = kSelectTimeoutUs;
221cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
222cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    fd_set rs;
223cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    FD_ZERO(&rs);
224cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
225cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int maxSocket = -1;
226cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    for (List<StreamInfo>::iterator it = mStreams.begin();
227cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber         it != mStreams.end(); ++it) {
228cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        FD_SET(it->mRTPSocket, &rs);
229cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        FD_SET(it->mRTCPSocket, &rs);
230cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
231cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (it->mRTPSocket > maxSocket) {
232cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            maxSocket = it->mRTPSocket;
233cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
234cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (it->mRTCPSocket > maxSocket) {
235cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            maxSocket = it->mRTCPSocket;
236cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
237cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
238cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
239cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int res = select(maxSocket + 1, &rs, NULL, NULL, &tv);
240cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK_GE(res, 0);
241cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
242cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (res > 0) {
243cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        for (List<StreamInfo>::iterator it = mStreams.begin();
244cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber             it != mStreams.end(); ++it) {
245cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            if (FD_ISSET(it->mRTPSocket, &rs)) {
246cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                receive(&*it, true);
247cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
248cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            if (FD_ISSET(it->mRTCPSocket, &rs)) {
249cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                receive(&*it, false);
250cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
251cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
252cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
253cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
254cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    postPollEvent();
255cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
256cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
257cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatus_t ARTPConnection::receive(StreamInfo *s, bool receiveRTP) {
258cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<ABuffer> buffer = new ABuffer(65536);
259cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
260cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    struct sockaddr_in from;
261cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    socklen_t fromSize = sizeof(from);
262cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
263cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    ssize_t nbytes = recvfrom(
264cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            receiveRTP ? s->mRTPSocket : s->mRTCPSocket,
265cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            buffer->data(),
266cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            buffer->capacity(),
267cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            0,
268cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            (struct sockaddr *)&from,
269cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            &fromSize);
270cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
271cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (nbytes < 0) {
272cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return -1;
273cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
274cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
275cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    buffer->setRange(0, nbytes);
276cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
277cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    status_t err;
278cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (receiveRTP) {
279cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        err = parseRTP(s, buffer);
280cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    } else {
281cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        err = parseRTCP(s, buffer);
282cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
283cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
284cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return err;
285cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
286cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
287cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatus_t ARTPConnection::parseRTP(StreamInfo *s, const sp<ABuffer> &buffer) {
288cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    size_t size = buffer->size();
289cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
290cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (size < 12) {
291cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // Too short to be a valid RTP header.
292cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return -1;
293cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
294cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
295cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    const uint8_t *data = buffer->data();
296cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
297cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if ((data[0] >> 6) != 2) {
298cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // Unsupported version.
299cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return -1;
300cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
301cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
302cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (data[0] & 0x20) {
303cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // Padding present.
304cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
305cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size_t paddingLength = data[size - 1];
306cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
307cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (paddingLength + 12 > size) {
308cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // If we removed this much padding we'd end up with something
309cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // that's too short to be a valid RTP header.
310cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return -1;
311cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
312cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
313cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size -= paddingLength;
314cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
315cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
316cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int numCSRCs = data[0] & 0x0f;
317cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
318cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    size_t payloadOffset = 12 + 4 * numCSRCs;
319cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
320cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (size < payloadOffset) {
321cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // Not enough data to fit the basic header and all the CSRC entries.
322cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return -1;
323cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
324cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
325cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (data[0] & 0x10) {
326cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // Header eXtension present.
327cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
328cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (size < payloadOffset + 4) {
329cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // Not enough data to fit the basic header, all CSRC entries
330cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // and the first 4 bytes of the extension header.
331cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
332cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return -1;
333cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
334cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
335cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        const uint8_t *extensionData = &data[payloadOffset];
336cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
337cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size_t extensionLength =
338cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            4 * (extensionData[2] << 8 | extensionData[3]);
339cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
340cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (size < payloadOffset + 4 + extensionLength) {
341cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return -1;
342cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
343cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
344cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        payloadOffset += 4 + extensionLength;
345cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
346cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
347cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    uint32_t srcId = u32at(&data[8]);
348cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
349cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<ARTPSource> source;
350cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    ssize_t index = mSources.indexOfKey(srcId);
351cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (index < 0) {
352cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        index = mSources.size();
353cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
354cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        source = new ARTPSource(
355cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                srcId, s->mSessionDesc, s->mIndex, s->mNotifyMsg);
356cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
357cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mSources.add(srcId, source);
358cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    } else {
359cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        source = mSources.valueAt(index);
360cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
361cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
362cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    uint32_t rtpTime = u32at(&data[4]);
363cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
364cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> meta = buffer->meta();
365cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    meta->setInt32("ssrc", srcId);
366cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    meta->setInt32("rtp-time", rtpTime);
367cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    meta->setInt32("PT", data[1] & 0x7f);
368cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    meta->setInt32("M", data[1] >> 7);
369cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
370cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    buffer->setInt32Data(u16at(&data[2]));
371cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
372cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#if VERBOSE
373cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    printf("RTP = {\n"
374cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           "  PT: %d\n"
375cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           "  sequence number: %d\n"
376cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           "  RTP-time: 0x%08x\n"
377cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           "  M: %d\n"
378cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           "  SSRC: 0x%08x\n"
379cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           "}\n",
380cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           data[1] & 0x7f,
381cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           u16at(&data[2]),
382cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           rtpTime,
383cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           data[1] >> 7,
384cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           srcId);
385cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
386cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    // hexdump(&data[payloadOffset], size - payloadOffset);
387cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif
388cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
389cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    buffer->setRange(payloadOffset, size - payloadOffset);
390cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
391cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    source->processRTPPacket(buffer);
392cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
393cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return OK;
394cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
395cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
396cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatus_t ARTPConnection::parseRTCP(StreamInfo *s, const sp<ABuffer> &buffer) {
397cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    const uint8_t *data = buffer->data();
398cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    size_t size = buffer->size();
399cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
400cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    while (size > 0) {
401cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (size < 8) {
402cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // Too short to be a valid RTCP header
403cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return -1;
404cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
405cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
406cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if ((data[0] >> 6) != 2) {
407cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // Unsupported version.
408cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return -1;
409cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
410cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
411cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (data[0] & 0x20) {
412cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // Padding present.
413cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
414cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            size_t paddingLength = data[size - 1];
415cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
416cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            if (paddingLength + 12 > size) {
417cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                // If we removed this much padding we'd end up with something
418cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                // that's too short to be a valid RTP header.
419cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                return -1;
420cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
421cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
422cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            size -= paddingLength;
423cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
424cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
425cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size_t headerLength = 4 * (data[2] << 8 | data[3]) + 4;
426cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
427cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (size < headerLength) {
428cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // Only received a partial packet?
429cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return -1;
430cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
431cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
432cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        switch (data[1]) {
433cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            case 200:
434cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
435cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                parseSR(s, data, headerLength);
436cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
437cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
438cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
439cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            default:
440cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            {
441cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#if VERBOSE
442cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                printf("Unknown RTCP packet type %d of size %ld\n",
443cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                       data[1], headerLength);
444cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
445cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                hexdump(data, headerLength);
446cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif
447cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                break;
448cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
449cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
450cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
451cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        data += headerLength;
452cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size -= headerLength;
453cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
454cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
455cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return OK;
456cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
457cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
458cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberstatus_t ARTPConnection::parseSR(
459cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        StreamInfo *s, const uint8_t *data, size_t size) {
460cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    size_t RC = data[0] & 0x1f;
461cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
462cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (size < (7 + RC * 6) * 4) {
463cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // Packet too short for the minimal SR header.
464cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return -1;
465cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
466cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
467cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    uint32_t id = u32at(&data[4]);
468cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    uint64_t ntpTime = u64at(&data[8]);
469cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    uint32_t rtpTime = u32at(&data[16]);
470cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
471cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#if VERBOSE
472cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    printf("SR = {\n"
473cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           "  SSRC:      0x%08x\n"
474cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           "  NTP-time:  0x%016llx\n"
475cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           "  RTP-time:  0x%08x\n"
476cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           "}\n",
477cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber           id, ntpTime, rtpTime);
478cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#endif
479cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
480cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<ARTPSource> source;
481cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    ssize_t index = mSources.indexOfKey(id);
482cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (index < 0) {
483cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        index = mSources.size();
484cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
485cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        source = new ARTPSource(
486cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                id, s->mSessionDesc, s->mIndex, s->mNotifyMsg);
487cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
488cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mSources.add(id, source);
489cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    } else {
490cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        source = mSources.valueAt(index);
491cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
492cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
493cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    source->timeUpdate(rtpTime, ntpTime);
494cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
495cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return 0;
496cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
497cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
498cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}  // namespace android
499cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
500