Quoting Hendrik Leppkes (2015-03-23 12:45:19)
> ---
> configure | 4 +
> libavcodec/Makefile | 1 +
> libavcodec/allcodecs.c | 1 +
> libavcodec/libdcadec.c | 197
> +++++++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 203 insertions(+)
> create mode 100644 libavcodec/libdcadec.c
>
> diff --git a/configure b/configure
> index 3c38a8c..6eaac29 100755
> --- a/configure
> +++ b/configure
> @@ -184,6 +184,7 @@ External library support:
> --enable-libcdio enable audio CD grabbing with libcdio
> --enable-libdc1394 enable IIDC-1394 grabbing using libdc1394
> and libraw1394 [no]
> + --enable-libdcadec enable DCA decoding via libdcadec [no]
> --enable-libfaac enable AAC encoding via libfaac [no]
> --enable-libfdk-aac enable AAC de/encoding via libfdk-aac [no]
> --enable-libfreetype enable libfreetype [no]
> @@ -1149,6 +1150,7 @@ EXTERNAL_LIBRARY_LIST="
> libbs2b
> libcdio
> libdc1394
> + libdcadec
> libfaac
> libfdk_aac
> libfontconfig
> @@ -2004,6 +2006,7 @@ mpeg4video_parser_select="error_resilience h263dsp
> mpeg_er mpegvideo qpeldsp"
> vc1_parser_select="mpegvideo startcode vc1_decoder"
>
> # external libraries
> +libdcadec_decoder_deps="libdcadec"
> libfaac_encoder_deps="libfaac"
> libfaac_encoder_select="audio_frame_queue"
> libfdk_aac_decoder_deps="libfdk_aac"
> @@ -4206,6 +4209,7 @@ enabled avisynth && { { check_header
> "avisynth/avisynth_c.h" && check_l
> enabled frei0r && { check_header frei0r.h || die "ERROR: frei0r.h
> header not found"; }
> enabled gnutls && require_pkg_config gnutls gnutls/gnutls.h
> gnutls_global_init
> enabled libbs2b && require_pkg_config libbs2b bs2b.h bs2b_open
> +enabled libdcadec && require libdcadec libdcadec/dca_context.h
> dcadec_context_create -ldcadec
> enabled libfaac && require2 libfaac "stdint.h faac.h"
> faacEncGetVersion -lfaac
> enabled libfdk_aac && require libfdk_aac fdk-aac/aacenc_lib.h
> aacEncOpen -lfdk-aac
> enabled libfontconfig && require_pkg_config fontconfig
> "fontconfig/fontconfig.h" FcInit
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index 71ebdb8..e86a386 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -607,6 +607,7 @@ OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o
> mpegaudiodata.o \
> OBJS-$(CONFIG_WTV_DEMUXER) += mpeg4audio.o mpegaudiodata.o
>
> # external codec libraries
> +OBJS-$(CONFIG_LIBDCADEC_DECODER) += libdcadec.o dca.o
> OBJS-$(CONFIG_LIBFAAC_ENCODER) += libfaac.o
> OBJS-$(CONFIG_LIBFDK_AAC_DECODER) += libfdk-aacdec.o
> OBJS-$(CONFIG_LIBFDK_AAC_ENCODER) += libfdk-aacenc.o
> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
> index 4cba5fb..0f03964 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -440,6 +440,7 @@ void avcodec_register_all(void)
> REGISTER_ENCDEC (XSUB, xsub);
>
> /* external libraries */
> + REGISTER_DECODER(LIBDCADEC, libdcadec)
> REGISTER_ENCODER(LIBFAAC, libfaac);
> REGISTER_ENCDEC (LIBFDK_AAC, libfdk_aac);
> REGISTER_ENCDEC (LIBGSM, libgsm);
> diff --git a/libavcodec/libdcadec.c b/libavcodec/libdcadec.c
> new file mode 100644
> index 0000000..7ca8942
> --- /dev/null
> +++ b/libavcodec/libdcadec.c
> @@ -0,0 +1,197 @@
> +/*
> + * libdcadec decoder wrapper
> + * Copyright (C) 2015 Hendrik Leppkes
> + *
> + * 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 <libdcadec/dca_context.h>
> +
> +#include "libavutil/avassert.h"
> +#include "libavutil/channel_layout.h"
> +#include "libavutil/common.h"
> +#include "libavutil/opt.h"
> +#include "avcodec.h"
> +#include "dca.h"
> +#include "dca_syncwords.h"
> +#include "internal.h"
> +
> +typedef struct DCADecContext {
> + struct dcadec_context *ctx;
> + uint8_t *buffer;
> + int buffer_size;
> +} DCADecContext;
> +
> +static int dcadec_decode_frame(AVCodecContext *avctx, void *data,
> + int *got_frame_ptr, AVPacket *avpkt)
> +{
> + DCADecContext *s = avctx->priv_data;
> + AVFrame *frame = data;
> + int ret, i, k;
> + int **samples, nsamples, channel_mask, sample_rate, bits_per_sample,
> profile;
> + uint32_t mrk;
> + uint8_t *input = avpkt->data;
> + int input_size = avpkt->size;
> +
> + /* convert bytestream syntax to RAW BE format if required */
> + mrk = AV_RB32(input);
This read should be checked. The packet size can be anything positive.
> + if (mrk != DCA_SYNCWORD_CORE_BE && mrk != DCA_SYNCWORD_SUBSTREAM) {
> + s->buffer = av_fast_realloc(s->buffer, &s->buffer_size, avpkt->size
> + FF_INPUT_BUFFER_PADDING_SIZE);
> + if (!s->buffer)
> + return AVERROR(ENOMEM);
> +
> + if ((ret = ff_dca_convert_bitstream(avpkt->data, avpkt->size,
> s->buffer, s->buffer_size)) < 0)
> + return ret;
> +
> + input = s->buffer;
> + input_size = ret;
> + }
> +
> + if ((ret = dcadec_context_parse(s->ctx, input, input_size)) < 0) {
> + av_log(avctx, AV_LOG_ERROR, "dcadec_context_parse() failed: %d
> (%s)\n", -ret, dcadec_strerror(ret));
> + return AVERROR_UNKNOWN;
> + }
> + if ((ret = dcadec_context_filter(s->ctx, &samples, &nsamples,
> &channel_mask,
> + &sample_rate, &bits_per_sample,
> &profile)) < 0) {
> + av_log(avctx, AV_LOG_ERROR, "dcadec_context_filter() failed: %d
> (%s)\n", -ret, dcadec_strerror(ret));
> + return AVERROR_UNKNOWN;
> + }
> +
> + avctx->channels = av_get_channel_layout_nb_channels(channel_mask);
> + avctx->channel_layout = channel_mask;
> + avctx->sample_rate = sample_rate;
> +
> + av_assert0(bits_per_sample >= 16 && bits_per_sample <= 24);
While I disagree with Luca about asserts being evil in general, in this
case an assert is really wrong.
The code should never assert on values from beyond its control,
especially values from an external library.
> + if (bits_per_sample == 16)
> + avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
> + else
> + avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
> +
> + avctx->bits_per_raw_sample = bits_per_sample;
> +
> + switch (profile) {
> + case DCADEC_PROFILE_DS:
> + avctx->profile = FF_PROFILE_DTS;
> + break;
> + case DCADEC_PROFILE_DS_96_24:
> + avctx->profile = FF_PROFILE_DTS_96_24;
> + break;
> + case DCADEC_PROFILE_DS_ES:
> + avctx->profile = FF_PROFILE_DTS_ES;
> + break;
> + case DCADEC_PROFILE_HD_HRA:
> + avctx->profile = FF_PROFILE_DTS_HD_HRA;
> + break;
> + case DCADEC_PROFILE_HD_MA:
> + avctx->profile = FF_PROFILE_DTS_HD_MA;
> + break;
> + case DCADEC_PROFILE_EXPRESS:
> + avctx->profile = FF_PROFILE_DTS_EXPRESS;
> + break;
> + case DCADEC_PROFILE_UNKNOWN:
> + default:
> + avctx->profile = FF_PROFILE_UNKNOWN;
> + break;
> + }
> +
> + /* bitrate is only meaningful if there are no HD extensions, as they
> distort the bitrate */
> + if (profile == DCADEC_PROFILE_DS || profile == DCADEC_PROFILE_DS_96_24
> || profile == DCADEC_PROFILE_DS_ES) {
> + struct dcadec_core_info *info = dcadec_context_get_core_info(s->ctx);
> + avctx->bit_rate = info->bit_rate;
> + dcadec_context_free_core_info(info);
No possibility of failure here? It looks almost like a malloc+free.
> + } else
> + avctx->bit_rate = 0;
> +
> + frame->nb_samples = nsamples;
> + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
> + return ret;
> +
> + for (i = 0; i < avctx->channels; i++) {
> + if (frame->format == AV_SAMPLE_FMT_S16P) {
> + int16_t *plane = (int16_t *)frame->extended_data[i];
> + for (k = 0; k < nsamples; k++)
> + plane[k] = samples[i][k];
> + } else {
> + int32_t *plane = (int32_t *)frame->extended_data[i];
> + int shift = 32 - bits_per_sample;
> + for (k = 0; k < nsamples; k++)
> + plane[k] = samples[i][k] << shift;
> + }
> + }
This looks awfully inefficient, but I guess nobody cares.
--
Anton Khirnov
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel