mirror of https://git.ffmpeg.org/ffmpeg.git
avcodec: add Interplay ACM decoder
Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
parent
4746653466
commit
c89e075d5a
|
@ -989,6 +989,7 @@ following image formats are supported:
|
||||||
@item iLBC (Internet Low Bitrate Codec) @tab E @tab E
|
@item iLBC (Internet Low Bitrate Codec) @tab E @tab E
|
||||||
@tab encoding and decoding supported through external library libilbc
|
@tab encoding and decoding supported through external library libilbc
|
||||||
@item IMC (Intel Music Coder) @tab @tab X
|
@item IMC (Intel Music Coder) @tab @tab X
|
||||||
|
@item Interplay ACM @tab @tab X
|
||||||
@item MACE (Macintosh Audio Compression/Expansion) 3:1 @tab @tab X
|
@item MACE (Macintosh Audio Compression/Expansion) 3:1 @tab @tab X
|
||||||
@item MACE (Macintosh Audio Compression/Expansion) 6:1 @tab @tab X
|
@item MACE (Macintosh Audio Compression/Expansion) 6:1 @tab @tab X
|
||||||
@item MLP (Meridian Lossless Packing) @tab @tab X
|
@item MLP (Meridian Lossless Packing) @tab @tab X
|
||||||
|
|
|
@ -320,6 +320,7 @@ OBJS-$(CONFIG_INDEO2_DECODER) += indeo2.o
|
||||||
OBJS-$(CONFIG_INDEO3_DECODER) += indeo3.o
|
OBJS-$(CONFIG_INDEO3_DECODER) += indeo3.o
|
||||||
OBJS-$(CONFIG_INDEO4_DECODER) += indeo4.o ivi.o
|
OBJS-$(CONFIG_INDEO4_DECODER) += indeo4.o ivi.o
|
||||||
OBJS-$(CONFIG_INDEO5_DECODER) += indeo5.o ivi.o
|
OBJS-$(CONFIG_INDEO5_DECODER) += indeo5.o ivi.o
|
||||||
|
OBJS-$(CONFIG_INTERPLAY_ACM_DECODER) += interplayacm.o
|
||||||
OBJS-$(CONFIG_INTERPLAY_DPCM_DECODER) += dpcm.o
|
OBJS-$(CONFIG_INTERPLAY_DPCM_DECODER) += dpcm.o
|
||||||
OBJS-$(CONFIG_INTERPLAY_VIDEO_DECODER) += interplayvideo.o
|
OBJS-$(CONFIG_INTERPLAY_VIDEO_DECODER) += interplayvideo.o
|
||||||
OBJS-$(CONFIG_JACOSUB_DECODER) += jacosubdec.o ass.o
|
OBJS-$(CONFIG_JACOSUB_DECODER) += jacosubdec.o ass.o
|
||||||
|
|
|
@ -399,6 +399,7 @@ void avcodec_register_all(void)
|
||||||
REGISTER_DECODER(GSM_MS, gsm_ms);
|
REGISTER_DECODER(GSM_MS, gsm_ms);
|
||||||
REGISTER_DECODER(IAC, iac);
|
REGISTER_DECODER(IAC, iac);
|
||||||
REGISTER_DECODER(IMC, imc);
|
REGISTER_DECODER(IMC, imc);
|
||||||
|
REGISTER_DECODER(INTERPLAY_ACM, interplay_acm);
|
||||||
REGISTER_DECODER(MACE3, mace3);
|
REGISTER_DECODER(MACE3, mace3);
|
||||||
REGISTER_DECODER(MACE6, mace6);
|
REGISTER_DECODER(MACE6, mace6);
|
||||||
REGISTER_DECODER(METASOUND, metasound);
|
REGISTER_DECODER(METASOUND, metasound);
|
||||||
|
|
|
@ -496,6 +496,7 @@ enum AVCodecID {
|
||||||
AV_CODEC_ID_DSD_LSBF_PLANAR,
|
AV_CODEC_ID_DSD_LSBF_PLANAR,
|
||||||
AV_CODEC_ID_DSD_MSBF_PLANAR,
|
AV_CODEC_ID_DSD_MSBF_PLANAR,
|
||||||
AV_CODEC_ID_4GV,
|
AV_CODEC_ID_4GV,
|
||||||
|
AV_CODEC_ID_INTERPLAY_ACM,
|
||||||
|
|
||||||
/* subtitle codecs */
|
/* subtitle codecs */
|
||||||
AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs.
|
AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs.
|
||||||
|
|
|
@ -2622,6 +2622,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||||
.long_name = NULL_IF_CONFIG_SMALL("DSD (Direct Stream Digital), most significant bit first, planar"),
|
.long_name = NULL_IF_CONFIG_SMALL("DSD (Direct Stream Digital), most significant bit first, planar"),
|
||||||
.props = AV_CODEC_PROP_LOSSY,
|
.props = AV_CODEC_PROP_LOSSY,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.id = AV_CODEC_ID_INTERPLAY_ACM,
|
||||||
|
.type = AVMEDIA_TYPE_AUDIO,
|
||||||
|
.name = "interplayacm",
|
||||||
|
.long_name = NULL_IF_CONFIG_SMALL("Interplay ACM"),
|
||||||
|
.props = AV_CODEC_PROP_LOSSY,
|
||||||
|
},
|
||||||
|
|
||||||
/* subtitle codecs */
|
/* subtitle codecs */
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,615 @@
|
||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
#include "avcodec.h"
|
||||||
|
#define BITSTREAM_READER_LE
|
||||||
|
#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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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),
|
||||||
|
};
|
|
@ -29,8 +29,8 @@
|
||||||
#include "libavutil/version.h"
|
#include "libavutil/version.h"
|
||||||
|
|
||||||
#define LIBAVCODEC_VERSION_MAJOR 57
|
#define LIBAVCODEC_VERSION_MAJOR 57
|
||||||
#define LIBAVCODEC_VERSION_MINOR 13
|
#define LIBAVCODEC_VERSION_MINOR 14
|
||||||
#define LIBAVCODEC_VERSION_MICRO 102
|
#define LIBAVCODEC_VERSION_MICRO 100
|
||||||
|
|
||||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||||
LIBAVCODEC_VERSION_MINOR, \
|
LIBAVCODEC_VERSION_MINOR, \
|
||||||
|
|
Loading…
Reference in New Issue