FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavformat
rtpdec_amr.c
Go to the documentation of this file.
1
/*
2
* RTP AMR Depacketizer, RFC 3267
3
* Copyright (c) 2010 Martin Storsjo
4
*
5
* This file is part of FFmpeg.
6
*
7
* FFmpeg is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* FFmpeg is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with FFmpeg; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
22
#include "
libavutil/channel_layout.h
"
23
#include "
avformat.h
"
24
#include "
rtpdec_formats.h
"
25
#include "
libavutil/avstring.h
"
26
27
static
const
uint8_t
frame_sizes_nb
[16] = {
28
12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0
29
};
30
static
const
uint8_t
frame_sizes_wb
[16] = {
31
17, 23, 32, 36, 40, 46, 50, 58, 60, 5, 5, 0, 0, 0, 0, 0
32
};
33
34
struct
PayloadContext
{
35
int
octet_align
;
36
int
crc
;
37
int
interleaving
;
38
int
channels
;
39
};
40
41
static
av_cold
int
amr_init
(
AVFormatContext
*
s
,
int
st_index,
PayloadContext
*
data
)
42
{
43
data->
channels
= 1;
44
return
0;
45
}
46
47
static
int
amr_handle_packet
(
AVFormatContext
*ctx,
PayloadContext
*
data
,
48
AVStream
*st,
AVPacket
*
pkt
, uint32_t *timestamp,
49
const
uint8_t
*
buf
,
int
len
, uint16_t seq,
50
int
flags
)
51
{
52
const
uint8_t
*
frame_sizes
=
NULL
;
53
int
frames;
54
int
i;
55
const
uint8_t
*speech_data;
56
uint8_t
*ptr;
57
58
if
(st->
codec
->
codec_id
==
AV_CODEC_ID_AMR_NB
) {
59
frame_sizes =
frame_sizes_nb
;
60
}
else
if
(st->
codec
->
codec_id
==
AV_CODEC_ID_AMR_WB
) {
61
frame_sizes =
frame_sizes_wb
;
62
}
else
{
63
av_log
(ctx,
AV_LOG_ERROR
,
"Bad codec ID\n"
);
64
return
AVERROR_INVALIDDATA
;
65
}
66
67
if
(st->
codec
->
channels
!= 1) {
68
av_log
(ctx,
AV_LOG_ERROR
,
"Only mono AMR is supported\n"
);
69
return
AVERROR_INVALIDDATA
;
70
}
71
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_MONO
;
72
73
/* The AMR RTP packet consists of one header byte, followed
74
* by one TOC byte for each AMR frame in the packet, followed
75
* by the speech data for all the AMR frames.
76
*
77
* The header byte contains only a codec mode request, for
78
* requesting what kind of AMR data the sender wants to
79
* receive. Not used at the moment.
80
*/
81
82
/* Count the number of frames in the packet. The highest bit
83
* is set in a TOC byte if there are more frames following.
84
*/
85
for
(frames = 1; frames < len && (buf[frames] & 0x80); frames++) ;
86
87
if
(1 + frames >= len) {
88
/* We hit the end of the packet while counting frames. */
89
av_log
(ctx,
AV_LOG_ERROR
,
"No speech data found\n"
);
90
return
AVERROR_INVALIDDATA
;
91
}
92
93
speech_data = buf + 1 + frames;
94
95
/* Everything except the codec mode request byte should be output. */
96
if
(
av_new_packet
(pkt, len - 1)) {
97
av_log
(ctx,
AV_LOG_ERROR
,
"Out of memory\n"
);
98
return
AVERROR
(ENOMEM);
99
}
100
pkt->
stream_index
= st->
index
;
101
ptr = pkt->
data
;
102
103
for
(i = 0; i < frames; i++) {
104
uint8_t
toc = buf[1 + i];
105
int
frame_size
= frame_sizes[(toc >> 3) & 0x0f];
106
107
if
(speech_data + frame_size > buf + len) {
108
/* Too little speech data */
109
av_log
(ctx,
AV_LOG_WARNING
,
"Too little speech data in the RTP packet\n"
);
110
/* Set the unwritten part of the packet to zero. */
111
memset(ptr, 0, pkt->
data
+ pkt->
size
- ptr);
112
pkt->
size
= ptr - pkt->
data
;
113
return
0;
114
}
115
116
/* Extract the AMR frame mode from the TOC byte */
117
*ptr++ = toc & 0x7C;
118
119
/* Copy the speech data */
120
memcpy(ptr, speech_data, frame_size);
121
speech_data +=
frame_size
;
122
ptr +=
frame_size
;
123
}
124
125
if
(speech_data < buf + len) {
126
av_log
(ctx,
AV_LOG_WARNING
,
"Too much speech data in the RTP packet?\n"
);
127
/* Set the unwritten part of the packet to zero. */
128
memset(ptr, 0, pkt->
data
+ pkt->
size
- ptr);
129
pkt->
size
= ptr - pkt->
data
;
130
}
131
132
return
0;
133
}
134
135
static
int
amr_parse_fmtp
(
AVFormatContext
*
s
,
136
AVStream
*stream,
PayloadContext
*
data
,
137
const
char
*attr,
const
char
*
value
)
138
{
139
/* Some AMR SDP configurations contain "octet-align", without
140
* the trailing =1. Therefore, if the value is empty,
141
* interpret it as "1".
142
*/
143
if
(!strcmp(value,
""
)) {
144
av_log
(s,
AV_LOG_WARNING
,
"AMR fmtp attribute %s had "
145
"nonstandard empty value\n"
, attr);
146
value =
"1"
;
147
}
148
if
(!strcmp(attr,
"octet-align"
))
149
data->
octet_align
= atoi(value);
150
else
if
(!strcmp(attr,
"crc"
))
151
data->
crc
= atoi(value);
152
else
if
(!strcmp(attr,
"interleaving"
))
153
data->
interleaving
= atoi(value);
154
else
if
(!strcmp(attr,
"channels"
))
155
data->
channels
= atoi(value);
156
return
0;
157
}
158
159
static
int
amr_parse_sdp_line
(
AVFormatContext
*
s
,
int
st_index,
160
PayloadContext
*
data
,
const
char
*
line
)
161
{
162
const
char
*p;
163
int
ret
;
164
165
if
(st_index < 0)
166
return
0;
167
168
/* Parse an fmtp line this one:
169
* a=fmtp:97 octet-align=1; interleaving=0
170
* That is, a normal fmtp: line followed by semicolon & space
171
* separated key/value pairs.
172
*/
173
if
(
av_strstart
(line,
"fmtp:"
, &p)) {
174
ret =
ff_parse_fmtp
(s, s->
streams
[st_index], data, p,
amr_parse_fmtp
);
175
if
(!data->
octet_align
|| data->
crc
||
176
data->
interleaving
|| data->
channels
!= 1) {
177
av_log
(s,
AV_LOG_ERROR
,
"Unsupported RTP/AMR configuration!\n"
);
178
return
-1;
179
}
180
return
ret
;
181
}
182
return
0;
183
}
184
185
RTPDynamicProtocolHandler
ff_amr_nb_dynamic_handler
= {
186
.
enc_name
=
"AMR"
,
187
.codec_type =
AVMEDIA_TYPE_AUDIO
,
188
.codec_id =
AV_CODEC_ID_AMR_NB
,
189
.priv_data_size =
sizeof
(
PayloadContext
),
190
.
init
=
amr_init
,
191
.parse_sdp_a_line =
amr_parse_sdp_line
,
192
.
parse_packet
=
amr_handle_packet
,
193
};
194
195
RTPDynamicProtocolHandler
ff_amr_wb_dynamic_handler
= {
196
.
enc_name
=
"AMR-WB"
,
197
.codec_type =
AVMEDIA_TYPE_AUDIO
,
198
.codec_id =
AV_CODEC_ID_AMR_WB
,
199
.priv_data_size =
sizeof
(
PayloadContext
),
200
.
init
=
amr_init
,
201
.parse_sdp_a_line =
amr_parse_sdp_line
,
202
.
parse_packet
=
amr_handle_packet
,
203
};
Generated on Sun Mar 8 2015 02:35:12 for FFmpeg by
1.8.2