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