Statistics
| Branch: | Revision:

ffmpeg / libavformat / voc.c @ c04c3282

History | View | Annotate | Download (7.76 KB)

1
/*
2
 * Creative Voice File demuxer.
3
 * Copyright (c) 2006  Aurelien Jacobs <aurel@gnuage.org>
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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
19

    
20
#include "avformat.h"
21
#include "avi.h"    /* for CodecTag */
22
#include "voc.h"
23

    
24

    
25
typedef enum voc_type {
26
    VOC_TYPE_EOF              = 0x00,
27
    VOC_TYPE_VOICE_DATA       = 0x01,
28
    VOC_TYPE_VOICE_DATA_CONT  = 0x02,
29
    VOC_TYPE_SILENCE          = 0x03,
30
    VOC_TYPE_MARKER           = 0x04,
31
    VOC_TYPE_ASCII            = 0x05,
32
    VOC_TYPE_REPETITION_START = 0x06,
33
    VOC_TYPE_REPETITION_END   = 0x07,
34
    VOC_TYPE_EXTENDED         = 0x08,
35
    VOC_TYPE_NEW_VOICE_DATA   = 0x09,
36
} voc_type_t;
37

    
38

    
39
static const int voc_max_pkt_size = 2048;
40
static const unsigned char voc_magic[] = "Creative Voice File\x1A";
41

    
42
static const CodecTag voc_codec_tags[] = {
43
    {CODEC_ID_PCM_U8,        0x00},
44
    {CODEC_ID_ADPCM_SBPRO_4, 0x01},
45
    {CODEC_ID_ADPCM_SBPRO_3, 0x02},
46
    {CODEC_ID_ADPCM_SBPRO_2, 0x03},
47
    {CODEC_ID_PCM_S16LE,     0x04},
48
    {CODEC_ID_PCM_ALAW,      0x06},
49
    {CODEC_ID_PCM_MULAW,     0x07},
50
    {CODEC_ID_ADPCM_CT,    0x0200},
51
    {0, 0},
52
};
53

    
54

    
55
#ifdef CONFIG_DEMUXERS
56

    
57
static int voc_probe(AVProbeData *p)
58
{
59
    int version, check;
60

    
61
    if (p->buf_size < 26)
62
        return 0;
63
    if (memcmp(p->buf, voc_magic, sizeof(voc_magic) - 1))
64
        return 0;
65
    version = p->buf[22] | (p->buf[23] << 8);
66
    check = p->buf[24] | (p->buf[25] << 8);
67
    if (~version + 0x1234 != check)
68
        return 10;
69

    
70
    return AVPROBE_SCORE_MAX;
71
}
72

    
73
static int voc_read_header(AVFormatContext *s, AVFormatParameters *ap)
74
{
75
    voc_dec_context_t *voc = s->priv_data;
76
    ByteIOContext *pb = &s->pb;
77
    int header_size;
78
    AVStream *st;
79

    
80
    url_fskip(pb, 20);
81
    header_size = get_le16(pb) - 22;
82
    if (header_size != 4) {
83
        av_log(s, AV_LOG_ERROR, "unkown header size: %d\n", header_size);
84
        return AVERROR_NOTSUPP;
85
    }
86
    url_fskip(pb, header_size);
87
    st = av_new_stream(s, 0);
88
    if (!st)
89
        return AVERROR_NOMEM;
90
    st->codec->codec_type = CODEC_TYPE_AUDIO;
91

    
92
    voc->remaining_size = 0;
93
    return 0;
94
}
95

    
96
static int voc_get_bps(int codec_id)
97
{
98
    switch (codec_id) {
99
    case CODEC_ID_PCM_S16LE:
100
        return 16;
101
    case CODEC_ID_ADPCM_CT:
102
        return 4;
103
    default:
104
        return 8;
105
    }
106
}
107

    
108
int
109
voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size)
110
{
111
    voc_dec_context_t *voc = s->priv_data;
112
    AVCodecContext *dec = st->codec;
113
    ByteIOContext *pb = &s->pb;
114
    voc_type_t type;
115
    int size;
116
    int sample_rate = 0;
117
    int channels = 1;
118

    
119
    while (!voc->remaining_size) {
120
        type = get_byte(pb);
121
        if (type == VOC_TYPE_EOF)
122
            return AVERROR_IO;
123
        voc->remaining_size = get_le24(pb);
124
        max_size -= 4;
125

    
126
        switch (type) {
127
        case VOC_TYPE_VOICE_DATA:
128
            dec->sample_rate = 1000000 / (256 - get_byte(pb));
129
            if (sample_rate)
130
                dec->sample_rate = sample_rate;
131
            dec->channels = channels;
132
            dec->codec_id = codec_get_id(voc_codec_tags, get_byte(pb));
133
            dec->bits_per_sample = voc_get_bps(dec->codec_id);
134
            voc->remaining_size -= 2;
135
            max_size -= 2;
136
            channels = 1;
137
            break;
138

    
139
        case VOC_TYPE_VOICE_DATA_CONT:
140
            break;
141

    
142
        case VOC_TYPE_EXTENDED:
143
            sample_rate = get_le16(pb);
144
            get_byte(pb);
145
            channels = get_byte(pb) + 1;
146
            sample_rate = 256000000 / (channels * (65536 - sample_rate));
147
            voc->remaining_size = 0;
148
            max_size -= 4;
149
            break;
150

    
151
        case VOC_TYPE_NEW_VOICE_DATA:
152
            dec->sample_rate = get_le32(pb);
153
            dec->bits_per_sample = get_byte(pb);
154
            dec->channels = get_byte(pb);
155
            dec->codec_id = codec_get_id(voc_codec_tags, get_le16(pb));
156
            url_fskip(pb, 4);
157
            voc->remaining_size -= 12;
158
            max_size -= 12;
159
            break;
160

    
161
        default:
162
            url_fskip(pb, voc->remaining_size);
163
            max_size -= voc->remaining_size;
164
            voc->remaining_size = 0;
165
            break;
166
        }
167
    }
168

    
169
    dec->bit_rate = dec->sample_rate * dec->bits_per_sample;
170

    
171
    if (max_size <= 0)
172
        max_size = voc_max_pkt_size;
173
    size = FFMIN(voc->remaining_size, max_size);
174
    voc->remaining_size -= size;
175
    return av_get_packet(pb, pkt, size);
176
}
177

    
178
static int voc_read_packet(AVFormatContext *s, AVPacket *pkt)
179
{
180
    return voc_get_packet(s, pkt, s->streams[0], 0);
181
}
182

    
183
static int voc_read_close(AVFormatContext *s)
184
{
185
    return 0;
186
}
187

    
188
static AVInputFormat voc_iformat = {
189
    "voc",
190
    "Creative Voice File format",
191
    sizeof(voc_dec_context_t),
192
    voc_probe,
193
    voc_read_header,
194
    voc_read_packet,
195
    voc_read_close,
196
};
197

    
198
#endif /* CONFIG_DEMUXERS */
199

    
200

    
201
#ifdef CONFIG_MUXERS
202

    
203
typedef struct voc_enc_context {
204
    int param_written;
205
} voc_enc_context_t;
206

    
207
static int voc_write_header(AVFormatContext *s)
208
{
209
    ByteIOContext *pb = &s->pb;
210
    const int header_size = 26;
211
    const int version = 0x0114;
212

    
213
    if (s->nb_streams != 1
214
        || s->streams[0]->codec->codec_type != CODEC_TYPE_AUDIO)
215
        return AVERROR_NOTSUPP;
216

    
217
    put_buffer(pb, voc_magic, sizeof(voc_magic) - 1);
218
    put_le16(pb, header_size);
219
    put_le16(pb, version);
220
    put_le16(pb, ~version + 0x1234);
221

    
222
    return 0;
223
}
224

    
225
static int voc_write_packet(AVFormatContext *s, AVPacket *pkt)
226
{
227
    voc_enc_context_t *voc = s->priv_data;
228
    AVCodecContext *enc = s->streams[0]->codec;
229
    ByteIOContext *pb = &s->pb;
230

    
231
    if (!voc->param_written) {
232
        int format = codec_get_tag(voc_codec_tags, enc->codec_id);
233

    
234
        if (format > 0xFF) {
235
            put_byte(pb, VOC_TYPE_NEW_VOICE_DATA);
236
            put_le24(pb, pkt->size + 12);
237
            put_le32(pb, enc->sample_rate);
238
            put_byte(pb, enc->bits_per_sample);
239
            put_byte(pb, enc->channels);
240
            put_le16(pb, format);
241
            put_le32(pb, 0);
242
        } else {
243
            if (s->streams[0]->codec->channels > 1) {
244
                put_byte(pb, VOC_TYPE_EXTENDED);
245
                put_le24(pb, 4);
246
                put_le16(pb, 65536-256000000/(enc->sample_rate*enc->channels));
247
                put_byte(pb, format);
248
                put_byte(pb, enc->channels - 1);
249
            }
250
            put_byte(pb, VOC_TYPE_VOICE_DATA);
251
            put_le24(pb, pkt->size + 2);
252
            put_byte(pb, 256 - 1000000 / enc->sample_rate);
253
            put_byte(pb, format);
254
        }
255
        voc->param_written = 1;
256
    } else {
257
        put_byte(pb, VOC_TYPE_VOICE_DATA_CONT);
258
        put_le24(pb, pkt->size);
259
    }
260

    
261
    put_buffer(pb, pkt->data, pkt->size);
262
    return 0;
263
}
264

    
265
static int voc_write_trailer(AVFormatContext *s)
266
{
267
    put_byte(&s->pb, 0);
268
    return 0;
269
}
270

    
271
static AVOutputFormat voc_oformat = {
272
    "voc",
273
    "Creative Voice File format",
274
    "audio/x-voc",
275
    "voc",
276
    sizeof(voc_enc_context_t),
277
    CODEC_ID_PCM_U8,
278
    CODEC_ID_NONE,
279
    voc_write_header,
280
    voc_write_packet,
281
    voc_write_trailer,
282
};
283

    
284
#endif /* CONFIG_MUXERS */
285

    
286

    
287
int voc_init(void)
288
{
289
#ifdef CONFIG_DEMUXERS
290
    av_register_input_format(&voc_iformat);
291
#endif /* CONFIG_DEMUXERS */
292
#ifdef CONFIG_MUXERS
293
    av_register_output_format(&voc_oformat);
294
#endif /* CONFIG_MUXERS */
295
    return 0;
296
}