Statistics
| Branch: | Revision:

ffmpeg / libav / wav.c @ 5798368b

History | View | Annotate | Download (6.99 KB)

1
/* 
2
 * WAV encoder and decoder
3
 * Copyright (c) 2001 Gerard Lantau.
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program 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
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
 */
19
#include "avformat.h"
20
#include "avi.h"
21

    
22
CodecTag codec_wav_tags[] = {
23
    { CODEC_ID_MP2, 0x55 },
24
    { CODEC_ID_MP3LAME, 0x55 },
25
    { CODEC_ID_MP2, 0x50 },
26
    { CODEC_ID_AC3, 0x2000 },
27
    { CODEC_ID_PCM_S16LE, 0x01 },
28
    { CODEC_ID_PCM_U8, 0x01 }, /* must come after s16le in this list */
29
    { CODEC_ID_PCM_ALAW, 0x06 },
30
    { CODEC_ID_PCM_MULAW, 0x07 },
31
    { 0, 0 },
32
};
33

    
34
/* WAVEFORMATEX header */
35
int put_wav_header(ByteIOContext *pb, AVCodecContext *enc)
36
{
37
    int tag, bps, blkalign, bytespersec;
38

    
39
    tag = codec_get_tag(codec_wav_tags, enc->codec_id);
40
    if (tag == 0)
41
        return -1;
42
    put_le16(pb, tag); 
43
    put_le16(pb, enc->channels);
44
    put_le32(pb, enc->sample_rate);
45
    if (enc->codec_id == CODEC_ID_PCM_U8 ||
46
        enc->codec_id == CODEC_ID_PCM_ALAW ||
47
        enc->codec_id == CODEC_ID_PCM_MULAW) {
48
        bps = 8;
49
    } else if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3LAME) {
50
        bps = 0;
51
    } else {
52
        bps = 16;
53
    }
54
    
55
    if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3LAME)
56
        blkalign = 1;
57
    else
58
        blkalign = enc->channels*bps >> 3;
59
    if (enc->codec_id == CODEC_ID_PCM_U8 ||
60
        enc->codec_id == CODEC_ID_PCM_S16LE) {
61
        bytespersec = enc->sample_rate * blkalign;
62
    } else {
63
        bytespersec = enc->bit_rate / 8;
64
    }
65
    put_le32(pb, bytespersec); /* bytes per second */
66
    put_le16(pb, blkalign); /* block align */
67
    put_le16(pb, bps); /* bits per sample */
68
    if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3LAME) {
69
        put_le16(pb, 12); /* wav_extra_size */
70
        put_le16(pb, 1); /* wID */
71
        put_le32(pb, 2); /* fdwFlags */
72
        put_le16(pb, 1152); /* nBlockSize */
73
        put_le16(pb, 1); /* nFramesPerBlock */
74
        put_le16(pb, 1393); /* nCodecDelay */
75
    } else
76
        put_le16(pb, 0); /* wav_extra_size */
77

    
78
    return 0;
79
}
80

    
81
int wav_codec_get_id(unsigned int tag, int bps)
82
{
83
    int id;
84
    id = codec_get_id(codec_wav_tags, tag);
85
    if (id <= 0)
86
        return id;
87
    /* handle specific u8 codec */
88
    if (id == CODEC_ID_PCM_S16LE && bps == 8)
89
        id = CODEC_ID_PCM_U8;
90
    return id;
91
}
92

    
93
typedef struct {
94
    offset_t data;
95
} WAVContext;
96

    
97
static int wav_write_header(AVFormatContext *s)
98
{
99
    WAVContext *wav;
100
    ByteIOContext *pb = &s->pb;
101
    offset_t fmt;
102

    
103
    wav = malloc(sizeof(WAVContext));
104
    if (!wav)
105
        return -1;
106
    memset(wav, 0, sizeof(WAVContext));
107
    s->priv_data = wav;
108

    
109
    put_tag(pb, "RIFF");
110
    put_le32(pb, 0); /* file length */
111
    put_tag(pb, "WAVE");
112

    
113
    /* format header */
114
    fmt = start_tag(pb, "fmt ");
115
    if (put_wav_header(pb, &s->streams[0]->codec) < 0) {
116
        free(wav);
117
        return -1;
118
    }
119
    end_tag(pb, fmt);
120

    
121
    /* data header */
122
    wav->data = start_tag(pb, "data");
123
    
124
    put_flush_packet(pb);
125

    
126
    return 0;
127
}
128

    
129
static int wav_write_packet(AVFormatContext *s, int stream_index_ptr,
130
                           UINT8 *buf, int size)
