diff --git a/Changelog b/Changelog index 358662bfed..898a2473e8 100644 --- a/Changelog +++ b/Changelog @@ -23,6 +23,8 @@ version : - audio mix filter - avprobe output is now standard INI or JSON. The old format can still be used with -of old. +- Indeo Audio decoder + version 0.8: diff --git a/doc/general.texi b/doc/general.texi index 680b971bc7..dee8f9e096 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -706,6 +706,7 @@ following image formats are supported: @tab encoding supported through external library libgsm @item GSM Microsoft variant @tab E @tab X @tab encoding supported through external library libgsm +@item IAC (Indeo Audio Coder) @tab @tab X @item IMC (Intel Music Coder) @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 diff --git a/libavcodec/Makefile b/libavcodec/Makefile index da8aa8ac20..3bfd78bc63 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -197,6 +197,7 @@ OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o OBJS-$(CONFIG_H264_VDA_HWACCEL) += vda_h264.o OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o +OBJS-$(CONFIG_IAC_DECODER) += imc.o OBJS-$(CONFIG_IDCIN_DECODER) += idcinvideo.o OBJS-$(CONFIG_IFF_BYTERUN1_DECODER) += iff.o OBJS-$(CONFIG_IFF_ILBM_DECODER) += iff.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index a1df47af69..01d13d5348 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -260,6 +260,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (FLAC, flac); REGISTER_DECODER (GSM, gsm); REGISTER_DECODER (GSM_MS, gsm_ms); + REGISTER_DECODER (IAC, iac); REGISTER_DECODER (IMC, imc); REGISTER_DECODER (MACE3, mace3); REGISTER_DECODER (MACE6, mace6); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 102df3a7a0..4a07d6dd57 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -393,6 +393,7 @@ enum CodecID { CODEC_ID_8SVX_FIB, CODEC_ID_BMV_AUDIO, CODEC_ID_RALF, + CODEC_ID_IAC, /* subtitle codecs */ CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. diff --git a/libavcodec/imc.c b/libavcodec/imc.c index 4b8ad7c536..3856f4a851 100644 --- a/libavcodec/imc.c +++ b/libavcodec/imc.c @@ -79,7 +79,7 @@ typedef struct IMCChannel { typedef struct { AVFrame frame; - IMCChannel chctx[1]; + IMCChannel chctx[2]; /** MDCT tables */ //@{ @@ -98,6 +98,9 @@ typedef struct { FFTContext fft; DECLARE_ALIGNED(32, FFTComplex, samples)[COEFFS / 2]; float *out_samples; + + int8_t cyclTab[32], cyclTab2[32]; + float weights1[31], weights2[31]; } IMCContext; static VLC huffman_vlc[4][4]; @@ -117,7 +120,8 @@ static av_cold int imc_decode_init(AVCodecContext *avctx) IMCContext *q = avctx->priv_data; double r1, r2; - if (avctx->channels != 1) { + if ((avctx->codec_id == CODEC_ID_IMC && avctx->channels != 1) + || (avctx->codec_id == CODEC_ID_IAC && avctx->channels > 2)) { av_log_ask_for_sample(avctx, "Number of channels is not supported\n"); return AVERROR_PATCHWELCOME; } @@ -169,6 +173,18 @@ static av_cold int imc_decode_init(AVCodecContext *avctx) } q->one_div_log2 = 1 / log(2); + memcpy(q->cyclTab, cyclTab, sizeof(cyclTab)); + memcpy(q->cyclTab2, cyclTab2, sizeof(cyclTab2)); + if (avctx->codec_id == CODEC_ID_IAC) { + q->cyclTab[29] = 31; + q->cyclTab2[31] = 28; + memcpy(q->weights1, iac_weights1, sizeof(iac_weights1)); + memcpy(q->weights2, iac_weights2, sizeof(iac_weights2)); + } else { + memcpy(q->weights1, imc_weights1, sizeof(imc_weights1)); + memcpy(q->weights2, imc_weights2, sizeof(imc_weights2)); + } + if ((ret = ff_fft_init(&q->fft, 7, 1))) { av_log(avctx, AV_LOG_INFO, "FFT init failed\n"); return ret; @@ -210,13 +226,13 @@ static void imc_calculate_coeffs(IMCContext *q, float *flcoeffs1, } for (i = 0; i < BANDS; i++) { - for (cnt2 = i; cnt2 < cyclTab[i]; cnt2++) + for (cnt2 = i; cnt2 < q->cyclTab[i]; cnt2++) flcoeffs5[cnt2] = flcoeffs5[cnt2] + workT3[i]; workT2[cnt2 - 1] = workT2[cnt2 - 1] + workT3[i]; } for (i = 1; i < BANDS; i++) { - accum = (workT2[i - 1] + accum) * imc_weights1[i - 1]; + accum = (workT2[i - 1] + accum) * q->weights1[i - 1]; flcoeffs5[i] += accum; } @@ -224,7 +240,7 @@ static void imc_calculate_coeffs(IMCContext *q, float *flcoeffs1, workT2[i] = 0.0; for (i = 0; i < BANDS; i++) { - for (cnt2 = i - 1; cnt2 > cyclTab2[i]; cnt2--) + for (cnt2 = i - 1; cnt2 > q->cyclTab2[i]; cnt2--) flcoeffs5[cnt2] += workT3[i]; workT2[cnt2+1] += workT3[i]; } @@ -232,7 +248,7 @@ static void imc_calculate_coeffs(IMCContext *q, float *flcoeffs1, accum = 0.0; for (i = BANDS-2; i >= 0; i--) { - accum = (workT2[i+1] + accum) * imc_weights2[i]; + accum = (workT2[i+1] + accum) * q->weights2[i]; flcoeffs5[i] += accum; // there is missing code here, but it seems to never be triggered } @@ -701,16 +717,17 @@ static int imc_decode_block(AVCodecContext *avctx, IMCContext *q, int ch) /* Check the frame header */ imc_hdr = get_bits(&q->gb, 9); - if (imc_hdr != IMC_FRAME_ID) { - av_log(avctx, AV_LOG_ERROR, "imc frame header check failed!\n"); - av_log(avctx, AV_LOG_ERROR, "got %x instead of 0x21.\n", imc_hdr); + if (imc_hdr & 0x18) { + av_log(avctx, AV_LOG_ERROR, "frame header check failed!\n"); + av_log(avctx, AV_LOG_ERROR, "got %X.\n", imc_hdr); return AVERROR_INVALIDDATA; } stream_format_code = get_bits(&q->gb, 3); if (stream_format_code & 1) { - av_log(avctx, AV_LOG_ERROR, "Stream code format %X is not supported\n", stream_format_code); - return AVERROR_INVALIDDATA; + av_log_ask_for_sample(avctx, "Stream format %X is not supported\n", + stream_format_code); + return AVERROR_PATCHWELCOME; } // av_log(avctx, AV_LOG_DEBUG, "stream_format_code = %d\n", stream_format_code); @@ -773,6 +790,11 @@ static int imc_decode_block(AVCodecContext *avctx, IMCContext *q, int ch) } } } + if (avctx->codec_id == CODEC_ID_IAC) { + bitscount += !!chctx->bandWidthT[BANDS - 1]; + if (!(stream_format_code & 0x2)) + bitscount += 16; + } if ((ret = bit_allocation(q, chctx, stream_format_code, 512 - bitscount - get_bits_count(&q->gb), @@ -860,8 +882,8 @@ static int imc_decode_frame(AVCodecContext *avctx, void *data, LOCAL_ALIGNED_16(uint16_t, buf16, [IMC_BLOCK_SIZE / 2]); - if (buf_size < IMC_BLOCK_SIZE) { - av_log(avctx, AV_LOG_ERROR, "imc frame too small!\n"); + if (buf_size < IMC_BLOCK_SIZE * avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "frame too small!\n"); return AVERROR_INVALIDDATA; } @@ -885,6 +907,18 @@ static int imc_decode_frame(AVCodecContext *avctx, void *data, return ret; } + if (avctx->channels == 2) { + float *src = (float*)q->frame.data[0], t1, t2; + + for (i = 0; i < COEFFS; i++) { + t1 = src[0]; + t2 = src[1]; + src[0] = t1 + t2; + src[1] = t1 - t2; + src += 2; + } + } + *got_frame_ptr = 1; *(AVFrame *)data = q->frame; @@ -913,3 +947,15 @@ AVCodec ff_imc_decoder = { .capabilities = CODEC_CAP_DR1, .long_name = NULL_IF_CONFIG_SMALL("IMC (Intel Music Coder)"), }; + +AVCodec ff_iac_decoder = { + .name = "iac", + .type = AVMEDIA_TYPE_AUDIO, + .id = CODEC_ID_IAC, + .priv_data_size = sizeof(IMCContext), + .init = imc_decode_init, + .close = imc_decode_close, + .decode = imc_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("IAC (Indeo Audio Coder)"), +}; diff --git a/libavcodec/imcdata.h b/libavcodec/imcdata.h index 8e99391d61..ea9b3747fc 100644 --- a/libavcodec/imcdata.h +++ b/libavcodec/imcdata.h @@ -44,6 +44,25 @@ static const int8_t cyclTab2[32] = { 12, 13, 14, 15, 16, 17, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}; +static const float iac_weights1[31] = { + 0.0538585, 0.0576251, 0.0645592, 0.0494032, 0.0428915, 0.0592188, + 0.0604145, 0.0673549, 0.0797351, 0.0972911, 0.119376, 0.144777, + 0.17181, 0.198625, 0.242918, 0.262113, 0.278434, 0.310752, + 0.319978, 0.328482, 0.354631, 0.380212, 0.388783, 0.400428, + 0.43096, 0.462397, 0.479469, 0.499329, 0.534526, 0.568631, + 0.589218 +}; + +static const float iac_weights2[31] = { + 0.000375307, 0.000450455, 0.000612191, 0.000297262, 0.000202956, + 0.000484887, 0.000511777, 0.000686431, 0.00108256, 0.00185267, + 0.00321869, 0.00541861, 0.00860266, 0.012726, 0.0219151, + 0.0269104, 0.0316774, 0.0426107, 0.046113, 0.0494974, + 0.0608692, 0.0734633, 0.0780208, 0.0844921, 0.103034, + 0.124606, 0.137421, 0.153336, 0.184296, 0.217792, + 0.239742 +}; + static const float imc_weights1[31] = { 0.119595, 0.123124, 0.129192, 9.97377e-2, 8.1923e-2, 9.61153e-2, 8.77885e-2, 8.61174e-2, 9.00882e-2, 9.91658e-2, 0.112991, 0.131126, 0.152886, 0.177292, 0.221782, 0.244917, 0.267386, diff --git a/libavcodec/version.h b/libavcodec/version.h index da7796abb0..e8f0b5cb84 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -27,8 +27,8 @@ */ #define LIBAVCODEC_VERSION_MAJOR 54 -#define LIBAVCODEC_VERSION_MINOR 13 -#define LIBAVCODEC_VERSION_MICRO 1 +#define LIBAVCODEC_VERSION_MINOR 14 +#define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavformat/riff.c b/libavformat/riff.c index 8a913452a7..922a863a84 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -322,6 +322,7 @@ const AVCodecTag ff_codec_wav_tags[] = { { CODEC_ID_ATRAC3, 0x0270 }, { CODEC_ID_ADPCM_G722, 0x028F }, { CODEC_ID_IMC, 0x0401 }, + { CODEC_ID_IAC, 0x0402 }, { CODEC_ID_GSM_MS, 0x1500 }, { CODEC_ID_TRUESPEECH, 0x1501 }, { CODEC_ID_AAC, 0x1600 }, /* ADTS AAC */