From patchwork Thu Oct 6 21:38:44 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marton Balint X-Patchwork-Id: 899 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.140.66 with SMTP id o63csp1107014vsd; Thu, 6 Oct 2016 14:39:08 -0700 (PDT) X-Received: by 10.28.88.77 with SMTP id m74mr4475033wmb.94.1475789948731; Thu, 06 Oct 2016 14:39:08 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id b126si19740117wmg.43.2016.10.06.14.39.07; Thu, 06 Oct 2016 14:39:08 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 3A247689BE3; Fri, 7 Oct 2016 00:38:49 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from iq.passwd.hu (iq.passwd.hu [217.27.212.140]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id C31E5689B07 for ; Fri, 7 Oct 2016 00:38:41 +0300 (EEST) Received: from localhost (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id BF679100C72; Thu, 6 Oct 2016 23:38:56 +0200 (CEST) X-Virus-Scanned: amavisd-new at passwd.hu Received: from iq.passwd.hu ([127.0.0.1]) by localhost (iq.passwd.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id piP7KuP+a6hS; Thu, 6 Oct 2016 23:38:54 +0200 (CEST) Received: from bluegene.passwd.hu (localhost [127.0.0.1]) by iq.passwd.hu (Postfix) with ESMTP id F339C100C49; Thu, 6 Oct 2016 23:38:53 +0200 (CEST) From: Marton Balint To: ffmpeg-devel@ffmpeg.org Date: Thu, 6 Oct 2016 23:38:44 +0200 Message-Id: <1475789924-14612-1-git-send-email-cus@passwd.hu> X-Mailer: git-send-email 2.6.6 Subject: [FFmpeg-devel] [PATCH] lavfi/sidedata: add filter for manipulating frame side data X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Marton Balint MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" This is a similar filter to f_metadata, only it works on side data. Since adding side data from a user provided arbitrary binary string is unsafe, because current code assumes that a side data of a certain kind has the proper size, this filter only implements selection and deletion. Also, no value matching support is implemented yet, because there is no uniform way to specify a side data textually. Signed-off-by: Marton Balint --- Changelog | 1 + doc/filters.texi | 30 ++++++++ libavfilter/Makefile | 2 + libavfilter/allfilters.c | 2 + libavfilter/f_sidedata.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++ libavfilter/version.h | 2 +- 6 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 libavfilter/f_sidedata.c diff --git a/Changelog b/Changelog index dc48882..5148712 100644 --- a/Changelog +++ b/Changelog @@ -35,6 +35,7 @@ version : - sdl1 output device and sdl1 support removed - extended mov edit list support - libfaac encoder removed +- sidedata video and asidedata audio filter version 3.1: diff --git a/doc/filters.texi b/doc/filters.texi index 4b2f7bf..5516ae0 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -17568,6 +17568,36 @@ ffmpeg -i audio.flac -lavfi showwavespic=split_channels=1:s=1024x800 waveform.pn @end example @end itemize +@section sidedata, asidedata + +Delete frame side data, or select frames based on it. + +This filter accepts the following options: + +@table @option +@item mode +Set mode of operation of the filter. + +Can be one of the following: + +@table @samp +@item select +Select every frame with side data of @code{type}. + +@item delete +Delete side data of @code{type}. If @code{type} is not set, delete all side +data in the frame. + +@end table + +@item type +Set side data type used with all modes. Must be set for @code{select} mode. For +the list of frame side data types, refer to the @code{AVFrameSideDataType} enum +in @file{libavutil/frame.h}. For example, to choose +@code{AV_FRAME_DATA_PANSCAN} side data, you must specify @code{PANSCAN}. + +@end table + @section spectrumsynth Sythesize audio from 2 input video spectrums, first input stream represents diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 57a38d3..7ed4696 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -62,6 +62,7 @@ OBJS-$(CONFIG_ASETPTS_FILTER) += setpts.o OBJS-$(CONFIG_ASETRATE_FILTER) += af_asetrate.o OBJS-$(CONFIG_ASETTB_FILTER) += settb.o OBJS-$(CONFIG_ASHOWINFO_FILTER) += af_ashowinfo.o +OBJS-$(CONFIG_ASIDEDATA_FILTER) += f_sidedata.o OBJS-$(CONFIG_ASPLIT_FILTER) += split.o OBJS-$(CONFIG_ASTATS_FILTER) += af_astats.o OBJS-$(CONFIG_ASTREAMSELECT_FILTER) += f_streamselect.o @@ -270,6 +271,7 @@ OBJS-$(CONFIG_SHOWINFO_FILTER) += vf_showinfo.o OBJS-$(CONFIG_SHOWPALETTE_FILTER) += vf_showpalette.o OBJS-$(CONFIG_SHUFFLEFRAMES_FILTER) += vf_shuffleframes.o OBJS-$(CONFIG_SHUFFLEPLANES_FILTER) += vf_shuffleplanes.o +OBJS-$(CONFIG_SIDEDATA_FILTER) += f_sidedata.o OBJS-$(CONFIG_SIGNALSTATS_FILTER) += vf_signalstats.o OBJS-$(CONFIG_SMARTBLUR_FILTER) += vf_smartblur.o OBJS-$(CONFIG_SOBEL_FILTER) += vf_convolution.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 8f542fd..82a65ee 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -80,6 +80,7 @@ void avfilter_register_all(void) REGISTER_FILTER(ASETRATE, asetrate, af); REGISTER_FILTER(ASETTB, asettb, af); REGISTER_FILTER(ASHOWINFO, ashowinfo, af); + REGISTER_FILTER(ASIDEDATA, asidedata, af); REGISTER_FILTER(ASPLIT, asplit, af); REGISTER_FILTER(ASTATS, astats, af); REGISTER_FILTER(ASTREAMSELECT, astreamselect, af); @@ -286,6 +287,7 @@ void avfilter_register_all(void) REGISTER_FILTER(SHOWPALETTE, showpalette, vf); REGISTER_FILTER(SHUFFLEFRAMES, shuffleframes, vf); REGISTER_FILTER(SHUFFLEPLANES, shuffleplanes, vf); + REGISTER_FILTER(SIDEDATA, sidedata, vf); REGISTER_FILTER(SIGNALSTATS, signalstats, vf); REGISTER_FILTER(SMARTBLUR, smartblur, vf); REGISTER_FILTER(SOBEL, sobel, vf); diff --git a/libavfilter/f_sidedata.c b/libavfilter/f_sidedata.c new file mode 100644 index 0000000..4863cc9 --- /dev/null +++ b/libavfilter/f_sidedata.c @@ -0,0 +1,181 @@ +/* + * 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 + */ + +/** + * @file + * filter for manipulating frame side data + */ + +#include "libavutil/avassert.h" +#include "libavutil/internal.h" +#include "libavutil/frame.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" + +enum SideDataMode { + SIDEDATA_SELECT, + SIDEDATA_DELETE, + SIDEDATA_NB +}; + +typedef struct SideDataContext { + const AVClass *class; + + int mode; + enum AVFrameSideDataType type; +} SideDataContext; + +#define OFFSET(x) offsetof(SideDataContext, x) +#define DEFINE_OPTIONS(filt_name, FLAGS) \ +static const AVOption filt_name##_options[] = { \ + { "mode", "set a mode of operation", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, SIDEDATA_NB-1, FLAGS, "mode" }, \ + { "select", "select frame", 0, AV_OPT_TYPE_CONST, {.i64 = SIDEDATA_SELECT }, 0, 0, FLAGS, "mode" }, \ + { "delete", "delete side data", 0, AV_OPT_TYPE_CONST, {.i64 = SIDEDATA_DELETE }, 0, 0, FLAGS, "mode" }, \ + { "type", "set side data type", OFFSET(type), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, INT_MAX, FLAGS, "type" }, \ + { "PANSCAN", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_PANSCAN }, 0, 0, FLAGS, "type" }, \ + { "A53_CC", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_A53_CC }, 0, 0, FLAGS, "type" }, \ + { "STEREO3D", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_STEREO3D }, 0, 0, FLAGS, "type" }, \ + { "MATRIXENCODING", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_MATRIXENCODING }, 0, 0, FLAGS, "type" }, \ + { "DOWNMIX_INFO", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_DOWNMIX_INFO }, 0, 0, FLAGS, "type" }, \ + { "REPLAYGAIN", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_REPLAYGAIN }, 0, 0, FLAGS, "type" }, \ + { "DISPLAYMATRIX", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_DISPLAYMATRIX }, 0, 0, FLAGS, "type" }, \ + { "AFD", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_AFD }, 0, 0, FLAGS, "type" }, \ + { "MOTION_VECTORS", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_MOTION_VECTORS }, 0, 0, FLAGS, "type" }, \ + { "SKIP_SAMPLES", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_SKIP_SAMPLES }, 0, 0, FLAGS, "type" }, \ + { "AUDIO_SERVICE_TYPE", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_AUDIO_SERVICE_TYPE }, 0, 0, FLAGS, "type" }, \ + { "MASTERING_DISPLAY_METADATA", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_MASTERING_DISPLAY_METADATA }, 0, 0, FLAGS, "type" }, \ + { "GOP_TIMECODE", "", 0, AV_OPT_TYPE_CONST, {.i64 = AV_FRAME_DATA_GOP_TIMECODE }, 0, 0, FLAGS, "type" }, \ + { NULL } \ +} + +static av_cold int init(AVFilterContext *ctx) +{ + SideDataContext *s = ctx->priv; + + if (s->type == -1 && s->mode != SIDEDATA_DELETE) { + av_log(ctx, AV_LOG_ERROR, "Side data type must be set\n"); + return AVERROR(EINVAL); + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + SideDataContext *s = ctx->priv; + AVFrameSideData *sd = NULL; + + if (s->type != -1) + sd = av_frame_get_side_data(frame, s->type); + + switch (s->mode) { + case SIDEDATA_SELECT: + if (sd) { + return ff_filter_frame(outlink, frame); + } + break; + case SIDEDATA_DELETE: + if (s->type == -1) { + while (frame->nb_side_data) + av_frame_remove_side_data(frame, frame->side_data[0]->type); + } else if (sd) { + av_frame_remove_side_data(frame, s->type); + } + return ff_filter_frame(outlink, frame); + break; + default: + av_assert0(0); + }; + + av_frame_free(&frame); + + return 0; +} + +#if CONFIG_ASIDEDATA_FILTER + +DEFINE_OPTIONS(asidedata, AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM); +AVFILTER_DEFINE_CLASS(asidedata); + +static const AVFilterPad ainputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad aoutputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +AVFilter ff_af_asidedata = { + .name = "asidedata", + .description = NULL_IF_CONFIG_SMALL("Manipulate audio frame side data."), + .priv_size = sizeof(SideDataContext), + .priv_class = &asidedata_class, + .init = init, + .query_formats = ff_query_formats_all, + .inputs = ainputs, + .outputs = aoutputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, +}; +#endif /* CONFIG_ASIDEDATA_FILTER */ + +#if CONFIG_SIDEDATA_FILTER + +DEFINE_OPTIONS(sidedata, AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM); +AVFILTER_DEFINE_CLASS(sidedata); + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter ff_vf_sidedata = { + .name = "sidedata", + .description = NULL_IF_CONFIG_SMALL("Manipulate video frame side data."), + .priv_size = sizeof(SideDataContext), + .priv_class = &sidedata_class, + .init = init, + .inputs = inputs, + .outputs = outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, +}; +#endif /* CONFIG_SIDEDATA_FILTER */ diff --git a/libavfilter/version.h b/libavfilter/version.h index 93d249b..8c6cf06 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 63 +#define LIBAVFILTER_VERSION_MINOR 64 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \