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 } AttrNameMap;
74 
75 /* All known fmtp parameters and the corresponding RTPAttrTypeEnum */
76 #define ATTR_NAME_TYPE_INT 0
77 #define ATTR_NAME_TYPE_STR 1
78 static const AttrNameMap attr_names[] = {
79  { "SizeLength", ATTR_NAME_TYPE_INT,
80  offsetof(PayloadContext, sizelength) },
81  { "IndexLength", ATTR_NAME_TYPE_INT,
82  offsetof(PayloadContext, indexlength) },
83  { "IndexDeltaLength", ATTR_NAME_TYPE_INT,
84  offsetof(PayloadContext, indexdeltalength) },
85  { "profile-level-id", ATTR_NAME_TYPE_INT,
86  offsetof(PayloadContext, profile_level_id) },
87  { "StreamType", ATTR_NAME_TYPE_INT,
88  offsetof(PayloadContext, streamtype) },
89  { "mode", ATTR_NAME_TYPE_STR,
90  offsetof(PayloadContext, mode) },
91  { NULL, -1, -1 },
92 };
93 
95 {
96  av_freep(&data->au_headers);
97  av_freep(&data->mode);
98 }
99 
100 static int parse_fmtp_config(AVCodecParameters *par, const char *value)
101 {
102  /* decode the hexa encoded parameter */
103  int len = ff_hex_to_data(NULL, value);
104  av_freep(&par->extradata);
105  if (ff_alloc_extradata(par, len))
106  return AVERROR(ENOMEM);
108  return 0;
109 }
110 
112 {
113  int au_headers_length, au_header_size, i;
114  GetBitContext getbitcontext;
115 
116  if (len < 2)
117  return AVERROR_INVALIDDATA;
118 
119  /* decode the first 2 bytes where the AUHeader sections are stored
120  length in bits */
121  au_headers_length = AV_RB16(buf);
122 
123  if (au_headers_length > RTP_MAX_PACKET_LENGTH)
124  return -1;
125 
126  data->au_headers_length_bytes = (au_headers_length + 7) / 8;
127 
128  /* skip AU headers length section (2 bytes) */
129  buf += 2;
130  len -= 2;
131 
132  if (len < data->au_headers_length_bytes)
133  return AVERROR_INVALIDDATA;
134 
135  init_get_bits(&getbitcontext, buf, data->au_headers_length_bytes * 8);
136 
137  /* XXX: Wrong if optional additional sections are present (cts, dts etc...) */
138  au_header_size = data->sizelength + data->indexlength;
139  if (au_header_size <= 0 || (au_headers_length % au_header_size != 0))
140  return -1;
141 
142  data->nb_au_headers = au_headers_length / au_header_size;
143  if (!data->au_headers || data->au_headers_allocated < data->nb_au_headers) {
144  av_free(data->au_headers);
145  data->au_headers = av_malloc(sizeof(struct AUHeaders) * data->nb_au_headers);
146  if (!data->au_headers)
147  return AVERROR(ENOMEM);
148  data->au_headers_allocated = data->nb_au_headers;
149  }
150 
151  for (i = 0; i < data->nb_au_headers; ++i) {
152  data->au_headers[i].size = get_bits_long(&getbitcontext, data->sizelength);
153  data->au_headers[i].index = get_bits_long(&getbitcontext, data->indexlength);
154  }
155 
156  return 0;
157 }
158 
159 
160 /* Follows RFC 3640 */
162  AVStream *st, AVPacket *pkt, uint32_t *timestamp,
163  const uint8_t *buf, int len, uint16_t seq,
164  int flags)
165 {
166  int ret;
167 
168 
169  if (!buf) {
170  if (data->cur_au_index > data->nb_au_headers) {
171  av_log(ctx, AV_LOG_ERROR, "Invalid parser state\n");
172  return AVERROR_INVALIDDATA;
173  }
174  if (data->buf_size - data->buf_pos < data->au_headers[data->cur_au_index].size) {
175  av_log(ctx, AV_LOG_ERROR, "Invalid AU size\n");
176  return AVERROR_INVALIDDATA;
177  }
178  if ((ret = av_new_packet(pkt, data->au_headers[data->cur_au_index].size)) < 0) {
179  av_log(ctx, AV_LOG_ERROR, "Out of memory\n");
180  return ret;
181  }
182  memcpy(pkt->data, &data->buf[data->buf_pos], data->au_headers[data->cur_au_index].size);
183  data->buf_pos += data->au_headers[data->cur_au_index].size;
184  pkt->stream_index = st->index;
185  data->cur_au_index++;
186 
187  if (data->cur_au_index == data->nb_au_headers) {
188  data->buf_pos = 0;
189  return 0;
190  }
191 
192  return 1;
193  }
194 
195  if (rtp_parse_mp4_au(data, buf, len)) {
196  av_log(ctx, AV_LOG_ERROR, "Error parsing AU headers\n");
197  return -1;
198  }
199 
200  buf += data->au_headers_length_bytes + 2;
201  len -= data->au_headers_length_bytes + 2;
202  if (data->nb_au_headers == 1 && len < data->au_headers[0].size) {
203  /* Packet is fragmented */
204 
205  if (!data->buf_pos) {
206  if (data->au_headers[0].size > MAX_AAC_HBR_FRAME_SIZE) {
207  av_log(ctx, AV_LOG_ERROR, "Invalid AU size\n");
208  return AVERROR_INVALIDDATA;
209  }
210 
211  data->buf_size = data->au_headers[0].size;
212  data->timestamp = *timestamp;
213  }
214 
215  if (data->timestamp != *timestamp ||
216  data->au_headers[0].size != data->buf_size ||
217  data->buf_pos + len > MAX_AAC_HBR_FRAME_SIZE) {
218  data->buf_pos = 0;
219  data->buf_size = 0;
220  av_log(ctx, AV_LOG_ERROR, "Invalid packet received\n");
221  return AVERROR_INVALIDDATA;
222  }
223 
224  memcpy(&data->buf[data->buf_pos], buf, len);
225  data->buf_pos += len;
226 
227  if (!(flags & RTP_FLAG_MARKER))
228  return AVERROR(EAGAIN);
229 
230  if (data->buf_pos != data->buf_size) {
231  data->buf_pos = 0;
232  av_log(ctx, AV_LOG_ERROR, "Missed some packets, discarding frame\n");
233  return AVERROR_INVALIDDATA;
234  }
235 
236  data->buf_pos = 0;
237  ret = av_new_packet(pkt, data->buf_size);
238  if (ret < 0) {
239  av_log(ctx, AV_LOG_ERROR, "Out of memory\n");
240  return ret;
241  }
242  pkt->stream_index = st->index;
243 
244  memcpy(pkt->data, data->buf, data->buf_size);
245 
246  return 0;
247  }
248 
249  if (len < data->au_headers[0].size) {
250  av_log(ctx, AV_LOG_ERROR, "First AU larger than packet size\n");
251  return AVERROR_INVALIDDATA;
252  }
253  if ((ret = av_new_packet(pkt, data->au_headers[0].size)) < 0) {
254  av_log(ctx, AV_LOG_ERROR, "Out of memory\n");
255  return ret;
256  }
257  memcpy(pkt->data, buf, data->au_headers[0].size);
258  len -= data->au_headers[0].size;
259  buf += data->au_headers[0].size;
260  pkt->stream_index = st->index;
261 
262  if (len > 0 && data->nb_au_headers > 1) {
263  data->buf_size = FFMIN(len, sizeof(data->buf));
264  memcpy(data->buf, buf, data->buf_size);
265  data->cur_au_index = 1;
266  data->buf_pos = 0;
267  return 1;
268  }
269 
270  return 0;
271 }
272 
274  AVStream *stream, PayloadContext *data,
275  const char *attr, const char *value)
276 {
277  AVCodecParameters *par = stream->codecpar;
278  int res, i;
279 
280  if (!strcmp(attr, "config")) {
281  res = parse_fmtp_config(par, value);
282 
283  if (res < 0)
284  return res;
285  }
286 
287  if (par->codec_id == AV_CODEC_ID_AAC) {
288  /* Looking for a known attribute */
289  for (i = 0; attr_names[i].str; ++i) {
290  if (!av_strcasecmp(attr, attr_names[i].str)) {
292  int val = atoi(value);
293  if (val > 32) {
295  "The %s field size is invalid (%d)\n",
296  attr, val);
297  return AVERROR_INVALIDDATA;
298  }
299  *(int *)((char *)data+
300  attr_names[i].offset) = val;
301  } else if (attr_names[i].type == ATTR_NAME_TYPE_STR) {
302  char *val = av_strdup(value);
303  if (!val)
304  return AVERROR(ENOMEM);
305  *(char **)((char *)data+
306  attr_names[i].offset) = val;
307  }
308  }
309  }
310  }
311  return 0;
312 }
313 
314 static int parse_sdp_line(AVFormatContext *s, int st_index,
315  PayloadContext *data, const char *line)
316 {
317  const char *p;
318 
319  if (st_index < 0)
320  return 0;
321 
322  if (av_strstart(line, "fmtp:", &p))
323  return ff_parse_fmtp(s, s->streams[st_index], data, p, parse_fmtp);
324 
325  return 0;
326 }
327 
329  .enc_name = "MP4V-ES",
330  .codec_type = AVMEDIA_TYPE_VIDEO,
331  .codec_id = AV_CODEC_ID_MPEG4,
332  .need_parsing = AVSTREAM_PARSE_FULL,
333  .priv_data_size = sizeof(PayloadContext),
334  .parse_sdp_a_line = parse_sdp_line,
335 };
336 
338  .enc_name = "mpeg4-generic",
339  .codec_type = AVMEDIA_TYPE_AUDIO,
340  .codec_id = AV_CODEC_ID_AAC,
341  .priv_data_size = sizeof(PayloadContext),
342  .parse_sdp_a_line = parse_sdp_line,
343  .close = close_context,
345 };
AVCodecParameters::extradata
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:3971
AVERROR
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
ff_mp4v_es_dynamic_handler
const RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler
Definition: rtpdec_mpeg4.c:328
AVCodecParameters
This struct describes the properties of an encoded stream.
Definition: avcodec.h:3949
PayloadContext::au_headers
struct PayloadContext::AUHeaders * au_headers
rtpdec_formats.h
ff_parse_fmtp
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
get_bits_long
static unsigned int get_bits_long(GetBitContext *s, int n)
Read 0-32 bits.
Definition: get_bits.h:546
av_strcasecmp
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:213
AV_CODEC_ID_MPEG4
@ AV_CODEC_ID_MPEG4
Definition: avcodec.h:230
PayloadContext::objecttype
int objecttype
Definition: rtpdec_mpeg4.c:45
RTP_FLAG_MARKER
#define RTP_FLAG_MARKER
RTP marker bit was set for this packet.
Definition: rtpdec.h:93
AVPacket::data
uint8_t * data
Definition: avcodec.h:1477
data
const char data[16]
Definition: mxf.c:91
parse_packet
static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
Parse a packet, add all split parts to parse_queue.
Definition: utils.c:1451
AttrNameMap
Definition: rtpdec_mpeg4.c:69
PayloadContext::profile_level_id
int profile_level_id
Definition: rtpdec_mpeg4.c:43
close_context
static void close_context(PayloadContext *data)
Definition: rtpdec_mpeg4.c:94
PayloadContext::sizelength
int sizelength
Definition: rtpdec_mpeg4.c:40
PayloadContext::indexlength
int indexlength
Definition: rtpdec_mpeg4.c:41
init_get_bits
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition: get_bits.h:659
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
PayloadContext::AUHeaders
mpeg 4 AU headers
Definition: rtpdec_mpeg4.c:49
PayloadContext::timestamp
uint32_t timestamp
current frame timestamp
Definition: rtpdec_ac3.c:31
RTPDynamicProtocolHandler::enc_name
const char * enc_name
Definition: rtpdec.h:116
PayloadContext::nb_au_headers
int nb_au_headers
Definition: rtpdec_mpeg4.c:60
PayloadContext::buf_pos
int buf_pos
Definition: rtpdec_mpeg4.c:65
parse_fmtp
static int parse_fmtp(AVFormatContext *s, AVStream *stream, PayloadContext *data, const char *attr, const char *value)
Definition: rtpdec_mpeg4.c:273
GetBitContext
Definition: get_bits.h:61
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
buf
void * buf
Definition: avisynth_c.h:766
s
#define s(width, name)
Definition: cbs_vp9.c:257
av_new_packet
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
AttrNameMap::str
const char * str
Definition: rtpdec_mpeg4.c:70
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
PayloadContext::au_headers_length_bytes
int au_headers_length_bytes
Definition: rtpdec_mpeg4.c:61
ctx
AVFormatContext * ctx
Definition: movenc.c:48
PayloadContext::streamtype
int streamtype
Definition: rtpdec_mpeg4.c:44
get_bits.h
PayloadContext::AUHeaders::dts
int dts
Definition: rtpdec_mpeg4.c:55
PayloadContext::AUHeaders::rap_flag
int rap_flag
Definition: rtpdec_mpeg4.c:56
ff_hex_to_data
int ff_hex_to_data(uint8_t *data, const char *p)
Parse a string of hexadecimal strings.
Definition: utils.c:4882
AVFormatContext
Format I/O context.
Definition: avformat.h:1342
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1017
NULL
#define NULL
Definition: coverity.c:32
PayloadContext::au_headers_allocated
int au_headers_allocated
Definition: rtpdec_mpeg4.c:59
AV_CODEC_ID_AAC
@ AV_CODEC_ID_AAC
Definition: avcodec.h:566
PayloadContext::AUHeaders::cts
int cts
Definition: rtpdec_mpeg4.c:53
parse_fmtp_config
static int parse_fmtp_config(AVCodecParameters *par, const char *value)
Definition: rtpdec_mpeg4.c:100
aac_parse_packet
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:161
ATTR_NAME_TYPE_INT
#define ATTR_NAME_TYPE_INT
Definition: rtpdec_mpeg4.c:76
FFMAX
#define FFMAX(a, b)
Definition: common.h:94
size
int size
Definition: twinvq_data.h:11134
PayloadContext::buf_size
int buf_size
Definition: rtpdec_mpeg4.c:65
PayloadContext::AUHeaders::index
int index
Definition: rtpdec_mpeg4.c:51
val
const char const char void * val
Definition: avisynth_c.h:863
FFMIN
#define FFMIN(a, b)
Definition: common.h:96
line
Definition: graph2dot.c:48
attributes.h
av_strstart
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
MAX_AAC_HBR_FRAME_SIZE
#define MAX_AAC_HBR_FRAME_SIZE
Definition: rtpdec_mpeg4.c:36
AttrNameMap::type
uint16_t type
Definition: rtpdec_mpeg4.c:71
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
PayloadContext::AUHeaders::dts_flag
int dts_flag
Definition: rtpdec_mpeg4.c:54
ATTR_NAME_TYPE_STR
#define ATTR_NAME_TYPE_STR
Definition: rtpdec_mpeg4.c:77
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
uint8_t
uint8_t
Definition: audio_convert.c:194
parse_sdp_line
static int parse_sdp_line(AVFormatContext *s, int st_index, PayloadContext *data, const char *line)
Definition: rtpdec_mpeg4.c:314
len
int len
Definition: vorbis_enc_data.h:452
attr_names
static const AttrNameMap attr_names[]
Definition: rtpdec_mpeg4.c:78
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:870
rtp_parse_mp4_au
static int rtp_parse_mp4_au(PayloadContext *data, const uint8_t *buf, int len)
Definition: rtpdec_mpeg4.c:111
PayloadContext::AUHeaders::size
int size
Definition: rtpdec_mpeg4.c:50
RTP_MAX_PACKET_LENGTH
#define RTP_MAX_PACKET_LENGTH
Definition: rtpdec.h:36
ff_mpeg4_generic_dynamic_handler
const RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler
Definition: rtpdec_mpeg4.c:337
PayloadContext::buf
uint8_t * buf
the temporary storage buffer
Definition: rtpdec_asf.c:183
AVStream::index
int index
stream index in AVFormatContext
Definition: avformat.h:871
AttrNameMap::offset
uint32_t offset
Definition: rtpdec_mpeg4.c:72
pkt
static AVPacket pkt
Definition: demuxing_decoding.c:54
mode
mode
Definition: ebur128.h:83
PayloadContext::AUHeaders::cts_flag
int cts_flag
Definition: rtpdec_mpeg4.c:52
AVPacket::stream_index
int stream_index
Definition: avcodec.h:1479
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
PayloadContext::mode
char * mode
Definition: rtpdec_mpeg4.c:46
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
PayloadContext::cur_au_index
int cur_au_index
Definition: rtpdec_mpeg4.c:62
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3957
AVPacket
This structure stores compressed data.
Definition: avcodec.h:1454
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
AVSTREAM_PARSE_FULL
@ AVSTREAM_PARSE_FULL
full parsing and repack
Definition: avformat.h:791
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:565
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
avstring.h
PayloadContext::indexdeltalength
int indexdeltalength
Definition: rtpdec_mpeg4.c:42
PayloadContext
RTP/JPEG specific private data.
Definition: rdt.c:83
RTPDynamicProtocolHandler
Definition: rtpdec.h:115
AV_RB16
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:94
PayloadContext::AUHeaders::streamstate
int streamstate
Definition: rtpdec_mpeg4.c:57
ff_alloc_extradata
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:3309