Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
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 Libav.
6
*
7
* Libav 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
* Libav 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 Libav; 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
#include "
avformat.h
"
29
#include "
internal.h
"
30
31
static
const
char
AMR_header
[] =
"#!AMR\n"
;
32
static
const
char
AMRWB_header
[] =
"#!AMR-WB\n"
;
33
34
#if CONFIG_AMR_MUXER
35
static
int
amr_write_header(
AVFormatContext
*s)
36
{
37
AVIOContext
*pb = s->
pb
;
38
AVCodecContext
*enc = s->
streams
[0]->
codec
;
39
40
s->
priv_data
=
NULL
;
41
42
if
(enc->
codec_id
==
CODEC_ID_AMR_NB
)
43
{
44
avio_write
(pb,
AMR_header
,
sizeof
(
AMR_header
) - 1);
/* magic number */
45
}
46
else
if
(enc->
codec_id
==
CODEC_ID_AMR_WB
)
47
{
48
avio_write
(pb,
AMRWB_header
,
sizeof
(
AMRWB_header
) - 1);
/* magic number */
49
}
50
else
51
{
52
return
-1;
53
}
54
avio_flush
(pb);
55
return
0;
56
}
57
58
static
int
amr_write_packet(
AVFormatContext
*s,
AVPacket
*pkt)
59
{
60
avio_write
(s->
pb
, pkt->
data
, pkt->
size
);
61
avio_flush
(s->
pb
);
62
return
0;
63
}
64
#endif
/* CONFIG_AMR_MUXER */
65
66
static
int
amr_probe
(
AVProbeData
*p)
67
{
68
//Only check for "#!AMR" which could be amr-wb, amr-nb.
69
//This will also trigger multichannel files: "#!AMR_MC1.0\n" and
70
//"#!AMR-WB_MC1.0\n" (not supported)
71
72
if
(memcmp(p->
buf
,
AMR_header
,5)==0)
73
return
AVPROBE_SCORE_MAX
;
74
else
75
return
0;
76
}
77
78
/* amr input */
79
static
int
amr_read_header
(
AVFormatContext
*s,
80
AVFormatParameters
*ap)
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
{
91
return
AVERROR
(ENOMEM);
92
}
93
if
(memcmp(header,
AMR_header
,6)!=0)
94
{
95
avio_read
(pb, header+6, 3);
96
if
(memcmp(header,
AMRWB_header
,9)!=0)
97
{
98
return
-1;
99
}
100
101
st->
codec
->
codec_tag
=
MKTAG
(
's'
,
'a'
,
'w'
,
'b'
);
102
st->
codec
->
codec_id
=
CODEC_ID_AMR_WB
;
103
st->
codec
->
sample_rate
= 16000;
104
st->
codec
->
frame_size
= 320;
105
}
106
else
107
{
108
st->
codec
->
codec_tag
=
MKTAG
(
's'
,
'a'
,
'm'
,
'r'
);
109
st->
codec
->
codec_id
=
CODEC_ID_AMR_NB
;
110
st->
codec
->
sample_rate
= 8000;
111
st->
codec
->
frame_size
= 160;
112
}
113
st->
codec
->
channels
= 1;
114
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
115
avpriv_set_pts_info
(st, 64, 1, st->
codec
->
sample_rate
);
116
117
return
0;
118
}
119
120
static
int
amr_read_packet
(
AVFormatContext
*s,
121
AVPacket
*pkt)
122
{
123
AVCodecContext
*enc = s->
streams
[0]->
codec
;
124
int
read,
size
= 0, toc, mode;
125
int64_t pos =
avio_tell
(s->
pb
);
126
127
if
(s->
pb
->
eof_reached
)
128
{
129
return
AVERROR
(EIO);
130
}
131
132
//FIXME this is wrong, this should rather be in a AVParset
133
toc=
avio_r8
(s->
pb
);
134
mode = (toc >> 3) & 0x0F;
135
136
if
(enc->
codec_id
==
CODEC_ID_AMR_NB
)
137
{
138
static
const
uint8_t packed_size[16] = {12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0};
139
140
size=packed_size[mode]+1;
141
}
142
else
if
(enc->
codec_id
==
CODEC_ID_AMR_WB
)
143
{
144
static
uint8_t packed_size[16] = {18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1};
145
146
size=packed_size[mode];
147
}
148
else
149
{
150
assert(0);
151
}
152
153
if
( (size==0) ||
av_new_packet
(pkt, size))
154
{
155
return
AVERROR
(EIO);
156
}
157
158
/* Both AMR formats have 50 frames per second */
159
s->
streams
[0]->
codec
->
bit_rate
= size*8*50;
160
161
pkt->
stream_index
= 0;
162
pkt->
pos
= pos;
163
pkt->
data
[0]=toc;
164
pkt->
duration
= enc->
codec_id
==
CODEC_ID_AMR_NB
? 160 : 320;
165
read =
avio_read
(s->
pb
, pkt->
data
+1, size-1);
166
167
if
(read != size-1)
168
{
169
av_free_packet
(pkt);
170
return
AVERROR
(EIO);
171
}
172
173
return
0;
174
}
175
176
#if CONFIG_AMR_DEMUXER
177
AVInputFormat
ff_amr_demuxer = {
178
.
name
=
"amr"
,
179
.long_name =
NULL_IF_CONFIG_SMALL
(
"3GPP AMR file format"
),
180
.read_probe =
amr_probe
,
181
.read_header =
amr_read_header
,
182
.read_packet =
amr_read_packet
,
183
.flags =
AVFMT_GENERIC_INDEX
,
184
};
185
#endif
186
187
#if CONFIG_AMR_MUXER
188
AVOutputFormat
ff_amr_muxer = {
189
.
name
=
"amr"
,
190
.long_name =
NULL_IF_CONFIG_SMALL
(
"3GPP AMR file format"
),
191
.mime_type =
"audio/amr"
,
192
.extensions =
"amr"
,
193
.audio_codec =
CODEC_ID_AMR_NB
,
194
.video_codec =
CODEC_ID_NONE
,
195
.write_header = amr_write_header,
196
.write_packet = amr_write_packet,
197
};
198
#endif