Browse code

avcodec/shorten: add support for AIFF packing, not bitexact

Also report unsupported packing.

Signed-off-by: Paul B Mahol <onemda@gmail.com>

Paul B Mahol authored on 2016/04/10 04:07:10
Showing 1 changed files
... ...
@@ -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;