FFmpeg
rtpdec_mpeg4.c
Go to the documentation of this file.
1 /*
2  * Common code for the RTP depacketization of MPEG-4 formats.
3  * Copyright (c) 2010 Fabrice Bellard
4  * Romain Degez
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 MPEG-4 / RTP Code
26  * @author Fabrice Bellard
27  * @author Romain Degez
28  */
29 
30 #include "rtpdec_formats.h"
31 #include "internal.h"
32 #include "libavutil/attributes.h"
33 #include "libavutil/avstring.h"
34 #include "libavcodec/get_bits.h"
35 
36 #define MAX_AAC_HBR_FRAME_SIZE 8191
37 
38 /** Structure listing useful vars to parse RTP packet payload */
39 struct PayloadContext {
46  char *mode;
47 
48  /** mpeg 4 AU headers */
49  struct AUHeaders {
50  int size;
51  int index;
52  int cts_flag;
53  int cts;
54  int dts_flag;
55  int dts;
56  int rap_flag;
58  } *au_headers;
63 
66  uint32_t timestamp;
67 };
68 
69 typedef struct AttrNameMap {
70  const char *str;
71  uint16_t type;
72  uint32_t offset;
73 
74  /** Range for integer values */
75  struct Range {
76  int min;
77  int max;
78  } range;
79 } AttrNameMap;
80 
81 /* All known fmtp parameters and the corresponding RTPAttrTypeEnum */
82 #define ATTR_NAME_TYPE_INT 0
83 #define ATTR_NAME_TYPE_STR 1
84 static const AttrNameMap attr_names[] = {
85  { "SizeLength", ATTR_NAME_TYPE_INT,
86  offsetof(PayloadContext, sizelength),
87  {0, 32} }, // SizeLength number of bits used to encode AU-size integer value
88  { "IndexLength", ATTR_NAME_TYPE_INT,
89  offsetof(PayloadContext, indexlength),
90  {0, 32} }, // IndexLength number of bits used to encode AU-Index integer value
91  { "IndexDeltaLength", ATTR_NAME_TYPE_INT,
93  {0, 32} }, // IndexDeltaLength number of bits to encode AU-Index-delta integer value
94  { "profile-level-id", ATTR_NAME_TYPE_INT,
96  {INT32_MIN, INT32_MAX} }, // It differs depending on StreamType
97  { "StreamType", ATTR_NAME_TYPE_INT,
98  offsetof(PayloadContext, streamtype),
99  {0x00, 0x3F} }, // Values from ISO/IEC 14496-1, 'StreamType Values' table
100  { "mode", ATTR_NAME_TYPE_STR,
101  offsetof(PayloadContext, mode),
102  {0} },
103  { NULL, -1, -1, {0} },
104 };
105 
107 {
108  av_freep(&data->au_headers);
109  av_freep(&data->mode);
110 }
111 
112 static int parse_fmtp_config(AVCodecParameters *par, const char *value)
113 {
114  /* decode the hexa encoded parameter */
115  int len = ff_hex_to_data(NULL, value);
116  av_freep(&par->extradata);
117  if (ff_alloc_extradata(par, len))
118  return AVERROR(ENOMEM);
119  ff_hex_to_data(par->extradata, value);
120  return 0;
121 }
122 
124 {
125  int au_headers_length, au_header_size, i;
126  GetBitContext getbitcontext;
127 
128  if (len < 2)
129  return AVERROR_INVALIDDATA;
130 
131  /* decode the first 2 bytes where the AUHeader sections are stored
132  length in bits */
133  au_headers_length = AV_RB16(buf);
134 
135  if (au_headers_length > RTP_MAX_PACKET_LENGTH)
136  return -1;
137 
138  data->au_headers_length_bytes = (au_headers_length + 7) / 8;
139 
140  /* skip AU headers length section (2 bytes) */
141  buf += 2;
142  len -= 2;
143 
144  if (len < data->au_headers_length_bytes)
145  return AVERROR_INVALIDDATA;
146 
147  init_get_bits(&getbitcontext, buf, data->au_headers_length_bytes * 8);
148 
149  /* XXX: Wrong if optional additional sections are present (cts, dts etc...) */
150  au_header_size = data->sizelength + data->indexlength;
151  if (au_header_size <= 0 || (au_headers_length % au_header_size != 0))
152  return -1;
153 
154  data->nb_au_headers = au_headers_length / au_header_size;
155  if (!data->au_headers || data->au_headers_allocated < data->nb_au_headers) {
156  av_free(data->au_headers);
157  data->au_headers = av_malloc(sizeof(struct AUHeaders) * data->nb_au_headers);
158  if (!data->au_headers)
159  return AVERROR(ENOMEM);
160  data->au_headers_allocated = data->nb_au_headers;
161  }
162 
163  for (i = 0; i < data->nb_au_headers; ++i) {
164  data->au_headers[i].size = get_bits_long(&getbitcontext, data->sizelength);
165  data->au_headers[i].index = get_bits_long(&getbitcontext, data->indexlength);
166  }
167 
168  return 0;
169 }
170 
171 
172 /* Follows RFC 3640 */
174  AVStream *st, AVPacket *pkt, uint32_t *timestamp,
175  const uint8_t *buf, int len, uint16_t seq,
176  int flags)
177 {
178  int ret;
179 
180 
181  if (!buf) {
182  if (data->cur_au_index > data->nb_au_headers) {
183  av_log(ctx, AV_LOG_ERROR, "Invalid parser state\n");
184  return AVERROR_INVALIDDATA;
185  }
186  if (data->buf_size - data->buf_pos < data->au_headers[data->cur_au_index].size) {
187  av_log(ctx, AV_LOG_ERROR, "Invalid AU size\n");
188  return AVERROR_INVALIDDATA;
189  }
190  if ((ret = av_new_packet(pkt, data->au_headers[data->cur_au_index].size)) < 0) {
191  av_log(ctx, AV_LOG_ERROR, "Out of memory\n");
192  return ret;
193  }
194  memcpy(pkt->data, &data->buf[data->buf_pos], data->au_headers[data->cur_au_index].size);
195  data->buf_pos += data->au_headers[data->cur_au_index].size;
196  pkt->stream_index = st->index;
197  data->cur_au_index++;
198 
199  if (data->cur_au_index == data->nb_au_headers) {
200  data->buf_pos = 0;
201  return 0;
202  }
203 
204  return 1;
205  }
206 
207  if (rtp_parse_mp4_au(data, buf, len)) {
208  av_log(ctx, AV_LOG_ERROR, "Error parsing AU headers\n");
209  return -1;
210  }
211 
212  buf += data->au_headers_length_bytes + 2;
213  len -= data->au_headers_length_bytes + 2;
214  if (data->nb_au_headers == 1 && len < data->au_headers[0].size) {
215  /* Packet is fragmented */
216 
217  if (!data->buf_pos) {
218  if (data->au_headers[0].size > MAX_AAC_HBR_FRAME_SIZE) {
219  av_log(ctx, AV_LOG_ERROR, "Invalid AU size\n");
220  return AVERROR_INVALIDDATA;
221  }
222 
223  data->buf_size = data->au_headers[0].size;
224  data->timestamp = *timestamp;
225  }
226 
227  if (data->timestamp != *timestamp ||
228  data->au_headers[0].size != data->buf_size ||
229  data->buf_pos + len > MAX_AAC_HBR_FRAME_SIZE) {
230  data->buf_pos = 0;
231  data->buf_size = 0;
232  av_log(ctx, AV_LOG_ERROR, "Invalid packet received\n");
233  return AVERROR_INVALIDDATA;
234  }
235 
236  memcpy(&data->buf[data->buf_pos], buf, len);
237  data->buf_pos += len;
238 
239  if (!(flags & RTP_FLAG_MARKER))
240  return AVERROR(EAGAIN);
241 
242  if (data->buf_pos != data->buf_size) {
243  data->buf_pos = 0;
244  av_log(ctx, AV_LOG_ERROR, "Missed some packets, discarding frame\n");
245  return AVERROR_INVALIDDATA;
246  }
247 
248  data->buf_pos = 0;
249  ret = av_new_packet(pkt, data->buf_size);
250  if (ret < 0) {
251  av_log(ctx, AV_LOG_ERROR, "Out of memory\n");
252  return ret;
253  }
254  pkt->stream_index = st->index;
255 
256  memcpy(pkt->data, data->buf, data->buf_size);
257 
258  return 0;
259  }
260 
261  if (len < data->au_headers[0].size) {
262  av_log(ctx, AV_LOG_ERROR, "First AU larger than packet size\n");
263  return AVERROR_INVALIDDATA;
264  }
265  if ((ret = av_new_packet(pkt, data->au_headers[0].size)) < 0) {
266  av_log(ctx, AV_LOG_ERROR, "Out of memory\n");
267  return ret;
268  }
269  memcpy(pkt->data, buf, data->au_headers[0].size);
270  len -= data->au_headers[0].size;
271  buf += data->au_headers[0].size;
272  pkt->stream_index = st->index;
273 
274  if (len > 0 && data->nb_au_headers > 1) {
275  data->buf_size = FFMIN(len, sizeof(data->buf));
276  memcpy(data->buf, buf, data->buf_size);
277  data->cur_au_index = 1;
278  data->buf_pos = 0;
279  return 1;
280  }
281 
282  return 0;
283 }
284 
286  AVStream *stream, PayloadContext *data,
287  const char *attr, const char *value)
288 {
289  AVCodecParameters *par = stream->codecpar;
290  int res, i;
291 
292  if (!strcmp(attr, "config")) {
293  res = parse_fmtp_config(par, value);
294 
295  if (res < 0)
296  return res;
297  }
298 
299  if (par->codec_id == AV_CODEC_ID_AAC) {
300  /* Looking for a known attribute */
301  for (i = 0; attr_names[i].str; ++i) {
302  if (!av_strcasecmp(attr, attr_names[i].str)) {
303  if (attr_names[i].type == ATTR_NAME_TYPE_INT) {
304  char *end_ptr = NULL;
305  long long int val = strtoll(value, &end_ptr, 10);
306  if (end_ptr == value || end_ptr[0] != '\0') {
307  av_log(s, AV_LOG_ERROR,
308  "The %s field value is not a valid number: %s\n",
309  attr, value);
310  return AVERROR_INVALIDDATA;
311  }
312  if (val < attr_names[i].range.min ||
313  val > attr_names[i].range.max) {
314  av_log(s, AV_LOG_ERROR,
315  "fmtp field %s should be in range [%d,%d] (provided value: %lld)",
316  attr, attr_names[i].range.min, attr_names[i].range.max, val);
317  return AVERROR_INVALIDDATA;
318  }
319 
320  *(int *)((char *)data+
321  attr_names[i].offset) = (int) val;
322  } else if (attr_names[i].type == ATTR_NAME_TYPE_STR) {
323  char *val = av_strdup(value);
324  if (!val)
325  return AVERROR(ENOMEM);
326  *(char **)((char *)data+
327  attr_names[i].offset) = val;
328  }
329  }
330  }
331  }
332  return 0;
333 }
334 
335 static int parse_sdp_line(AVFormatContext *s, int st_index,
336  PayloadContext *data, const char *line)
337 {
338  const char *p;
339 
340  if (st_index < 0)
341  return 0;
342 
343  if (av_strstart(line, "fmtp:", &p))
344  return ff_parse_fmtp(s, s->streams[st_index], data, p, parse_fmtp);
345 
346  return 0;
347 }
348 
350  .enc_name = "MP4V-ES",
351  .codec_type = AVMEDIA_TYPE_VIDEO,
352  .codec_id = AV_CODEC_ID_MPEG4,
353  .need_parsing = AVSTREAM_PARSE_FULL,
354  .priv_data_size = sizeof(PayloadContext),
355  .parse_sdp_a_line = parse_sdp_line,
356 };
357 
359  .enc_name = "mpeg4-generic",
360  .codec_type = AVMEDIA_TYPE_AUDIO,
361  .codec_id = AV_CODEC_ID_AAC,
362  .priv_data_size = sizeof(PayloadContext),
363  .parse_sdp_a_line = parse_sdp_line,
364  .close = close_context,
366 };
AVPacket pkt
Definition: rtpdec_qt.c:37
const RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler
Definition: rtpdec_mpeg4.c:349
uint32_t offset
Definition: rtpdec_mpeg4.c:72
#define NULL
Definition: coverity.c:32
const char const char void * val
Definition: avisynth_c.h:863
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
#define RTP_MAX_PACKET_LENGTH
Definition: rtpdec.h:36
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
RTP/JPEG specific private data.
Definition: rdt.c:83
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3957
int index
stream index in AVFormatContext
Definition: avformat.h:882
GLint GLenum type
Definition: opengl_enc.c:104
static void close_context(PayloadContext *data)
Definition: rtpdec_mpeg4.c:106
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
Definition: bytestream.h:87
This struct describes the properties of an encoded stream.
Definition: avcodec.h:3949
Macro definitions for various function/variable attributes.
Format I/O context.
Definition: avformat.h:1358
uint8_t
struct AttrNameMap::Range range
#define av_malloc(s)
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:108
static int parse_fmtp(AVFormatContext *s, AVStream *stream, PayloadContext *data, const char *attr, const char *value)
Definition: rtpdec_mpeg4.c:285
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1426
mpeg 4 AU headers
Definition: rtpdec_mpeg4.c:49
uint8_t * data
Definition: avcodec.h:1477
bitstream reader API header.
ptrdiff_t size
Definition: opengl_enc.c:100
#define av_log(a,...)
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:86
uint32_t timestamp
current frame timestamp
Definition: rtpdec_ac3.c:31
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#define RTP_FLAG_MARKER
RTP marker bit was set for this packet.
Definition: rtpdec.h:93
Definition: graph2dot.c:48
#define FFMAX(a, b)
Definition: common.h:94
int au_headers_allocated
Definition: rtpdec_mpeg4.c:59
uint16_t type
Definition: rtpdec_mpeg4.c:71
int ff_alloc_extradata(AVCodecParameters *par, int size)
Allocate extradata with additional AV_INPUT_BUFFER_PADDING_SIZE at end which is always set to 0...
Definition: utils.c:3294
#define FFMIN(a, b)
Definition: common.h:96
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:213
static int parse_fmtp_config(AVCodecParameters *par, const char *value)
Definition: rtpdec_mpeg4.c:112
static int aac_parse_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_mpeg4.c:173
AVFormatContext * ctx
Definition: movenc.c:48
#define ATTR_NAME_TYPE_INT
Definition: rtpdec_mpeg4.c:82
#define s(width, name)
Definition: cbs_vp9.c:257
const char * str
Definition: rtpdec_mpeg4.c:70
Stream structure.
Definition: avformat.h:881
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
#define MAX_AAC_HBR_FRAME_SIZE
Definition: rtpdec_mpeg4.c:36
struct PayloadContext::AUHeaders * au_headers
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition: get_bits.h:659
uint8_t * buf
the temporary storage buffer
Definition: rtpdec_asf.c:183
#define ATTR_NAME_TYPE_STR
Definition: rtpdec_mpeg4.c:83
int ff_parse_fmtp(AVFormatContext *s, AVStream *stream, PayloadContext *data, const char *p, int(*parse_fmtp)(AVFormatContext *s, AVStream *stream, PayloadContext *data, const char *attr, const char *value))
Definition: rtpdec.c:889
static int rtp_parse_mp4_au(PayloadContext *data, const uint8_t *buf, int len)
Definition: rtpdec_mpeg4.c:123
int ff_hex_to_data(uint8_t *data, const char *p)
Parse a string of hexadecimal strings.
Definition: utils.c:4864
static unsigned int get_bits_long(GetBitContext *s, int n)
Read 0-32 bits.
Definition: get_bits.h:546
const char * enc_name
Definition: rtpdec.h:116
static int parse_sdp_line(AVFormatContext *s, int st_index, PayloadContext *data, const char *line)
Definition: rtpdec_mpeg4.c:335
const RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler
Definition: rtpdec_mpeg4.c:358
#define flags(name, subs,...)
Definition: cbs_av1.c:561
static const AttrNameMap attr_names[]
Definition: rtpdec_mpeg4.c:84
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:34
full parsing and repack
Definition: avformat.h:800
Range for integer values.
Definition: rtpdec_mpeg4.c:75
static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
Parse a packet, add all split parts to parse_queue.
Definition: utils.c:1438
#define av_free(p)
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:3971
#define av_freep(p)
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1028
int au_headers_length_bytes
Definition: rtpdec_mpeg4.c:61
int stream_index
Definition: avcodec.h:1479
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame 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.Frame references ownership and permissions
This structure stores compressed data.
Definition: avcodec.h:1454
mode
Use these values in ebur128_init (or&#39;ed).
Definition: ebur128.h:83