OSDN Git Service

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