1 /*
2 * Xiph RTP Protocols
3 * Copyright (c) 2009 Colin McQuillian
4 * Copyright (c) 2010 Josh Allmann
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 /**
24 * @file
25 * @brief Xiph / RTP Code
26 * @author Colin McQuillan <m.niloc@gmail.com>
27 * @author Josh Allmann <joshua.allmann@gmail.com>
28 */
29
35
38
39 /**
40 * RTP/Xiph specific private data.
41 */
43 unsigned ident;
///< 24-bit stream configuration identifier
49 };
50
52 {
54 }
55
57 {
63 }
64 }
65
67 {
71 }
72
75 {
76 if (st_index < 0)
77 return 0;
79 return 0;
80 }
81
82
87 {
88
89 int ident, fragmented, tdt, num_pkts, pkt_len;
90
91 if (!buf) {
96 }
102 }
106 }
112 }
113
114 if (len < 6) {
117 }
118
119 // read xiph rtp headers
121 fragmented = buf[3] >> 6;
122 tdt = (buf[3] >> 4) & 3;
123 num_pkts = buf[3] & 0xf;
125
126 if (pkt_len > len - 6) {
128 "Invalid packet length %d in %d byte packet\n", pkt_len,
129 len);
131 }
132
133 if (ident != data->
ident) {
135 "Unimplemented Xiph SDP configuration change detected\n");
137 }
138
139 if (tdt) {
141 "Unimplemented RTP Xiph packet settings (%d,%d,%d)\n",
142 fragmented, tdt, num_pkts);
144 }
145
146 buf += 6; // move past header bits
147 len -= 6;
148
149 if (fragmented == 0) {
153 }
155 memcpy(pkt->
data, buf, pkt_len);
156 buf += pkt_len;
157 len -= pkt_len;
158 num_pkts--;
159
160 if (num_pkts > 0) {
169 }
170 }
175 return 1;
176 }
177
178 return 0;
179
180 } else if (fragmented == 1) {
181 // start of xiph data fragment
183
184 // end packet has been lost somewhere, so drop buffered data
186
189
192
193 } else {
196 // skip if fragmented timestamp is incorrect;
197 // a start packet has been lost somewhere
201 }
204 "Received packet without a start fragment; dropping.\n");
206 }
207
208 // copy data to fragment buffer
210
211 if (fragmented == 3) {
212 // end of xiph data packet
214 if (ret < 0) {
216 "Error occurred when getting fragment buffer.");
218 }
219
220 return 0;
221 }
222 }
223
225 }
226
227 /**
228 * Length encoding described in RFC5215 section 3.1.1.
229 */
231 {
233 for (; *buf < buf_end; ++*
buf) {
234 n <<= 7;
235 n += **buf & 0x7f;
236 if (!(**buf & 0x80)) {
239 }
240 }
241 return 0;
242 }
243
244 /**
245 * Based off parse_packed_headers in Vorbis RTP
246 */
247 static int
249 const uint8_t * packed_headers_end,
251 {
252
253 unsigned num_packed, num_headers,
length, length1, length2, extradata_alloc;
255
256 if (packed_headers_end - packed_headers < 9) {
258 "Invalid %td byte packed header.",
259 packed_headers_end - packed_headers);
261 }
262
263 num_packed = bytestream_get_be32(&packed_headers);
264 xiph_data->
ident = bytestream_get_be24(&packed_headers);
265 length = bytestream_get_be16(&packed_headers);
266 num_headers =
get_base128(&packed_headers, packed_headers_end);
267 length1 =
get_base128(&packed_headers, packed_headers_end);
268 length2 =
get_base128(&packed_headers, packed_headers_end);
269
270 if (num_packed != 1 || num_headers > 3) {
272 "Unimplemented number of headers: %d packed headers, %d headers\n",
273 num_packed, num_headers);
275 }
276
277 if (packed_headers_end - packed_headers != length ||
278 length1 > length || length2 > length - length1) {
280 "Bad packed header lengths (%d,%d,%td,%d)\n", length1,
281 length2, packed_headers_end - packed_headers, length);
283 }
284
285 /* allocate extra space:
286 * -- length/255 +2 for xiphlacing
287 * -- one for the '2' marker
288 * -- FF_INPUT_BUFFER_PADDING_SIZE required */
290
292 if (!ptr) {
295 }
296 *ptr++ = 2;
299 memcpy(ptr, packed_headers, length);
302 // clear out remaining parts of the buffer
304
305 return 0;
306 }
307
310 char *attr,
char *
value)
311 {
313 int result = 0;
314
315 if (!strcmp(attr, "sampling")) {
316 if (!strcmp(value, "YCbCr-4:2:0")) {
318 } else if (!strcmp(value, "YCbCr-4:4:2")) {
320 } else if (!strcmp(value, "YCbCr-4:4:4")) {
322 } else {
324 "Unsupported pixel format %s\n", attr);
326 }
327 } else if (!strcmp(attr, "width")) {
328 /* This is an integer between 1 and 1048561
329 * and MUST be in multiples of 16. */
330 codec->
width = atoi(value);
331 return 0;
332 } else if (!strcmp(attr, "height")) {
333 /* This is an integer between 1 and 1048561
334 * and MUST be in multiples of 16. */
335 codec->
height = atoi(value);
336 return 0;
337 } else if (!strcmp(attr, "delivery-method")) {
338 /* Possible values are: inline, in_band, out_band/specific_name. */
340 } else if (!strcmp(attr, "configuration-uri")) {
341 /* NOTE: configuration-uri is supported only under 2 conditions:
342 *--after the delivery-method tag
343 * --with a delivery-method value of out_band */
345 } else if (!strcmp(attr, "configuration")) {
346 /* NOTE: configuration is supported only AFTER the delivery-method tag
347 * The configuration value is a base64 encoded packed header */
348 uint8_t *decoded_packet = NULL;
349 int packet_size;
350 size_t decoded_alloc = strlen(value) / 4 * 3 + 4;
351
352 if (decoded_alloc <= INT_MAX) {
353 decoded_packet =
av_malloc(decoded_alloc);
354 if (decoded_packet) {
355 packet_size =
357
359 (decoded_packet, decoded_packet + packet_size, codec,
360 xiph_data);
361 } else {
363 "Out of memory while decoding SDP configuration.\n");
365 }
366 } else {
369 }
371 }
372 return result;
373 }
374
377 {
378 const char *p;
379
380 if (st_index < 0)
381 return 0;
382
386 }
387
388 return 0;
389 }
390
399 };
400
410 };