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
PayloadContext
*
amr_new_context
(
void
)
42
{
43
PayloadContext
*
data
=
av_mallocz
(
sizeof
(
PayloadContext
));
44
if
(!data)
return
data
;
45
data->
channels
= 1;
46
return
data
;
47
}
48
49
static
void
amr_free_context
(
PayloadContext
*
data
)
50
{
51
av_free
(data);
52
}
53
54
static
int
amr_handle_packet
(
AVFormatContext
*ctx,
PayloadContext
*
data
,
55
AVStream
*st,
AVPacket
*
pkt
, uint32_t *timestamp,
56
const
uint8_t
*
buf
,
int
len
, uint16_t seq,
57
int
flags
)
58
{
59
const
uint8_t
*
frame_sizes
= NULL;
60
int
frames;
61
int
i;
62
const
uint8_t
*speech_data;
63
uint8_t
*ptr;
64
65
if
(st->
codec
->
codec_id
==
AV_CODEC_ID_AMR_NB
) {
66
frame_sizes =
frame_sizes_nb
;
67
}
else
if
(st->
codec
->
codec_id
==
AV_CODEC_ID_AMR_WB
) {
68
frame_sizes =
frame_sizes_wb
;
69
}
else
{
70
av_log
(ctx,
AV_LOG_ERROR
,
"Bad codec ID\n"
);
71
return
AVERROR_INVALIDDATA
;
72
}
73
74
if
(st->
codec
->
channels
!= 1) {
75
av_log
(ctx,
AV_LOG_ERROR
,
"Only mono AMR is supported\n"
);
76
return
AVERROR_INVALIDDATA
;
77
}
78
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_MONO
;
79
80
/* The AMR RTP packet consists of one header byte, followed
81
* by one TOC byte for each AMR frame in the packet, followed
82
* by the speech data for all the AMR frames.
83
*
84
* The header byte contains only a codec mode request, for
85
* requesting what kind of AMR data the sender wants to
86
* receive. Not used at the moment.
87
*/
88
89
/* Count the number of frames in the packet. The highest bit
90
* is set in a TOC byte if there are more frames following.
91
*/
92
for
(frames = 1; frames < len && (buf[frames] & 0x80); frames++) ;
93
94
if
(1 + frames >= len) {
95
/* We hit the end of the packet while counting frames. */
96
av_log
(ctx,
AV_LOG_ERROR
,
"No speech data found\n"
);
97
return
AVERROR_INVALIDDATA
;
98
}
99
100
speech_data = buf + 1 + frames;
101
102
/* Everything except the codec mode request byte should be output. */
103
if
(
av_new_packet
(pkt, len - 1)) {
104
av_log
(ctx,
AV_LOG_ERROR
,
"Out of memory\n"
);
105
return
AVERROR
(ENOMEM);
106
}
107
pkt->
stream_index
= st->
index
;
108
ptr = pkt->
data
;
109
110
for
(i = 0; i < frames; i++) {
111
uint8_t
toc = buf[1 + i];
112
int
frame_size
= frame_sizes[(toc >> 3) & 0x0f];
113
114
if
(speech_data + frame_size > buf + len) {
115
/* Too little speech data */
116
av_log
(ctx,
AV_LOG_WARNING
,
"Too little speech data in the RTP packet\n"
);
117
/* Set the unwritten part of the packet to zero. */
118
memset(ptr, 0, pkt->
data
+ pkt->
size
- ptr);
119
pkt->
size
= ptr - pkt->
data
;
120
return
0;
121
}
122
123
/* Extract the AMR frame mode from the TOC byte */
124
*ptr++ = toc & 0x7C;
125
126
/* Copy the speech data */
127
memcpy(ptr, speech_data, frame_size);
128
speech_data +=
frame_size
;
129
ptr +=
frame_size
;
130
}
131
132
if
(speech_data < buf + len) {
133
av_log
(ctx,
AV_LOG_WARNING
,
"Too much speech data in the RTP packet?\n"
);
134
/* Set the unwritten part of the packet to zero. */
135
memset(ptr, 0, pkt->
data
+ pkt->
size
- ptr);
136
pkt->
size
= ptr - pkt->
data
;
137
}
138
139
return
0;
140
}
141
142
static
int
amr_parse_fmtp
(
AVFormatContext
*
s
,
143
AVStream
*stream,
PayloadContext
*
data
,
144
char
*attr,
char
*
value
)
145
{
146
/* Some AMR SDP configurations contain "octet-align", without
147
* the trailing =1. Therefore, if the value is empty,
148
* interpret it as "1".
149
*/
150
if
(!strcmp(value,
""
)) {
151
av_log
(s,
AV_LOG_WARNING
,
"AMR fmtp attribute %s had "
152
"nonstandard empty value\n"
, attr);
153
strcpy(value,
"1"
);
154
}
155
if
(!strcmp(attr,
"octet-align"
))
156
data->
octet_align
= atoi(value);
157
else
if
(!strcmp(attr,
"crc"
))
158
data->
crc
= atoi(value);
159
else
if
(!strcmp(attr,
"interleaving"
))
160
data->
interleaving
= atoi(value);
161
else
if
(!strcmp(attr,
"channels"
))
162
data->
channels
= atoi(value);
163
return
0;
164
}
165
166
static
int
amr_parse_sdp_line
(
AVFormatContext
*
s
,
int
st_index,
167
PayloadContext
*
data
,
const
char
*
line
)
168
{
169
const
char
*p;
170
int
ret
;
171
172
if
(st_index < 0)
173
return
0;
174
175
/* Parse an fmtp line this one:
176
* a=fmtp:97 octet-align=1; interleaving=0
177
* That is, a normal fmtp: line followed by semicolon & space
178
* separated key/value pairs.
179
*/
180
if
(
av_strstart
(line,
"fmtp:"
, &p)) {
181
ret =
ff_parse_fmtp
(s, s->
streams
[st_index], data, p,
amr_parse_fmtp
);
182
if
(!data->
octet_align
|| data->
crc
||
183
data->
interleaving
|| data->
channels
!= 1) {
184
av_log
(s,
AV_LOG_ERROR
,
"Unsupported RTP/AMR configuration!\n"
);
185
return
-1;
186
}
187
return
ret
;
188
}
189
return
0;
190
}
191
192
RTPDynamicProtocolHandler
ff_amr_nb_dynamic_handler
= {
193
.
enc_name
=
"AMR"
,
194
.codec_type =
AVMEDIA_TYPE_AUDIO
,
195
.codec_id =
AV_CODEC_ID_AMR_NB
,
196
.parse_sdp_a_line =
amr_parse_sdp_line
,
197
.alloc =
amr_new_context
,
198
.free =
amr_free_context
,
199
.parse_packet =
amr_handle_packet
,
200
};
201
202
RTPDynamicProtocolHandler
ff_amr_wb_dynamic_handler
= {
203
.
enc_name
=
"AMR-WB"
,
204
.codec_type =
AVMEDIA_TYPE_AUDIO
,
205
.codec_id =
AV_CODEC_ID_AMR_WB
,
206
.parse_sdp_a_line =
amr_parse_sdp_line
,
207
.alloc =
amr_new_context
,
208
.free =
amr_free_context
,
209
.parse_packet =
amr_handle_packet
,
210
};
Generated on Sun Jul 20 2014 23:06:06 for FFmpeg by
1.8.2