/* * Interplay ACM decoder * * Copyright (c) 2004-2008 Marko Kreen * Copyright (c) 2008 Adam Gashlin * Copyright (c) 2015 Paul B Mahol * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "libavutil/intreadwrite.h" #define BITSTREAM_READER_LE #include "avcodec.h" #include "get_bits.h" #include "internal.h" static const int8_t map_1bit[] = { -1, +1 }; static const int8_t map_2bit_near[] = { -2, -1, +1, +2 }; static const int8_t map_2bit_far[] = { -3, -2, +2, +3 }; static const int8_t map_3bit[] = { -4, -3, -2, -1, +1, +2, +3, +4 }; static int mul_3x3 [3 * 3 * 3]; static int mul_3x5 [5 * 5 * 5]; static int mul_2x11[11 * 11]; typedef struct InterplayACMContext { GetBitContext gb; uint8_t *bitstream; int max_framesize; int bitstream_size; int bitstream_index; int level; int rows; int cols; int wrapbuf_len; int block_len; int skip; int *block; int *wrapbuf; int *ampbuf; int *midbuf; } InterplayACMContext; static av_cold int decode_init(AVCodecContext *avctx) { InterplayACMContext *s = avctx->priv_data; int x1, x2, x3; if (avctx->extradata_size < 14) return AVERROR_INVALIDDATA; if (avctx->channels <= 0) { av_log(avctx, AV_LOG_ERROR, "Invalid number of channels: %d\n", avctx->channels); return AVERROR_INVALIDDATA; } s->level = AV_RL16(avctx->extradata + 12) & 0xf; s->rows = AV_RL16(avctx->extradata + 12) >> 4; s->cols = 1 << s->level; s->wrapbuf_len = 2 * s->cols - 2; s->block_len = s->rows * s->cols; s->max_framesize = s->block_len; s->block = av_calloc(s->block_len, sizeof(int)); s->wrapbuf = av_calloc(s->wrapbuf_len, sizeof(int)); s->ampbuf = av_calloc(0x10000, sizeof(int)); s->bitstream = av_calloc(s->max_framesize, sizeof(*s->bitstream)); if (!s->block || !s->wrapbuf || !s->ampbuf || !s->bitstream) return AVERROR(ENOMEM); s->midbuf = s->ampbuf + 0x8000; avctx->sample_fmt = AV_SAMPLE_FMT_S16; for (x3 = 0; x3 < 3; x3++) for (x2 = 0; x2 < 3; x2++) for (x1 = 0; x1 < 3; x1++) mul_3x3[x1 + x2 * 3 + x3* 3 * 3] = x1 + (x2 << 4) + (x3 << 8); for (x3 = 0; x3 < 5; x3++) for (x2 = 0; x2 < 5; x2++) for (x1 = 0; x1 < 5; x1++) mul_3x5[x1 + x2 * 5 + x3 * 5 * 5] = x1 + (x2 << 4) + (x3 << 8); for (x2 = 0; x2 < 11; x2++) for (x1 = 0; x1 < 11; x1++) mul_2x11[x1 + x2 * 11] = x1 + (x2 << 4); return 0; } #define set_pos(s, r, c, idx) do { \ unsigned pos = ((r) << s->level) + (c); \ s->block[pos] = s->midbuf[(idx)]; \ } while (0) static int zero(InterplayACMContext *s, unsigned ind, unsigned col) { unsigned i; for (i = 0; i < s->rows; i++) set_pos(s, i, col, 0); return 0; } static int bad(InterplayACMContext *s, unsigned ind, unsigned col) { return AVERROR_INVALIDDATA; } static int linear(InterplayACMContext *s, unsigned ind, unsigned col) { GetBitContext *gb = &s->gb; unsigned int i; int b, middle = 1 << (ind - 1); for (i = 0; i < s->rows; i++) { b = get_bits(gb, ind); set_pos(s, i, col, b - middle); } return 0; } static int k13(InterplayACMContext *s, unsigned ind, unsigned col) { GetBitContext *gb = &s->gb; unsigned i, b; for (i = 0; i < s->rows; i++) { b = get_bits1(gb); if (b == 0) { set_pos(s, i++, col, 0); if (i >= s->rows) break; set_pos(s, i, col, 0); continue; } b = get_bits1(gb); if (b == 0) { set_pos(s, i, col, 0); continue; } b = get_bits1(gb); set_pos(s, i, col, map_1bit[b]); } return 0; } static int k12(InterplayACMContext *s, unsigned ind, unsigned col) { GetBitContext *gb = &s->gb; unsigned i, b; for (i = 0; i < s->rows; i++) { b = get_bits1(gb); if (b == 0) { set_pos(s, i, col, 0); continue; } b = get_bits1(gb); set_pos(s, i, col, map_1bit[b]); } return 0; } static int k24(InterplayACMContext *s, unsigned ind, unsigned col) { GetBitContext *gb = &s->gb; unsigned i, b; for (i = 0; i < s->rows; i++) { b = get_bits1(gb); if (b == 0) { set_pos(s, i++, col, 0); if (i >= s->rows) break; set_pos(s, i, col, 0); continue; } b = get_bits1(gb); if (b == 0) { set_pos(s, i, col, 0); continue; } b = get_bits(gb, 2); set_pos(s, i, col, map_2bit_near[b]); } return 0; } static int k23(InterplayACMContext *s, unsigned ind, unsigned col) { GetBitContext *gb = &s->gb; unsigned i, b; for (i = 0; i < s->rows; i++) { b = get_bits1(gb); if (b == 0) { set_pos(s, i, col, 0); continue; } b = get_bits(gb, 2); set_pos(s, i, col, map_2bit_near[b]); } return 0; } static int k35(InterplayACMContext *s, unsigned ind, unsigned col) { GetBitContext *gb = &s->gb; unsigned i, b; for (i = 0; i < s->rows; i++) { b = get_bits1(gb); if (b == 0) { set_pos(s, i++, col, 0); if (i >= s->rows) break; set_pos(s, i, col, 0); continue; } b = get_bits1(gb); if (b == 0) { set_pos(s, i, col, 0); continue; } b = get_bits1(gb); if (b == 0) { b = get_bits1(gb); set_pos(s, i, col, map_1bit[b]); continue; } b = get_bits(gb, 2); set_pos(s, i, col, map_2bit_far[b]); } return 0; } static int k34(InterplayACMContext *s, unsigned ind, unsigned col) { GetBitContext *gb = &s->gb; unsigned i, b; for (i = 0; i < s->rows; i++) { b = get_bits1(gb); if (b == 0) { set_pos(s, i, col, 0); continue; } b = get_bits1(gb); if (b == 0) { b = get_bits1(gb); set_pos(s, i, col, map_1bit[b]); continue; } b = get_bits(gb, 2); set_pos(s, i, col, map_2bit_far[b]); } return 0; } static int k45(InterplayACMContext *s, unsigned ind, unsigned col) { GetBitContext *gb = &s->gb; unsigned i, b; for (i = 0; i < s->rows; i++) { b = get_bits1(gb); if (b == 0) { set_pos(s, i, col, 0); i++; if (i >= s->rows) break; set_pos(s, i, col, 0); continue; } b = get_bits1(gb); if (b == 0) { set_pos(s, i, col, 0); continue; } b = get_bits(gb, 3); set_pos(s, i, col, map_3bit[b]); } return 0; } static int k44(InterplayACMContext *s, unsigned ind, unsigned col) { GetBitContext *gb = &s->gb; unsigned i, b; for (i = 0; i < s->rows; i++) { b = get_bits1(gb); if (b == 0) { set_pos(s, i, col, 0); continue; } b = get_bits(gb, 3); set_pos(s, i, col, map_3bit[b]); } return 0; } static int t15(InterplayACMContext *s, unsigned ind, unsigned col) { GetBitContext *gb = &s->gb; unsigned i, b; int n1, n2, n3; for (i = 0; i < s->rows; i++) { /* b = (x1) + (x2 * 3) + (x3 * 9) */ b = get_bits(gb, 5); if (b > 26) { av_log(NULL, AV_LOG_ERROR, "Too large b = %d > 26\n", b); return AVERROR_INVALIDDATA; } n1 = (mul_3x3[b] & 0x0F) - 1; n2 = ((mul_3x3[b] >> 4) & 0x0F) - 1; n3 = ((mul_3x3[b] >> 8) & 0x0F) - 1; set_pos(s, i++, col, n1); if (i >= s->rows) break; set_pos(s, i++, col, n2); if (i >= s->rows) break; set_pos(s, i, col, n3); } return 0; } static int t27(InterplayACMContext *s, unsigned ind, unsigned col) { GetBitContext *gb = &s->gb; unsigned i, b; int n1, n2, n3; for (i = 0; i < s->rows; i++) { /* b = (x1) + (x2 * 5) + (x3 * 25) */ b = get_bits(gb, 7); if (b > 124) { av_log(NULL, AV_LOG_ERROR, "Too large b = %d > 124\n", b); return AVERROR_INVALIDDATA; } n1 = (mul_3x5[b] & 0x0F) - 2; n2 = ((mul_3x5[b] >> 4) & 0x0F) - 2; n3 = ((mul_3x5[b] >> 8) & 0x0F) - 2; set_pos(s, i++, col, n1); if (i >= s->rows) break; set_pos(s, i++, col, n2); if (i >= s->rows) break; set_pos(s, i, col, n3); } return 0; } static int t37(InterplayACMContext *s, unsigned ind, unsigned col) { GetBitContext *gb = &s->gb; unsigned i, b; int n1, n2; for (i = 0; i < s->rows; i++) { /* b = (x1) + (x2 * 11) */ b = get_bits(gb, 7); if (b > 120) { av_log(NULL, AV_LOG_ERROR, "Too large b = %d > 120\n", b); return AVERROR_INVALIDDATA; } n1 = (mul_2x11[b] & 0x0F) - 5; n2 = ((mul_2x11[b] >> 4) & 0x0F) - 5; set_pos(s, i++, col, n1); if (i >= s->rows) break; set_pos(s, i, col, n2); } return 0; } typedef int (*filler)(InterplayACMContext *s, unsigned ind, unsigned col); static const filler filler_list[] = { zero, bad, bad, linear, linear, linear, linear, linear, linear, linear, linear, linear, linear, linear, linear, linear, linear, k13, k12, t15, k24, k23, t27, k35, k34, bad, k45, k44, bad, t37, bad, bad, }; static int fill_block(InterplayACMContext *s) { GetBitContext *gb = &s->gb; unsigned i, ind; int ret; for (i = 0; i < s->cols; i++) { ind = get_bits(gb, 5); ret = filler_list[ind](s, ind, i); if (ret < 0) return ret; } return 0; } static void juggle(int *wrap_p, int *block_p, unsigned sub_len, unsigned sub_count) { unsigned i, j; int *p, r0, r1, r2, r3; for (i = 0; i < sub_len; i++) { p = block_p; r0 = wrap_p[0]; r1 = wrap_p[1]; for (j = 0; j < sub_count/2; j++) { r2 = *p; *p = r1 * 2 + (r0 + r2); p += sub_len; r3 = *p; *p = r2 * 2 - (r1 + r3); p += sub_len; r0 = r2; r1 = r3; } *wrap_p++ = r0; *wrap_p++ = r1; block_p++; } } static void juggle_block(InterplayACMContext *s) { unsigned sub_count, sub_len, todo_count, step_subcount, i; int *wrap_p, *block_p, *p; /* juggle only if subblock_len > 1 */ if (s->level == 0) return; /* 2048 / subblock_len */ if (s->level > 9) step_subcount = 1; else step_subcount = (2048 >> s->level) - 2; /* Apply juggle() (rows)x(cols) * from (step_subcount * 2) x (subblock_len/2) * to (step_subcount * subblock_len) x (1) */ todo_count = s->rows; block_p = s->block; while (1) { wrap_p = s->wrapbuf; sub_count = step_subcount; if (sub_count > todo_count) sub_count = todo_count; sub_len = s->cols / 2; sub_count *= 2; juggle(wrap_p, block_p, sub_len, sub_count); wrap_p += sub_len * 2; for (i = 0, p = block_p; i < sub_count; i++) { p[0]++; p += sub_len; } while (sub_len > 1) { sub_len /= 2; sub_count *= 2; juggle(wrap_p, block_p, sub_len, sub_count); wrap_p += sub_len * 2; } if (todo_count <= step_subcount) break; todo_count -= step_subcount; block_p += step_subcount << s->level; } } static int decode_block(InterplayACMContext *s) { GetBitContext *gb = &s->gb; int pwr, count, val, i, x, ret; pwr = get_bits(gb, 4); val = get_bits(gb, 16); count = 1 << pwr; for (i = 0, x = 0; i < count; i++) { s->midbuf[i] = x; x += val; } for (i = 1, x = -val; i <= count; i++) { s->midbuf[-i] = x; x -= val; } ret = fill_block(s); if (ret < 0) return ret; juggle_block(s); return 0; } static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *pkt) { InterplayACMContext *s = avctx->priv_data; GetBitContext *gb = &s->gb; AVFrame *frame = data; const uint8_t *buf; int16_t *samples; int ret, n, buf_size, input_buf_size; if (!pkt->size && !s->bitstream_size) { *got_frame_ptr = 0; return 0; } buf_size = FFMIN(pkt->size, s->max_framesize - s->bitstream_size); input_buf_size = buf_size; if (s->bitstream_index + s->bitstream_size + buf_size > s->max_framesize) { memmove(s->bitstream, &s->bitstream[s->bitstream_index], s->bitstream_size); s->bitstream_index = 0; } if (pkt->data) memcpy(&s->bitstream[s->bitstream_index + s->bitstream_size], pkt->data, buf_size); buf = &s->bitstream[s->bitstream_index]; buf_size += s->bitstream_size; s->bitstream_size = buf_size; if (buf_size < s->max_framesize && pkt->data) { *got_frame_ptr = 0; return input_buf_size; } if ((ret = init_get_bits8(gb, buf, buf_size)) < 0) return ret; frame->nb_samples = s->block_len / avctx->channels; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; skip_bits(gb, s->skip); ret = decode_block(s); if (ret < 0) return ret; samples = (int16_t *)frame->data[0]; for (n = 0; n < frame->nb_samples * avctx->channels; n++) { int val = s->block[n] >> s->level; *samples++ = val; } *got_frame_ptr = 1; s->skip = get_bits_count(gb) - 8 * (get_bits_count(gb) / 8); n = get_bits_count(gb) / 8; if (n > buf_size && pkt->data) { s->bitstream_size = 0; s->bitstream_index = 0; return AVERROR_INVALIDDATA; } if (s->bitstream_size) { s->bitstream_index += n; s->bitstream_size -= n; return input_buf_size; } return n; } static av_cold int decode_close(AVCodecContext *avctx) { InterplayACMContext *s = avctx->priv_data; av_freep(&s->block); av_freep(&s->wrapbuf); av_freep(&s->ampbuf); av_freep(&s->bitstream); s->bitstream_size = 0; return 0; } AVCodec ff_interplay_acm_decoder = { .name = "interplayacm", .long_name = NULL_IF_CONFIG_SMALL("Interplay ACM"), .type = AVMEDIA_TYPE_AUDIO, .id = AV_CODEC_ID_INTERPLAY_ACM, .init = decode_init, .close = decode_close, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, .priv_data_size = sizeof(InterplayACMContext), };