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
amr.c
Go to the documentation of this file.
1
/*
2
* amr file format
3
* Copyright (c) 2001 ffmpeg project
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
/*
23
Write and read amr data according to RFC3267, http://www.ietf.org/rfc/rfc3267.txt?number=3267
24
25
Only mono files are supported.
26
27
*/
28
29
#include "
libavutil/channel_layout.h
"
30
#include "
avformat.h
"
31
#include "
internal.h
"
32
33
typedef
struct
{
34
uint64_t
cumulated_size
;
35
uint64_t
block_count
;
36
}
AMRContext
;
37
38
static
const
char
AMR_header
[] =
"#!AMR\n"
;
39
static
const
char
AMRWB_header
[] =
"#!AMR-WB\n"
;
40
41
#if CONFIG_AMR_MUXER
42
static
int
amr_write_header(
AVFormatContext
*
s
)
43
{
44
AVIOContext
*pb = s->
pb
;
45
AVCodecContext
*enc = s->
streams
[0]->
codec
;
46
47
s->
priv_data
=
NULL
;
48
49
if
(enc->
codec_id
==
AV_CODEC_ID_AMR_NB
) {
50
avio_write
(pb,
AMR_header
,
sizeof
(
AMR_header
) - 1);
/* magic number */
51
}
else
if
(enc->
codec_id
==
AV_CODEC_ID_AMR_WB
) {
52
avio_write
(pb,
AMRWB_header
,
sizeof
(
AMRWB_header
) - 1);
/* magic number */
53
}
else
{
54
return
-1;
55
}
56
avio_flush
(pb);
57
return
0;
58
}
59
60
static
int
amr_write_packet(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
61
{
62
avio_write
(s->
pb
, pkt->
data
, pkt->
size
);
63
return
0;
64
}
65
#endif
/* CONFIG_AMR_MUXER */
66
67
static
int
amr_probe
(
AVProbeData
*p)
68
{
69
// Only check for "#!AMR" which could be amr-wb, amr-nb.
70
// This will also trigger multichannel files: "#!AMR_MC1.0\n" and
71
// "#!AMR-WB_MC1.0\n" (not supported)
72
73
if
(!memcmp(p->
buf
,
AMR_header
, 5))
74
return
AVPROBE_SCORE_MAX
;
75
else
76
return
0;
77
}
78
79
/* amr input */
80
static
int
amr_read_header
(
AVFormatContext
*
s
)
81
{
82
AVIOContext
*pb = s->
pb
;
83
AVStream
*st;
84
uint8_t
header
[9];
85
86
avio_read
(pb, header, 6);
87
88
st =
avformat_new_stream
(s,
NULL
);
89
if
(!st)
90
return
AVERROR
(ENOMEM);
91
if
(memcmp(header,
AMR_header
, 6)) {
92
avio_read
(pb, header + 6, 3);
93
if
(memcmp(header,
AMRWB_header
, 9)) {
94
return
-1;
95
}
96
97
st->
codec
->
codec_tag
=
MKTAG
(
's'
,
'a'
,
'w'
,
'b'
);
98
st->
codec
->
codec_id
=
AV_CODEC_ID_AMR_WB
;
99
st->
codec
->
sample_rate
= 16000;
100
}
else
{
101
st->
codec
->
codec_tag
=
MKTAG
(
's'
,
'a'
,
'm'
,
'r'
);
102
st->
codec
->
codec_id
=
AV_CODEC_ID_AMR_NB
;
103
st->
codec
->
sample_rate
= 8000;
104
}
105
st->
codec
->
channels
= 1;
106
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_MONO
;
107
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
108
avpriv_set_pts_info
(st, 64, 1, st->
codec
->
sample_rate
);
109
110
return
0;
111
}
112
113
static
int
amr_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
114
{
115
AVCodecContext
*enc = s->
streams
[0]->
codec
;
116
int
read,
size
= 0, toc,
mode
;
117
int64_t pos =
avio_tell
(s->
pb
);
118
AMRContext
*amr = s->
priv_data
;
119
120
if
(
avio_feof
(s->
pb
)) {
121
return
AVERROR
(EIO);
122
}
123
124
// FIXME this is wrong, this should rather be in a AVParser
125
toc =
avio_r8
(s->
pb
);
126
mode = (toc >> 3) & 0x0F;
127
128
if
(enc->
codec_id
==
AV_CODEC_ID_AMR_NB
) {
129
static
const
uint8_t
packed_size[16] = {
130
12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0
131
};
132
133
size = packed_size[
mode
] + 1;
134
}
else
if
(enc->
codec_id
==
AV_CODEC_ID_AMR_WB
) {
135
static
const
uint8_t
packed_size[16] = {
136
18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1
137
};
138
139
size = packed_size[
mode
];
140
}
141
142
if
(!size ||
av_new_packet
(pkt, size))
143
return
AVERROR
(EIO);
144
145
if
(amr->
cumulated_size
< UINT64_MAX - size) {
146
amr->
cumulated_size
+=
size
;
147
/* Both AMR formats have 50 frames per second */
148
s->
streams
[0]->
codec
->
bit_rate
= amr->
cumulated_size
/ ++amr->
block_count
* 8 * 50;
149
}
150
151
pkt->
stream_index
= 0;
152
pkt->
pos
= pos;
153
pkt->
data
[0] = toc;
154
pkt->
duration
= enc->
codec_id
==
AV_CODEC_ID_AMR_NB
? 160 : 320;
155
read =
avio_read
(s->
pb
, pkt->
data
+ 1, size - 1);
156
157
if
(read != size - 1) {
158
av_free_packet
(pkt);
159
return
AVERROR
(EIO);
160
}
161
162
return
0;
163
}
164
165
#if CONFIG_AMR_DEMUXER
166
AVInputFormat
ff_amr_demuxer = {
167
.
name
=
"amr"
,
168
.long_name =
NULL_IF_CONFIG_SMALL
(
"3GPP AMR"
),
169
.priv_data_size =
sizeof
(
AMRContext
),
170
.
read_probe
=
amr_probe
,
171
.
read_header
=
amr_read_header
,
172
.
read_packet
=
amr_read_packet
,
173
.
flags
=
AVFMT_GENERIC_INDEX
,
174
};
175
#endif
176
177
#if CONFIG_AMR_MUXER
178
AVOutputFormat
ff_amr_muxer = {
179
.
name
=
"amr"
,
180
.long_name =
NULL_IF_CONFIG_SMALL
(
"3GPP AMR"
),
181
.mime_type =
"audio/amr"
,
182
.extensions =
"amr"
,
183
.audio_codec =
AV_CODEC_ID_AMR_NB
,
184
.video_codec =
AV_CODEC_ID_NONE
,
185
.write_header = amr_write_header,
186
.write_packet = amr_write_packet,
187
.flags =
AVFMT_NOTIMESTAMPS
,
188
};
189
#endif
Generated on Sun Mar 8 2015 02:35:08 for FFmpeg by
1.8.2