Mercurial > libavformat.hg
annotate wav.c @ 3233:e2bdb989f7da libavformat
Decrease returning probe score for WAV demuxer to avoid
probe conflict between WAV and future ACT demuxer.
This is necessary because ACT has standard WAV header
at top of it's own.
author | voroshil |
---|---|
date | Sat, 19 Apr 2008 14:52:19 +0000 |
parents | d52c718e83f9 |
children | 7a0230981402 |
rev | line source |
---|---|
885 | 1 /* |
1415
3b00fb8ef8e4
replace coder/decoder file description in libavformat by muxer/demuxer
aurel
parents:
1358
diff
changeset
|
2 * WAV muxer and demuxer |
0 | 3 * Copyright (c) 2001, 2002 Fabrice Bellard. |
4 * | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1172
diff
changeset
|
5 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1172
diff
changeset
|
6 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1172
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
0 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1172
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
0 | 11 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1172
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
0 | 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. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1172
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
896
edbe5c3717f9
Update licensing information: The FSF changed postal address.
diego
parents:
893
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 20 */ |
21 #include "avformat.h" | |
2545
213268d7594e
move unrelated functions declarations out of allformats.h
aurel
parents:
2274
diff
changeset
|
22 #include "raw.h" |
1172
6a5e58d2114b
move common stuff from avienc.c and wav.c to new file riff.c
mru
parents:
1169
diff
changeset
|
23 #include "riff.h" |
0 | 24 |
25 typedef struct { | |
26 offset_t data; | |
1136
d65cd7c3573e
dont read over the end of a data chunk and at the end search for the next
michael
parents:
1122
diff
changeset
|
27 offset_t data_end; |
1781 | 28 int64_t minpts; |
29 int64_t maxpts; | |
30 int last_duration; | |
0 | 31 } WAVContext; |
32 | |
1149 | 33 #ifdef CONFIG_MUXERS |
0 | 34 static int wav_write_header(AVFormatContext *s) |
35 { | |
36 WAVContext *wav = s->priv_data; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2545
diff
changeset
|
37 ByteIOContext *pb = s->pb; |
1781 | 38 offset_t fmt, fact; |
0 | 39 |
40 put_tag(pb, "RIFF"); | |
41 put_le32(pb, 0); /* file length */ | |
42 put_tag(pb, "WAVE"); | |
43 | |
44 /* format header */ | |
45 fmt = start_tag(pb, "fmt "); | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
817
diff
changeset
|
46 if (put_wav_header(pb, s->streams[0]->codec) < 0) { |
0 | 47 av_free(wav); |
48 return -1; | |
49 } | |
50 end_tag(pb, fmt); | |
51 | |
1781 | 52 if(s->streams[0]->codec->codec_tag != 0x01 /* hence for all other than PCM */ |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2545
diff
changeset
|
53 && !url_is_streamed(s->pb)) { |
1781 | 54 fact = start_tag(pb, "fact"); |
55 put_le32(pb, 0); | |
56 end_tag(pb, fact); | |
57 } | |
58 | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
817
diff
changeset
|
59 av_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate); |
1781 | 60 wav->maxpts = wav->last_duration = 0; |
61 wav->minpts = INT64_MAX; | |
645
9fc2d2cc4608
wav timestamp truncation fix by (Wolfram Gloger <wmglo dent.med.uni-muenchen de>)
michael
parents:
587
diff
changeset
|
62 |
0 | 63 /* data header */ |
64 wav->data = start_tag(pb, "data"); | |
885 | 65 |
0 | 66 put_flush_packet(pb); |
67 | |
68 return 0; | |
69 } | |
70 | |
468 | 71 static int wav_write_packet(AVFormatContext *s, AVPacket *pkt) |
0 | 72 { |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2545
diff
changeset
|
73 ByteIOContext *pb = s->pb; |
1781 | 74 WAVContext *wav = s->priv_data; |
468 | 75 put_buffer(pb, pkt->data, pkt->size); |
1781 | 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; | |
80 } else | |
81 av_log(s, AV_LOG_ERROR, "wav_write_packet: NOPTS\n"); | |
0 | 82 return 0; |
83 } | |
84 | |
85 static int wav_write_trailer(AVFormatContext *s) | |
86 { | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2545
diff
changeset
|
87 ByteIOContext *pb = s->pb; |
0 | 88 WAVContext *wav = s->priv_data; |
89 offset_t file_size; | |
90 | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2545
diff
changeset
|
91 if (!url_is_streamed(s->pb)) { |
0 | 92 end_tag(pb, wav->data); |
93 | |
94 /* update file size */ | |
95 file_size = url_ftell(pb); | |
96 url_fseek(pb, 4, SEEK_SET); | |
65 | 97 put_le32(pb, (uint32_t)(file_size - 8)); |
0 | 98 url_fseek(pb, file_size, SEEK_SET); |
99 | |
100 put_flush_packet(pb); | |
1781 | 101 |
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); | |
112 } | |
0 | 113 } |
114 return 0; | |
115 } | |
858
66cc656ea404
Replace CONFIG_ENCODERS/CONFIG_DECODERS with CONFIG_MUXERS/CONFIG_DEMUXERS
diego
parents:
846
diff
changeset
|
116 #endif //CONFIG_MUXERS |
0 | 117 |
118 /* return the size of the found tag */ | |
119 /* XXX: > 2GB ? */ | |
65 | 120 static int find_tag(ByteIOContext *pb, uint32_t tag1) |
0 | 121 { |
122 unsigned int tag; | |
123 int size; | |
124 | |
125 for(;;) { | |
126 if (url_feof(pb)) | |
127 return -1; | |
128 tag = get_le32(pb); | |
129 size = get_le32(pb); | |
130 if (tag == tag1) | |
131 break; | |
132 url_fseek(pb, size, SEEK_CUR); | |
133 } | |
134 if (size < 0) | |
135 size = 0x7fffffff; | |
136 return size; | |
137 } | |
138 | |
139 static int wav_probe(AVProbeData *p) | |
140 { | |
141 /* check file header */ | |
142 if (p->buf_size <= 32) | |
143 return 0; | |
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') | |
3233
e2bdb989f7da
Decrease returning probe score for WAV demuxer to avoid
voroshil
parents:
2771
diff
changeset
|
148 /* |
e2bdb989f7da
Decrease returning probe score for WAV demuxer to avoid
voroshil
parents:
2771
diff
changeset
|
149 Since ACT demuxer has standard WAV header at top of it's own, |
e2bdb989f7da
Decrease returning probe score for WAV demuxer to avoid
voroshil
parents:
2771
diff
changeset
|
150 returning score is decreased to avoid probe conflict |
e2bdb989f7da
Decrease returning probe score for WAV demuxer to avoid
voroshil
parents:
2771
diff
changeset
|
151 between ACT and WAV. |
e2bdb989f7da
Decrease returning probe score for WAV demuxer to avoid
voroshil
parents:
2771
diff
changeset
|
152 */ |
e2bdb989f7da
Decrease returning probe score for WAV demuxer to avoid
voroshil
parents:
2771
diff
changeset
|
153 return AVPROBE_SCORE_MAX - 1; |
0 | 154 else |
155 return 0; | |
156 } | |
157 | |
158 /* wav input */ | |
159 static int wav_read_header(AVFormatContext *s, | |
160 AVFormatParameters *ap) | |
161 { | |
162 int size; | |
163 unsigned int tag; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2545
diff
changeset
|
164 ByteIOContext *pb = s->pb; |
0 | 165 AVStream *st; |
1136
d65cd7c3573e
dont read over the end of a data chunk and at the end search for the next
michael
parents:
1122
diff
changeset
|
166 WAVContext *wav = s->priv_data; |
0 | 167 |
168 /* check RIFF header */ | |
169 tag = get_le32(pb); | |
170 | |
171 if (tag != MKTAG('R', 'I', 'F', 'F')) | |
172 return -1; | |
173 get_le32(pb); /* file size */ | |
174 tag = get_le32(pb); | |
175 if (tag != MKTAG('W', 'A', 'V', 'E')) | |
176 return -1; | |
885 | 177 |
0 | 178 /* parse fmt header */ |
179 size = find_tag(pb, MKTAG('f', 'm', 't', ' ')); | |
180 if (size < 0) | |
181 return -1; | |
182 st = av_new_stream(s, 0); | |
183 if (!st) | |
2273
7eb456c4ed8a
Replace all occurrences of AVERROR_NOMEM with AVERROR(ENOMEM).
takis
parents:
2023
diff
changeset
|
184 return AVERROR(ENOMEM); |
0 | 185 |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
817
diff
changeset
|
186 get_wav_header(pb, st->codec, size); |
2023 | 187 st->need_parsing = AVSTREAM_PARSE_FULL; |
567 | 188 |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
817
diff
changeset
|
189 av_set_pts_info(st, 64, 1, st->codec->sample_rate); |
567 | 190 |
0 | 191 size = find_tag(pb, MKTAG('d', 'a', 't', 'a')); |
192 if (size < 0) | |
193 return -1; | |
1136
d65cd7c3573e
dont read over the end of a data chunk and at the end search for the next
michael
parents:
1122
diff
changeset
|
194 wav->data_end= url_ftell(pb) + size; |
0 | 195 return 0; |
196 } | |
197 | |
198 #define MAX_SIZE 4096 | |
199 | |
200 static int wav_read_packet(AVFormatContext *s, | |
201 AVPacket *pkt) | |
202 { | |
1136
d65cd7c3573e
dont read over the end of a data chunk and at the end search for the next
michael
parents:
1122
diff
changeset
|
203 int ret, size, left; |
309 | 204 AVStream *st; |
1136
d65cd7c3573e
dont read over the end of a data chunk and at the end search for the next
michael
parents:
1122
diff
changeset
|
205 WAVContext *wav = s->priv_data; |
0 | 206 |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2545
diff
changeset
|
207 if (url_feof(s->pb)) |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2273
diff
changeset
|
208 return AVERROR(EIO); |
309 | 209 st = s->streams[0]; |
210 | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2545
diff
changeset
|
211 left= wav->data_end - url_ftell(s->pb); |
1136
d65cd7c3573e
dont read over the end of a data chunk and at the end search for the next
michael
parents:
1122
diff
changeset
|
212 if(left <= 0){ |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2545
diff
changeset
|
213 left = find_tag(s->pb, MKTAG('d', 'a', 't', 'a')); |
1136
d65cd7c3573e
dont read over the end of a data chunk and at the end search for the next
michael
parents:
1122
diff
changeset
|
214 if (left < 0) { |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2273
diff
changeset
|
215 return AVERROR(EIO); |
1136
d65cd7c3573e
dont read over the end of a data chunk and at the end search for the next
michael
parents:
1122
diff
changeset
|
216 } |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2545
diff
changeset
|
217 wav->data_end= url_ftell(s->pb) + left; |
1136
d65cd7c3573e
dont read over the end of a data chunk and at the end search for the next
michael
parents:
1122
diff
changeset
|
218 } |
d65cd7c3573e
dont read over the end of a data chunk and at the end search for the next
michael
parents:
1122
diff
changeset
|
219 |
309 | 220 size = MAX_SIZE; |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
817
diff
changeset
|
221 if (st->codec->block_align > 1) { |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
817
diff
changeset
|
222 if (size < st->codec->block_align) |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
817
diff
changeset
|
223 size = st->codec->block_align; |
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
817
diff
changeset
|
224 size = (size / st->codec->block_align) * st->codec->block_align; |
309 | 225 } |
1136
d65cd7c3573e
dont read over the end of a data chunk and at the end search for the next
michael
parents:
1122
diff
changeset
|
226 size= FFMIN(size, left); |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2545
diff
changeset
|
227 ret= av_get_packet(s->pb, pkt, size); |
1756 | 228 if (ret <= 0) |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2273
diff
changeset
|
229 return AVERROR(EIO); |
0 | 230 pkt->stream_index = 0; |
231 | |
232 /* note: we need to modify the packet size here to handle the last | |
233 packet */ | |
234 pkt->size = ret; | |
235 return ret; | |
236 } | |
237 | |
238 static int wav_read_close(AVFormatContext *s) | |
239 { | |
240 return 0; | |
241 } | |
242 | |
885 | 243 static int wav_read_seek(AVFormatContext *s, |
558 | 244 int stream_index, int64_t timestamp, int flags) |
309 | 245 { |
246 AVStream *st; | |
247 | |
248 st = s->streams[0]; | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
817
diff
changeset
|
249 switch(st->codec->codec_id) { |
309 | 250 case CODEC_ID_MP2: |
251 case CODEC_ID_MP3: | |
252 case CODEC_ID_AC3: | |
496
112057e05179
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
482
diff
changeset
|
253 case CODEC_ID_DTS: |
309 | 254 /* use generic seeking with dynamically generated indexes */ |
255 return -1; | |
256 default: | |
257 break; | |
258 } | |
558 | 259 return pcm_read_seek(s, stream_index, timestamp, flags); |
309 | 260 } |
261 | |
1169 | 262 #ifdef CONFIG_WAV_DEMUXER |
263 AVInputFormat wav_demuxer = { | |
0 | 264 "wav", |
265 "wav format", | |
1136
d65cd7c3573e
dont read over the end of a data chunk and at the end search for the next
michael
parents:
1122
diff
changeset
|
266 sizeof(WAVContext), |
0 | 267 wav_probe, |
268 wav_read_header, | |
269 wav_read_packet, | |
270 wav_read_close, | |
309 | 271 wav_read_seek, |
1756 | 272 .flags= AVFMT_GENERIC_INDEX, |
1679 | 273 .codec_tag= (const AVCodecTag*[]){codec_wav_tags, 0}, |
0 | 274 }; |
1169 | 275 #endif |
276 #ifdef CONFIG_WAV_MUXER | |
277 AVOutputFormat wav_muxer = { | |
0 | 278 "wav", |
279 "wav format", | |
280 "audio/x-wav", | |
281 "wav", | |
282 sizeof(WAVContext), | |
283 CODEC_ID_PCM_S16LE, | |
284 CODEC_ID_NONE, | |
285 wav_write_header, | |
286 wav_write_packet, | |
287 wav_write_trailer, | |
1679 | 288 .codec_tag= (const AVCodecTag*[]){codec_wav_tags, 0}, |
0 | 289 }; |
1169 | 290 #endif |