Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
rtpdec_latm.c
Go to the documentation of this file.
1
22
#include "
rtpdec_formats.h
"
23
#include "
internal.h
"
24
#include "
libavutil/avstring.h
"
25
#include "
libavcodec/get_bits.h
"
26
27
struct
PayloadContext
{
28
AVIOContext
*
dyn_buf
;
29
uint8_t *
buf
;
30
int
pos
,
len
;
31
uint32_t
timestamp
;
32
};
33
34
static
PayloadContext
*
latm_new_context
(
void
)
35
{
36
return
av_mallocz
(
sizeof
(
PayloadContext
));
37
}
38
39
static
void
latm_free_context
(
PayloadContext
*
data
)
40
{
41
if
(!data)
42
return
;
43
if
(data->
dyn_buf
) {
44
uint8_t *p;
45
avio_close_dyn_buf
(data->
dyn_buf
, &p);
46
av_free
(p);
47
}
48
av_free
(data->
buf
);
49
av_free
(data);
50
}
51
52
static
int
latm_parse_packet
(
AVFormatContext
*ctx,
PayloadContext
*
data
,
53
AVStream
*st,
AVPacket
*pkt, uint32_t *timestamp,
54
const
uint8_t *buf,
int
len
,
int
flags
)
55
{
56
int
ret, cur_len;
57
58
if
(buf) {
59
if
(!data->
dyn_buf
|| data->
timestamp
!= *timestamp) {
60
av_freep
(&data->
buf
);
61
if
(data->
dyn_buf
)
62
avio_close_dyn_buf
(data->
dyn_buf
, &data->
buf
);
63
data->
dyn_buf
=
NULL
;
64
av_freep
(&data->
buf
);
65
66
data->
timestamp
= *timestamp;
67
if
((ret =
avio_open_dyn_buf
(&data->
dyn_buf
)) < 0)
68
return
ret;
69
}
70
avio_write
(data->
dyn_buf
, buf, len);
71
72
if
(!(flags &
RTP_FLAG_MARKER
))
73
return
AVERROR
(EAGAIN);
74
av_free
(data->
buf
);
75
data->
len
=
avio_close_dyn_buf
(data->
dyn_buf
, &data->
buf
);
76
data->
dyn_buf
=
NULL
;
77
data->
pos
= 0;
78
}
79
80
if
(!data->
buf
) {
81
av_log
(ctx,
AV_LOG_ERROR
,
"No data available yet\n"
);
82
return
AVERROR
(EIO);
83
}
84
85
cur_len = 0;
86
while
(data->
pos
< data->
len
) {
87
uint8_t val = data->
buf
[data->
pos
++];
88
cur_len += val;
89
if
(val != 0xff)
90
break
;
91
}
92
if
(data->
pos
+ cur_len > data->
len
) {
93
av_log
(ctx,
AV_LOG_ERROR
,
"Malformed LATM packet\n"
);
94
return
AVERROR
(EIO);
95
}
96
97
if
((ret =
av_new_packet
(pkt, cur_len)) < 0)
98
return
ret;
99
memcpy(pkt->
data
, data->
buf
+ data->
pos
, cur_len);
100
data->
pos
+= cur_len;
101
pkt->
stream_index
= st->
index
;
102
return
data->
pos
< data->
len
;
103
}
104
105
static
int
parse_fmtp_config
(
AVStream
*st,
char
*value)
106
{
107
int
len
=
ff_hex_to_data
(
NULL
, value), i, ret = 0;
108
GetBitContext
gb;
109
uint8_t *config;
110
int
audio_mux_version, same_time_framing, num_programs, num_layers;
111
112
/* Pad this buffer, too, to avoid out of bounds reads with get_bits below */
113
config =
av_mallocz
(len +
FF_INPUT_BUFFER_PADDING_SIZE
);
114
if
(!config)
115
return
AVERROR
(ENOMEM);
116
ff_hex_to_data
(config, value);
117
init_get_bits
(&gb, config, len*8);
118
audio_mux_version =
get_bits
(&gb, 1);
119
same_time_framing =
get_bits
(&gb, 1);
120
skip_bits
(&gb, 6);
/* num_sub_frames */
121
num_programs =
get_bits
(&gb, 4);
122
num_layers =
get_bits
(&gb, 3);
123
if
(audio_mux_version != 0 || same_time_framing != 1 || num_programs != 0 ||
124
num_layers != 0) {
125
av_log
(
NULL
,
AV_LOG_WARNING
,
"Unsupported LATM config (%d,%d,%d,%d)\n"
,
126
audio_mux_version, same_time_framing,
127
num_programs, num_layers);
128
ret =
AVERROR_PATCHWELCOME
;
129
goto
end;
130
}
131
av_freep
(&st->
codec
->
extradata
);
132
st->
codec
->
extradata_size
= (
get_bits_left
(&gb) + 7)/8;
133
st->
codec
->
extradata
=
av_mallocz
(st->
codec
->
extradata_size
+
134
FF_INPUT_BUFFER_PADDING_SIZE
);
135
if
(!st->
codec
->
extradata
) {
136
ret =
AVERROR
(ENOMEM);
137
goto
end;
138
}
139
for
(i = 0; i < st->
codec
->
extradata_size
; i++)
140
st->
codec
->
extradata
[i] =
get_bits
(&gb, 8);
141
142
end:
143
av_free
(config);
144
return
ret;
145
}
146
147
static
int
parse_fmtp
(
AVStream
*stream,
PayloadContext
*
data
,
148
char
*attr,
char
*value)
149
{
150
int
res;
151
152
if
(!strcmp(attr,
"config"
)) {
153
res =
parse_fmtp_config
(stream, value);
154
if
(res < 0)
155
return
res;
156
}
else
if
(!strcmp(attr,
"cpresent"
)) {
157
int
cpresent = atoi(value);
158
if
(cpresent != 0)
159
av_log_missing_feature
(
NULL
,
"RTP MP4A-LATM with in-band "
160
"configuration"
, 1);
161
}
162
163
return
0;
164
}
165
166
static
int
latm_parse_sdp_line
(
AVFormatContext
*s,
int
st_index,
167
PayloadContext
*
data
,
const
char
*
line
)
168
{
169
const
char
*p;
170
171
if
(
av_strstart
(line,
"fmtp:"
, &p))
172
return
ff_parse_fmtp
(s->
streams
[st_index], data, p,
parse_fmtp
);
173
174
return
0;
175
}
176
177
RTPDynamicProtocolHandler
ff_mp4a_latm_dynamic_handler
= {
178
.
enc_name
=
"MP4A-LATM"
,
179
.codec_type =
AVMEDIA_TYPE_AUDIO
,
180
.codec_id =
CODEC_ID_AAC
,
181
.parse_sdp_a_line =
latm_parse_sdp_line
,
182
.alloc =
latm_new_context
,
183
.free =
latm_free_context
,
184
.parse_packet =
latm_parse_packet
185
};