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 Libav.
7  *
8  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
30 #include "rtpdec_formats.h"
31 #include "internal.h"
32 #include "libavutil/avstring.h"
33 #include "libavcodec/get_bits.h"
34 
36 struct PayloadContext {
43  char *mode;
44 
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 };
61 
62 typedef struct {
63  const char *str;
64  uint16_t type;
65  uint32_t offset;
66 } AttrNameMap;
67 
68 /* All known fmtp parameters and the corresponding RTPAttrTypeEnum */
69 #define ATTR_NAME_TYPE_INT 0
70 #define ATTR_NAME_TYPE_STR 1
71 static const AttrNameMap attr_names[] = {
72  { "SizeLength", ATTR_NAME_TYPE_INT,
73  offsetof(PayloadContext, sizelength) },
74  { "IndexLength", ATTR_NAME_TYPE_INT,
75  offsetof(PayloadContext, indexlength) },
76  { "IndexDeltaLength", ATTR_NAME_TYPE_INT,
77  offsetof(PayloadContext, indexdeltalength) },
78  { "profile-level-id", ATTR_NAME_TYPE_INT,
79  offsetof(PayloadContext, profile_level_id) },
80  { "StreamType", ATTR_NAME_TYPE_INT,
81  offsetof(PayloadContext, streamtype) },
82  { "mode", ATTR_NAME_TYPE_STR,
83  offsetof(PayloadContext, mode) },
84  { NULL, -1, -1 },
85 };
86 
88 {
89  return av_mallocz(sizeof(PayloadContext));
90 }
91 
93 {
94  av_free(data->au_headers);
95  av_free(data->mode);
96  av_free(data);
97 }
98 
99 static int parse_fmtp_config(AVCodecContext *codec, char *value)
100 {
101  /* decode the hexa encoded parameter */
102  int len = ff_hex_to_data(NULL, value);
103  av_free(codec->extradata);
105  if (!codec->extradata)
106  return AVERROR(ENOMEM);
107  codec->extradata_size = len;
108  ff_hex_to_data(codec->extradata, value);
109  return 0;
110 }
111 
112 static int rtp_parse_mp4_au(PayloadContext *data, const uint8_t *buf)
113 {
114  int au_headers_length, au_header_size, i;
115  GetBitContext getbitcontext;
116 
117  /* decode the first 2 bytes where the AUHeader sections are stored
118  length in bits */
119  au_headers_length = AV_RB16(buf);
120 
121  if (au_headers_length > RTP_MAX_PACKET_LENGTH)
122  return -1;
123 
124  data->au_headers_length_bytes = (au_headers_length + 7) / 8;
125 
126  /* skip AU headers length section (2 bytes) */
127  buf += 2;
128 
129  init_get_bits(&getbitcontext, buf, data->au_headers_length_bytes * 8);
130 
131  /* XXX: Wrong if optionnal additional sections are present (cts, dts etc...) */
132  au_header_size = data->sizelength + data->indexlength;
133  if (au_header_size <= 0 || (au_headers_length % au_header_size != 0))
134  return -1;
135 
136  data->nb_au_headers = au_headers_length / au_header_size;
137  if (!data->au_headers || data->au_headers_allocated < data->nb_au_headers) {
138  av_free(data->au_headers);
139  data->au_headers = av_malloc(sizeof(struct AUHeaders) * data->nb_au_headers);
140  data->au_headers_allocated = data->nb_au_headers;
141  }
142 
143  /* XXX: We handle multiple AU Section as only one (need to fix this for interleaving)
144  In my test, the FAAD decoder does not behave correctly when sending each AU one by one
145  but does when sending the whole as one big packet... */
146  data->au_headers[0].size = 0;
147  data->au_headers[0].index = 0;
148  for (i = 0; i < data->nb_au_headers; ++i) {
149  data->au_headers[0].size += get_bits_long(&getbitcontext, data->sizelength);
150  data->au_headers[0].index = get_bits_long(&getbitcontext, data->indexlength);
151  }
152 
153  data->nb_au_headers = 1;
154 
155  return 0;
156 }
157 
158 
159 /* Follows RFC 3640 */
161  AVStream *st, AVPacket *pkt, uint32_t *timestamp,
162  const uint8_t *buf, int len, uint16_t seq,
163  int flags)
164 {
165  if (rtp_parse_mp4_au(data, buf))
166  return -1;
167 
168  buf += data->au_headers_length_bytes + 2;
169  len -= data->au_headers_length_bytes + 2;
170 
171  /* XXX: Fixme we only handle the case where rtp_parse_mp4_au define
172  one au_header */
173  av_new_packet(pkt, data->au_headers[0].size);
174  memcpy(pkt->data, buf, data->au_headers[0].size);
175 
176  pkt->stream_index = st->index;
177  return 0;
178 }
179 
180 static int parse_fmtp(AVStream *stream, PayloadContext *data,
181  char *attr, char *value)
182 {
183  AVCodecContext *codec = stream->codec;
184  int res, i;
185 
186  if (!strcmp(attr, "config")) {
187  res = parse_fmtp_config(codec, value);
188 
189  if (res < 0)
190  return res;
191  }
192 
193  if (codec->codec_id == AV_CODEC_ID_AAC) {
194  /* Looking for a known attribute */
195  for (i = 0; attr_names[i].str; ++i) {
196  if (!av_strcasecmp(attr, attr_names[i].str)) {
197  if (attr_names[i].type == ATTR_NAME_TYPE_INT) {
198  *(int *)((char *)data+
199  attr_names[i].offset) = atoi(value);
200  } else if (attr_names[i].type == ATTR_NAME_TYPE_STR)
201  *(char **)((char *)data+
202  attr_names[i].offset) = av_strdup(value);
203  }
204  }
205  }
206  return 0;
207 }
208 
209 static int parse_sdp_line(AVFormatContext *s, int st_index,
210  PayloadContext *data, const char *line)
211 {
212  const char *p;
213 
214  if (st_index < 0)
215  return 0;
216 
217  if (av_strstart(line, "fmtp:", &p))
218  return ff_parse_fmtp(s->streams[st_index], data, p, parse_fmtp);
219 
220  return 0;
221 }
222 
224  .enc_name = "MP4V-ES",
225  .codec_type = AVMEDIA_TYPE_VIDEO,
226  .codec_id = AV_CODEC_ID_MPEG4,
227  .parse_sdp_a_line = parse_sdp_line,
228 };
229 
231  .enc_name = "mpeg4-generic",
232  .codec_type = AVMEDIA_TYPE_AUDIO,
233  .codec_id = AV_CODEC_ID_AAC,
234  .parse_sdp_a_line = parse_sdp_line,
235  .alloc = new_context,
236  .free = free_context,
237  .parse_packet = aac_parse_packet
238 };
uint32_t offset
Definition: rtpdec_mpeg4.c:65
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:61
static int parse_fmtp_config(AVCodecContext *codec, char *value)
Definition: rtpdec_mpeg4.c:99
#define RTP_MAX_PACKET_LENGTH
Definition: rtpdec.h:35
RTP/JPEG specific private data.
Definition: rdt.c:83
int index
stream index in AVFormatContext
Definition: avformat.h:623
RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler
Definition: rtpdec_mpeg4.c:230
Format I/O context.
Definition: avformat.h:828
uint8_t
static void free_context(PayloadContext *data)
Definition: rtpdec_mpeg4.c:92
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:1454
AVStream ** streams
Definition: avformat.h:876
mpeg 4 AU headers
Definition: rtpdec_mpeg4.c:46
const char data[16]
Definition: mxf.c:66
uint8_t * data
Definition: avcodec.h:915
static int flags
Definition: log.c:42
bitstream reader API header.
static int rtp_parse_mp4_au(PayloadContext *data, const uint8_t *buf)
Definition: rtpdec_mpeg4.c:112
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:56
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:139
#define AV_RB16
Definition: intreadwrite.h:53
Definition: graph2dot.c:48
int au_headers_allocated
Definition: rtpdec_mpeg4.c:56
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:641
uint16_t type
Definition: rtpdec_mpeg4.c:64
int av_strcasecmp(const char *a, const char *b)
Definition: avstring.c:140
RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler
Definition: rtpdec_mpeg4.c:223
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:160
#define ATTR_NAME_TYPE_INT
Definition: rtpdec_mpeg4.c:69
const char * str
Definition: rtpdec_mpeg4.c:63
Stream structure.
Definition: avformat.h:622
NULL
Definition: eval.c:52
enum AVCodecID codec_id
Definition: avcodec.h:1350
char * av_strdup(const char *s)
Duplicate the string s.
Definition: mem.c:166
main external API structure.
Definition: avcodec.h:1339
int extradata_size
Definition: avcodec.h:1455
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:372
#define ATTR_NAME_TYPE_STR
Definition: rtpdec_mpeg4.c:70
const char enc_name[50]
Definition: rtpdec.h:115
int ff_hex_to_data(uint8_t *data, const char *p)
Parse a string of hexadecimal strings.
Definition: utils.c:3255
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:209
static const AttrNameMap attr_names[]
Definition: rtpdec_mpeg4.c:71
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:32
int len
static int parse_fmtp(AVStream *stream, PayloadContext *data, char *attr, char *value)
Definition: rtpdec_mpeg4.c:180
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:773
int au_headers_length_bytes
Definition: rtpdec_mpeg4.c:58
int stream_index
Definition: avcodec.h:917
This structure stores compressed data.
Definition: avcodec.h:898
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:158
static PayloadContext * new_context(void)
Definition: rtpdec_mpeg4.c:87