Message ID | 20190102185338.4910-1-onemda@gmail.com |
---|---|
State | Accepted |
Headers | show |
On 1/2/2019 3:53 PM, Paul B Mahol wrote: > Signed-off-by: Paul B Mahol <onemda@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; > + } > + > + 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)); You're never freeing this. > + 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; > + > + 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; > + } > + > + current = current << 1; > + if (s->dict[s->dict_entry].l < 0) { > + int16_t datum; > + > + datum = s->dict[s->dict_entry].r; > + > + if (!s->delta_compression) > + s->sample = 0; > + s->sample = (s->sample + datum) & 0xFF; > + > + frame->data[0][n++] = s->sample; > + > + s->dict_entry = 0; > + } > + } > + } > + > + frame->nb_samples = n; > + > + *got_frame = 1; > + > + return pkt->size; > +} > + > +AVCodec ff_hcom_decoder = { > + .name = "hcom", > + .long_name = NULL_IF_CONFIG_SMALL("HCOM Audio"), > + .type = AVMEDIA_TYPE_AUDIO, > + .id = AV_CODEC_ID_HCOM, > + .priv_data_size = sizeof(HCOMContext), > + .init = hcom_init, > + .decode = hcom_decode, > + .capabilities = AV_CODEC_CAP_DR1, > +}; >
On 1/2/19, James Almer <jamrial@gmail.com> wrote: > On 1/2/2019 3:53 PM, Paul B Mahol wrote: >> Signed-off-by: Paul B Mahol <onemda@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; >> + } >> + >> + 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)); > > You're never freeing this. > Fixed locally.
On 1/2/2019 3:53 PM, Paul B Mahol wrote: > +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; > + > + 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; > + } > + > + current = current << 1; This sounds like get_bits is a better fit than bytestream2 for this decoder. > + if (s->dict[s->dict_entry].l < 0) { > + int16_t datum; > + > + datum = s->dict[s->dict_entry].r; > + > + if (!s->delta_compression) > + s->sample = 0; > + s->sample = (s->sample + datum) & 0xFF; > + > + frame->data[0][n++] = s->sample; > + > + s->dict_entry = 0; > + } > + } > + } > + > + frame->nb_samples = n; > + > + *got_frame = 1; > + > + return pkt->size; > +}
On Wed, 2 Jan 2019 at 19:02, Paul B Mahol <onemda@gmail.com> wrote: > Signed-off-by: Paul B Mahol <onemda@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.
2019-01-03 0:51 GMT+01:00, Rostislav Pehlivanov <atomnuker@gmail.com>: > On Wed, 2 Jan 2019 at 19:02, Paul B Mahol <onemda@gmail.com> wrote: >> + 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. Fwiw, I believe these brackets are useful. But that may only be me debugging. Carl Eugen
On 1/6/19, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote: > 2019-01-03 0:51 GMT+01:00, Rostislav Pehlivanov <atomnuker@gmail.com>: >> On Wed, 2 Jan 2019 at 19:02, Paul B Mahol <onemda@gmail.com> wrote: > > >>> + 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. > > Fwiw, I believe these brackets are useful. > But that may only be me debugging. > Locally fixed. Will apply ASAP! This work is being sponsored by N. G. with 10 $.
2019-01-14 20:32 GMT+01:00, Paul B Mahol <onemda@gmail.com>: > On 1/6/19, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote: >> 2019-01-03 0:51 GMT+01:00, Rostislav Pehlivanov <atomnuker@gmail.com>: >>> On Wed, 2 Jan 2019 at 19:02, Paul B Mahol <onemda@gmail.com> wrote: >> >> >>>> + 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. >> >> Fwiw, I believe these brackets are useful. >> But that may only be me debugging. >> > > Locally fixed. Sad. Carl Eugen
On Wed, Jan 02, 2019 at 06:12:08PM -0300, James Almer wrote: > On 1/2/2019 3:53 PM, Paul B Mahol wrote: > > +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; > > + > > + 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; > > + } > > + > > + current = current << 1; > > This sounds like get_bits is a better fit than bytestream2 for this decoder. this looks like a standard vlc/huffman reader and could be using the existing vlc code (init_vlc / get_vlc2 / ...) thanks [...]
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; + } + + 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; + + 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; + } + + current = current << 1; + if (s->dict[s->dict_entry].l < 0) { + int16_t datum; + + datum = s->dict[s->dict_entry].r; + + if (!s->delta_compression) + s->sample = 0; + s->sample = (s->sample + datum) & 0xFF; + + frame->data[0][n++] = s->sample; + + s->dict_entry = 0; + } + } + } + + frame->nb_samples = n; + + *got_frame = 1; + + return pkt->size; +} + +AVCodec ff_hcom_decoder = { + .name = "hcom", + .long_name = NULL_IF_CONFIG_SMALL("HCOM Audio"), + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_HCOM, + .priv_data_size = sizeof(HCOMContext), + .init = hcom_init, + .decode = hcom_decode, + .capabilities = AV_CODEC_CAP_DR1, +};
Signed-off-by: Paul B Mahol <onemda@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