2 * WAV muxer and demuxer
3 * Copyright (c) 2001, 2002 Fabrice Bellard.
5 * This file is part of FFmpeg.
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.
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.
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
34 static int wav_write_header(AVFormatContext
*s
)
36 WAVContext
*wav
= s
->priv_data
;
37 ByteIOContext
*pb
= s
->pb
;
41 put_le32(pb
, 0); /* file length */
45 fmt
= start_tag(pb
, "fmt ");
46 if (put_wav_header(pb
, s
->streams
[0]->codec
) < 0) {
52 if(s
->streams
[0]->codec
->codec_tag
!= 0x01 /* hence for all other than PCM */
53 && !url_is_streamed(s
->pb
)) {
54 fact
= start_tag(pb
, "fact");
59 av_set_pts_info(s
->streams
[0], 64, 1, s
->streams
[0]->codec
->sample_rate
);
60 wav
->maxpts
= wav
->last_duration
= 0;
61 wav
->minpts
= INT64_MAX
;
64 wav
->data
= start_tag(pb
, "data");
71 static int wav_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
73 ByteIOContext
*pb
= s
->pb
;
74 WAVContext
*wav
= s
->priv_data
;
75 put_buffer(pb
, pkt
->data
, pkt
->size
);
76 if(pkt
->pts
!= AV_NOPTS_VALUE
) {
77 wav
->minpts
= FFMIN(wav
->minpts
, pkt
->pts
);
78 wav
->maxpts
= FFMAX(wav
->maxpts
, pkt
->pts
);
79 wav
->last_duration
= pkt
->duration
;
81 av_log(s
, AV_LOG_ERROR
, "wav_write_packet: NOPTS\n");
85 static int wav_write_trailer(AVFormatContext
*s
)
87 ByteIOContext
*pb
= s
->pb
;
88 WAVContext
*wav
= s
->priv_data
;
91 if (!url_is_streamed(s
->pb
)) {
92 end_tag(pb
, wav
->data
);
94 /* update file size */
95 file_size
= url_ftell(pb
);
96 url_fseek(pb
, 4, SEEK_SET
);
97 put_le32(pb
, (uint32_t)(file_size
- 8));
98 url_fseek(pb
, file_size
, SEEK_SET
);
100 put_flush_packet(pb
);
102 if(s
->streams
[0]->codec
->codec_tag
!= 0x01) {
103 /* Update num_samps in fact chunk */
104 int number_of_samples
;
105 number_of_samples
= av_rescale(wav
->maxpts
- wav
->minpts
+ wav
->last_duration
,
106 s
->streams
[0]->codec
->sample_rate
* (int64_t)s
->streams
[0]->time_base
.num
,
107 s
->streams
[0]->time_base
.den
);
108 url_fseek(pb
, wav
->data
-12, SEEK_SET
);
109 put_le32(pb
, number_of_samples
);
110 url_fseek(pb
, file_size
, SEEK_SET
);
111 put_flush_packet(pb
);
116 #endif //CONFIG_MUXERS
118 /* return the size of the found tag */
120 static int find_tag(ByteIOContext
*pb
, uint32_t tag1
)
132 url_fseek(pb
, size
, SEEK_CUR
);
139 static int wav_probe(AVProbeData
*p
)
141 /* check file header */
142 if (p
->buf_size
<= 32)
144 if (p
->buf
[0] == 'R' && p
->buf
[1] == 'I' &&
145 p
->buf
[2] == 'F' && p
->buf
[3] == 'F' &&
146 p
->buf
[8] == 'W' && p
->buf
[9] == 'A' &&
147 p
->buf
[10] == 'V' && p
->buf
[11] == 'E')
149 Since ACT demuxer has standard WAV header at top of it's own,
150 returning score is decreased to avoid probe conflict
153 return AVPROBE_SCORE_MAX
- 1;
159 static int wav_read_header(AVFormatContext
*s
,
160 AVFormatParameters
*ap
)
164 ByteIOContext
*pb
= s
->pb
;
166 WAVContext
*wav
= s
->priv_data
;
168 /* check RIFF header */
171 if (tag
!= MKTAG('R', 'I', 'F', 'F'))
173 get_le32(pb
); /* file size */
175 if (tag
!= MKTAG('W', 'A', 'V', 'E'))
178 /* parse fmt header */
179 size
= find_tag(pb
, MKTAG('f', 'm', 't', ' '));
182 st
= av_new_stream(s
, 0);
184 return AVERROR(ENOMEM
);
186 get_wav_header(pb
, st
->codec
, size
);
187 st
->need_parsing
= AVSTREAM_PARSE_FULL
;
189 av_set_pts_info(st
, 64, 1, st
->codec
->sample_rate
);
191 size
= find_tag(pb
, MKTAG('d', 'a', 't', 'a'));
194 wav
->data_end
= url_ftell(pb
) + size
;
198 #define MAX_SIZE 4096
200 static int wav_read_packet(AVFormatContext
*s
,
205 WAVContext
*wav
= s
->priv_data
;
211 left
= wav
->data_end
- url_ftell(s
->pb
);
213 left
= find_tag(s
->pb
, MKTAG('d', 'a', 't', 'a'));
217 wav
->data_end
= url_ftell(s
->pb
) + left
;
221 if (st
->codec
->block_align
> 1) {
222 if (size
< st
->codec
->block_align
)
223 size
= st
->codec
->block_align
;
224 size
= (size
/ st
->codec
->block_align
) * st
->codec
->block_align
;
226 size
= FFMIN(size
, left
);
227 ret
= av_get_packet(s
->pb
, pkt
, size
);
230 pkt
->stream_index
= 0;
232 /* note: we need to modify the packet size here to handle the last
238 static int wav_read_close(AVFormatContext
*s
)
243 static int wav_read_seek(AVFormatContext
*s
,
244 int stream_index
, int64_t timestamp
, int flags
)
249 switch(st
->codec
->codec_id
) {
254 /* use generic seeking with dynamically generated indexes */
259 return pcm_read_seek(s
, stream_index
, timestamp
, flags
);
262 #ifdef CONFIG_WAV_DEMUXER
263 AVInputFormat wav_demuxer
= {
272 .flags
= AVFMT_GENERIC_INDEX
,
273 .codec_tag
= (const AVCodecTag
*[]){codec_wav_tags
, 0},
276 #ifdef CONFIG_WAV_MUXER
277 AVOutputFormat wav_muxer
= {
288 .codec_tag
= (const AVCodecTag
*[]){codec_wav_tags
, 0},