131
{
132
    ByteIOContext *pb = &s->pb;
133
    put_buffer(pb, buf, size);
134
    return 0;
135
}
136

    
137
static int wav_write_trailer(AVFormatContext *s)
138
{
139
    ByteIOContext *pb = &s->pb;
140
    WAVContext *wav = s->priv_data;
141
    offset_t file_size;
142

    
143
    if (!url_is_streamed(&s->pb)) {
144
        end_tag(pb, wav->data);
145

    
146
        /* update file size */
147
        file_size = url_ftell(pb);
148
        url_fseek(pb, 4, SEEK_SET);
149
        put_le32(pb, (UINT32)(file_size - 8));
150
        url_fseek(pb, file_size, SEEK_SET);
151

    
152
        put_flush_packet(pb);
153
    }
154

    
155
    free(wav);
156
    return 0;
157
}
158

    
159
/* return the size of the found tag */
160
/* XXX: > 2GB ? */
161
static int find_tag(ByteIOContext *pb, UINT32 tag1)
162
{
163
    unsigned int tag;
164
    int size;
165

    
166
    for(;;) {
167
        if (url_feof(pb))
168
            return -1;
169
        tag = get_le32(pb);
170
        size = get_le32(pb);
171
        if (tag == tag1)
172
            break;
173
        url_fseek(pb, size, SEEK_CUR);
174
    }
175
    if (size < 0)
176
        size = 0x7fffffff;
177
    return size;
178
}
179

    
180
/* wav input */
181
static int wav_read_header(AVFormatContext *s,
182
                           AVFormatParameters *ap)
183
{
184
    int size;
185
    unsigned int tag;
186
    ByteIOContext *pb = &s->pb;
187
    unsigned int id, channels, rate, bit_rate, extra_size, bps;
188
    AVStream *st;
189

    
190
    /* check RIFF header */
191
    tag = get_le32(pb);
192

    
193
    if (tag != MKTAG('R', 'I', 'F', 'F'))
194
        return -1;
195
    get_le32(pb); /* file size */
196
    tag = get_le32(pb);
197
    if (tag != MKTAG('W', 'A', 'V', 'E'))
198
        return -1;
199
    
200
    /* parse fmt header */
201
    size = find_tag(pb, MKTAG('f', 'm', 't', ' '));
202
    if (size < 0)
203
        return -1;
204
    id = get_le16(pb); 
205
    channels = get_le16(pb);
206
    rate = get_le32(pb);
207
    bit_rate = get_le32(pb) * 8;
208
    get_le16(pb); /* block align */
209
    bps = get_le16(pb); /* bits per sample */
210
    if (size >= 18) {
211
        /* wav_extra_size */
212
        extra_size = get_le16(pb); 
213
        /* skip unused data */
214
        url_fseek(pb, size - 18, SEEK_CUR);
215
    }
216

    
217
    size = find_tag(pb, MKTAG('d', 'a', 't', 'a'));
218
    if (size < 0)
219
        return -1;
220
    
221
    /* now we are ready: build format streams */
222
    st = malloc(sizeof(AVStream));
223
    if (!st)
224
        return -1;
225
    s->nb_streams = 1;
226
    s->streams[0] = st;
227

    
228
    st->id = 0;
229
    
230
    st->codec.codec_type = CODEC_TYPE_AUDIO;
231
    st->codec.codec_tag = id;
232
    st->codec.codec_id = wav_codec_get_id(id, bps);
233
    st->codec.channels = channels;
234
    st->codec.sample_rate = rate;
235
    return 0;
236
}
237

    
238
#define MAX_SIZE 4096
239

    
240
static int wav_read_packet(AVFormatContext *s,
241
                           AVPacket *pkt)
242
{
243
    int packet_size, n, ret;
244

    
245
    if (url_feof(&s->pb))
246
        return -EIO;
247
    packet_size = url_get_packet_size(&s->pb);
248
    n = MAX_SIZE / packet_size;
249
    if (n <= 0)
250
        return n = 1;
251
    if (av_new_packet(pkt, n * packet_size))
252
        return -EIO;
253
    pkt->stream_index = 0;
254

    
255
    ret = get_buffer(&s->pb, pkt->data, pkt->size);
256
    if (ret < 0)
257
        av_free_packet(pkt);
258
    /* note: we need to modify the packet size here to handle the last
259
       packet */
260
    pkt->size = ret;
261
    return ret;
262
}
263

    
264
static int wav_read_close(AVFormatContext *s)
265
{
266
    return 0;
267
}
268

    
269
AVFormat wav_format = {
270
    "wav",
271
    "wav format",
272
    "audio/x-wav",
273
    "wav",
274
    CODEC_ID_PCM_S16LE,
275
    CODEC_ID_NONE,
276
    wav_write_header,
277
    wav_write_packet,
278
    wav_write_trailer,
279

    
280
    wav_read_header,
281
    wav_read_packet,
282
    wav_read_close,
283
};