minor help output formatting fix
[libav.git] / libavformat / wav.c
CommitLineData
115329f1 1/*
7fbde343 2 * WAV muxer and demuxer
e095026a 3 * Copyright (c) 2001, 2002 Fabrice Bellard.
de6d9b64 4 *
b78e7197
DB
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
19720f15
FB
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
b78e7197 10 * version 2.1 of the License, or (at your option) any later version.
de6d9b64 11 *
b78e7197 12 * FFmpeg is distributed in the hope that it will be useful,
de6d9b64 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19720f15
FB
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
de6d9b64 16 *
19720f15 17 * You should have received a copy of the GNU Lesser General Public
b78e7197 18 * License along with FFmpeg; if not, write to the Free Software
5509bffa 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
de6d9b64 20 */
de6d9b64 21#include "avformat.h"
e006c307 22#include "allformats.h"
9d9f4119 23#include "riff.h"
46a3d068 24
de6d9b64
FB
25typedef struct {
26 offset_t data;
b582d7ba 27 offset_t data_end;
de6d9b64
FB
28} WAVContext;
29
277e84f5 30#ifdef CONFIG_MUXERS
de6d9b64
FB
31static int wav_write_header(AVFormatContext *s)
32{
c9a65ca8 33 WAVContext *wav = s->priv_data;
de6d9b64
FB
34 ByteIOContext *pb = &s->pb;
35 offset_t fmt;
36
de6d9b64
FB
37 put_tag(pb, "RIFF");
38 put_le32(pb, 0); /* file length */
39 put_tag(pb, "WAVE");
40
41 /* format header */
42 fmt = start_tag(pb, "fmt ");
01f4895c 43 if (put_wav_header(pb, s->streams[0]->codec) < 0) {
1ea4f593 44 av_free(wav);
46a3d068
FB
45 return -1;
46 }
de6d9b64
FB
47 end_tag(pb, fmt);
48
01f4895c 49 av_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate);
a1e568bd 50
de6d9b64
FB
51 /* data header */
52 wav->data = start_tag(pb, "data");
115329f1 53
de6d9b64
FB
54 put_flush_packet(pb);
55
56 return 0;
57}
58
e928649b 59static int wav_write_packet(AVFormatContext *s, AVPacket *pkt)
de6d9b64
FB
60{
61 ByteIOContext *pb = &s->pb;
e928649b 62 put_buffer(pb, pkt->data, pkt->size);
de6d9b64
FB
63 return 0;
64}
65
66static int wav_write_trailer(AVFormatContext *s)
67{
68 ByteIOContext *pb = &s->pb;
69 WAVContext *wav = s->priv_data;
70 offset_t file_size;
71
72 if (!url_is_streamed(&s->pb)) {
73 end_tag(pb, wav->data);
74
75 /* update file size */
76 file_size = url_ftell(pb);
77 url_fseek(pb, 4, SEEK_SET);
0c1a9eda 78 put_le32(pb, (uint32_t)(file_size - 8));
de6d9b64
FB
79 url_fseek(pb, file_size, SEEK_SET);
80
81 put_flush_packet(pb);
82 }
de6d9b64
FB
83 return 0;
84}
a9e35095 85#endif //CONFIG_MUXERS
de6d9b64
FB
86
87/* return the size of the found tag */
88/* XXX: > 2GB ? */
0c1a9eda 89static int find_tag(ByteIOContext *pb, uint32_t tag1)
de6d9b64
FB
90{
91 unsigned int tag;
92 int size;
93
94 for(;;) {
95 if (url_feof(pb))
96 return -1;
97 tag = get_le32(pb);
98 size = get_le32(pb);
99 if (tag == tag1)
100 break;
101 url_fseek(pb, size, SEEK_CUR);
102 }
103 if (size < 0)
104 size = 0x7fffffff;
105 return size;
106}
107
c9a65ca8
FB
108static int wav_probe(AVProbeData *p)
109{
110 /* check file header */
111 if (p->buf_size <= 32)
112 return 0;
113 if (p->buf[0] == 'R' && p->buf[1] == 'I' &&
114 p->buf[2] == 'F' && p->buf[3] == 'F' &&
115 p->buf[8] == 'W' && p->buf[9] == 'A' &&
116 p->buf[10] == 'V' && p->buf[11] == 'E')
117 return AVPROBE_SCORE_MAX;
118 else
119 return 0;
120}
121
de6d9b64
FB
122/* wav input */
123static int wav_read_header(AVFormatContext *s,
124 AVFormatParameters *ap)
125{
126 int size;
127 unsigned int tag;
128 ByteIOContext *pb = &s->pb;
de6d9b64 129 AVStream *st;
b582d7ba 130 WAVContext *wav = s->priv_data;
de6d9b64
FB
131
132 /* check RIFF header */
133 tag = get_le32(pb);
134
135 if (tag != MKTAG('R', 'I', 'F', 'F'))
136 return -1;
137 get_le32(pb); /* file size */
138 tag = get_le32(pb);
139 if (tag != MKTAG('W', 'A', 'V', 'E'))
140 return -1;
115329f1 141
de6d9b64
FB
142 /* parse fmt header */
143 size = find_tag(pb, MKTAG('f', 'm', 't', ' '));
144 if (size < 0)
145 return -1;
c9a65ca8 146 st = av_new_stream(s, 0);
de6d9b64 147 if (!st)
c9a65ca8 148 return AVERROR_NOMEM;
de6d9b64 149
01f4895c 150 get_wav_header(pb, st->codec, size);
f9b5459e 151 st->need_parsing = 1;
595bf4ef 152
01f4895c 153 av_set_pts_info(st, 64, 1, st->codec->sample_rate);
595bf4ef 154
e095026a
FB
155 size = find_tag(pb, MKTAG('d', 'a', 't', 'a'));
156 if (size < 0)
157 return -1;
b582d7ba 158 wav->data_end= url_ftell(pb) + size;
de6d9b64
FB
159 return 0;
160}
161
162#define MAX_SIZE 4096
163
164static int wav_read_packet(AVFormatContext *s,
165 AVPacket *pkt)
166{
b582d7ba 167 int ret, size, left;
f9b5459e 168 AVStream *st;
b582d7ba 169 WAVContext *wav = s->priv_data;
de6d9b64
FB
170
171 if (url_feof(&s->pb))
0bd586c5 172 return AVERROR_IO;
f9b5459e
FB
173 st = s->streams[0];
174
b582d7ba
MN
175 left= wav->data_end - url_ftell(&s->pb);
176 if(left <= 0){
177 left = find_tag(&(s->pb), MKTAG('d', 'a', 't', 'a'));
178 if (left < 0) {
179 return AVERROR_IO;
180 }
181 wav->data_end= url_ftell(&s->pb) + left;
182 }
183
f9b5459e 184 size = MAX_SIZE;
01f4895c
MN
185 if (st->codec->block_align > 1) {
186 if (size < st->codec->block_align)
187 size = st->codec->block_align;
188 size = (size / st->codec->block_align) * st->codec->block_align;
f9b5459e 189 }
b582d7ba 190 size= FFMIN(size, left);
e9b78eeb
MN
191 ret= av_get_packet(&s->pb, pkt, size);
192 if (ret <= 0)
0bd586c5 193 return AVERROR_IO;
de6d9b64
FB
194 pkt->stream_index = 0;
195
5ed8fafc
FB
196 /* note: we need to modify the packet size here to handle the last
197 packet */
198 pkt->size = ret;
de6d9b64
FB
199 return ret;
200}
201
202static int wav_read_close(AVFormatContext *s)
203{
204 return 0;
205}
206
115329f1 207static int wav_read_seek(AVFormatContext *s,
7b3c1382 208 int stream_index, int64_t timestamp, int flags)
f9b5459e
FB
209{
210 AVStream *st;
211
212 st = s->streams[0];
01f4895c 213 switch(st->codec->codec_id) {
f9b5459e
FB
214 case CODEC_ID_MP2:
215 case CODEC_ID_MP3:
216 case CODEC_ID_AC3:
23c99253 217 case CODEC_ID_DTS:
f9b5459e
FB
218 /* use generic seeking with dynamically generated indexes */
219 return -1;
220 default:
221 break;
222 }
7b3c1382 223 return pcm_read_seek(s, stream_index, timestamp, flags);
f9b5459e
FB
224}
225
ff70e601
MR
226#ifdef CONFIG_WAV_DEMUXER
227AVInputFormat wav_demuxer = {
c9a65ca8
FB
228 "wav",
229 "wav format",
b582d7ba 230 sizeof(WAVContext),
c9a65ca8
FB
231 wav_probe,
232 wav_read_header,
233 wav_read_packet,
234 wav_read_close,
f9b5459e 235 wav_read_seek,
e9b78eeb 236 .flags= AVFMT_GENERIC_INDEX,
6c77805f 237 .codec_tag= (const AVCodecTag*[]){codec_wav_tags, 0},
c9a65ca8 238};
ff70e601
MR
239#endif
240#ifdef CONFIG_WAV_MUXER
241AVOutputFormat wav_muxer = {
de6d9b64
FB
242 "wav",
243 "wav format",
244 "audio/x-wav",
245 "wav",
c9a65ca8 246 sizeof(WAVContext),
5ed8fafc 247 CODEC_ID_PCM_S16LE,
de6d9b64
FB
248 CODEC_ID_NONE,
249 wav_write_header,
250 wav_write_packet,
251 wav_write_trailer,
6c77805f 252 .codec_tag= (const AVCodecTag*[]){codec_wav_tags, 0},
de6d9b64 253};
ff70e601 254#endif