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