amr typefix patch by (Johannes Carlsson <joca at rixmail dot se>)
[ffmpeg.git] / libavformat / amr.c
1 /* 
2  * amr file format
3  * Copyright (c) 2001 ffmpeg project
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 /*
21 Write and read amr data according to RFC3267, http://www.ietf.org/rfc/rfc3267.txt?number=3267
22
23 Only amr narrowband (not amr-wb) is supported for now.
24
25 */
26 #include "avformat.h"
27 #include "avi.h"
28
29 static const unsigned char AMR_header [] = "#!AMR\n";
30
31 /* AMR_FILE header */
32 static int put_amr_header(ByteIOContext *pb, AVCodecContext *enc)
33 {
34     put_tag(pb, AMR_header);       /* magic number */
35     return 0;
36 }
37
38 static int amr_write_header(AVFormatContext *s)
39 {
40     ByteIOContext *pb = &s->pb;
41
42     s->priv_data = NULL;
43
44     /* format header */
45     if (put_amr_header(pb, &s->streams[0]->codec) < 0) {
46         return -1;
47     }
48
49     put_flush_packet(pb);
50
51     return 0;
52 }
53
54 static int amr_write_packet(AVFormatContext *s, int stream_index_ptr,
55                            uint8_t *buf, int size, int force_pts)
56 {
57     put_buffer(&s->pb, buf, size);
58     put_flush_packet(&s->pb);
59     return 0;
60 }
61
62 static int amr_write_trailer(AVFormatContext *s)
63 {
64     return 0;
65 }
66
67 static int amr_probe(AVProbeData *p)
68 {
69     /* check file header */
70     if (p->buf_size < 6)
71         return 0;
72     if(memcmp(p->buf,AMR_header,6)==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     ByteIOContext *pb = &s->pb;
83     AVStream *st;
84     uint8_t header[6];
85
86     get_buffer(pb, header, 6);
87
88     if(memcmp(header,AMR_header,6)!=0)
89     {
90         return -1;
91     }
92
93     st = av_new_stream(s, 0);
94     if (!st)
95         return AVERROR_NOMEM;
96
97     st->codec.codec_type = CODEC_TYPE_AUDIO;
98     st->codec.codec_tag = CODEC_ID_AMR_NB;
99     st->codec.codec_id = CODEC_ID_AMR_NB;
100     st->codec.channels = 1;
101     st->codec.sample_rate = 8000;
102     return 0;
103 }
104
105 #define MAX_SIZE 32
106
107 static int amr_read_packet(AVFormatContext *s,
108                           AVPacket *pkt)
109 {
110     static uint16_t packed_size[16] = {12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0};
111     uint8_t toc, q, ft;
112     int read;
113     int size;
114
115     if (url_feof(&s->pb))
116         return -EIO;
117
118     toc=0;
119
120     toc=get_byte(&s->pb);
121
122     q  = (toc >> 2) & 0x01;
123     ft = (toc >> 3) & 0x0F;
124
125     size=packed_size[ft];
126     //printf("amr_read_packet size=%d\n",size);
127
128     if (av_new_packet(pkt, size+1))
129         return -EIO;
130     pkt->stream_index = 0;
131     
132     pkt->data[0]=toc;
133
134     read = get_buffer(&s->pb, pkt->data+1, size);
135
136     if (read != size)
137     {
138         av_free_packet(pkt);
139         return -EIO;
140     }
141
142     return 0;
143 }
144
145 static int amr_read_close(AVFormatContext *s)
146 {
147     return 0;
148 }
149
150 static AVInputFormat amr_iformat = {
151     "amr",
152     "3gpp amr file format",
153     0,
154     amr_probe,
155     amr_read_header,
156     amr_read_packet,
157     amr_read_close,
158 };
159
160 static AVOutputFormat amr_oformat = {
161     "amr",
162     "3gpp amr file format",
163     "audio/amr",
164     "amr",
165     0,
166     CODEC_ID_AMR_NB,
167     CODEC_ID_NONE,
168     amr_write_header,
169     amr_write_packet,
170     amr_write_trailer,
171 };
172
173 int amr_init(void)
174 {
175     av_register_input_format(&amr_iformat);
176     av_register_output_format(&amr_oformat);
177     return 0;
178 }