Mercurial > libavformat.hg
annotate wv.c @ 3754:8d267b43eaba libavformat
Move malloc() down until after all initializations, so that the resource is
only allocated if initialization worked. This means that on failure, we
don't have to deallocate it.
author | rbultje |
---|---|
date | Sat, 23 Aug 2008 18:46:30 +0000 |
parents | 17c0ce4cc314 |
children | 1d3d17de20ba |
rev | line source |
---|---|
1324 | 1 /* |
2 * WavPack demuxer | |
3 * Copyright (c) 2006 Konstantin Shishkov. | |
4 * | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1324
diff
changeset
|
5 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1324
diff
changeset
|
6 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1324
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
1324 | 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:
1324
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
1324 | 11 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1324
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
1324 | 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:
1324
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
1324 | 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 */ | |
21 | |
3286 | 22 #include "libavutil/bswap.h" |
1324 | 23 #include "avformat.h" |
24 | |
25 // specs say that maximum block size is 1Mb | |
26 #define WV_BLOCK_LIMIT 1047576 | |
27 | |
28 #define WV_EXTRA_SIZE 12 | |
29 | |
30 enum WV_FLAGS{ | |
31 WV_MONO = 0x0004, | |
32 WV_HYBRID = 0x0008, | |
33 WV_JOINT = 0x0010, | |
34 WV_CROSSD = 0x0020, | |
35 WV_HSHAPE = 0x0040, | |
36 WV_FLOAT = 0x0080, | |
37 WV_INT32 = 0x0100, | |
38 WV_HBR = 0x0200, | |
39 WV_HBAL = 0x0400, | |
40 WV_MCINIT = 0x0800, | |
41 WV_MCEND = 0x1000, | |
42 }; | |
43 | |
44 static const int wv_rates[16] = { | |
45 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000, | |
46 32000, 44100, 48000, 64000, 88200, 96000, 192000, -1 | |
47 }; | |
48 | |
49 typedef struct{ | |
50 uint32_t blksize, flags; | |
51 int rate, chan, bpp; | |
1743 | 52 uint32_t samples, soff; |
1324 | 53 int block_parsed; |
54 uint8_t extra[WV_EXTRA_SIZE]; | |
1743 | 55 int64_t pos; |
1324 | 56 }WVContext; |
57 | |
58 static int wv_probe(AVProbeData *p) | |
59 { | |
60 /* check file header */ | |
61 if (p->buf_size <= 32) | |
62 return 0; | |
63 if (p->buf[0] == 'w' && p->buf[1] == 'v' && | |
64 p->buf[2] == 'p' && p->buf[3] == 'k') | |
65 return AVPROBE_SCORE_MAX; | |
66 else | |
67 return 0; | |
68 } | |
69 | |
70 static int wv_read_block_header(AVFormatContext *ctx, ByteIOContext *pb) | |
71 { | |
72 WVContext *wc = ctx->priv_data; | |
73 uint32_t tag, ver; | |
74 int size; | |
75 int rate, bpp, chan; | |
76 | |
1743 | 77 wc->pos = url_ftell(pb); |
1324 | 78 tag = get_le32(pb); |
79 if (tag != MKTAG('w', 'v', 'p', 'k')) | |
80 return -1; | |
81 size = get_le32(pb); | |
82 if(size < 24 || size > WV_BLOCK_LIMIT){ | |
83 av_log(ctx, AV_LOG_ERROR, "Incorrect block size %i\n", size); | |
84 return -1; | |
85 } | |
86 wc->blksize = size; | |
87 ver = get_le16(pb); | |
2380
41c9871ea3c4
Support for WavPack version 0x410 (false stereo chunks)
kostya
parents:
2314
diff
changeset
|
88 if(ver < 0x402 || ver > 0x410){ |
1324 | 89 av_log(ctx, AV_LOG_ERROR, "Unsupported version %03X\n", ver); |
90 return -1; | |
91 } | |
92 get_byte(pb); // track no | |
93 get_byte(pb); // track sub index | |
1743 | 94 wc->samples = get_le32(pb); // total samples in file |
95 wc->soff = get_le32(pb); // offset in samples of current block | |
1324 | 96 get_buffer(pb, wc->extra, WV_EXTRA_SIZE); |
1673 | 97 wc->flags = AV_RL32(wc->extra + 4); |
1324 | 98 //parse flags |
99 if(wc->flags & WV_FLOAT){ | |
100 av_log(ctx, AV_LOG_ERROR, "Floating point data is not supported\n"); | |
101 return -1; | |
102 } | |
103 if(wc->flags & WV_HYBRID){ | |
104 av_log(ctx, AV_LOG_ERROR, "Hybrid coding mode is not supported\n"); | |
105 return -1; | |
106 } | |
107 | |
108 bpp = ((wc->flags & 3) + 1) << 3; | |
109 chan = 1 + !(wc->flags & WV_MONO); | |
110 rate = wv_rates[(wc->flags >> 23) & 0xF]; | |
111 if(rate == -1){ | |
112 av_log(ctx, AV_LOG_ERROR, "Unknown sampling rate\n"); | |
113 return -1; | |
114 } | |
115 if(!wc->bpp) wc->bpp = bpp; | |
116 if(!wc->chan) wc->chan = chan; | |
117 if(!wc->rate) wc->rate = rate; | |
118 | |
1389
9ed80abc8eb7
Ignore blocks with no samples and flags (but usually with MD5 sum)
kostya
parents:
1387
diff
changeset
|
119 if(wc->flags && bpp != wc->bpp){ |
1324 | 120 av_log(ctx, AV_LOG_ERROR, "Bits per sample differ, this block: %i, header block: %i\n", bpp, wc->bpp); |
121 return -1; | |
122 } | |
1389
9ed80abc8eb7
Ignore blocks with no samples and flags (but usually with MD5 sum)
kostya
parents:
1387
diff
changeset
|
123 if(wc->flags && chan != wc->chan){ |
1324 | 124 av_log(ctx, AV_LOG_ERROR, "Channels differ, this block: %i, header block: %i\n", chan, wc->chan); |
125 return -1; | |
126 } | |
1389
9ed80abc8eb7
Ignore blocks with no samples and flags (but usually with MD5 sum)
kostya
parents:
1387
diff
changeset
|
127 if(wc->flags && rate != wc->rate){ |
1324 | 128 av_log(ctx, AV_LOG_ERROR, "Sampling rate differ, this block: %i, header block: %i\n", rate, wc->rate); |
129 return -1; | |
130 } | |
131 wc->blksize = size - 24; | |
132 return 0; | |
133 } | |
134 | |
135 static int wv_read_header(AVFormatContext *s, | |
136 AVFormatParameters *ap) | |
137 { | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2555
diff
changeset
|
138 ByteIOContext *pb = s->pb; |
1324 | 139 WVContext *wc = s->priv_data; |
140 AVStream *st; | |
141 | |
142 if(wv_read_block_header(s, pb) < 0) | |
143 return -1; | |
144 | |
145 wc->block_parsed = 0; | |
146 /* now we are ready: build format streams */ | |
147 st = av_new_stream(s, 0); | |
148 if (!st) | |
149 return -1; | |
150 st->codec->codec_type = CODEC_TYPE_AUDIO; | |
151 st->codec->codec_id = CODEC_ID_WAVPACK; | |
152 st->codec->channels = wc->chan; | |
153 st->codec->sample_rate = wc->rate; | |
154 st->codec->bits_per_sample = wc->bpp; | |
155 av_set_pts_info(st, 64, 1, wc->rate); | |
1743 | 156 s->start_time = 0; |
157 s->duration = (int64_t)wc->samples * AV_TIME_BASE / st->codec->sample_rate; | |
1324 | 158 return 0; |
159 } | |
160 | |
161 static int wv_read_packet(AVFormatContext *s, | |
162 AVPacket *pkt) | |
163 { | |
164 WVContext *wc = s->priv_data; | |
1391 | 165 int ret; |
1324 | 166 |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2555
diff
changeset
|
167 if (url_feof(s->pb)) |
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1743
diff
changeset
|
168 return AVERROR(EIO); |
1324 | 169 if(wc->block_parsed){ |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2555
diff
changeset
|
170 if(wv_read_block_header(s, s->pb) < 0) |
1324 | 171 return -1; |
172 } | |
173 | |
174 if(av_new_packet(pkt, wc->blksize + WV_EXTRA_SIZE) < 0) | |
2273
7eb456c4ed8a
Replace all occurrences of AVERROR_NOMEM with AVERROR(ENOMEM).
takis
parents:
1787
diff
changeset
|
175 return AVERROR(ENOMEM); |
1324 | 176 memcpy(pkt->data, wc->extra, WV_EXTRA_SIZE); |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2555
diff
changeset
|
177 ret = get_buffer(s->pb, pkt->data + WV_EXTRA_SIZE, wc->blksize); |
1324 | 178 if(ret != wc->blksize){ |
179 av_free_packet(pkt); | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2273
diff
changeset
|
180 return AVERROR(EIO); |
1324 | 181 } |
182 pkt->stream_index = 0; | |
183 wc->block_parsed = 1; | |
184 pkt->size = ret + WV_EXTRA_SIZE; | |
1743 | 185 pkt->pts = wc->soff; |
186 av_add_index_entry(s->streams[0], wc->pos, pkt->pts, 0, 0, AVINDEX_KEYFRAME); | |
1324 | 187 return 0; |
188 } | |
189 | |
1743 | 190 static int wv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) |
191 { | |
192 AVStream *st = s->streams[stream_index]; | |
193 WVContext *wc = s->priv_data; | |
194 AVPacket pkt1, *pkt = &pkt1; | |
195 int ret; | |
196 int index = av_index_search_timestamp(st, timestamp, flags); | |
197 int64_t pos, pts; | |
198 | |
199 /* if found, seek there */ | |
200 if (index >= 0){ | |
201 wc->block_parsed = 1; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2555
diff
changeset
|
202 url_fseek(s->pb, st->index_entries[index].pos, SEEK_SET); |
1743 | 203 return 0; |
204 } | |
205 /* if timestamp is out of bounds, return error */ | |
206 if(timestamp < 0 || timestamp >= s->duration) | |
207 return -1; | |
208 | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2555
diff
changeset
|
209 pos = url_ftell(s->pb); |
1743 | 210 do{ |
211 ret = av_read_frame(s, pkt); | |
212 if (ret < 0){ | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2555
diff
changeset
|
213 url_fseek(s->pb, pos, SEEK_SET); |
1743 | 214 return -1; |
215 } | |
216 pts = pkt->pts; | |
217 av_free_packet(pkt); | |
218 }while(pts < timestamp); | |
219 return 0; | |
220 } | |
221 | |
1324 | 222 AVInputFormat wv_demuxer = { |
223 "wv", | |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3286
diff
changeset
|
224 NULL_IF_CONFIG_SMALL("WavPack"), |
1324 | 225 sizeof(WVContext), |
226 wv_probe, | |
227 wv_read_header, | |
228 wv_read_packet, | |
3482 | 229 NULL, |
1743 | 230 wv_read_seek, |
1324 | 231 }; |