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