High Definition Compatible Digital (HDCD) decoder filter, using libhdcd

Signed-off-by: Burt P <pburt0@gmail.com>
Signed-off-by: Diego Biurrun <diego@biurrun.de>
Signed-off-by: Luca Barbato <lu_zero@gentoo.org>
pull/244/merge
Burt P 8 years ago committed by Luca Barbato
parent 95f8029345
commit 728e80cd2e
  1. 1
      Changelog
  2. 4
      configure
  3. 47
      doc/filters.texi
  4. 9
      doc/general.texi
  5. 1
      libavfilter/Makefile
  6. 197
      libavfilter/af_hdcd.c
  7. 1
      libavfilter/allfilters.c
  8. 2
      libavfilter/version.h

@ -62,6 +62,7 @@ version <next>:
- Intel QSV video scaling and deinterlacing filter
- OpenH264 decoder wrapper
- Removed the legacy X11 screen grabber, use XCB instead
- HDCD decoding filter through libhdcd
version 11:

4
configure vendored

@ -197,6 +197,7 @@ External library support:
--enable-libfontconfig font configuration and management
--enable-libfreetype font rendering
--enable-libgsm GSM audio encoding/decoding
--enable-libhdcd HDCD decoding filter
--enable-libilbc ILBC audio encoding/decoding
--enable-libkvazaar HEVC video encoding
--enable-libmp3lame MP3 audio encoding
@ -1270,6 +1271,7 @@ EXTERNAL_LIBRARY_LIST="
libfontconfig
libfreetype
libgsm
libhdcd
libilbc
libkvazaar
libmp3lame
@ -2426,6 +2428,7 @@ frei0r_filter_deps="frei0r dlopen"
frei0r_filter_extralibs='$ldl'
frei0r_src_filter_deps="frei0r dlopen"
frei0r_src_filter_extralibs='$ldl'
hdcd_filter_deps="libhdcd"
hqdn3d_filter_deps="gpl"
interlace_filter_deps="gpl"
ocv_filter_deps="libopencv"
@ -4606,6 +4609,7 @@ enabled libfreetype && require_pkg_config freetype2 "ft2build.h FT_FREETYP
enabled libgsm && { for gsm_hdr in "gsm.h" "gsm/gsm.h"; do
check_lib "${gsm_hdr}" gsm_create -lgsm && break;
done || die "ERROR: libgsm not found"; }
enabled libhdcd && require_pkg_config libhdcd "hdcd/hdcd_simple.h" hdcd_new
enabled libilbc && require libilbc ilbc.h WebRtcIlbcfix_InitDecode -lilbc
enabled libkvazaar && require_pkg_config "kvazaar >= 0.8.1" kvazaar.h kvz_api_get
enabled libmfx && require_pkg_config libmfx "mfx/mfxvideo.h" MFXInit

@ -647,6 +647,53 @@ avconv -i fl -i fr -i fc -i sl -i sr -i lfe -filter_complex
out
@end example
@section hdcd
Decodes High Definition Compatible Digital (HDCD) data. A 16-bit PCM stream with
embedded HDCD codes is expanded into a 20-bit PCM stream.
The filter supports the Peak Extend and Low-level Gain Adjustment features
of HDCD, and detects the Transient Filter flag.
@example
avconv -i HDCD16.flac -af hdcd OUT24.flac
@end example
When using the filter with WAV, note that the default encoding for WAV is 16-bit,
so the resulting 20-bit stream will be truncated back to 16-bit. Use something
like @command{-acodec pcm_s24le} after the filter to get 24-bit PCM output.
@example
avconv -i HDCD16.wav -af hdcd OUT16.wav
avconv -i HDCD16.wav -af hdcd -acodec pcm_s24le OUT24.wav
@end example
The filter accepts the following options:
@table @option
@item analyze_mode
Replace audio with a solid tone and adjust the amplitude to signal some
specific aspect of the decoding process. The output file can be loaded in
an audio editor alongside the original to aid analysis.
Modes are:
@table @samp
@item 0, off
Disabled
@item 1, lle
Gain adjustment level at each sample
@item 2, pe
Samples where peak extend occurs
@item 3, cdt
Samples where the code detect timer is active
@item 4, tgm
Samples where the target gain does not match between channels
@item 5, pel
Any samples above peak extend level
@item 6, ltgm
Gain adjustment level at each sample, in each channel
@end table
@end table
@section resample
Convert the audio sample format, sample rate and channel layout. It is
not meant to be used directly; it is inserted automatically by libavfilter

