Statistics
| Branch: | Revision:

ffmpeg / libavformat / amr.c @ e19fbbec

History | View | Annotate | Download (4.63 KB)

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
#include "avformat.h"
29

    
30
static const char AMR_header [] = "#!AMR\n";
31
static const char AMRWB_header [] = "#!AMR-WB\n";
32

    
33
#ifdef CONFIG_MUXERS
34
static int amr_write_header(AVFormatContext *s)
35
{
36
    ByteIOContext *pb = &s->pb;
37
    AVCodecContext *enc = s->streams[0]->codec;
38

    
39
    s->priv_data = NULL;
40

    
41
    if (enc->codec_id == CODEC_ID_AMR_NB)
42
    {
43
        put_tag(pb, AMR_header);       /* magic number */
44
    }
45
    else if(enc->codec_id == CODEC_ID_AMR_WB)
46
    {
47
        put_tag(pb, AMRWB_header);       /* magic number */
48
    }
49
    else
50
    {
51
        return -1;
52
    }
53
    put_flush_packet(pb);
54
    return 0;
55
}
56

    
57
static int amr_write_packet(AVFormatContext *s, AVPacket *pkt)
58
{
59
    put_buffer(&s->pb, pkt->data, pkt->size);
60
    put_flush_packet(&s->pb);
61
    return 0;
62
}
63

    
64
static int amr_write_trailer(AVFormatContext *s)
65
{
66
    return 0;
67
}
68
#endif /* CONFIG_MUXERS */
69

    
70
static int amr_probe(AVProbeData *p)
71
{
72
    //Only check for "#!AMR" which could be amr-wb, amr-nb.
73
    //This will also trigger multichannel files: "#!AMR_MC1.0\n" and
74
    //"#!AMR-WB_MC1.0\n" (not supported)
75

    
76
    if (p->buf_size < 5)
77
        return 0;
78
    if(memcmp(p->buf,AMR_header,5)==0)
79
        return AVPROBE_SCORE_MAX;
80
    else
81
        return 0;
82
}
83

    
84
/* amr input */
85
static int amr_read_header(AVFormatContext *s,
86
                           AVFormatParameters *ap)
87
{
88
    ByteIOContext *pb = &s->pb;
89
    AVStream *st;
90
    uint8_t header[9];
91

    
92
    get_buffer(pb, header, 6);
93

    
94
    st = av_new_stream(s, 0);
95
    if (!st)
96
    {
97
        return AVERROR_NOMEM;
98
    }
99
    if(memcmp(header,AMR_header,6)!=0)
100
    {
101
        get_buffer(pb, header+6, 3);
102
        if(memcmp(header,AMRWB_header,9)!=0)
103
        {
104
            return -1;
105
        }
106

    
107
        st->codec->codec_tag = MKTAG('s', 'a', 'w', 'b');
108
        st->codec->codec_id = CODEC_ID_AMR_WB;
109
        st->codec->sample_rate = 16000;
110
    }
111
    else
112
    {
113
        st->codec->codec_tag = MKTAG('s', 'a', 'm', 'r');
114
        st->codec->codec_id = CODEC_ID_AMR_NB;
115
        st->codec->sample_rate = 8000;
116
    }
117
    st->codec->channels = 1;
118
    st->codec->codec_type = CODEC_TYPE_AUDIO;
119
    av_set_pts_info(st, 64, 1, st->codec->sample_rate);
120

    
121
    return 0;
122
}
123

    
124
static int amr_read_packet(AVFormatContext *s,
125
                          AVPacket *pkt)
126
{
127
    AVCodecContext *enc = s->streams[0]->codec;
128
    int read, size, toc, mode;
129

    
130
    if (url_feof(&s->pb))
131
    {
132
        return AVERROR_IO;
133
    }
134

    
135
//FIXME this is wrong, this should rather be in a AVParset
136
    toc=get_byte(&s->pb);
137
    mode = (toc >> 3) & 0x0F;
138

    
139
    if (enc->codec_id == CODEC_ID_AMR_NB)
140
    {
141
        static const uint8_t packed_size[16] = {12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0};
142

    
143
        size=packed_size[mode]+1;
144
    }
145
    else if(enc->codec_id == CODEC_ID_AMR_WB)
146
    {
147
        static uint8_t packed_size[16] = {18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1};
148

    
149
        size=packed_size[mode];
150
    }
151
    else
152
    {
153
        assert(0);
154
    }
155

    
156
    if ( (size==0) || av_new_packet(pkt, size))
157
    {
158
        return AVERROR_IO;
159
    }
160

    
161
    pkt->stream_index = 0;
162
    pkt->pos= url_ftell(&s->pb);
163
    pkt->data[0]=toc;
164
    pkt->duration= enc->codec_id == CODEC_ID_AMR_NB ? 160 : 320;
165
    read = get_buffer(&s->pb, pkt->data+1, size-1);
166

    
167
    if (read != size-1)
168
    {
169
        av_free_packet(pkt);
170
        return AVERROR_IO;
171
    }
172

    
173
    return 0;
174
}
175

    
176
#ifdef CONFIG_AMR_DEMUXER
177
AVInputFormat amr_demuxer = {
178
    "amr",
179
    "3gpp amr file format",
180
    0, /*priv_data_size*/
181
    amr_probe,
182
    amr_read_header,
183
    amr_read_packet,
184
    NULL,
185
};
186
#endif
187

    
188
#ifdef CONFIG_AMR_MUXER
189
AVOutputFormat amr_muxer = {
190
    "amr",
191
    "3gpp amr file format",
192
    "audio/amr",
193
    "amr",
194
    0,
195
    CODEC_ID_AMR_NB,
196
    CODEC_ID_NONE,
197
    amr_write_header,
198
    amr_write_packet,
199
    amr_write_trailer,
200
};
201
#endif