]> git.sesse.net Git - ffmpeg/blob - libavformat/rtpdec_xiph.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavformat / rtpdec_xiph.c
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
30 #include "libavutil/avassert.h"
31 #include "libavutil/avstring.h"
32 #include "libavutil/base64.h"
33 #include "libavcodec/bytestream.h"
34
35 #include "rtpdec.h"
36 #include "rtpdec_formats.h"
37
38 /**
39  * RTP/Xiph specific private data.
40  */
41 struct PayloadContext {
42     unsigned ident;             ///< 24-bit stream configuration identifier
43     uint32_t timestamp;
44     AVIOContext* fragment;    ///< buffer for split payloads
45     uint8_t *split_buf;
46     int split_pos, split_buf_len, split_buf_size;
47     int split_pkts;
48 };
49
50 static PayloadContext *xiph_new_context(void)
51 {
52     return av_mallocz(sizeof(PayloadContext));
53 }
54
55 static inline void free_fragment_if_needed(PayloadContext * data)
56 {
57     if (data->fragment) {
58         uint8_t* p;
59         avio_close_dyn_buf(data->fragment, &p);
60         av_free(p);
61         data->fragment = NULL;
62     }
63 }
64
65 static void xiph_free_context(PayloadContext * data)
66 {
67     free_fragment_if_needed(data);
68     av_free(data->split_buf);
69     av_free(data);
70 }
71
72 static int xiph_handle_packet(AVFormatContext * ctx,
73                               PayloadContext * data,
74                               AVStream * st,
75                               AVPacket * pkt,
76                               uint32_t * timestamp,
77                               const uint8_t * buf, int len, int flags)
78 {
79
80     int ident, fragmented, tdt, num_pkts, pkt_len;
81
82     if (!buf) {
83         if (!data->split_buf || data->split_pos + 2 > data->split_buf_len ||
84             data->split_pkts <= 0) {
85             av_log(ctx, AV_LOG_ERROR, "No more data to return\n");
86             return AVERROR_INVALIDDATA;
87         }
88         pkt_len = AV_RB16(data->split_buf + data->split_pos);
89         data->split_pos += 2;
90         if (data->split_pos + pkt_len > data->split_buf_len) {
91             av_log(ctx, AV_LOG_ERROR, "Not enough data to return\n");
92             return AVERROR_INVALIDDATA;
93         }
94         if (av_new_packet(pkt, pkt_len)) {
95             av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
96             return AVERROR(ENOMEM);
97         }
98         pkt->stream_index = st->index;
99         memcpy(pkt->data, data->split_buf + data->split_pos, pkt_len);
100         data->split_pos += pkt_len;
101         data->split_pkts--;
102         return data->split_pkts > 0;
103     }
104
105     if (len < 6) {
106         av_log(ctx, AV_LOG_ERROR, "Invalid %d byte packet\n", len);
107         return AVERROR_INVALIDDATA;
108     }
109
110     // read xiph rtp headers
111     ident       = AV_RB24(buf);
112     fragmented  = buf[3] >> 6;
113     tdt         = (buf[3] >> 4) & 3;
114     num_pkts    = buf[3] & 0xf;
115     pkt_len     = AV_RB16(buf + 4);
116
117     if (pkt_len > len - 6) {
118         av_log(ctx, AV_LOG_ERROR,
119                "Invalid packet length %d in %d byte packet\n", pkt_len,
120                len);
121         return AVERROR_INVALIDDATA;
122     }
123
124     if (ident != data->ident) {
125         av_log(ctx, AV_LOG_ERROR,
126                "Unimplemented Xiph SDP configuration change detected\n");
127         return AVERROR_PATCHWELCOME;
128     }
129
130     if (tdt) {
131         av_log(ctx, AV_LOG_ERROR,
132                "Unimplemented RTP Xiph packet settings (%d,%d,%d)\n",
133                fragmented, tdt, num_pkts);
134         return AVERROR_PATCHWELCOME;
135     }
136
137     buf += 6; // move past header bits
138     len -= 6;
139
140     if (fragmented == 0) {
141         if (av_new_packet(pkt, pkt_len)) {
142             av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
143             return AVERROR(ENOMEM);
144         }
145         pkt->stream_index = st->index;
146         memcpy(pkt->data, buf, pkt_len);
147         buf += pkt_len;
148         len -= pkt_len;
149         num_pkts--;
150
151         if (num_pkts > 0) {
152             if (len > data->split_buf_size || !data->split_buf) {
153                 av_freep(&data->split_buf);
154                 data->split_buf_size = 2 * len;
155                 data->split_buf = av_malloc(data->split_buf_size);
156                 if (!data->split_buf) {
157                     av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
158                     av_free_packet(pkt);
159                     return AVERROR(ENOMEM);
160                 }
161             }
162             memcpy(data->split_buf, buf, len);
163             data->split_buf_len = len;
164             data->split_pos = 0;
165             data->split_pkts = num_pkts;
166             return 1;
167         }
168
169         return 0;
170
171     } else if (fragmented == 1) {
172         // start of xiph data fragment
173         int res;
174
175         // end packet has been lost somewhere, so drop buffered data
176         free_fragment_if_needed(data);
177
178         if((res = avio_open_dyn_buf(&data->fragment)) < 0)
179             return res;
180
181         avio_write(data->fragment, buf, pkt_len);
182         data->timestamp = *timestamp;
183
184     } else {
185         av_assert1(fragmented < 4);
186         if (data->timestamp != *timestamp) {
187             // skip if fragmented timestamp is incorrect;
188             // a start packet has been lost somewhere
189             free_fragment_if_needed(data);
190             av_log(ctx, AV_LOG_ERROR, "RTP timestamps don't match!\n");
191             return AVERROR_INVALIDDATA;
192         }
193         if (!data->fragment) {
194             av_log(ctx, AV_LOG_WARNING,
195                    "Received packet without a start fragment; dropping.\n");
196             return AVERROR(EAGAIN);
197         }
198
199         // copy data to fragment buffer
200         avio_write(data->fragment, buf, pkt_len);
201
202         if (fragmented == 3) {
203             // end of xiph data packet
204             av_init_packet(pkt);
205             pkt->size = avio_close_dyn_buf(data->fragment, &pkt->data);
206
207             if (pkt->size < 0) {
208                 av_log(ctx, AV_LOG_ERROR,
209                        "Error occurred when getting fragment buffer.");
210                 return pkt->size;
211             }
212
213             pkt->stream_index = st->index;
214             pkt->destruct = av_destruct_packet;
215
216             data->fragment = NULL;
217
218             return 0;
219         }
220     }
221
222    return AVERROR(EAGAIN);
223 }
224
225 /**
226  * Length encoding described in RFC5215 section 3.1.1.
227  */
228 static int get_base128(const uint8_t ** buf, const uint8_t * buf_end)
229 {
230     int n = 0;
231     for (; *buf < buf_end; ++*buf) {
232         n <<= 7;
233         n += **buf & 0x7f;
234         if (!(**buf & 0x80)) {
235             ++*buf;
236             return n;
237         }
238     }
239     return 0;
240 }
241
242 /**
243  * Based off parse_packed_headers in Vorbis RTP
244  */
245 static int
246 parse_packed_headers(const uint8_t * packed_headers,
247                      const uint8_t * packed_headers_end,
248                      AVCodecContext * codec, PayloadContext * xiph_data)
249 {
250
251     unsigned num_packed, num_headers, length, length1, length2, extradata_alloc;
252     uint8_t *ptr;
253
254     if (packed_headers_end - packed_headers < 9) {
255         av_log(codec, AV_LOG_ERROR,
256                "Invalid %td byte packed header.",
257                packed_headers_end - packed_headers);
258         return AVERROR_INVALIDDATA;
259     }
260
261     num_packed         = bytestream_get_be32(&packed_headers);
262     xiph_data->ident   = bytestream_get_be24(&packed_headers);
263     length             = bytestream_get_be16(&packed_headers);
264     num_headers        = get_base128(&packed_headers, packed_headers_end);
265     length1            = get_base128(&packed_headers, packed_headers_end);
266     length2            = get_base128(&packed_headers, packed_headers_end);
267
268     if (num_packed != 1 || num_headers > 3) {
269         av_log(codec, AV_LOG_ERROR,
270                "Unimplemented number of headers: %d packed headers, %d headers\n",
271                num_packed, num_headers);
272         return AVERROR_PATCHWELCOME;
273     }
274
275     if (packed_headers_end - packed_headers != length ||
276         length1 > length || length2 > length - length1) {
277         av_log(codec, AV_LOG_ERROR,
278                "Bad packed header lengths (%d,%d,%td,%d)\n", length1,
279                length2, packed_headers_end - packed_headers, length);
280         return AVERROR_INVALIDDATA;
281     }
282
283     /* allocate extra space:
284      * -- length/255 +2 for xiphlacing
285      * -- one for the '2' marker
286      * -- FF_INPUT_BUFFER_PADDING_SIZE required */
287     extradata_alloc = length + length/255 + 3 + FF_INPUT_BUFFER_PADDING_SIZE;
288
289     ptr = codec->extradata = av_malloc(extradata_alloc);
290     if (!ptr) {
291         av_log(codec, AV_LOG_ERROR, "Out of memory\n");
292         return AVERROR(ENOMEM);
293     }
294     *ptr++ = 2;
295     ptr += av_xiphlacing(ptr, length1);
296     ptr += av_xiphlacing(ptr, length2);
297     memcpy(ptr, packed_headers, length);
298     ptr += length;
299     codec->extradata_size = ptr - codec->extradata;
300     // clear out remaining parts of the buffer
301     memset(ptr, 0, extradata_alloc - codec->extradata_size);
302
303     return 0;
304 }
305
306 static int xiph_parse_fmtp_pair(AVStream* stream,
307                                 PayloadContext *xiph_data,
308                                 char *attr, char *value)
309 {
310     AVCodecContext *codec = stream->codec;
311     int result = 0;
312
313     if (!strcmp(attr, "sampling")) {
314         if (!strcmp(value, "YCbCr-4:2:0")) {
315             codec->pix_fmt = AV_PIX_FMT_YUV420P;
316         } else if (!strcmp(value, "YCbCr-4:4:2")) {
317             codec->pix_fmt = AV_PIX_FMT_YUV422P;
318         } else if (!strcmp(value, "YCbCr-4:4:4")) {
319             codec->pix_fmt = AV_PIX_FMT_YUV444P;
320         } else {
321             av_log(codec, AV_LOG_ERROR,
322                    "Unsupported pixel format %s\n", attr);
323             return AVERROR_INVALIDDATA;
324         }
325     } else if (!strcmp(attr, "width")) {
326         /* This is an integer between 1 and 1048561
327          * and MUST be in multiples of 16. */
328         codec->width = atoi(value);
329         return 0;
330     } else if (!strcmp(attr, "height")) {
331         /* This is an integer between 1 and 1048561
332          * and MUST be in multiples of 16. */
333         codec->height = atoi(value);
334         return 0;
335     } else if (!strcmp(attr, "delivery-method")) {
336         /* Possible values are: inline, in_band, out_band/specific_name. */
337         return AVERROR_PATCHWELCOME;
338     } else if (!strcmp(attr, "configuration-uri")) {
339         /* NOTE: configuration-uri is supported only under 2 conditions:
340          *--after the delivery-method tag
341          * --with a delivery-method value of out_band */
342         return AVERROR_PATCHWELCOME;
343     } else if (!strcmp(attr, "configuration")) {
344         /* NOTE: configuration is supported only AFTER the delivery-method tag
345          * The configuration value is a base64 encoded packed header */
346         uint8_t *decoded_packet = NULL;
347         int packet_size;
348         size_t decoded_alloc = strlen(value) / 4 * 3 + 4;
349
350         if (decoded_alloc <= INT_MAX) {
351             decoded_packet = av_malloc(decoded_alloc);
352             if (decoded_packet) {
353                 packet_size =
354                     av_base64_decode(decoded_packet, value, decoded_alloc);
355
356                 result = parse_packed_headers
357                     (decoded_packet, decoded_packet + packet_size, codec,
358                     xiph_data);
359             } else {
360                 av_log(codec, AV_LOG_ERROR,
361                        "Out of memory while decoding SDP configuration.\n");
362                 result = AVERROR(ENOMEM);
363             }
364         } else {
365             av_log(codec, AV_LOG_ERROR, "Packet too large\n");
366             result = AVERROR_INVALIDDATA;
367         }
368         av_free(decoded_packet);
369     }
370     return result;
371 }
372
373 static int xiph_parse_sdp_line(AVFormatContext *s, int st_index,
374                                PayloadContext *data, const char *line)
375 {
376     const char *p;
377
378     if (st_index < 0)
379         return 0;
380
381     if (av_strstart(line, "fmtp:", &p)) {
382         return ff_parse_fmtp(s->streams[st_index], data, p,
383                              xiph_parse_fmtp_pair);
384     }
385
386     return 0;
387 }
388
389 RTPDynamicProtocolHandler ff_theora_dynamic_handler = {
390     .enc_name         = "theora",
391     .codec_type       = AVMEDIA_TYPE_VIDEO,
392     .codec_id         = AV_CODEC_ID_THEORA,
393     .parse_sdp_a_line = xiph_parse_sdp_line,
394     .alloc            = xiph_new_context,
395     .free             = xiph_free_context,
396     .parse_packet     = xiph_handle_packet
397 };
398
399 RTPDynamicProtocolHandler ff_vorbis_dynamic_handler = {
400     .enc_name         = "vorbis",
401     .codec_type       = AVMEDIA_TYPE_AUDIO,
402     .codec_id         = AV_CODEC_ID_VORBIS,
403     .parse_sdp_a_line = xiph_parse_sdp_line,
404     .alloc            = xiph_new_context,
405     .free             = xiph_free_context,
406     .parse_packet     = xiph_handle_packet
407 };