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) {
47 av_log(s
, AV_LOG_ERROR
, "%s codec not supported in WAVE format\n",
48 s
->streams
[0]->codec
->codec
? s
->streams
[0]->codec
->codec
->name
: "NONE");
54 if(s
->streams
[0]->codec
->codec_tag
!= 0x01 /* hence for all other than PCM */
55 && !url_is_streamed(s
->pb
)) {
56 fact
= start_tag(pb
, "fact");
61 av_set_pts_info(s
->streams
[0], 64, 1, s
->streams
[0]->codec
->sample_rate
);
62 wav
->maxpts
= wav
->last_duration
= 0;
63 wav
->minpts
= INT64_MAX
;
66 wav
->data
= start_tag(pb
, "data");
73 static int wav_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
75 ByteIOContext
*pb
= s
->pb
;
76 WAVContext
*wav
= s
->priv_data
;
77 put_buffer(pb
, pkt
->data
, pkt
->size
);
78 if(pkt
->pts
!= AV_NOPTS_VALUE
) {
79 wav
->minpts
= FFMIN(wav
->minpts
, pkt
->pts
);
80 wav
->maxpts
= FFMAX(wav
->maxpts
, pkt
->pts
);
81 wav
->last_duration
= pkt
->duration
;
83 av_log(s
, AV_LOG_ERROR
, "wav_write_packet: NOPTS\n");
87 static int wav_write_trailer(AVFormatContext
*s
)
89 ByteIOContext
*pb
= s
->pb
;
90 WAVContext
*wav
= s
->priv_data
;
93 if (!url_is_streamed(s
->pb
)) {
94 end_tag(pb
, wav
->data
);
96 /* update file size */
97 file_size
= url_ftell(pb
);
98 url_fseek(pb
, 4, SEEK_SET
);
99 put_le32(pb
, (uint32_t)(file_size
- 8));
100 url_fseek(pb
, file_size
, SEEK_SET
);
102 put_flush_packet(pb
);
104 if(s
->streams
[0]->codec
->codec_tag
!= 0x01) {
105 /* Update num_samps in fact chunk */
106 int number_of_samples
;
107 number_of_samples
= av_rescale(wav
->maxpts
- wav
->minpts
+ wav
->last_duration
,
108 s
->streams
[0]->codec
->sample_rate
* (int64_t)s
->streams
[0]->time_base
.num
,
109 s
->streams
[0]->time_base
.den
);
110 url_fseek(pb
, wav
->data
-12, SEEK_SET
);
111 put_le32(pb
, number_of_samples
);
112 url_fseek(pb
, file_size
, SEEK_SET
);
113 put_flush_packet(pb
);
118 #endif /* CONFIG_WAV_MUXER */
120 /* return the size of the found tag */
122 static int find_tag(ByteIOContext
*pb
, uint32_t tag1
)
134 url_fseek(pb
, size
, SEEK_CUR
);
141 static int wav_probe(AVProbeData
*p
)
143 /* check file header */
144 if (p
->buf_size
<= 32)
146 if (p
->buf
[0] == 'R' && p
->buf
[1] == 'I' &&
147 p
->buf
[2] == 'F' && p
->buf
[3] == 'F' &&
148 p
->buf
[8] == 'W' && p
->buf
[9] == 'A' &&
149 p
->buf
[10] == 'V' && p
->buf
[11] == 'E')
151 Since ACT demuxer has standard WAV header at top of it's own,
152 returning score is decreased to avoid probe conflict
155 return AVPROBE_SCORE_MAX
- 1;
161 static int wav_read_header(AVFormatContext
*s
,
162 AVFormatParameters
*ap
)
166 ByteIOContext
*pb
= s
->pb
;
168 WAVContext
*wav
= s
->priv_data
;
170 /* check RIFF header */
173 if (tag
!= MKTAG('R', 'I', 'F', 'F'))
175 get_le32(pb
); /* file size */
177 if (tag
!= MKTAG('W', 'A', 'V', 'E'))
180 /* parse fmt header */
181 size
= find_tag(pb
, MKTAG('f', 'm', 't', ' '));
184 st
= av_new_stream(s
, 0);
186 return AVERROR(ENOMEM
);
188 get_wav_header(pb
, st
->codec
, size
);
189 st
->need_parsing
= AVSTREAM_PARSE_FULL
;
191 av_set_pts_info(st
, 64, 1, st
->codec
->sample_rate
);
193 size
= find_tag(pb
, MKTAG('d', 'a', 't', 'a'));
196 wav
->data_end
= url_ftell(pb
) + size
;
200 #define MAX_SIZE 4096
202 static int wav_read_packet(AVFormatContext
*s
,
207 WAVContext
*wav
= s
->priv_data
;
213 left
= wav
->data_end
- url_ftell(s
->pb
);
215 left
= find_tag(s
->pb
, MKTAG('d', 'a', 't', 'a'));
219 wav
->data_end
= url_ftell(s
->pb
) + left
;
223 if (st
->codec
->block_align
> 1) {
224 if (size
< st
->codec
->block_align
)
225 size
= st
->codec
->block_align
;
226 size
= (size
/ st
->codec
->block_align
) * st
->codec
->block_align
;
228 size
= FFMIN(size
, left
);
229 ret
= av_get_packet(s
->pb
, pkt
, size
);
232 pkt
->stream_index
= 0;
234 /* note: we need to modify the packet size here to handle the last
240 static int wav_read_seek(AVFormatContext
*s
,
241 int stream_index
, int64_t timestamp
, int flags
)
246 switch(st
->codec
->codec_id
) {
251 /* use generic seeking with dynamically generated indexes */
256 return pcm_read_seek(s
, stream_index
, timestamp
, flags
);
259 #if CONFIG_WAV_DEMUXER
260 AVInputFormat wav_demuxer
= {
262 NULL_IF_CONFIG_SMALL("WAV format"),
269 .flags
= AVFMT_GENERIC_INDEX
,
270 .codec_tag
= (const AVCodecTag
* const []){codec_wav_tags
, 0},
274 AVOutputFormat wav_muxer
= {
276 NULL_IF_CONFIG_SMALL("WAV format"),
285 .codec_tag
= (const AVCodecTag
* const []){codec_wav_tags
, 0},