rtpdec_xiph.c
Go to the documentation of this file.
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
48 };
49 
51 {
52  return av_mallocz(sizeof(PayloadContext));
53 }
54 
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 
66 {
68  av_free(data->split_buf);
69  av_free(data);
70 }
71 
72 static int xiph_vorbis_init(AVFormatContext *ctx, int st_index,
74 {
75  if (st_index < 0)
76  return 0;
78  return 0;
79 }
80 
81 
83  AVStream *st, AVPacket *pkt, uint32_t *timestamp,
84  const uint8_t *buf, int len, uint16_t seq,
85  int flags)
86 {
87 
88  int ident, fragmented, tdt, num_pkts, pkt_len;
89 
90  if (!buf) {
91  if (!data->split_buf || data->split_pos + 2 > data->split_buf_len ||
92  data->split_pkts <= 0) {
93  av_log(ctx, AV_LOG_ERROR, "No more data to return\n");
94  return AVERROR_INVALIDDATA;
95  }
96  pkt_len = AV_RB16(data->split_buf + data->split_pos);
97  data->split_pos += 2;
98  if (data->split_pos + pkt_len > data->split_buf_len) {
99  av_log(ctx, AV_LOG_ERROR, "Not enough data to return\n");
100  return AVERROR_INVALIDDATA;
101  }
102  if (av_new_packet(pkt, pkt_len)) {
103  av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
104  return AVERROR(ENOMEM);
105  }
106  pkt->stream_index = st->index;
107  memcpy(pkt->data, data->split_buf + data->split_pos, pkt_len);
108  data->split_pos += pkt_len;
109  data->split_pkts--;
110  return data->split_pkts > 0;
111  }
112 
113  if (len < 6) {
114  av_log(ctx, AV_LOG_ERROR, "Invalid %d byte packet\n", len);
115  return AVERROR_INVALIDDATA;
116  }
117 
118  // read xiph rtp headers
119  ident = AV_RB24(buf);
120  fragmented = buf[3] >> 6;
121  tdt = (buf[3] >> 4) & 3;
122  num_pkts = buf[3] & 0xf;
123  pkt_len = AV_RB16(buf + 4);
124 
125  if (pkt_len > len - 6) {
126  av_log(ctx, AV_LOG_ERROR,
127  "Invalid packet length %d in %d byte packet\n", pkt_len,
128  len);
129  return AVERROR_INVALIDDATA;
130  }
131 
132  if (ident != data->ident) {
133  av_log(ctx, AV_LOG_ERROR,
134  "Unimplemented Xiph SDP configuration change detected\n");
135  return AVERROR_PATCHWELCOME;
136  }
137 
138  if (tdt) {
139  av_log(ctx, AV_LOG_ERROR,
140  "Unimplemented RTP Xiph packet settings (%d,%d,%d)\n",
141  fragmented, tdt, num_pkts);
142  return AVERROR_PATCHWELCOME;
143  }
144 
145  buf += 6; // move past header bits
146  len -= 6;
147 
148  if (fragmented == 0) {
149  if (av_new_packet(pkt, pkt_len)) {
150  av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
151  return AVERROR(ENOMEM);
152  }
153  pkt->stream_index = st->index;
154  memcpy(pkt->data, buf, pkt_len);
155  buf += pkt_len;
156  len -= pkt_len;
157  num_pkts--;
158 
159  if (num_pkts > 0) {
160  if (len > data->split_buf_size || !data->split_buf) {
161  av_freep(&data->split_buf);
162  data->split_buf_size = 2 * len;
163  data->split_buf = av_malloc(data->split_buf_size);
164  if (!data->split_buf) {
165  av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
166  av_free_packet(pkt);
167  return AVERROR(ENOMEM);
168  }
169  }
170  memcpy(data->split_buf, buf, len);
171  data->split_buf_len = len;
172  data->split_pos = 0;
173  data->split_pkts = num_pkts;
174  return 1;
175  }
176 
177  return 0;
178 
179  } else if (fragmented == 1) {
180  // start of xiph data fragment
181  int res;
182 
183  // end packet has been lost somewhere, so drop buffered data
185 
186  if((res = avio_open_dyn_buf(&data->fragment)) < 0)
187  return res;
188 
189  avio_write(data->fragment, buf, pkt_len);
190  data->timestamp = *timestamp;
191 
192  } else {
193  av_assert1(fragmented < 4);
194  if (data->timestamp != *timestamp) {
195  // skip if fragmented timestamp is incorrect;
196  // a start packet has been lost somewhere
198  av_log(ctx, AV_LOG_ERROR, "RTP timestamps don't match!\n");
199  return AVERROR_INVALIDDATA;
200  }
201  if (!data->fragment) {
202  av_log(ctx, AV_LOG_WARNING,
203  "Received packet without a start fragment; dropping.\n");
204  return AVERROR(EAGAIN);
205  }
206 
207  // copy data to fragment buffer
208  avio_write(data->fragment, buf, pkt_len);
209 
210  if (fragmented == 3) {
211  // end of xiph data packet
212  int ret = ff_rtp_finalize_packet(pkt, &data->fragment, st->index);
213  if (ret < 0) {
214  av_log(ctx, AV_LOG_ERROR,
215  "Error occurred when getting fragment buffer.");
216  return ret;
217  }
218 
219  return 0;
220  }
221  }
222 
223  return AVERROR(EAGAIN);
224 }
225 
226 /**
227  * Length encoding described in RFC5215 section 3.1.1.
228  */
229 static int get_base128(const uint8_t ** buf, const uint8_t * buf_end)
230 {
231  int n = 0;
232  for (; *buf < buf_end; ++*buf) {
233  n <<= 7;
234  n += **buf & 0x7f;
235  if (!(**buf & 0x80)) {
236  ++*buf;
237  return n;
238  }
239  }
240  return 0;
241 }
242 
243 /**
244  * Based off parse_packed_headers in Vorbis RTP
245  */
246 static int
247 parse_packed_headers(const uint8_t * packed_headers,
248  const uint8_t * packed_headers_end,
249  AVCodecContext * codec, PayloadContext * xiph_data)
250 {
251 
252  unsigned num_packed, num_headers, length, length1, length2, extradata_alloc;
253  uint8_t *ptr;
254 
255  if (packed_headers_end - packed_headers < 9) {
256  av_log(codec, AV_LOG_ERROR,
257  "Invalid %td byte packed header.",
258  packed_headers_end - packed_headers);
259  return AVERROR_INVALIDDATA;
260  }
261 
262  num_packed = bytestream_get_be32(&packed_headers);
263  xiph_data->ident = bytestream_get_be24(&packed_headers);
264  length = bytestream_get_be16(&packed_headers);
265  num_headers = get_base128(&packed_headers, packed_headers_end);
266  length1 = get_base128(&packed_headers, packed_headers_end);
267  length2 = get_base128(&packed_headers, packed_headers_end);
268 
269  if (num_packed != 1 || num_headers > 3) {
270  av_log(codec, AV_LOG_ERROR,
271  "Unimplemented number of headers: %d packed headers, %d headers\n",
272  num_packed, num_headers);
273  return AVERROR_PATCHWELCOME;
274  }
275 
276  if (packed_headers_end - packed_headers != length ||
277  length1 > length || length2 > length - length1) {
278  av_log(codec, AV_LOG_ERROR,
279  "Bad packed header lengths (%d,%d,%td,%d)\n", length1,
280  length2, packed_headers_end - packed_headers, length);
281  return AVERROR_INVALIDDATA;
282  }
283 
284  /* allocate extra space:
285  * -- length/255 +2 for xiphlacing
286  * -- one for the '2' marker
287  * -- FF_INPUT_BUFFER_PADDING_SIZE required */
288  extradata_alloc = length + length/255 + 3 + FF_INPUT_BUFFER_PADDING_SIZE;
289 
290  ptr = codec->extradata = av_malloc(extradata_alloc);
291  if (!ptr) {
292  av_log(codec, AV_LOG_ERROR, "Out of memory\n");
293  return AVERROR(ENOMEM);
294  }
295  *ptr++ = 2;
296  ptr += av_xiphlacing(ptr, length1);
297  ptr += av_xiphlacing(ptr, length2);
298  memcpy(ptr, packed_headers, length);
299  ptr += length;
300  codec->extradata_size = ptr - codec->extradata;
301  // clear out remaining parts of the buffer
302  memset(ptr, 0, extradata_alloc - codec->extradata_size);
303 
304  return 0;
305 }
306 
307 static int xiph_parse_fmtp_pair(AVStream* stream,
308  PayloadContext *xiph_data,
309  char *attr, char *value)
310 {
311  AVCodecContext *codec = stream->codec;
312  int result = 0;
313 
314  if (!strcmp(attr, "sampling")) {
315  if (!strcmp(value, "YCbCr-4:2:0")) {
316  codec->pix_fmt = AV_PIX_FMT_YUV420P;
317  } else if (!strcmp(value, "YCbCr-4:4:2")) {
318  codec->pix_fmt = AV_PIX_FMT_YUV422P;
319  } else if (!strcmp(value, "YCbCr-4:4:4")) {
320  codec->pix_fmt = AV_PIX_FMT_YUV444P;
321  } else {
322  av_log(codec, AV_LOG_ERROR,
323  "Unsupported pixel format %s\n", attr);
324  return AVERROR_INVALIDDATA;
325  }
326  } else if (!strcmp(attr, "width")) {
327  /* This is an integer between 1 and 1048561
328  * and MUST be in multiples of 16. */
329  codec->width = atoi(value);
330  return 0;
331  } else if (!strcmp(attr, "height")) {
332  /* This is an integer between 1 and 1048561
333  * and MUST be in multiples of 16. */
334  codec->height = atoi(value);
335  return 0;
336  } else if (!strcmp(attr, "delivery-method")) {
337  /* Possible values are: inline, in_band, out_band/specific_name. */
338  return AVERROR_PATCHWELCOME;
339  } else if (!strcmp(attr, "configuration-uri")) {
340  /* NOTE: configuration-uri is supported only under 2 conditions:
341  *--after the delivery-method tag
342  * --with a delivery-method value of out_band */
343  return AVERROR_PATCHWELCOME;
344  } else if (!strcmp(attr, "configuration")) {
345  /* NOTE: configuration is supported only AFTER the delivery-method tag
346  * The configuration value is a base64 encoded packed header */
347  uint8_t *decoded_packet = NULL;
348  int packet_size;
349  size_t decoded_alloc = strlen(value) / 4 * 3 + 4;
350 
351  if (decoded_alloc <= INT_MAX) {
352  decoded_packet = av_malloc(decoded_alloc);
353  if (decoded_packet) {
354  packet_size =
355  av_base64_decode(decoded_packet, value, decoded_alloc);
356 
357  result = parse_packed_headers
358  (decoded_packet, decoded_packet + packet_size, codec,
359  xiph_data);
360  } else {
361  av_log(codec, AV_LOG_ERROR,
362  "Out of memory while decoding SDP configuration.\n");
363  result = AVERROR(ENOMEM);
364  }
365  } else {
366  av_log(codec, AV_LOG_ERROR, "Packet too large\n");
367  result = AVERROR_INVALIDDATA;
368  }
369  av_free(decoded_packet);
370  }
371  return result;
372 }
373 
374 static int xiph_parse_sdp_line(AVFormatContext *s, int st_index,
375  PayloadContext *data, const char *line)
376 {
377  const char *p;
378 
379  if (st_index < 0)
380  return 0;
381 
382  if (av_strstart(line, "fmtp:", &p)) {
383  return ff_parse_fmtp(s->streams[st_index], data, p,
385  }
386 
387  return 0;
388 }
389 
391  .enc_name = "theora",
392  .codec_type = AVMEDIA_TYPE_VIDEO,
393  .codec_id = AV_CODEC_ID_THEORA,
394  .parse_sdp_a_line = xiph_parse_sdp_line,
395  .alloc = xiph_new_context,
396  .free = xiph_free_context,
397  .parse_packet = xiph_handle_packet
398 };
399 
401  .enc_name = "vorbis",
402  .codec_type = AVMEDIA_TYPE_AUDIO,
403  .codec_id = AV_CODEC_ID_VORBIS,
404  .init = xiph_vorbis_init,
405  .parse_sdp_a_line = xiph_parse_sdp_line,
406  .alloc = xiph_new_context,
407  .free = xiph_free_context,
408  .parse_packet = xiph_handle_packet
409 };
AVPacket pkt
Definition: rtpdec_qt.c:37
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:205
const char * s
Definition: avisynth_c.h:668
Bytestream IO Context.
Definition: avio.h:68
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static PayloadContext * xiph_new_context(void)
Definition: rtpdec_xiph.c:50
void av_free_packet(AVPacket *pkt)
Free a packet.
Definition: avpacket.c:242
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:988
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:73
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
RTP/JPEG specific private data.
Definition: rdt.c:83
int index
stream index in AVFormatContext
Definition: avformat.h:644
RTPDynamicProtocolHandler ff_theora_dynamic_handler
Definition: rtpdec_xiph.c:390
#define AV_RB24
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
uint8_t * buf
the temporary storage buffer
Definition: rtpdec_asf.c:160
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:976
static void free_fragment_if_needed(PayloadContext *data)
Definition: rtpdec_xiph.c:55
static int xiph_vorbis_init(AVFormatContext *ctx, int st_index, PayloadContext *data)
Definition: rtpdec_xiph.c:72
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
Format I/O context.
Definition: avformat.h:944
static int xiph_parse_sdp_line(AVFormatContext *s, int st_index, PayloadContext *data, const char *line)
Definition: rtpdec_xiph.c:374
uint8_t
enum AVStreamParseType need_parsing
Definition: avformat.h:811
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
AVStream ** streams
Definition: avformat.h:992
uint8_t * data
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:173
AVIOContext * fragment
buffer for split payloads
Definition: rtpdec_xiph.c:44
unsigned ident
24-bit stream configuration identifier
Definition: rtpdec_xiph.c:42
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:73
uint32_t timestamp
current frame timestamp
static void xiph_free_context(PayloadContext *data)
Definition: rtpdec_xiph.c:65
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
#define AV_RB16
Definition: graph2dot.c:48
simple assert() macros that are a bit more flexible than ISO C assert().
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:72
Only parse headers, do not repack.
Definition: avformat.h:583
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
#define FF_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:53
ret
Definition: avfilter.c:821
int width
picture width / height.
static int get_base128(const uint8_t **buf, const uint8_t *buf_end)
Length encoding described in RFC5215 section 3.1.1.
Definition: rtpdec_xiph.c:229
Stream structure.
Definition: avformat.h:643
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
NULL
Definition: eval.c:55
AVIOContext * data
Definition: rtpdec_vp8.c:35
main external API structure.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
static int parse_packed_headers(const uint8_t *packed_headers, const uint8_t *packed_headers_end, AVCodecContext *codec, PayloadContext *xiph_data)
Based off parse_packed_headers in Vorbis RTP.
Definition: rtpdec_xiph.c:247
unsigned int av_xiphlacing(unsigned char *s, unsigned int v)
Encode extradata length to a buffer.
double value
Definition: eval.c:82
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
const char enc_name[50]
Definition: rtpdec.h:120
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
static int flags
Definition: cpu.c:23
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:33
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:68
static int xiph_handle_packet(AVFormatContext *ctx, PayloadContext *data, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, int flags)
Definition: rtpdec_xiph.c:82
RTPDynamicProtocolHandler ff_vorbis_dynamic_handler
Definition: rtpdec_xiph.c:400
int ff_rtp_finalize_packet(AVPacket *pkt, AVIOContext **dyn_buf, int stream_idx)
Close the dynamic buffer and make a packet from it.
Definition: rtpdec.c:865
uint8_t * split_buf
Definition: rtpdec_xiph.c:45
int av_base64_decode(uint8_t *out, const char *in_str, int out_size)
Decode a base64-encoded string.
int ff_parse_fmtp(AVStream *stream, PayloadContext *data, const char *p, int(*parse_fmtp)(AVStream *stream, PayloadContext *data, char *attr, char *value))
Definition: rtpdec.c:829
const char int length
Definition: avisynth_c.h:668
This structure stores compressed data.
static int xiph_parse_fmtp_pair(AVStream *stream, PayloadContext *xiph_data, char *attr, char *value)
Definition: rtpdec_xiph.c:307