[FFmpeg-devel] [PATCH 1/2] avcodec: add HCOM decoder
Rostislav Pehlivanov
atomnuker at gmail.com
Thu Jan 3 01:51:11 EET 2019
On Wed, 2 Jan 2019 at 19:02, Paul B Mahol <onemda at gmail.com> wrote:
> Signed-off-by: Paul B Mahol <onemda at gmail.com>
> ---
> libavcodec/Makefile | 1 +
> libavcodec/allcodecs.c | 1 +
> libavcodec/avcodec.h | 1 +
> libavcodec/codec_desc.c | 7 ++
> libavcodec/hcom.c | 137 ++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 147 insertions(+)
> create mode 100644 libavcodec/hcom.c
>
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index 99799ceed2..bf746c143d 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -362,6 +362,7 @@ OBJS-$(CONFIG_H264_V4L2M2M_DECODER) +=
> v4l2_m2m_dec.o
> OBJS-$(CONFIG_H264_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
> OBJS-$(CONFIG_HAP_DECODER) += hapdec.o hap.o
> OBJS-$(CONFIG_HAP_ENCODER) += hapenc.o hap.o
> +OBJS-$(CONFIG_HCOM_DECODER) += hcom.o
> OBJS-$(CONFIG_HEVC_DECODER) += hevcdec.o hevc_mvs.o \
> hevc_cabac.o hevc_refs.o
> hevcpred.o \
> hevcdsp.o hevc_filter.o
> hevc_data.o
> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
> index 4755af71b2..fe0376e27e 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -424,6 +424,7 @@ extern AVCodec ff_g723_1_decoder;
> extern AVCodec ff_g729_decoder;
> extern AVCodec ff_gsm_decoder;
> extern AVCodec ff_gsm_ms_decoder;
> +extern AVCodec ff_hcom_decoder;
> extern AVCodec ff_iac_decoder;
> extern AVCodec ff_ilbc_decoder;
> extern AVCodec ff_imc_decoder;
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index 92567ec6d0..e92d7accf4 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -646,6 +646,7 @@ enum AVCodecID {
> AV_CODEC_ID_APTX_HD,
> AV_CODEC_ID_SBC,
> AV_CODEC_ID_ATRAC9,
> + AV_CODEC_ID_HCOM,
>
> /* 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 2363a53283..10a639101c 100644
> --- a/libavcodec/codec_desc.c
> +++ b/libavcodec/codec_desc.c
> @@ -2943,6 +2943,13 @@ static const AVCodecDescriptor codec_descriptors[]
> = {
> .long_name = NULL_IF_CONFIG_SMALL("ATRAC9 (Adaptive TRansform
> Acoustic Coding 9)"),
> .props = AV_CODEC_PROP_LOSSY,
> },
> + {
> + .id = AV_CODEC_ID_HCOM,
> + .type = AVMEDIA_TYPE_AUDIO,
> + .name = "hcom",
> + .long_name = NULL_IF_CONFIG_SMALL("HCOM Audio"),
> + .props = AV_CODEC_PROP_LOSSY,
> + },
>
> /* subtitle codecs */
> {
> diff --git a/libavcodec/hcom.c b/libavcodec/hcom.c
> new file mode 100644
> index 0000000000..e516d20a94
> --- /dev/null
> +++ b/libavcodec/hcom.c
> @@ -0,0 +1,137 @@
> +/*
> + * HCOM audio decoder
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> 02110-1301 USA
> + */
> +
> +#include "libavutil/intreadwrite.h"
> +
> +#include "avcodec.h"
> +#include "bytestream.h"
> +#include "internal.h"
> +
> +typedef struct HEntry {
> + int16_t l, r;
> +} HEntry;
> +
> +typedef struct HCOMContext {
> + AVCodecContext *avctx;
> +
> + uint8_t first_sample;
> + uint8_t sample;
> + int dict_entries;
> + int dict_entry;
> + int delta_compression;
> +
> + HEntry *dict;
> +} HCOMContext;
> +
> +static av_cold int hcom_init(AVCodecContext *avctx)
> +{
> + HCOMContext *s = avctx->priv_data;
> +
> + if (avctx->channels != 1) {
> + av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n");
> + return AVERROR_INVALIDDATA;
> + }
>
You can just set avctx->channels = 1 and the layout to mono, its a decoder.
+
> + if (avctx->extradata_size <= 7)
> + return AVERROR_INVALIDDATA;
> + s->dict_entries = AV_RB16(avctx->extradata);
> + if (avctx->extradata_size < s->dict_entries * 4 + 7)
> + return AVERROR_INVALIDDATA;
> + s->delta_compression = AV_RB32(avctx->extradata + 2);
> + s->sample = s->first_sample = avctx->extradata[avctx->extradata_size
> - 1];
> +
> + s->dict = av_calloc(s->dict_entries, sizeof(*s->dict));
> + if (!s->dict)
> + return AVERROR(ENOMEM);
> + for (int i = 0; i < s->dict_entries; i++) {
> + s->dict[i].l = AV_RB16(avctx->extradata + 6 + 4 * i);
> + s->dict[i].r = AV_RB16(avctx->extradata + 6 + 4 * i + 2);
> + }
> +
> + avctx->sample_fmt = AV_SAMPLE_FMT_U8;
> + s->dict_entry = 0;
> +
> + return 0;
> +}
> +
> +static int hcom_decode(AVCodecContext *avctx, void *data,
> + int *got_frame, AVPacket *pkt)
> +{
> + HCOMContext *s = avctx->priv_data;
> + AVFrame *frame = data;
> + GetByteContext gb;
> + uint32_t current;
> + int ret, n = 0;
> +
> + if (pkt->size > INT16_MAX)
> + return AVERROR_INVALIDDATA;
>
Also check the size is mod 4 or remove the check altogether if it doesn't
make the decoder blow up.
+
> + frame->nb_samples = pkt->size * 8;
> + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
> + return ret;
> +
> + bytestream2_init(&gb, pkt->data, pkt->size);
> + while (bytestream2_get_bytes_left(&gb) >= 4) {
> + int bits = 32;
> +
> + current = bytestream2_get_be32(&gb);
> +
> + while (bits-- > 0) {
> +
> + if (current & 0x80000000) {
> + s->dict_entry = s->dict[s->dict_entry].r;
> + } else {
> + s->dict_entry = s->dict[s->dict_entry].l;
> + }
>
No need for brackets here.
Also yeah, get_bits seems like a better choice.
More information about the ffmpeg-devel
mailing list