diff options
author | Burt P <pburt0@gmail.com> | 2016-08-26 16:12:30 +0200 |
---|---|---|
committer | Luca Barbato <lu_zero@gentoo.org> | 2016-08-29 19:09:59 +0200 |
commit | 728e80cd2e1d4b7c3e26489efcd77bd7a9e84a99 (patch) | |
tree | 77fa0700ed362642136a2f958fe55041d5b6150c | |
parent | 95f80293456d9d4b1b096621260c38bc90325ec0 (diff) | |
download | ffmpeg-728e80cd2e1d4b7c3e26489efcd77bd7a9e84a99.tar.gz |
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>
-rw-r--r-- | Changelog | 1 | ||||
-rwxr-xr-x | configure | 4 | ||||
-rw-r--r-- | doc/filters.texi | 47 | ||||
-rw-r--r-- | doc/general.texi | 9 | ||||
-rw-r--r-- | libavfilter/Makefile | 1 | ||||
-rw-r--r-- | libavfilter/af_hdcd.c | 197 | ||||
-rw-r--r-- | libavfilter/allfilters.c | 1 | ||||
-rw-r--r-- | libavfilter/version.h | 2 |
8 files changed, 261 insertions, 1 deletions
@@ -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: @@ -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 diff --git a/doc/filters.texi b/doc/filters.texi index 2651f170a0..954765f08e 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -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 diff --git a/doc/general.texi b/doc/general.texi index ea56beff92..1708871d8a 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -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 diff --git a/libavfilter/Makefile b/libavfilter/Makefile index dea8ffa50f..c3c1beaa0f 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -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 diff --git a/libavfilter/af_hdcd.c b/libavfilter/af_hdcd.c new file mode 100644 index 0000000000..b9dadecca4 --- /dev/null +++ b/libavfilter/af_hdcd.c @@ -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, +}; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index de49d65298..ec27b5ae6e 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -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); diff --git a/libavfilter/version.h b/libavfilter/version.h index 7f3ede2d04..febfc8fa1d 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -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, \ |