Attached a patch which adds a "skipblend" filter, which I've been using for a while. My hope is that an ffmpeg developer here can merge it. The filter is similar to the framestep filter, but additionally blends frames together at each step, for a motion blur effect. The number of frames that are blended (i.e. the exposure time, in frames) can be set, allowing control over the strength of the motion blur. The filter has timeline support, and supports both 8-bit and 16-bit pixel formats. Tests and documentation included.
The main use so far that I (and others) have for this filter is to blend down high framerate footage, generated through computer rendering, to produce a high quality motion blur effect. Note that a similar effect is already possible by repeatedly chaining the tblend and framestep=step=2 filters; see for example: https://video.stackexchange.com/questions/16552/4x-resample-videoframes-using-ffmpeg But this is limited to steps that are powers of two, and this does not allow an intermediate exposure time. It's also slower. In the documentation, I've also added links between framestep, tblend, and the new skipblend filter, to help users to find the right filter they are looking for. Kind regards, Matthias
From 9f2f5b68d664ee879eed363c309cca887443251d Mon Sep 17 00:00:00 2001 From: "Matthias C. M. Troffaes" <matthias.troffaes@gmail.com> Date: Wed, 5 Apr 2017 11:56:04 +0100 Subject: [PATCH] avfilter: add skipblend filter --- Changelog | 1 + doc/filters.texi | 30 +++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- libavfilter/vf_skipblend.c | 272 +++++++++++++++++++++++++ tests/fate/filter-video.mak | 12 ++ tests/ref/fate/filter-skipblend-anim-1 | 17 ++ tests/ref/fate/filter-skipblend-anim-2 | 17 ++ tests/ref/fate/filter-skipblend-gray-1 | 14 ++ tests/ref/fate/filter-skipblend-gray-2 | 13 ++ 11 files changed, 379 insertions(+), 1 deletion(-) create mode 100644 libavfilter/vf_skipblend.c create mode 100644 tests/ref/fate/filter-skipblend-anim-1 create mode 100644 tests/ref/fate/filter-skipblend-anim-2 create mode 100644 tests/ref/fate/filter-skipblend-gray-1 create mode 100644 tests/ref/fate/filter-skipblend-gray-2 diff --git a/Changelog b/Changelog index 0343ce9cd1..3545b3aa75 100644 --- a/Changelog +++ b/Changelog @@ -94,6 +94,7 @@ version 4.0: - segafilm muxer - vfrdet filter - SRCNN filter +- skipblend video filter version 3.4: diff --git a/doc/filters.texi b/doc/filters.texi index 740eec670c..59fa9bffd2 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -5775,6 +5775,7 @@ The threshold below which a pixel value is considered black; it defaults to @end table +@anchor{tblend} @section blend, tblend Blend two video frames into each other. @@ -5786,6 +5787,8 @@ stream, the first input is the "top" layer and second input is The @code{tblend} (time blend) filter takes two consecutive frames from one single stream, and outputs the result obtained by blending the new frame on top of the old frame. +See @ref{skipblend} for blending more than two frames at once +from the same stream. A description of the accepted options follows. @@ -9992,9 +9995,11 @@ This flag is enabled by default. @end table @end table +@anchor{framestep} @section framestep Select one frame every N-th frame. +See @ref{skipblend} for blending skipped frames. This filter accepts the following option: @table @option @@ -15508,6 +15513,31 @@ ffmpeg -i input1.mkv -i input2.mkv -filter_complex "[0:v][1:v] signature=nb_inpu @end itemize +@anchor{skipblend} +@section skipblend + +Skip frames whilst blending skipped frames, for a motion blur +effect. The number of frames that are blended (i.e. the exposure time, +in frames) can be controlled, allowing control over the strength of the +motion blur. +See @ref{framestep} for skipping frames without blending. +See @ref{tblend} for blending consecutive frames without skipping. + +This filter accepts the following options: +@table @option +@item step +Skip @code{step} frames each step. +Allowed values are positive integers between @code{1} and @code{65535}. +Default value is @code{1}. +@item blend +Blend the first @code{blend} frames on every step, +to produce a motion blur effect. +Allowed values are positive integers between @code{1} and @code{step}, +where @code{1} corresponds to no motion blur, and @code{step} +corresponds to maximal motion blur. +Default value is @code{step}. +@end table + @anchor{smartblur} @section smartblur diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 7beec310f8..1eaa47d9b6 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -356,6 +356,7 @@ OBJS-$(CONFIG_SHUFFLEPLANES_FILTER) += vf_shuffleplanes.o OBJS-$(CONFIG_SIDEDATA_FILTER) += f_sidedata.o OBJS-$(CONFIG_SIGNALSTATS_FILTER) += vf_signalstats.o OBJS-$(CONFIG_SIGNATURE_FILTER) += vf_signature.o +OBJS-$(CONFIG_SKIPBLEND_FILTER) += vf_skipblend.o OBJS-$(CONFIG_SMARTBLUR_FILTER) += vf_smartblur.o OBJS-$(CONFIG_SOBEL_FILTER) += vf_convolution.o OBJS-$(CONFIG_SOBEL_OPENCL_FILTER) += vf_convolution_opencl.o opencl.o \ diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 6f1e7cfb7d..f0c515a4d3 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -340,6 +340,7 @@ extern AVFilter ff_vf_shuffleplanes; extern AVFilter ff_vf_sidedata; extern AVFilter ff_vf_signalstats; extern AVFilter ff_vf_signature; +extern AVFilter ff_vf_skipblend; extern AVFilter ff_vf_smartblur; extern AVFilter ff_vf_sobel; extern AVFilter ff_vf_sobel_opencl; diff --git a/libavfilter/version.h b/libavfilter/version.h index bf81e77a5c..77e1a77b50 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 37 +#define LIBAVFILTER_VERSION_MINOR 38 #define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ diff --git a/libavfilter/vf_skipblend.c b/libavfilter/vf_skipblend.c new file mode 100644 index 0000000000..2915b436d0 --- /dev/null +++ b/libavfilter/vf_skipblend.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2012 Stefano Sabatini + * Copyright (c) 2017 Matthias C. M. Troffaes + * + * 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 skipblend filter, based on the framestep filter + */ + +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" +#include "internal.h" +#include "video.h" + +typedef struct NullContext { + const AVClass *class; + int64_t frame_step; ///< step size in frames + int64_t frame_blend; ///< how many frames to blend on each step + int nb_planes; ///< number of planes in the pixel format + int planewidth[4]; ///< width of each plane (after subsampling) + int planeheight[4]; ///< height of each plane (after subsampling) + uint32_t *data[4]; ///< buffer for blending input frames + + void (*blend_set)(AVFilterContext *ctx, AVFrame *in, int plane); + void (*blend_add)(AVFilterContext *ctx, AVFrame *in, int plane); + void (*blend_div)(AVFilterContext *ctx, AVFrame *in, int plane); +} SkipBlendContext; + +#define OFFSET(x) offsetof(SkipBlendContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +/* note: maximum value for blend must satisfy + blend * max_pixel_value <= max_buffer_value + where max_pixel_value is UINT16_MAX (support up to 16 bit formats) + and max_buffer_value is UINT32_MAX (internal blend buffer uses 32 bits) */ + +static const AVOption skipblend_options[] = { + { "step", "set frame step", OFFSET(frame_step), AV_OPT_TYPE_INT64, {.i64=1}, 1, UINT16_MAX, FLAGS}, + { "blend", "number of frames to blend per step", OFFSET(frame_blend), AV_OPT_TYPE_INT64, {.i64=UINT16_MAX}, 1, UINT16_MAX, FLAGS}, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(skipblend); + +#define DEFINE_BLEND(NAME, TYPE, DECL, EXPR) \ +static void blend_##NAME##_##TYPE(AVFilterContext *ctx, AVFrame *in, int plane)\ +{ \ + SkipBlendContext *s = ctx->priv; \ + DECL \ + const int height = s->planeheight[plane]; \ + const int width = s->planewidth[plane]; \ + const int stride = in->linesize[plane] / sizeof(TYPE); \ + TYPE *src = (TYPE *)in->data[plane]; \ + uint32_t *dst = s->data[plane]; \ + int y, x; \ + \ + for (y = 0; y < height; y++) { \ + for (x = 0; x < width; x++) { \ + EXPR; \ + } \ + src += stride; \ + } \ +} + +#define SET_DECL +#define SET_EXPR *dst++ = src[x] +#define ADD_DECL +#define ADD_EXPR *dst++ += src[x] +#define DIV_DECL const int frame_blend = s->frame_blend; +#define DIV_EXPR src[x] = *dst++ / frame_blend + +DEFINE_BLEND(set, uint8_t, SET_DECL, SET_EXPR) +DEFINE_BLEND(set, uint16_t, SET_DECL, SET_EXPR) +DEFINE_BLEND(add, uint8_t, ADD_DECL, ADD_EXPR) +DEFINE_BLEND(add, uint16_t, ADD_DECL, ADD_EXPR) +DEFINE_BLEND(div, uint8_t, DIV_DECL, DIV_EXPR) +DEFINE_BLEND(div, uint16_t, DIV_DECL, DIV_EXPR) + +#undef SET_DECL +#undef SET_EXPR +#undef ADD_DECL +#undef ADD_EXPR +#undef DIV_DECL +#undef DIV_EXPR +#undef DEFINE_BLEND + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + SkipBlendContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out = NULL; + int64_t frame_pos = inlink->frame_count_out % s->frame_step; + int direct = 0; + + /* update destination frame buffer; we need to do this even if filter is + disabled because buffer might be used for later frames when filter is + re-enabled */ + if (!frame_pos) { + /* copy first frame to destination frame buffer */ + for (int plane = 0; plane < s->nb_planes; plane++) + s->blend_set(ctx, in, plane); + } else if (frame_pos < s->frame_blend) { + /* add current frame to destination frame buffer */ + for (int plane = 0; plane < s->nb_planes; plane++) + s->blend_add(ctx, in, plane); + } + + /* write frame */ + if (ctx->is_disabled) { + /* filter is disabled, so pass input frame as is */ + return ff_filter_frame(outlink, in); + } else if ((frame_pos + 1) == s->frame_blend) { + /* filter is enabled, so write when all frames are blended */ + /* create a writable frame */ + if (av_frame_is_writable(in)) { + direct = 1; + out = in; + } else { + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + } + /* finalize destination frame */ + for (int plane = 0; plane < s->nb_planes; plane++) + s->blend_div(ctx, out, plane); + /* free extra frame if created, and pass on output frame */ + if (!direct) + av_frame_free(&in); + return ff_filter_frame(outlink, out); + } else { + av_frame_free(&in); + return 0; + } +} + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ411P, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_GRAY8, + AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_GBRP16, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_NV12, AV_PIX_FMT_NV21, + AV_PIX_FMT_NONE + }; + AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts); + if (!fmts_list) + return AVERROR(ENOMEM); + return ff_set_common_formats(ctx, fmts_list); +} + +static int config_input_props(AVFilterLink *inlink) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + const AVFilterContext *ctx = inlink->dst; + SkipBlendContext *s = ctx->priv; + + s->planewidth[0] = s->planewidth[3] = inlink->w; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->planeheight[0] = s->planeheight[3] = inlink->h; + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + s->nb_planes = av_pix_fmt_count_planes(inlink->format); + for (int plane = 0; plane < s->nb_planes; plane++) { + const int planesize = s->planewidth[plane] * s->planeheight[plane]; + s->data[plane] = av_mallocz_array(planesize, sizeof(uint32_t)); + if (!s->data[plane]) + return AVERROR(ENOMEM); + } + if (desc->comp[0].depth == 8) { + s->blend_set = blend_set_uint8_t; + s->blend_add = blend_add_uint8_t; + s->blend_div = blend_div_uint8_t; + } else if (desc->comp[0].depth == 16) { + s->blend_set = blend_set_uint16_t; + s->blend_add = blend_add_uint16_t; + s->blend_div = blend_div_uint16_t; + } else { + return AVERROR_BUG; + } + return 0; +} + +static int config_output_props(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + const SkipBlendContext *s = ctx->priv; + const AVFilterLink *inlink = ctx->inputs[0]; + + outlink->frame_rate = + av_div_q(inlink->frame_rate, (AVRational){s->frame_step, 1}); + + av_log(ctx, AV_LOG_VERBOSE, "step:%"PRId64" frame_rate:%d/%d(%f) -> frame_rate:%d/%d(%f)\n", + s->frame_step, + inlink->frame_rate.num, inlink->frame_rate.den, av_q2d(inlink->frame_rate), + outlink->frame_rate.num, outlink->frame_rate.den, av_q2d(outlink->frame_rate)); + + return 0; +} + +static av_cold int init(AVFilterContext *ctx) +{ + SkipBlendContext *s = ctx->priv; + s->frame_blend = FFMIN(s->frame_blend, s->frame_step); + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + SkipBlendContext *s = ctx->priv; + for (int plane = 0; plane < s->nb_planes; plane++) + av_freep(&s->data[plane]); +} + +static const AVFilterPad skipblend_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input_props, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad skipblend_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output_props, + }, + { NULL } +}; + +AVFilter ff_vf_skipblend = { + .name = "skipblend", + .description = NULL_IF_CONFIG_SMALL("Skip frames whilst blending skipped frames."), + .priv_size = sizeof(SkipBlendContext), + .priv_class = &skipblend_class, + .init = init, + .uninit = uninit, + .query_formats = query_formats, + .inputs = skipblend_inputs, + .outputs = skipblend_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, +}; diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 8bbdc04896..4fead47c03 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -372,6 +372,14 @@ FATE_FILTER_VSYNTH-$(CONFIG_SWAPRECT_FILTER) += $(FATE_SWAPRECT) FATE_FILTER_VSYNTH-$(CONFIG_TBLEND_FILTER) += fate-filter-tblend fate-filter-tblend: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf tblend=all_mode=difference128 +FATE_SKIPBLEND += fate-filter-skipblend-gray-1 +fate-filter-skipblend-gray-1: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf skipblend=step=6:blend=1 + +FATE_SKIPBLEND += fate-filter-skipblend-gray-2 +fate-filter-skipblend-gray-2: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf skipblend=step=6:blend=3 + +FATE_FILTER_VSYNTH-$(CONFIG_SKIPBLEND_FILTER) += $(FATE_SKIPBLEND) + FATE_FILTER_VSYNTH-$(CONFIG_TELECINE_FILTER) += fate-filter-telecine fate-filter-telecine: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf telecine @@ -447,6 +455,10 @@ fate-filter-fps-cfr: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/apple-animation-v fate-filter-fps-r: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -r 30 -vf fps -pix_fmt yuv420p fate-filter-fps: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -vf fps=30 -pix_fmt yuv420p +FATE_FILTER_SAMPLES-$(call ALLYES, SKIPBLEND_FILTER) += fate-filter-skipblend-anim-1 fate-filter-skipblend-anim-2 +fate-filter-skipblend-anim-1: CMD = framecrc -i $(TARGET_SAMPLES)/filter/anim.mkv -vf skipblend=step=6:blend=1 +fate-filter-skipblend-anim-2: CMD = framecrc -i $(TARGET_SAMPLES)/filter/anim.mkv -vf skipblend=step=6:blend=3 + FATE_FILTER_VSYNTH-$(call ALLYES, FORMAT_FILTER SPLIT_FILTER ALPHAEXTRACT_FILTER ALPHAMERGE_FILTER) += fate-filter-alphaextract_alphamerge_rgb fate-filter-alphaextract_alphamerge_rgb: tests/data/filtergraphs/alphamerge_alphaextract_rgb fate-filter-alphaextract_alphamerge_rgb: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/alphamerge_alphaextract_rgb diff --git a/tests/ref/fate/filter-skipblend-anim-1 b/tests/ref/fate/filter-skipblend-anim-1 new file mode 100644 index 0000000000..0a6dd19965 --- /dev/null +++ b/tests/ref/fate/filter-skipblend-anim-1 @@ -0,0 +1,17 @@ +#tb 0: 1001/4000 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x180 +#sar 0: 1/1 +0, 0, 0, 1, 172800, 0x5adff92c +0, 1, 1, 1, 172800, 0x37b7f659 +0, 2, 2, 1, 172800, 0xb4a6f1d1 +0, 3, 3, 1, 172800, 0xd596f9c6 +0, 4, 4, 1, 172800, 0xff5a015b +0, 5, 5, 1, 172800, 0x65477f11 +0, 6, 6, 1, 172800, 0x41569400 +0, 7, 7, 1, 172800, 0xcff9ddf9 +0, 8, 8, 1, 172800, 0xd6daba1e +0, 9, 9, 1, 172800, 0xad83bda1 +0, 10, 10, 1, 172800, 0x1518bdb3 +0, 11, 11, 1, 172800, 0xfdd1c7ca diff --git a/tests/ref/fate/filter-skipblend-anim-2 b/tests/ref/fate/filter-skipblend-anim-2 new file mode 100644 index 0000000000..3984f6dacb --- /dev/null +++ b/tests/ref/fate/filter-skipblend-anim-2 @@ -0,0 +1,17 @@ +#tb 0: 1001/4000 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x180 +#sar 0: 1/1 +0, 0, 0, 1, 172800, 0xa99bf27e +0, 1, 1, 1, 172800, 0x6e2fdfe3 +0, 2, 2, 1, 172800, 0x96e7ea35 +0, 3, 3, 1, 172800, 0x832ff6cf +0, 4, 4, 1, 172800, 0x7a2dffb9 +0, 5, 5, 1, 172800, 0xa0a05854 +0, 6, 6, 1, 172800, 0x91d93f46 +0, 7, 7, 1, 172800, 0x3051d27b +0, 8, 8, 1, 172800, 0x0c13b87c +0, 9, 9, 1, 172800, 0xa80eba4c +0, 10, 10, 1, 172800, 0xd206ba19 +0, 11, 11, 1, 172800, 0x6608b61c diff --git a/tests/ref/fate/filter-skipblend-gray-1 b/tests/ref/fate/filter-skipblend-gray-1 new file mode 100644 index 0000000000..dd209db4f0 --- /dev/null +++ b/tests/ref/fate/filter-skipblend-gray-1 @@ -0,0 +1,14 @@ +#tb 0: 6/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +0, 0, 0, 1, 152064, 0x05b789ef +0, 1, 1, 1, 152064, 0xe20f7c23 +0, 2, 2, 1, 152064, 0xc711ad61 +0, 3, 3, 1, 152064, 0xf25f6acc +0, 4, 4, 1, 152064, 0xce09f9d6 +0, 5, 5, 1, 152064, 0x0f9d6aca +0, 6, 6, 1, 152064, 0x4c9737ab +0, 7, 7, 1, 152064, 0x20cebfa9 +0, 8, 8, 1, 152064, 0xbb87b483 diff --git a/tests/ref/fate/filter-skipblend-gray-2 b/tests/ref/fate/filter-skipblend-gray-2 new file mode 100644 index 0000000000..c2dfc9bb02 --- /dev/null +++ b/tests/ref/fate/filter-skipblend-gray-2 @@ -0,0 +1,13 @@ +#tb 0: 6/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +0, 0, 0, 1, 152064, 0x999eb961 +0, 1, 1, 1, 152064, 0x0e947017 +0, 2, 2, 1, 152064, 0x2f338ae6 +0, 3, 3, 1, 152064, 0x4ead448b +0, 4, 4, 1, 152064, 0x6aef2c67 +0, 5, 5, 1, 152064, 0x809df637 +0, 6, 6, 1, 152064, 0x57b0bd89 +0, 7, 7, 1, 152064, 0x3649efd8 -- 2.17.1
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel