From 551fcbbccbca8e78443c049421f01f350d4bc370 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Mon, 16 Sep 2019 20:57:53 +0200 Subject: [PATCH] lavc/g729dec: Support decoding Sipro ACELP.KELVIN. Fixes ticket #4799. Analyzed-by: Aleksandr Ustinov --- Changelog | 1 + doc/general.texi | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/codec_desc.c | 6 ++++++ libavcodec/g729_parser.c | 5 +++-- libavcodec/g729dec.c | 21 +++++++++++++++++++-- libavcodec/version.h | 4 ++-- libavformat/riff.c | 1 + 10 files changed, 36 insertions(+), 6 deletions(-) diff --git a/Changelog b/Changelog index 4b29e015a0..08b7464cb1 100644 --- a/Changelog +++ b/Changelog @@ -9,6 +9,7 @@ version : - Supoort AMD AMF encoder on Linux (via Vulkan) - IMM5 video decoder - ZeroMQ protocol +- support Sipro ACELP.KELVIN decoding version 4.2: diff --git a/doc/general.texi b/doc/general.texi index 2744c238cf..79a23e1718 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -1067,6 +1067,7 @@ following image formats are supported: @item AAC+ @tab E @tab IX @tab encoding supported through external library libfdk-aac @item AC-3 @tab IX @tab IX +@item ACELP.KELVIN @tab @tab X @item ADPCM 4X Movie @tab @tab X @item APDCM Yamaha AICA @tab @tab X @item ADPCM CDROM XA @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 6bc4383c8f..37a84a6bb4 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -173,6 +173,7 @@ OBJS-$(CONFIG_AC3_FIXED_DECODER) += ac3dec_fixed.o ac3dec_data.o ac3.o kbd OBJS-$(CONFIG_AC3_ENCODER) += ac3enc_float.o ac3enc.o ac3tab.o \ ac3.o kbdwin.o OBJS-$(CONFIG_AC3_FIXED_ENCODER) += ac3enc_fixed.o ac3enc.o ac3tab.o ac3.o +OBJS-$(CONFIG_ACELP_KELVIN_DECODER) += g729dec.o lsp.o celp_math.o celp_filters.o acelp_filters.o acelp_pitch_delay.o acelp_vectors.o g729postfilter.o OBJS-$(CONFIG_AGM_DECODER) += agm.o OBJS-$(CONFIG_AIC_DECODER) += aic.o OBJS-$(CONFIG_ALAC_DECODER) += alac.o alac_data.o alacdsp.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index d5dfba1877..41f680101f 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -388,6 +388,7 @@ extern AVCodec ff_ac3_encoder; extern AVCodec ff_ac3_decoder; extern AVCodec ff_ac3_fixed_encoder; extern AVCodec ff_ac3_fixed_decoder; +extern AVCodec ff_acelp_kelvin_decoder; extern AVCodec ff_alac_encoder; extern AVCodec ff_alac_decoder; extern AVCodec ff_als_decoder; diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index de4feb6a65..0ec3e73865 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -653,6 +653,7 @@ enum AVCodecID { AV_CODEC_ID_SBC, AV_CODEC_ID_ATRAC9, AV_CODEC_ID_HCOM, + AV_CODEC_ID_ACELP_KELVIN, /* subtitle codecs */ AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index e6373be504..d2c6863d3c 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -2992,6 +2992,12 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("HCOM Audio"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_ACELP_KELVIN, + .name = "acelp.kelvin", + .long_name = NULL_IF_CONFIG_SMALL("Sipro ACELP.KELVIN"), + .props = AV_CODEC_PROP_LOSSY, + }, /* subtitle codecs */ { diff --git a/libavcodec/g729_parser.c b/libavcodec/g729_parser.c index 9982dbfffc..5a57025d62 100644 --- a/libavcodec/g729_parser.c +++ b/libavcodec/g729_parser.c @@ -45,9 +45,10 @@ static int g729_parse(AVCodecParserContext *s1, AVCodecContext *avctx, int next; if (!s->block_size) { - av_assert1(avctx->codec_id == AV_CODEC_ID_G729); /* FIXME: replace this heuristic block_size with more precise estimate */ s->block_size = (avctx->bit_rate < 8000) ? G729D_6K4_BLOCK_SIZE : G729_8K_BLOCK_SIZE; + if (avctx->codec_id == AV_CODEC_ID_ACELP_KELVIN) + s->block_size++; s->block_size *= avctx->channels; s->duration = avctx->frame_size; } @@ -76,7 +77,7 @@ static int g729_parse(AVCodecParserContext *s1, AVCodecContext *avctx, } AVCodecParser ff_g729_parser = { - .codec_ids = { AV_CODEC_ID_G729 }, + .codec_ids = { AV_CODEC_ID_G729, AV_CODEC_ID_ACELP_KELVIN }, .priv_data_size = sizeof(G729ParseContext), .parser_parse = g729_parse, .parser_close = ff_parse_close, diff --git a/libavcodec/g729dec.c b/libavcodec/g729dec.c index 2e4756b805..25951716ef 100644 --- a/libavcodec/g729dec.c +++ b/libavcodec/g729dec.c @@ -424,7 +424,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - if (buf_size % (G729_8K_BLOCK_SIZE * avctx->channels) == 0) { + if (buf_size % ((G729_8K_BLOCK_SIZE + (avctx->codec_id == AV_CODEC_ID_ACELP_KELVIN)) * avctx->channels) == 0) { packet_type = FORMAT_G729_8K; format = &format_g729_8k; //Reset voice decision @@ -445,6 +445,11 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, int bad_pitch = 0; ///< parity check failed int is_periodic = 0; ///< whether one of the subframes is declared as periodic or not out_frame = (int16_t*)frame->data[c]; + if (avctx->codec_id == AV_CODEC_ID_ACELP_KELVIN) { + if (*buf != ((avctx->channels - 1 - c) * 0x80 | 2)) + avpriv_request_sample(avctx, "First byte value %x for channel %d", *buf, c); + buf++; + } for (i = 0; i < buf_size; i++) frame_erasure |= buf[i]; @@ -727,7 +732,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, } *got_frame_ptr = 1; - return packet_type == FORMAT_G729_8K ? G729_8K_BLOCK_SIZE * avctx->channels : G729D_6K4_BLOCK_SIZE * avctx->channels; + return packet_type == FORMAT_G729_8K ? (G729_8K_BLOCK_SIZE + (avctx->codec_id == AV_CODEC_ID_ACELP_KELVIN)) * avctx->channels : G729D_6K4_BLOCK_SIZE * avctx->channels; } static av_cold int decode_close(AVCodecContext *avctx) @@ -749,3 +754,15 @@ AVCodec ff_g729_decoder = { .close = decode_close, .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, }; + +AVCodec ff_acelp_kelvin_decoder = { + .name = "acelp.kelvin", + .long_name = NULL_IF_CONFIG_SMALL("Sipro ACELP.KELVIN"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_ACELP_KELVIN, + .priv_data_size = sizeof(G729Context), + .init = decoder_init, + .decode = decode_frame, + .close = decode_close, + .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 5748d31051..c7a2bd0bdc 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 56 -#define LIBAVCODEC_VERSION_MICRO 102 +#define LIBAVCODEC_VERSION_MINOR 57 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavformat/riff.c b/libavformat/riff.c index f2c04f8d95..048a79e394 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -540,6 +540,7 @@ const AVCodecTag ff_codec_wav_tags[] = { { AV_CODEC_ID_AAC, 0x00ff }, { AV_CODEC_ID_G723_1, 0x0111 }, { AV_CODEC_ID_SIPR, 0x0130 }, + { AV_CODEC_ID_ACELP_KELVIN, 0x0135 }, { AV_CODEC_ID_WMAV1, 0x0160 }, { AV_CODEC_ID_WMAV2, 0x0161 }, { AV_CODEC_ID_WMAPRO, 0x0162 },