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 MPEG4 / RTP Code
26  * @author Fabrice Bellard
27  * @author Romain Degez
28  */
29 
30 #include "rtpdec_formats.h"
31 #include "internal.h"
32 #include "libavutil/avstring.h"
33 #include "libavcodec/get_bits.h"
34 
35 /** Structure listing useful vars to parse RTP packet payload */
36 struct PayloadContext {
43  char *mode;
44 
45  /** mpeg 4 AU headers */
46  struct AUHeaders {
47  int size;
48  int index;
49  int cts_flag;
50  int cts;
51  int dts_flag;
52  int dts;
53  int rap_flag;
55  } *au_headers;
60 
63 };
64 
65 typedef struct {
66  const char *str;
67  uint16_t type;
68  uint32_t offset;
69 } AttrNameMap;
70 
71 /* All known fmtp parameters and the corresponding RTPAttrTypeEnum */
72 #define ATTR_NAME_TYPE_INT 0
73 #define ATTR_NAME_TYPE_STR 1
74 static const AttrNameMap attr_names[] = {
75  { "SizeLength", ATTR_NAME_TYPE_INT,
76  offsetof(PayloadContext, sizelength) },
77  { "IndexLength", ATTR_NAME_TYPE_INT,
78  offsetof(PayloadContext, indexlength) },
79  { "IndexDeltaLength", ATTR_NAME_TYPE_INT,
80  offsetof(PayloadContext, indexdeltalength) },
81  { "profile-level-id", ATTR_NAME_TYPE_INT,
82  offsetof(PayloadContext, profile_level_id) },
83  { "StreamType", ATTR_NAME_TYPE_INT,
84  offsetof(PayloadContext, streamtype) },
85  { "mode", ATTR_NAME_TYPE_STR,
86  offsetof(PayloadContext, mode) },
87  { NULL, -1, -1 },
88 };
89 
91 {
92  return av_mallocz(sizeof(PayloadContext));
93 }
94 
96 {
97  av_free(data->au_headers);
98  av_free(data->mode);
99  av_free(data);
100 }
101 
102 static int parse_fmtp_config(AVCodecContext *codec, char *value)
103 {
104  /* decode the hexa encoded parameter */
105  int len = ff_hex_to_data(NULL, value);
106  av_free(codec->extradata);
108  if (!codec->extradata)
109  return AVERROR(ENOMEM);
110  codec->extradata_size = len;
111  ff_hex_to_data(codec->extradata, value);
112  return 0;
113 }
114 
116 {
117  int au_headers_length, au_header_size, i;
118  GetBitContext getbitcontext;
119 
120  if (len < 2)
121  return AVERROR_INVALIDDATA;
122 
123  /* decode the first 2 bytes where the AUHeader sections are stored
124  length in bits */
125  au_headers_length = AV_RB16(buf);
126 
127  if (au_headers_length > RTP_MAX_PACKET_LENGTH)
128  return -1;
129 
130  data->au_headers_length_bytes = (au_headers_length + 7) / 8;
131 
132  /* skip AU headers length section (2 bytes) */
133  buf += 2;
134  len -= 2;
135 
136  if (len < data->au_headers_length_bytes)
137  return AVERROR_INVALIDDATA;
138 
139  init_get_bits(&getbitcontext, buf, data->au_headers_length_bytes * 8);
140 
141  /* XXX: Wrong if optional 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  if (!data->au_headers)
151  return AVERROR(ENOMEM);
152  data->au_headers_allocated = data->nb_au_headers;
153  }
154 
155  for (i = 0; i < data->nb_au_headers; ++i) {
156  data->au_headers[i].size = get_bits_long(&getbitcontext, data->sizelength);
157  data->au_headers[i].index = get_bits_long(&getbitcontext, data->indexlength);
158  }
159 
160  return 0;
161 }
162 
163 
164 /* Follows RFC 3640 */
166  AVStream *st, AVPacket *pkt, uint32_t *timestamp,
167  const uint8_t *buf, int len, uint16_t seq,
168  int flags)
169 {
170  int ret;
171 
172  if (!buf) {
173  if (data->cur_au_index > data->nb_au_headers)
174  return AVERROR_INVALIDDATA;
175  if (data->buf_size - data->buf_pos < data->au_headers[data->cur_au_index].size)
176  return AVERROR_INVALIDDATA;
177  if ((ret = av_new_packet(pkt, data->au_headers[data->cur_au_index].size)) < 0)
178  return ret;
179  memcpy(pkt->data, &data->buf[data->buf_pos], data->au_headers[data->cur_au_index].size);
180  data->buf_pos += data->au_headers[data->cur_au_index].size;
181  pkt->stream_index = st->index;
182  data->cur_au_index++;
183  return data->cur_au_index < data->nb_au_headers;
184  }
185 
186  if (rtp_parse_mp4_au(data, buf, len))
187  return -1;
188 
189  buf += data->au_headers_length_bytes + 2;
190  len -= data->au_headers_length_bytes + 2;
191 
192  if (len < data->au_headers[0].size)
193  return AVERROR_INVALIDDATA;
194  if ((ret = av_new_packet(pkt, data->au_headers[0].size)) < 0)
195  return ret;
196  memcpy(pkt->data, buf, data->au_headers[0].size);
197  len -= data->au_headers[0].size;
198  buf += data->au_headers[0].size;
199  pkt->stream_index = st->index;
200 
201  if (len > 0 && data->nb_au_headers > 1) {
202  data->buf_size = FFMIN(len, sizeof(data->buf));
203  memcpy(data->buf, buf, data->buf_size);
204  data->cur_au_index = 1;
205  data->buf_pos = 0;
206  return 1;
207  }
208 
209  return 0;
210 }
211 
212 static int parse_fmtp(AVStream *stream, PayloadContext *data,
213  char *attr, char *value)
214 {
215  AVCodecContext *codec = stream->codec;
216  int res, i;
217 
218  if (!strcmp(attr, "config")) {
219  res = parse_fmtp_config(codec, value);
220 
221  if (res < 0)
222  return res;
223  }
224 
225  if (codec->codec_id == AV_CODEC_ID_AAC) {
226  /* Looking for a known attribute */
227  for (i = 0; attr_names[i].str; ++i) {
228  if (!av_strcasecmp(attr, attr_names[i].str)) {
229  if (attr_names[i].type == ATTR_NAME_TYPE_INT) {
230  *(int *)((char *)data+
231  attr_names[i].offset) = atoi(value);
232  } else if (attr_names[i].type == ATTR_NAME_TYPE_STR)
233  *(char **)((char *)data+
234  attr_names[i].offset) = av_strdup(value);
235  }
236  }
237  }
238  return 0;
239 }
240 
241 static int parse_sdp_line(AVFormatContext *s, int st_index,
242  PayloadContext *data, const char *line)
243 {
244  const char *p;
245 
246  if (st_index < 0)
247  return 0;
248 
249  if (av_strstart(line, "fmtp:", &p))
250  return ff_parse_fmtp(s->streams[st_index], data, p, parse_fmtp);
251 
252  return 0;
253 }
254 
255 static int init_video(AVFormatContext *s, int st_index, PayloadContext *data)
256 {
257  if (st_index < 0)
258  return 0;
259  s->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL;
260  return 0;
261 }
262 
264  .enc_name = "MP4V-ES",
265  .codec_type = AVMEDIA_TYPE_VIDEO,
266  .codec_id = AV_CODEC_ID_MPEG4,
267  .init = init_video,
268  .parse_sdp_a_line = parse_sdp_line,
269 };
270 
272  .enc_name = "mpeg4-generic",
273  .codec_type = AVMEDIA_TYPE_AUDIO,
274  .codec_id = AV_CODEC_ID_AAC,
275  .parse_sdp_a_line = parse_sdp_line,
276  .alloc = new_context,
277  .free = free_context,
278  .parse_packet = aac_parse_packet
279 };
AVPacket pkt
Definition: rtpdec_qt.c:37
uint32_t offset
Definition: rtpdec_mpeg4.c:68
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
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static int parse_fmtp_config(AVCodecContext *codec, char *value)
Definition: rtpdec_mpeg4.c:102
#define RTP_MAX_PACKET_LENGTH
Definition: rtpdec.h:36
RTP/JPEG specific private data.
Definition: rdt.c:83
int index
stream index in AVFormatContext
Definition: avformat.h:644
uint8_t * buf
the temporary storage buffer
Definition: rtpdec_asf.c:160
RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler
Definition: rtpdec_mpeg4.c:271
Format I/O context.
Definition: avformat.h:944
static int init_video(AVFormatContext *s, int st_index, PayloadContext *data)
Definition: rtpdec_mpeg4.c:255
uint8_t
static void free_context(PayloadContext *data)
Definition: rtpdec_mpeg4.c:95
mode
Definition: f_perms.c:27
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
mpeg 4 AU headers
Definition: rtpdec_mpeg4.c:46
uint8_t * data
bitstream reader API header.
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
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
int au_headers_allocated
Definition: rtpdec_mpeg4.c:56
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
uint16_t type
Definition: rtpdec_mpeg4.c:67
#define FF_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
#define FFMIN(a, b)
Definition: common.h:58
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:212
ret
Definition: avfilter.c:821
RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler
Definition: rtpdec_mpeg4.c:263
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:165
#define ATTR_NAME_TYPE_INT
Definition: rtpdec_mpeg4.c:72
const char * str
Definition: rtpdec_mpeg4.c:66
Stream structure.
Definition: avformat.h:643
NULL
Definition: eval.c:55
AVIOContext * data
Definition: rtpdec_vp8.c:35
enum AVCodecID codec_id
char * av_strdup(const char *s)
Duplicate the string s.
Definition: mem.c:220
main external API structure.
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
synthesis window for stochastic i
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:379
#define ATTR_NAME_TYPE_STR
Definition: rtpdec_mpeg4.c:73
const char enc_name[50]
Definition: rtpdec.h:120
static int rtp_parse_mp4_au(PayloadContext *data, const uint8_t *buf, int len)
Definition: rtpdec_mpeg4.c:115
int ff_hex_to_data(uint8_t *data, const char *p)
Parse a string of hexadecimal strings.
static unsigned int get_bits_long(GetBitContext *s, int n)
Read 0-32 bits.
Definition: get_bits.h:306
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
#define type
static int parse_sdp_line(AVFormatContext *s, int st_index, PayloadContext *data, const char *line)
Definition: rtpdec_mpeg4.c:241
static const AttrNameMap attr_names[]
Definition: rtpdec_mpeg4.c:74
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
full parsing and repack
Definition: avformat.h:582
static int parse_fmtp(AVStream *stream, PayloadContext *data, char *attr, char *value)
Definition: rtpdec_mpeg4.c:212
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
int au_headers_length_bytes
Definition: rtpdec_mpeg4.c:58
This structure stores compressed data.
static PayloadContext * new_context(void)
Definition: rtpdec_mpeg4.c:90