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