rtpdec_mpeg4.c
Go to the documentation of this file.
1 
30 #include "rtpdec_formats.h"
31 #include "internal.h"
32 #include "libavutil/avstring.h"
33 #include "libavcodec/get_bits.h"
34 
36 struct PayloadContext
37 {
44  char *mode;
45 
47  struct AUHeaders {
48  int size;
49  int index;
50  int cts_flag;
51  int cts;
52  int dts_flag;
53  int dts;
54  int rap_flag;
56  } *au_headers;
61 };
62 
63 typedef struct {
64  const char *str;
65  uint16_t type;
66  uint32_t offset;
67 } AttrNameMap;
68 
69 /* All known fmtp parameters and the corresponding RTPAttrTypeEnum */
70 #define ATTR_NAME_TYPE_INT 0
71 #define ATTR_NAME_TYPE_STR 1
72 static const AttrNameMap attr_names[]=
73 {
74  { "SizeLength", ATTR_NAME_TYPE_INT,
75  offsetof(PayloadContext, sizelength) },
76  { "IndexLength", ATTR_NAME_TYPE_INT,
77  offsetof(PayloadContext, indexlength) },
78  { "IndexDeltaLength", ATTR_NAME_TYPE_INT,
79  offsetof(PayloadContext, indexdeltalength) },
80  { "profile-level-id", ATTR_NAME_TYPE_INT,
81  offsetof(PayloadContext, profile_level_id) },
82  { "StreamType", ATTR_NAME_TYPE_INT,
83  offsetof(PayloadContext, streamtype) },
84  { "mode", ATTR_NAME_TYPE_STR,
85  offsetof(PayloadContext, mode) },
86  { NULL, -1, -1 },
87 };
88 
90 {
91  return av_mallocz(sizeof(PayloadContext));
92 }
93 
95 {
96  int i;
97  for (i = 0; i < data->nb_au_headers; i++) {
98  /* according to rtp_parse_mp4_au, we treat multiple
99  * au headers as one, so nb_au_headers is always 1.
100  * loop anyway in case this changes.
101  * (note: changes done carelessly might lead to a double free)
102  */
103  av_free(&data->au_headers[i]);
104  }
105  av_free(data->mode);
106  av_free(data);
107 }
108 
109 static int parse_fmtp_config(AVCodecContext * codec, char *value)
110 {
111  /* decode the hexa encoded parameter */
112  int len = ff_hex_to_data(NULL, value);
113  av_free(codec->extradata);
115  if (!codec->extradata)
116  return AVERROR(ENOMEM);
117  codec->extradata_size = len;
118  ff_hex_to_data(codec->extradata, value);
119  return 0;
120 }
121 
122 static int rtp_parse_mp4_au(PayloadContext *data, const uint8_t *buf)
123 {
124  int au_headers_length, au_header_size, i;
125  GetBitContext getbitcontext;
126 
127  /* decode the first 2 bytes where the AUHeader sections are stored
128  length in bits */
129  au_headers_length = AV_RB16(buf);
130 
131  if (au_headers_length > RTP_MAX_PACKET_LENGTH)
132  return -1;
133 
134  data->au_headers_length_bytes = (au_headers_length + 7) / 8;
135 
136  /* skip AU headers length section (2 bytes) */
137  buf += 2;
138 
139  init_get_bits(&getbitcontext, buf, data->au_headers_length_bytes * 8);
140 
141  /* XXX: Wrong if optionnal additional sections are present (cts, dts etc...) */
142  au_header_size = data->sizelength + data->indexlength;
143  if (au_header_size <= 0 || (au_headers_length % au_header_size != 0))
144  return -1;
145 
146  data->nb_au_headers = au_headers_length / au_header_size;
147  if (!data->au_headers || data->au_headers_allocated < data->nb_au_headers) {
148  av_free(data->au_headers);
149  data->au_headers = av_malloc(sizeof(struct AUHeaders) * data->nb_au_headers);
150  data->au_headers_allocated = data->nb_au_headers;
151  }
152 
153  /* XXX: We handle multiple AU Section as only one (need to fix this for interleaving)
154  In my test, the FAAD decoder does not behave correctly when sending each AU one by one
155  but does when sending the whole as one big packet... */
156  data->au_headers[0].size = 0;
157  data->au_headers[0].index = 0;
158  for (i = 0; i < data->nb_au_headers; ++i) {
159  data->au_headers[0].size += get_bits_long(&getbitcontext, data->sizelength);
160  data->au_headers[0].index = get_bits_long(&getbitcontext, data->indexlength);
161  }
162 
163  data->nb_au_headers = 1;
164 
165  return 0;
166 }
167 
168 
169 /* Follows RFC 3640 */
172  AVStream *st,
173  AVPacket *pkt,
174  uint32_t *timestamp,
175  const uint8_t *buf, int len, int flags)
176 {
177  if (rtp_parse_mp4_au(data, buf))
178  return -1;
179 
180  buf += data->au_headers_length_bytes + 2;
181  len -= data->au_headers_length_bytes + 2;
182 
183  /* XXX: Fixme we only handle the case where rtp_parse_mp4_au define
184  one au_header */
185  av_new_packet(pkt, data->au_headers[0].size);
186  memcpy(pkt->data, buf, data->au_headers[0].size);
187 
188  pkt->stream_index = st->index;
189  return 0;
190 }
191 
192 static int parse_fmtp(AVStream *stream, PayloadContext *data,
193  char *attr, char *value)
194 {
195  AVCodecContext *codec = stream->codec;
196  int res, i;
197 
198  if (!strcmp(attr, "config")) {
199  res = parse_fmtp_config(codec, value);
200 
201  if (res < 0)
202  return res;
203  }
204 
205  if (codec->codec_id == CODEC_ID_AAC) {
206  /* Looking for a known attribute */
207  for (i = 0; attr_names[i].str; ++i) {
208  if (!av_strcasecmp(attr, attr_names[i].str)) {
209  if (attr_names[i].type == ATTR_NAME_TYPE_INT) {
210  *(int *)((char *)data+
211  attr_names[i].offset) = atoi(value);
212  } else if (attr_names[i].type == ATTR_NAME_TYPE_STR)
213  *(char **)((char *)data+
214  attr_names[i].offset) = av_strdup(value);
215  }
216  }
217  }
218  return 0;
219 }
220 
221 static int parse_sdp_line(AVFormatContext *s, int st_index,
222  PayloadContext *data, const char *line)
223 {
224  const char *p;
225 
226  if (av_strstart(line, "fmtp:", &p))
227  return ff_parse_fmtp(s->streams[st_index], data, p, parse_fmtp);
228 
229  return 0;
230 }
231 
233  .enc_name = "MP4V-ES",
234  .codec_type = AVMEDIA_TYPE_VIDEO,
235  .codec_id = CODEC_ID_MPEG4,
236  .parse_sdp_a_line = parse_sdp_line,
237 };
238 
240  .enc_name = "mpeg4-generic",
241  .codec_type = AVMEDIA_TYPE_AUDIO,
242  .codec_id = CODEC_ID_AAC,
243  .parse_sdp_a_line = parse_sdp_line,
244  .alloc = new_context,
245  .free = free_context,
246  .parse_packet = aac_parse_packet
247 };
uint32_t offset
Definition: rtpdec_mpeg4.c:66
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:154
static int parse_fmtp_config(AVCodecContext *codec, char *value)
Definition: rtpdec_mpeg4.c:109
AV_WL32 AV_WL24 AV_WL16 AV_WB32 AV_WB24 AV_RB16
Definition: bytestream.h:89
#define RTP_MAX_PACKET_LENGTH
Definition: rtpdec.h:34
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:60
RTP/H264 specific private data.
Definition: rdt.c:83
int index
stream index in AVFormatContext
Definition: avformat.h:621
RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler
Definition: rtpdec_mpeg4.c:239
Format I/O context.
Definition: avformat.h:863
static void free_context(PayloadContext *data)
Definition: rtpdec_mpeg4.c:94
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:1387
AVStream ** streams
Definition: avformat.h:908
mpeg 4 AU headers
Definition: rtpdec_mpeg4.c:47
const char data[16]
Definition: mxf.c:60
uint8_t * data
Definition: avcodec.h:908
static int flags
Definition: log.c:34
bitstream reader API header.
static int rtp_parse_mp4_au(PayloadContext *data, const uint8_t *buf)
Definition: rtpdec_mpeg4.c:122
static int aac_parse_packet(AVFormatContext *ctx, PayloadContext *data, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, int flags)
Definition: rtpdec_mpeg4.c:170
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:137
#define AVERROR(e)
Definition: error.h:43
Definition: graph2dot.c:39
int au_headers_allocated
Definition: rtpdec_mpeg4.c:57
const char enc_name[50]
Definition: rtpdec.h:117
AVCodecContext * codec
codec context
Definition: avformat.h:623
uint16_t type
Definition: rtpdec_mpeg4.c:65
int av_strcasecmp(const char *a, const char *b)
Definition: avstring.c:137
RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler
Definition: rtpdec_mpeg4.c:232
#define ATTR_NAME_TYPE_INT
Definition: rtpdec_mpeg4.c:70
const char * str
Definition: rtpdec_mpeg4.c:64
Stream structure.
Definition: avformat.h:620
NULL
Definition: eval.c:50
char * av_strdup(const char *s)
Duplicate the string s.
Definition: mem.c:162
main external API structure.
Definition: avcodec.h:1329
int extradata_size
Definition: avcodec.h:1388
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:64
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:354
#define ATTR_NAME_TYPE_STR
Definition: rtpdec_mpeg4.c:71
#define FF_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
Definition: avcodec.h:497
int ff_hex_to_data(uint8_t *data, const char *p)
Parse a string of hexadecimal strings.
Definition: utils.c:3792
static unsigned int get_bits_long(GetBitContext *s, int n)
Read 0-32 bits.
Definition: get_bits.h:301
static int parse_sdp_line(AVFormatContext *s, int st_index, PayloadContext *data, const char *line)
Definition: rtpdec_mpeg4.c:221
static const AttrNameMap attr_names[]
Definition: rtpdec_mpeg4.c:72
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:29
int len
static int parse_fmtp(AVStream *stream, PayloadContext *data, char *attr, char *value)
Definition: rtpdec_mpeg4.c:192
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:757
int au_headers_length_bytes
Definition: rtpdec_mpeg4.c:59
int stream_index
Definition: avcodec.h:910
enum CodecID codec_id
Definition: avcodec.h:1575
static PayloadContext * new_context(void)
Definition: rtpdec_mpeg4.c:89