@ -157,6 +157,15 @@ Go to @url{https://github.com/dekkers/libilbc} and follow the instructions for
installing the library. Then pass @code{--enable-libilbc} to configure to
enable it.
@section libhdcd
Libav can make use of the libhdcd library for High Definition Compatible
Digital (HDCD) decoding via the @code{hdcd} filter.
Go to @url{https://github.com/bp0/libhdcd} and follow the instructions for
installing the library. Then pass @code{--enable-libhdcd} to configure to
enable it.
@section AviSynth
Libav can read AviSynth scripts as input. To enable support you need a

@ -34,6 +34,7 @@ OBJS-$(CONFIG_BS2B_FILTER) += af_bs2b.o
OBJS-$(CONFIG_CHANNELMAP_FILTER) += af_channelmap.o
OBJS-$(CONFIG_CHANNELSPLIT_FILTER) += af_channelsplit.o
OBJS-$(CONFIG_COMPAND_FILTER) += af_compand.o
OBJS-$(CONFIG_HDCD_FILTER) += af_hdcd.o
OBJS-$(CONFIG_JOIN_FILTER) += af_join.o
OBJS-$(CONFIG_RESAMPLE_FILTER) += af_resample.o
OBJS-$(CONFIG_VOLUME_FILTER) += af_volume.o

@ -0,0 +1,197 @@
/*
* This file is part of Libav.
*
* Libav 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.
*
* Libav 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 Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* HDCD decoding filter, using libhdcd
*/
#include <hdcd/hdcd_simple.h>
#include "libavutil/channel_layout.h"
#include "libavutil/opt.h"
#include "audio.h"
#include "avfilter.h"
#include "formats.h"
#include "internal.h"
typedef struct HDCDContext {
const AVClass *class;
hdcd_simple *shdcd;
/* AVOption members */
/** analyze mode replaces the audio with a solid tone and adjusts
* the amplitude to signal some specific aspect of the decoding
* process. See docs or HDCD_ANA_* defines. */
int analyze_mode;
/* end AVOption members */
} HDCDContext;
#define OFFSET(x) offsetof(HDCDContext, x)
#define A AV_OPT_FLAG_AUDIO_PARAM
#define HDCD_ANA_MAX 6
static const AVOption hdcd_options[] = {
{ "analyze_mode", "Replace audio with solid tone and signal some processing aspect in the amplitude.",
OFFSET(analyze_mode), AV_OPT_TYPE_INT, { .i64=HDCD_ANA_OFF }, 0, HDCD_ANA_MAX, A, "analyze_mode"},
{ "off", HDCD_ANA_OFF_DESC, 0, AV_OPT_TYPE_CONST, { .i64 = HDCD_ANA_OFF}, 0, 0, A, "analyze_mode" },
{ "lle", HDCD_ANA_LLE_DESC, 0, AV_OPT_TYPE_CONST, { .i64 = HDCD_ANA_LLE}, 0, 0, A, "analyze_mode" },
{ "pe", HDCD_ANA_PE_DESC, 0, AV_OPT_TYPE_CONST, { .i64 = HDCD_ANA_PE}, 0, 0, A, "analyze_mode" },
{ "cdt", HDCD_ANA_CDT_DESC, 0, AV_OPT_TYPE_CONST, { .i64 = HDCD_ANA_CDT}, 0, 0, A, "analyze_mode" },
{ "tgm", HDCD_ANA_TGM_DESC, 0, AV_OPT_TYPE_CONST, { .i64 = HDCD_ANA_TGM}, 0, 0, A, "analyze_mode" },
{ "pel", HDCD_ANA_PEL_DESC, 0, AV_OPT_TYPE_CONST, { .i64 = HDCD_ANA_PEL}, 0, 0, A, "analyze_mode" },
{ "ltgm", HDCD_ANA_LTGM_DESC, 0, AV_OPT_TYPE_CONST, { .i64 = HDCD_ANA_LTGM}, 0, 0, A, "analyze_mode" },
{ NULL }
};
static const AVClass hdcd_class = {
.class_name = "HDCD filter",
.item_name = av_default_item_name,
.option = hdcd_options,
.version = LIBAVFILTER_VERSION_INT,
};
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
{
AVFilterContext *ctx = inlink->dst;
HDCDContext *s = ctx->priv;
AVFilterLink *outlink = ctx->outputs[0];
AVFrame *out;
const int16_t *in_data;
int32_t *out_data;
int n, result;
int channel_count = av_get_channel_layout_nb_channels(in->channel_layout);
out = ff_get_audio_buffer(outlink, in->nb_samples);
if (!out) {
av_frame_free(&in);
return AVERROR(ENOMEM);
}
result = av_frame_copy_props(out, in);
if (result) {
av_frame_free(&out);
av_frame_free(&in);
return result;
}
in_data = (int16_t *)in->data[0];
out_data = (int32_t *)out->data[0];
for (n = 0; n < in->nb_samples * channel_count; n++)
out_data[n] = in_data[n];
hdcd_process(s->shdcd, out_data, in->nb_samples);
av_frame_free(&in);
return ff_filter_frame(outlink, out);
}
static int query_formats(AVFilterContext *ctx)
{
AVFilterFormats *in_formats, *out_formats, *sample_rates = NULL;
AVFilterChannelLayouts *layouts = NULL;
AVFilterLink *inlink = ctx->inputs[0];
AVFilterLink *outlink = ctx->outputs[0];
static const enum AVSampleFormat sample_fmts_in[] = {
AV_SAMPLE_FMT_S16,
AV_SAMPLE_FMT_NONE
};
static const enum AVSampleFormat sample_fmts_out[] = {
AV_SAMPLE_FMT_S32,
AV_SAMPLE_FMT_NONE
};
ff_add_channel_layout(&layouts, AV_CH_LAYOUT_STEREO);
ff_set_common_channel_layouts(ctx, layouts);
in_formats = ff_make_format_list(sample_fmts_in);
out_formats = ff_make_format_list(sample_fmts_out);
if (!in_formats || !out_formats)
return AVERROR(ENOMEM);
ff_formats_ref(in_formats, &inlink->out_formats);
ff_formats_ref(out_formats, &outlink->in_formats);
ff_add_format(&sample_rates, 44100);
ff_set_common_samplerates(ctx, sample_rates);
return 0;
}
static av_cold void uninit(AVFilterContext *ctx)
{
HDCDContext *s = ctx->priv;
char detect_str[256] = "";
/* log the HDCD decode information */
hdcd_detect_str(s->shdcd, detect_str, sizeof(detect_str));
av_log(ctx, AV_LOG_INFO, "%s\n", detect_str);
hdcd_free(s->shdcd);
}
/** callback for error logging */
static void af_hdcd_log(const void *priv, const char *fmt, va_list args)
{
av_vlog((AVFilterContext *)priv, AV_LOG_VERBOSE, fmt, args);
}
static av_cold int init(AVFilterContext *ctx)
{
HDCDContext *s = ctx->priv;
s->shdcd = hdcd_new();
hdcd_logger_attach(s->shdcd, af_hdcd_log, ctx);
if (s->analyze_mode)
hdcd_analyze_mode(s->shdcd, s->analyze_mode);
av_log(ctx, AV_LOG_VERBOSE, "Analyze mode: [%d] %s\n",
s->analyze_mode, hdcd_str_analyze_mode_desc(s->analyze_mode));
return 0;
}
static const AVFilterPad avfilter_af_hdcd_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
.filter_frame = filter_frame,
},
{ NULL }
};
static const AVFilterPad avfilter_af_hdcd_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
},
{ NULL }
};
AVFilter ff_af_hdcd = {
.name = "hdcd",
.description = NULL_IF_CONFIG_SMALL("Apply High Definition Compatible Digital (HDCD) decoding."),
.priv_size = sizeof(HDCDContext),
.priv_class = &hdcd_class,
.init = init,
.uninit = uninit,
.query_formats = query_formats,
.inputs = avfilter_af_hdcd_inputs,
.outputs = avfilter_af_hdcd_outputs,
};

@ -57,6 +57,7 @@ void avfilter_register_all(void)
REGISTER_FILTER(CHANNELMAP, channelmap, af);
REGISTER_FILTER(CHANNELSPLIT, channelsplit, af);
REGISTER_FILTER(COMPAND, compand, af);
REGISTER_FILTER(HDCD, hdcd, af);
REGISTER_FILTER(JOIN, join, af);
REGISTER_FILTER(RESAMPLE, resample, af);
REGISTER_FILTER(VOLUME, volume, af);

@ -30,7 +30,7 @@
#include "libavutil/version.h"
#define LIBAVFILTER_VERSION_MAJOR 6
#define LIBAVFILTER_VERSION_MINOR 6
#define LIBAVFILTER_VERSION_MINOR 7
#define LIBAVFILTER_VERSION_MICRO 0
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \

Loading…
Cancel
Save