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 03:58:46 for FFmpeg by
1.8.2