FFmpeg
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavformat
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
{
37
int
sizelength
;
38
int
indexlength
;
39
int
indexdeltalength
;
40
int
profile_level_id
;
41
int
streamtype
;
42
int
objecttype
;
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
;
54
int
streamstate
;
55
} *
au_headers
;
56
int
au_headers_allocated
;
57
int
nb_au_headers
;
58
int
au_headers_length_bytes
;
59
int
cur_au_index
;
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
87
static
PayloadContext
*
new_context
(
void
)
88
{
89
return
av_mallocz
(
sizeof
(
PayloadContext
));
90
}
91
92
static
void
free_context
(
PayloadContext
*
data
)
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
);
104
codec->
extradata
=
av_mallocz
(len +
FF_INPUT_BUFFER_PADDING_SIZE
);
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 optional 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 */
160
static
int
aac_parse_packet
(
AVFormatContext
*ctx,
PayloadContext
*
data
,
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
223
RTPDynamicProtocolHandler
ff_mp4v_es_dynamic_handler
= {
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
230
RTPDynamicProtocolHandler
ff_mpeg4_generic_dynamic_handler
= {
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
};
Generated on Sat May 25 2013 03:58:48 for FFmpeg by
1.8.2