Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
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
{
38
int
sizelength
;
39
int
indexlength
;
40
int
indexdeltalength
;
41
int
profile_level_id
;
42
int
streamtype
;
43
int
objecttype
;
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
;
55
int
streamstate
;
56
} *
au_headers
;
57
int
au_headers_allocated
;
58
int
nb_au_headers
;
59
int
au_headers_length_bytes
;
60
int
cur_au_index
;
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
89
static
PayloadContext
*
new_context
(
void
)
90
{
91
return
av_mallocz
(
sizeof
(
PayloadContext
));
92
}
93
94
static
void
free_context
(
PayloadContext
*
data
)
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
);
114
codec->
extradata
=
av_mallocz
(len +
FF_INPUT_BUFFER_PADDING_SIZE
);
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 */
170
static
int
aac_parse_packet
(
AVFormatContext
*ctx,
171
PayloadContext
*
data
,
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
232
RTPDynamicProtocolHandler
ff_mp4v_es_dynamic_handler
= {
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
239
RTPDynamicProtocolHandler
ff_mpeg4_generic_dynamic_handler
= {
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
};