Also report unsupported packing.
Signed-off-by: Paul B Mahol <onemda@gmail.com>
... | ... |
@@ -195,6 +195,70 @@ static int init_offset(ShortenContext *s) |
195 | 195 |
return 0; |
196 | 196 |
} |
197 | 197 |
|
198 |
+static int decode_aiff_header(AVCodecContext *avctx, const uint8_t *header, |
|
199 |
+ int header_size) |
|
200 |
+{ |
|
201 |
+ int len, bps, exp; |
|
202 |
+ GetByteContext gb; |
|
203 |
+ uint64_t val; |
|
204 |
+ uint32_t tag; |
|
205 |
+ |
|
206 |
+ bytestream2_init(&gb, header, header_size); |
|
207 |
+ |
|
208 |
+ if (bytestream2_get_le32(&gb) != MKTAG('F', 'O', 'R', 'M')) { |
|
209 |
+ av_log(avctx, AV_LOG_ERROR, "missing FORM tag\n"); |
|
210 |
+ return AVERROR_INVALIDDATA; |
|
211 |
+ } |
|
212 |
+ |
|
213 |
+ bytestream2_skip(&gb, 4); /* chunk size */ |
|
214 |
+ |
|
215 |
+ tag = bytestream2_get_le32(&gb); |
|
216 |
+ if (tag != MKTAG('A', 'I', 'F', 'F')) { |
|
217 |
+ av_log(avctx, AV_LOG_ERROR, "missing AIFF tag\n"); |
|
218 |
+ return AVERROR_INVALIDDATA; |
|
219 |
+ } |
|
220 |
+ |
|
221 |
+ while (bytestream2_get_le32(&gb) != MKTAG('C', 'O', 'M', 'M')) { |
|
222 |
+ len = bytestream2_get_be32(&gb); |
|
223 |
+ bytestream2_skip(&gb, len + (len & 1)); |
|
224 |
+ if (len < 0 || bytestream2_get_bytes_left(&gb) < 18) { |
|
225 |
+ av_log(avctx, AV_LOG_ERROR, "no COMM chunk found\n"); |
|
226 |
+ return AVERROR_INVALIDDATA; |
|
227 |
+ } |
|
228 |
+ } |
|
229 |
+ len = bytestream2_get_be32(&gb); |
|
230 |
+ |
|
231 |
+ if (len < 18) { |
|
232 |
+ av_log(avctx, AV_LOG_ERROR, "COMM chunk was too short\n"); |
|
233 |
+ return AVERROR_INVALIDDATA; |
|
234 |
+ } |
|
235 |
+ |
|
236 |
+ bytestream2_skip(&gb, 6); |
|
237 |
+ bps = bytestream2_get_be16(&gb); |
|
238 |
+ avctx->bits_per_coded_sample = bps; |
|
239 |
+ |
|
240 |
+ if (bps != 16 && bps != 8) { |
|
241 |
+ av_log(avctx, AV_LOG_ERROR, "unsupported number of bits per sample: %d\n", bps); |
|
242 |
+ return AVERROR(ENOSYS); |
|
243 |
+ } |
|
244 |
+ |
|
245 |
+ exp = bytestream2_get_be16(&gb) - 16383 - 63; |
|
246 |
+ val = bytestream2_get_be64(&gb); |
|
247 |
+ if (exp < -63 || exp > 63) { |
|
248 |
+ av_log(avctx, AV_LOG_ERROR, "exp %d is out of range\n", exp); |
|
249 |
+ return AVERROR_INVALIDDATA; |
|
250 |
+ } |
|
251 |
+ if (exp >= 0) |
|
252 |
+ avctx->sample_rate = val << exp; |
|
253 |
+ else |
|
254 |
+ avctx->sample_rate = (val + (1ULL<<(-exp-1))) >> -exp; |
|
255 |
+ len -= 18; |
|
256 |
+ if (len > 0) |
|
257 |
+ av_log(avctx, AV_LOG_INFO, "%d header bytes unparsed\n", len); |
|
258 |
+ |
|
259 |
+ return 0; |
|
260 |
+} |
|
261 |
+ |
|
198 | 262 |
static int decode_wave_header(AVCodecContext *avctx, const uint8_t *header, |
199 | 263 |
int header_size) |
200 | 264 |
{ |
... | ... |
@@ -407,8 +471,16 @@ static int read_header(ShortenContext *s) |
407 | 407 |
for (i = 0; i < s->header_size; i++) |
408 | 408 |
s->header[i] = (char)get_ur_golomb_shorten(&s->gb, VERBATIM_BYTE_SIZE); |
409 | 409 |
|
410 |
- if ((ret = decode_wave_header(s->avctx, s->header, s->header_size)) < 0) |
|
411 |
- return ret; |
|
410 |
+ if (AV_RL32(s->header) == MKTAG('R','I','F','F')) { |
|
411 |
+ if ((ret = decode_wave_header(s->avctx, s->header, s->header_size)) < 0) |
|
412 |
+ return ret; |
|
413 |
+ } else if (AV_RL32(s->header) == MKTAG('F','O','R','M')) { |
|
414 |
+ if ((ret = decode_aiff_header(s->avctx, s->header, s->header_size)) < 0) |
|
415 |
+ return ret; |
|
416 |
+ } else { |
|
417 |
+ avpriv_report_missing_feature(s->avctx, "unsupported bit packing %X", AV_RL32(s->header)); |
|
418 |
+ return AVERROR_PATCHWELCOME; |
|
419 |
+ } |
|
412 | 420 |
|
413 | 421 |
end: |
414 | 422 |
s->cur_chan = 0; |