* [FFmpeg-devel] [PATCH v3 1/5] avfilter/vf_yadif_cuda: simplify filter definition @ 2021-12-16 20:28 Aman Karmani 2021-12-16 20:28 ` [FFmpeg-devel] [PATCH v3 2/5] build: detect Metal.framework and build .metal files Aman Karmani ` (4 more replies) 0 siblings, 5 replies; 12+ messages in thread From: Aman Karmani @ 2021-12-16 20:28 UTC (permalink / raw) To: ffmpeg-devel; +Cc: philipl, Aman Karmani, kernrj From: Aman Karmani <aman@tmm1.net> Signed-off-by: Aman Karmani <aman@tmm1.net> --- libavfilter/vf_yadif_cuda.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/libavfilter/vf_yadif_cuda.c b/libavfilter/vf_yadif_cuda.c index da1ab5a8ff..685b8a2035 100644 --- a/libavfilter/vf_yadif_cuda.c +++ b/libavfilter/vf_yadif_cuda.c @@ -212,23 +212,6 @@ static av_cold void deint_cuda_uninit(AVFilterContext *ctx) s->input_frames = NULL; } -static int deint_cuda_query_formats(AVFilterContext *ctx) -{ - enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE, - }; - int ret; - - if ((ret = ff_formats_ref(ff_make_format_list(pix_fmts), - &ctx->inputs[0]->outcfg.formats)) < 0) - return ret; - if ((ret = ff_formats_ref(ff_make_format_list(pix_fmts), - &ctx->outputs[0]->incfg.formats)) < 0) - return ret; - - return 0; -} - static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -380,9 +363,9 @@ const AVFilter ff_vf_yadif_cuda = { .priv_size = sizeof(DeintCUDAContext), .priv_class = &yadif_cuda_class, .uninit = deint_cuda_uninit, + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_CUDA), FILTER_INPUTS(deint_cuda_inputs), FILTER_OUTPUTS(deint_cuda_outputs), - FILTER_QUERY_FUNC(deint_cuda_query_formats), .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, }; -- 2.33.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". ^ permalink raw reply [flat|nested] 12+ messages in thread
* [FFmpeg-devel] [PATCH v3 2/5] build: detect Metal.framework and build .metal files 2021-12-16 20:28 [FFmpeg-devel] [PATCH v3 1/5] avfilter/vf_yadif_cuda: simplify filter definition Aman Karmani @ 2021-12-16 20:28 ` Aman Karmani 2021-12-17 8:54 ` Martin Storsjö 2021-12-16 20:28 ` [FFmpeg-devel] [PATCH v3 3/5] avutil: add obj-c helpers into header-only include Aman Karmani ` (3 subsequent siblings) 4 siblings, 1 reply; 12+ messages in thread From: Aman Karmani @ 2021-12-16 20:28 UTC (permalink / raw) To: ffmpeg-devel; +Cc: philipl, Aman Karmani, kernrj From: Aman Karmani <aman@tmm1.net> Signed-off-by: Aman Karmani <aman@tmm1.net> --- .gitignore | 3 +++ configure | 8 +++++++- ffbuild/common.mak | 9 +++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9ed24b542e..1a5bb29ad5 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,9 @@ *.swp *.ver *.version +*.metal.air +*.metallib +*.metallib.c *.ptx *.ptx.c *.ptx.gz diff --git a/configure b/configure index 5fffcb8afe..ab00b2d7cb 100755 --- a/configure +++ b/configure @@ -309,6 +309,7 @@ External library support: if openssl, gnutls or libtls is not used [no] --enable-mediacodec enable Android MediaCodec support [no] --enable-mediafoundation enable encoding via MediaFoundation [auto] + --disable-metal disable Apple Metal framework [autodetect] --enable-libmysofa enable libmysofa, needed for sofalizer filter [no] --enable-openal enable OpenAL 1.1 capture support [no] --enable-opencl enable OpenCL processing [no] @@ -382,6 +383,7 @@ Toolchain options: --dep-cc=DEPCC use dependency generator DEPCC [$cc_default] --nvcc=NVCC use Nvidia CUDA compiler NVCC or clang [$nvcc_default] --ld=LD use linker LD [$ld_default] + --metalcc=METALCC use metal compiler METALCC [$metalcc_default] --pkg-config=PKGCONFIG use pkg-config tool PKGCONFIG [$pkg_config_default] --pkg-config-flags=FLAGS pass additional flags to pkgconf [] --ranlib=RANLIB use ranlib RANLIB [$ranlib_default] @@ -2564,6 +2566,7 @@ CMDLINE_SET=" ln_s logfile malloc_prefix + metalcc nm optflags nvcc @@ -3835,6 +3838,7 @@ host_cc_default="gcc" doxygen_default="doxygen" install="install" ln_s_default="ln -s -f" +metalcc_default="xcrun metal" nm_default="nm -g" pkg_config_default=pkg-config ranlib_default="ranlib" @@ -4435,7 +4439,7 @@ if enabled cuda_nvcc; then fi set_default arch cc cxx doxygen pkg_config ranlib strip sysinclude \ - target_exec x86asmexe + target_exec x86asmexe metalcc enabled cross_compile || host_cc_default=$cc set_default host_cc @@ -6326,6 +6330,7 @@ check_apple_framework CoreFoundation check_apple_framework CoreMedia check_apple_framework CoreVideo check_apple_framework CoreAudio +check_apple_framework Metal enabled avfoundation && { disable coregraphics applicationservices @@ -7620,6 +7625,7 @@ ARFLAGS=$arflags AR_O=$ar_o AR_CMD=$ar NM_CMD=$nm +METALCC=$metalcc RANLIB=$ranlib STRIP=$strip STRIPTYPE=$striptype diff --git a/ffbuild/common.mak b/ffbuild/common.mak index 0eb831d434..05440911f4 100644 --- a/ffbuild/common.mak +++ b/ffbuild/common.mak @@ -112,6 +112,15 @@ COMPILE_LASX = $(call COMPILE,CC,LASXFLAGS) $(BIN2CEXE): ffbuild/bin2c_host.o $(HOSTLD) $(HOSTLDFLAGS) $(HOSTLD_O) $^ $(HOSTEXTRALIBS) +%.metal.air: %.metal + $(METALCC) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) -o $@ + +%.metallib: %.metal.air + $(METALCC)lib --split-module-without-linking $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) -o $@ + +%.metallib.c: %.metallib $(BIN2CEXE) + $(BIN2C) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) $@ $(subst .,_,$(basename $(notdir $@))) + %.ptx: %.cu $(SRC_PATH)/compat/cuda/cuda_runtime.h $(COMPILE_NVCC) -- 2.33.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 2/5] build: detect Metal.framework and build .metal files 2021-12-16 20:28 ` [FFmpeg-devel] [PATCH v3 2/5] build: detect Metal.framework and build .metal files Aman Karmani @ 2021-12-17 8:54 ` Martin Storsjö 2021-12-17 19:52 ` Aman Karmani 0 siblings, 1 reply; 12+ messages in thread From: Martin Storsjö @ 2021-12-17 8:54 UTC (permalink / raw) To: FFmpeg development discussions and patches; +Cc: kernrj, Aman Karmani, philipl On Thu, 16 Dec 2021, Aman Karmani wrote: > From: Aman Karmani <aman@tmm1.net> > > Signed-off-by: Aman Karmani <aman@tmm1.net> > --- > .gitignore | 3 +++ > configure | 8 +++++++- > ffbuild/common.mak | 9 +++++++++ > 3 files changed, 19 insertions(+), 1 deletion(-) > > diff --git a/.gitignore b/.gitignore > index 9ed24b542e..1a5bb29ad5 100644 > --- a/.gitignore > +++ b/.gitignore > @@ -19,6 +19,9 @@ > *.swp > *.ver > *.version > +*.metal.air > +*.metallib > +*.metallib.c > *.ptx > *.ptx.c > *.ptx.gz > diff --git a/configure b/configure > index 5fffcb8afe..ab00b2d7cb 100755 > --- a/configure > +++ b/configure > @@ -309,6 +309,7 @@ External library support: > if openssl, gnutls or libtls is not used [no] > --enable-mediacodec enable Android MediaCodec support [no] > --enable-mediafoundation enable encoding via MediaFoundation [auto] > + --disable-metal disable Apple Metal framework [autodetect] > --enable-libmysofa enable libmysofa, needed for sofalizer filter [no] > --enable-openal enable OpenAL 1.1 capture support [no] > --enable-opencl enable OpenCL processing [no] > @@ -382,6 +383,7 @@ Toolchain options: > --dep-cc=DEPCC use dependency generator DEPCC [$cc_default] > --nvcc=NVCC use Nvidia CUDA compiler NVCC or clang [$nvcc_default] > --ld=LD use linker LD [$ld_default] > + --metalcc=METALCC use metal compiler METALCC [$metalcc_default] > --pkg-config=PKGCONFIG use pkg-config tool PKGCONFIG [$pkg_config_default] > --pkg-config-flags=FLAGS pass additional flags to pkgconf [] > --ranlib=RANLIB use ranlib RANLIB [$ranlib_default] > @@ -2564,6 +2566,7 @@ CMDLINE_SET=" > ln_s > logfile > malloc_prefix > + metalcc > nm > optflags > nvcc > @@ -3835,6 +3838,7 @@ host_cc_default="gcc" > doxygen_default="doxygen" > install="install" > ln_s_default="ln -s -f" > +metalcc_default="xcrun metal" > nm_default="nm -g" > pkg_config_default=pkg-config > ranlib_default="ranlib" > @@ -4435,7 +4439,7 @@ if enabled cuda_nvcc; then > fi > > set_default arch cc cxx doxygen pkg_config ranlib strip sysinclude \ > - target_exec x86asmexe > + target_exec x86asmexe metalcc > enabled cross_compile || host_cc_default=$cc > set_default host_cc > > @@ -6326,6 +6330,7 @@ check_apple_framework CoreFoundation > check_apple_framework CoreMedia > check_apple_framework CoreVideo > check_apple_framework CoreAudio > +check_apple_framework Metal > > enabled avfoundation && { > disable coregraphics applicationservices > @@ -7620,6 +7625,7 @@ ARFLAGS=$arflags > AR_O=$ar_o > AR_CMD=$ar > NM_CMD=$nm > +METALCC=$metalcc > RANLIB=$ranlib > STRIP=$strip > STRIPTYPE=$striptype > diff --git a/ffbuild/common.mak b/ffbuild/common.mak > index 0eb831d434..05440911f4 100644 > --- a/ffbuild/common.mak > +++ b/ffbuild/common.mak > @@ -112,6 +112,15 @@ COMPILE_LASX = $(call COMPILE,CC,LASXFLAGS) > $(BIN2CEXE): ffbuild/bin2c_host.o > $(HOSTLD) $(HOSTLDFLAGS) $(HOSTLD_O) $^ $(HOSTEXTRALIBS) > > +%.metal.air: %.metal > + $(METALCC) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) -o $@ > + > +%.metallib: %.metal.air > + $(METALCC)lib --split-module-without-linking $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) -o $@ Hmm, so does this try to run "xcrun metallib" instead of "xcrun metal"? I think that can be kinda brittle, e.g. if someone wants to configure a custom build env, where METALCC expands to e.g. "my-wrapped-metal-compiler.sh". I guess it feels a bit boring to need to define two separate variables, but if it really is two separate tools, then I think that'd be the best for clarity. // Martin _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 2/5] build: detect Metal.framework and build .metal files 2021-12-17 8:54 ` Martin Storsjö @ 2021-12-17 19:52 ` Aman Karmani 0 siblings, 0 replies; 12+ messages in thread From: Aman Karmani @ 2021-12-17 19:52 UTC (permalink / raw) To: FFmpeg development discussions and patches; +Cc: philipl, Richard Kern On Fri, Dec 17, 2021 at 12:54 AM Martin Storsjö <martin@martin.st> wrote: > On Thu, 16 Dec 2021, Aman Karmani wrote: > > > From: Aman Karmani <aman@tmm1.net> > > > > Signed-off-by: Aman Karmani <aman@tmm1.net> > > --- > > .gitignore | 3 +++ > > configure | 8 +++++++- > > ffbuild/common.mak | 9 +++++++++ > > 3 files changed, 19 insertions(+), 1 deletion(-) > > > > diff --git a/.gitignore b/.gitignore > > index 9ed24b542e..1a5bb29ad5 100644 > > --- a/.gitignore > > +++ b/.gitignore > > @@ -19,6 +19,9 @@ > > *.swp > > *.ver > > *.version > > +*.metal.air > > +*.metallib > > +*.metallib.c > > *.ptx > > *.ptx.c > > *.ptx.gz > > diff --git a/configure b/configure > > index 5fffcb8afe..ab00b2d7cb 100755 > > --- a/configure > > +++ b/configure > > @@ -309,6 +309,7 @@ External library support: > > if openssl, gnutls or libtls is not used [no] > > --enable-mediacodec enable Android MediaCodec support [no] > > --enable-mediafoundation enable encoding via MediaFoundation [auto] > > + --disable-metal disable Apple Metal framework [autodetect] > > --enable-libmysofa enable libmysofa, needed for sofalizer filter > [no] > > --enable-openal enable OpenAL 1.1 capture support [no] > > --enable-opencl enable OpenCL processing [no] > > @@ -382,6 +383,7 @@ Toolchain options: > > --dep-cc=DEPCC use dependency generator DEPCC [$cc_default] > > --nvcc=NVCC use Nvidia CUDA compiler NVCC or clang > [$nvcc_default] > > --ld=LD use linker LD [$ld_default] > > + --metalcc=METALCC use metal compiler METALCC [$metalcc_default] > > --pkg-config=PKGCONFIG use pkg-config tool PKGCONFIG > [$pkg_config_default] > > --pkg-config-flags=FLAGS pass additional flags to pkgconf [] > > --ranlib=RANLIB use ranlib RANLIB [$ranlib_default] > > @@ -2564,6 +2566,7 @@ CMDLINE_SET=" > > ln_s > > logfile > > malloc_prefix > > + metalcc > > nm > > optflags > > nvcc > > @@ -3835,6 +3838,7 @@ host_cc_default="gcc" > > doxygen_default="doxygen" > > install="install" > > ln_s_default="ln -s -f" > > +metalcc_default="xcrun metal" > > nm_default="nm -g" > > pkg_config_default=pkg-config > > ranlib_default="ranlib" > > @@ -4435,7 +4439,7 @@ if enabled cuda_nvcc; then > > fi > > > > set_default arch cc cxx doxygen pkg_config ranlib strip sysinclude \ > > - target_exec x86asmexe > > + target_exec x86asmexe metalcc > > enabled cross_compile || host_cc_default=$cc > > set_default host_cc > > > > @@ -6326,6 +6330,7 @@ check_apple_framework CoreFoundation > > check_apple_framework CoreMedia > > check_apple_framework CoreVideo > > check_apple_framework CoreAudio > > +check_apple_framework Metal > > > > enabled avfoundation && { > > disable coregraphics applicationservices > > @@ -7620,6 +7625,7 @@ ARFLAGS=$arflags > > AR_O=$ar_o > > AR_CMD=$ar > > NM_CMD=$nm > > +METALCC=$metalcc > > RANLIB=$ranlib > > STRIP=$strip > > STRIPTYPE=$striptype > > diff --git a/ffbuild/common.mak b/ffbuild/common.mak > > index 0eb831d434..05440911f4 100644 > > --- a/ffbuild/common.mak > > +++ b/ffbuild/common.mak > > @@ -112,6 +112,15 @@ COMPILE_LASX = $(call COMPILE,CC,LASXFLAGS) > > $(BIN2CEXE): ffbuild/bin2c_host.o > > $(HOSTLD) $(HOSTLDFLAGS) $(HOSTLD_O) $^ $(HOSTEXTRALIBS) > > > > +%.metal.air: %.metal > > + $(METALCC) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<) -o $@ > > + > > +%.metallib: %.metal.air > > + $(METALCC)lib --split-module-without-linking $(patsubst > $(SRC_PATH)/%,$(SRC_LINK)/%,$<) -o $@ > > Hmm, so does this try to run "xcrun metallib" instead of "xcrun metal"? I > think that can be kinda brittle, e.g. if someone wants to configure a > custom build env, where METALCC expands to e.g. > "my-wrapped-metal-compiler.sh". > I guess it feels a bit boring to need to define two separate variables, > but if it really is two separate tools, then I think that'd be the best > for clarity. > Good catch, I forgot about this little hack. I agree and will split the variables. > > // Martin > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". > _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". ^ permalink raw reply [flat|nested] 12+ messages in thread
* [FFmpeg-devel] [PATCH v3 3/5] avutil: add obj-c helpers into header-only include 2021-12-16 20:28 [FFmpeg-devel] [PATCH v3 1/5] avfilter/vf_yadif_cuda: simplify filter definition Aman Karmani 2021-12-16 20:28 ` [FFmpeg-devel] [PATCH v3 2/5] build: detect Metal.framework and build .metal files Aman Karmani @ 2021-12-16 20:28 ` Aman Karmani 2021-12-16 20:28 ` [FFmpeg-devel] [PATCH v3 4/5] avfilter: add metal utilities Aman Karmani ` (2 subsequent siblings) 4 siblings, 0 replies; 12+ messages in thread From: Aman Karmani @ 2021-12-16 20:28 UTC (permalink / raw) To: ffmpeg-devel; +Cc: philipl, Aman Karmani, kernrj From: Aman Karmani <aman@tmm1.net> Signed-off-by: Aman Karmani <aman@tmm1.net> --- libavutil/objc.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 libavutil/objc.h diff --git a/libavutil/objc.h b/libavutil/objc.h new file mode 100644 index 0000000000..3ca1303394 --- /dev/null +++ b/libavutil/objc.h @@ -0,0 +1,32 @@ +/* + * 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 + */ + +#ifndef AVUTIL_OBJC_H +#define AVUTIL_OBJC_H + +#include <Foundation/Foundation.h> + +inline void ff_objc_release(NSObject **obj) +{ + if (*obj) { + [*obj release]; + *obj = nil; + } +} + +#endif /* AVUTIL_OBJC_H */ \ No newline at end of file -- 2.33.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". ^ permalink raw reply [flat|nested] 12+ messages in thread
* [FFmpeg-devel] [PATCH v3 4/5] avfilter: add metal utilities 2021-12-16 20:28 [FFmpeg-devel] [PATCH v3 1/5] avfilter/vf_yadif_cuda: simplify filter definition Aman Karmani 2021-12-16 20:28 ` [FFmpeg-devel] [PATCH v3 2/5] build: detect Metal.framework and build .metal files Aman Karmani 2021-12-16 20:28 ` [FFmpeg-devel] [PATCH v3 3/5] avutil: add obj-c helpers into header-only include Aman Karmani @ 2021-12-16 20:28 ` Aman Karmani 2021-12-16 22:45 ` Marvin Scholz 2021-12-16 20:28 ` [FFmpeg-devel] [PATCH v3 5/5] avfilter: add vf_deinterlace_videotoolbox Aman Karmani 2021-12-17 3:30 ` [FFmpeg-devel] [PATCH v3 1/5] avfilter/vf_yadif_cuda: simplify filter definition Philip Langdale 4 siblings, 1 reply; 12+ messages in thread From: Aman Karmani @ 2021-12-16 20:28 UTC (permalink / raw) To: ffmpeg-devel; +Cc: philipl, Aman Karmani, kernrj From: Aman Karmani <aman@tmm1.net> Signed-off-by: Aman Karmani <aman@tmm1.net> --- libavfilter/metal/utils.h | 35 +++++++++++++++++++ libavfilter/metal/utils.m | 73 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 libavfilter/metal/utils.h create mode 100644 libavfilter/metal/utils.m diff --git a/libavfilter/metal/utils.h b/libavfilter/metal/utils.h new file mode 100644 index 0000000000..bd0319f63c --- /dev/null +++ b/libavfilter/metal/utils.h @@ -0,0 +1,35 @@ +/* + * 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 + */ + +#ifndef AVFILTER_METAL_UTILS_H +#define AVFILTER_METAL_UTILS_H + +#include <Metal/Metal.h> +#include <CoreVideo/CoreVideo.h> + +void ff_metal_compute_encoder_dispatch(id<MTLDevice> device, + id<MTLComputePipelineState> pipeline, + id<MTLComputeCommandEncoder> encoder, + NSUInteger width, NSUInteger height); + +CVMetalTextureRef ff_metal_texture_from_pixbuf(void *avclass, + CVMetalTextureCacheRef textureCache, + CVPixelBufferRef pixbuf, + int plane, + MTLPixelFormat format); +#endif /* AVFILTER_METAL_UTILS_H */ diff --git a/libavfilter/metal/utils.m b/libavfilter/metal/utils.m new file mode 100644 index 0000000000..5df0ed600e --- /dev/null +++ b/libavfilter/metal/utils.m @@ -0,0 +1,73 @@ +/* + * 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 "libavutil/log.h" +#include <libavfilter/metal/utils.h> + +void ff_metal_compute_encoder_dispatch(id<MTLDevice> device, + id<MTLComputePipelineState> pipeline, + id<MTLComputeCommandEncoder> encoder, + NSUInteger width, NSUInteger height) +{ + [encoder setComputePipelineState:pipeline]; + NSUInteger w = pipeline.threadExecutionWidth; + NSUInteger h = pipeline.maxTotalThreadsPerThreadgroup / w; + MTLSize threadsPerThreadgroup = MTLSizeMake(w, h, 1); + BOOL fallback = YES; + if (@available(macOS 10.15, iOS 11, tvOS 14.5, *)) { + if ([device supportsFamily:MTLGPUFamilyCommon3]) { + MTLSize threadsPerGrid = MTLSizeMake(width, height, 1); + [encoder dispatchThreads:threadsPerGrid threadsPerThreadgroup:threadsPerThreadgroup]; + fallback = NO; + } + } + if (fallback) { + MTLSize threadgroups = MTLSizeMake((width + w - 1) / w, + (height + h - 1) / h, + 1); + [encoder dispatchThreadgroups:threadgroups threadsPerThreadgroup:threadsPerThreadgroup]; + } +} + +CVMetalTextureRef ff_metal_texture_from_pixbuf(void *ctx, + CVMetalTextureCacheRef textureCache, + CVPixelBufferRef pixbuf, + int plane, + MTLPixelFormat format) +{ + CVMetalTextureRef tex = NULL; + CVReturn ret; + + ret = CVMetalTextureCacheCreateTextureFromImage( + NULL, + textureCache, + pixbuf, + NULL, + format, + CVPixelBufferGetWidthOfPlane(pixbuf, plane), + CVPixelBufferGetHeightOfPlane(pixbuf, plane), + plane, + &tex + ); + if (ret != kCVReturnSuccess) { + av_log(ctx, AV_LOG_ERROR, "Failed to create CVMetalTexture from image: %d\n", ret); + return NULL; + } + + return tex; +} \ No newline at end of file -- 2.33.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 4/5] avfilter: add metal utilities 2021-12-16 20:28 ` [FFmpeg-devel] [PATCH v3 4/5] avfilter: add metal utilities Aman Karmani @ 2021-12-16 22:45 ` Marvin Scholz [not found] ` <CAK=uwuwsNg+Ujk0rx_FXP4KEhEzZ9qXJFKCAJkQqgJ8fkNKOHQ@mail.gmail.com> 0 siblings, 1 reply; 12+ messages in thread From: Marvin Scholz @ 2021-12-16 22:45 UTC (permalink / raw) To: FFmpeg development discussions and patches; +Cc: kernrj, Aman Karmani, philipl On 16 Dec 2021, at 21:28, Aman Karmani wrote: > From: Aman Karmani <aman@tmm1.net> > Thanks for your work on this! Some comments inline: > Signed-off-by: Aman Karmani <aman@tmm1.net> > --- > libavfilter/metal/utils.h | 35 +++++++++++++++++++ > libavfilter/metal/utils.m | 73 > +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 108 insertions(+) > create mode 100644 libavfilter/metal/utils.h > create mode 100644 libavfilter/metal/utils.m > > diff --git a/libavfilter/metal/utils.h b/libavfilter/metal/utils.h > new file mode 100644 > index 0000000000..bd0319f63c > --- /dev/null > +++ b/libavfilter/metal/utils.h > @@ -0,0 +1,35 @@ > +/* > + * 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 > + */ > + > +#ifndef AVFILTER_METAL_UTILS_H > +#define AVFILTER_METAL_UTILS_H > + > +#include <Metal/Metal.h> > +#include <CoreVideo/CoreVideo.h> > + > +void ff_metal_compute_encoder_dispatch(id<MTLDevice> device, > + id<MTLComputePipelineState> > pipeline, > + id<MTLComputeCommandEncoder> > encoder, > + NSUInteger width, NSUInteger > height); > + > +CVMetalTextureRef ff_metal_texture_from_pixbuf(void *avclass, > + CVMetalTextureCacheRef > textureCache, > + CVPixelBufferRef > pixbuf, > + int plane, > + MTLPixelFormat > format); > +#endif /* AVFILTER_METAL_UTILS_H */ > diff --git a/libavfilter/metal/utils.m b/libavfilter/metal/utils.m > new file mode 100644 > index 0000000000..5df0ed600e > --- /dev/null > +++ b/libavfilter/metal/utils.m > @@ -0,0 +1,73 @@ > +/* > + * 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 "libavutil/log.h" > +#include <libavfilter/metal/utils.h> > + > +void ff_metal_compute_encoder_dispatch(id<MTLDevice> device, > + id<MTLComputePipelineState> > pipeline, > + id<MTLComputeCommandEncoder> > encoder, > + NSUInteger width, NSUInteger > height) > +{ > + [encoder setComputePipelineState:pipeline]; > + NSUInteger w = pipeline.threadExecutionWidth; > + NSUInteger h = pipeline.maxTotalThreadsPerThreadgroup / w; > + MTLSize threadsPerThreadgroup = MTLSizeMake(w, h, 1); > + BOOL fallback = YES; > + if (@available(macOS 10.15, iOS 11, tvOS 14.5, *)) { > + if ([device supportsFamily:MTLGPUFamilyCommon3]) { > + MTLSize threadsPerGrid = MTLSizeMake(width, height, 1); > + [encoder dispatchThreads:threadsPerGrid > threadsPerThreadgroup:threadsPerThreadgroup]; > + fallback = NO; > + } > + } Why not just do an else here instead of the fallback variable? > + if (fallback) { > + MTLSize threadgroups = MTLSizeMake((width + w - 1) / w, > + (height + h - 1) / h, > + 1); > + [encoder dispatchThreadgroups:threadgroups > threadsPerThreadgroup:threadsPerThreadgroup]; > + } > +} > + > +CVMetalTextureRef ff_metal_texture_from_pixbuf(void *ctx, > + CVMetalTextureCacheRef > textureCache, > + CVPixelBufferRef > pixbuf, > + int plane, > + MTLPixelFormat format) > +{ > + CVMetalTextureRef tex = NULL; > + CVReturn ret; > + > + ret = CVMetalTextureCacheCreateTextureFromImage( > + NULL, > + textureCache, > + pixbuf, > + NULL, > + format, > + CVPixelBufferGetWidthOfPlane(pixbuf, plane), > + CVPixelBufferGetHeightOfPlane(pixbuf, plane), > + plane, > + &tex > + ); > + if (ret != kCVReturnSuccess) { > + av_log(ctx, AV_LOG_ERROR, "Failed to create CVMetalTexture > from image: %d\n", ret); > + return NULL; > + } > + > + return tex; > +} > \ No newline at end of file Missing newline at end of file > -- > 2.33.0 > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". ^ permalink raw reply [flat|nested] 12+ messages in thread
[parent not found: <CAK=uwuwsNg+Ujk0rx_FXP4KEhEzZ9qXJFKCAJkQqgJ8fkNKOHQ@mail.gmail.com>]
* Re: [FFmpeg-devel] [PATCH v3 4/5] avfilter: add metal utilities [not found] ` <CAK=uwuwsNg+Ujk0rx_FXP4KEhEzZ9qXJFKCAJkQqgJ8fkNKOHQ@mail.gmail.com> @ 2021-12-16 23:13 ` Marvin Scholz [not found] ` <CAK=uwuxHQ28r6EOQKf7FE-QxRu2XYheLzg54S_YuLdLax=OjEA@mail.gmail.com> 0 siblings, 1 reply; 12+ messages in thread From: Marvin Scholz @ 2021-12-16 23:13 UTC (permalink / raw) To: Aman Karmani Cc: Richard Kern, FFmpeg development discussions and patches, philipl On 16 Dec 2021, at 23:53, Aman Karmani wrote: > On Thu, Dec 16, 2021 at 2:45 PM Marvin Scholz <epirat07@gmail.com> > wrote: > >> On 16 Dec 2021, at 21:28, Aman Karmani wrote: >> >>> From: Aman Karmani <aman@tmm1.net> >>> >> >> Thanks for your work on this! Some comments inline: >> >>> Signed-off-by: Aman Karmani <aman@tmm1.net> >>> --- >>> libavfilter/metal/utils.h | 35 +++++++++++++++++++ >>> libavfilter/metal/utils.m | 73 >>> +++++++++++++++++++++++++++++++++++++++ >>> 2 files changed, 108 insertions(+) >>> create mode 100644 libavfilter/metal/utils.h >>> create mode 100644 libavfilter/metal/utils.m >>> >>> diff --git a/libavfilter/metal/utils.h b/libavfilter/metal/utils.h >>> new file mode 100644 >>> index 0000000000..bd0319f63c >>> --- /dev/null >>> +++ b/libavfilter/metal/utils.h >>> @@ -0,0 +1,35 @@ >>> +/* >>> + * 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 >>> + */ >>> + >>> +#ifndef AVFILTER_METAL_UTILS_H >>> +#define AVFILTER_METAL_UTILS_H >>> + >>> +#include <Metal/Metal.h> >>> +#include <CoreVideo/CoreVideo.h> >>> + >>> +void ff_metal_compute_encoder_dispatch(id<MTLDevice> device, >>> + id<MTLComputePipelineState> >>> pipeline, >>> + id<MTLComputeCommandEncoder> >>> encoder, >>> + NSUInteger width, NSUInteger >>> height); >>> + >>> +CVMetalTextureRef ff_metal_texture_from_pixbuf(void *avclass, >>> + >>> CVMetalTextureCacheRef >>> textureCache, >>> + CVPixelBufferRef >>> pixbuf, >>> + int plane, >>> + MTLPixelFormat >>> format); >>> +#endif /* AVFILTER_METAL_UTILS_H */ >>> diff --git a/libavfilter/metal/utils.m b/libavfilter/metal/utils.m >>> new file mode 100644 >>> index 0000000000..5df0ed600e >>> --- /dev/null >>> +++ b/libavfilter/metal/utils.m >>> @@ -0,0 +1,73 @@ >>> +/* >>> + * 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 "libavutil/log.h" >>> +#include <libavfilter/metal/utils.h> >>> + >>> +void ff_metal_compute_encoder_dispatch(id<MTLDevice> device, >>> + id<MTLComputePipelineState> >>> pipeline, >>> + id<MTLComputeCommandEncoder> >>> encoder, >>> + NSUInteger width, NSUInteger >>> height) >>> +{ >>> + [encoder setComputePipelineState:pipeline]; >>> + NSUInteger w = pipeline.threadExecutionWidth; >>> + NSUInteger h = pipeline.maxTotalThreadsPerThreadgroup / w; >>> + MTLSize threadsPerThreadgroup = MTLSizeMake(w, h, 1); >>> + BOOL fallback = YES; >>> + if (@available(macOS 10.15, iOS 11, tvOS 14.5, *)) { >>> + if ([device supportsFamily:MTLGPUFamilyCommon3]) { >>> + MTLSize threadsPerGrid = MTLSizeMake(width, height, 1); >>> + [encoder dispatchThreads:threadsPerGrid >>> threadsPerThreadgroup:threadsPerThreadgroup]; >>> + fallback = NO; >>> + } >>> + } >> >> Why not just do an else here instead of the fallback variable? >> > > Well there's two if statements, and we need to run the fallback only > when > both fail. So where would the else go? I would need to duplicate it > twice. > Oh, is it not possible to just add the [device supportsFamily:MTLGPUFamilyCommon3] after the @available check? Or does that not work, just like its is not possible to negate a @available for some reason? > >> >>> + if (fallback) { >>> + MTLSize threadgroups = MTLSizeMake((width + w - 1) / w, >>> + (height + h - 1) / h, >>> + 1); >>> + [encoder dispatchThreadgroups:threadgroups >>> threadsPerThreadgroup:threadsPerThreadgroup]; >>> + } >>> +} >>> + >>> +CVMetalTextureRef ff_metal_texture_from_pixbuf(void *ctx, >>> + >>> CVMetalTextureCacheRef >>> textureCache, >>> + CVPixelBufferRef >>> pixbuf, >>> + int plane, >>> + MTLPixelFormat >>> format) >>> +{ >>> + CVMetalTextureRef tex = NULL; >>> + CVReturn ret; >>> + >>> + ret = CVMetalTextureCacheCreateTextureFromImage( >>> + NULL, >>> + textureCache, >>> + pixbuf, >>> + NULL, >>> + format, >>> + CVPixelBufferGetWidthOfPlane(pixbuf, plane), >>> + CVPixelBufferGetHeightOfPlane(pixbuf, plane), >>> + plane, >>> + &tex >>> + ); >>> + if (ret != kCVReturnSuccess) { >>> + av_log(ctx, AV_LOG_ERROR, "Failed to create CVMetalTexture >>> from image: %d\n", ret); >>> + return NULL; >>> + } >>> + >>> + return tex; >>> +} >>> \ No newline at end of file >> >> Missing newline at end of file >> > > Fixed locally, thanks. > > >> >>> -- >>> 2.33.0 >>> >>> _______________________________________________ >>> ffmpeg-devel mailing list >>> ffmpeg-devel@ffmpeg.org >>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel >>> >>> To unsubscribe, visit link above, or email >>> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". >> _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". ^ permalink raw reply [flat|nested] 12+ messages in thread
[parent not found: <CAK=uwuxHQ28r6EOQKf7FE-QxRu2XYheLzg54S_YuLdLax=OjEA@mail.gmail.com>]
* Re: [FFmpeg-devel] [PATCH v3 4/5] avfilter: add metal utilities [not found] ` <CAK=uwuxHQ28r6EOQKf7FE-QxRu2XYheLzg54S_YuLdLax=OjEA@mail.gmail.com> @ 2021-12-17 1:32 ` Marvin Scholz 0 siblings, 0 replies; 12+ messages in thread From: Marvin Scholz @ 2021-12-17 1:32 UTC (permalink / raw) To: Aman Karmani Cc: Richard Kern, FFmpeg development discussions and patches, philipl On 17 Dec 2021, at 2:14, Aman Karmani wrote: > On Thu, Dec 16, 2021 at 3:13 PM Marvin Scholz <epirat07@gmail.com> wrote: > >> >> >> On 16 Dec 2021, at 23:53, Aman Karmani wrote: >> >>> On Thu, Dec 16, 2021 at 2:45 PM Marvin Scholz <epirat07@gmail.com> >>> wrote: >>> >>>> On 16 Dec 2021, at 21:28, Aman Karmani wrote: >>>> >>>>> From: Aman Karmani <aman@tmm1.net> >>>>> >>>> >>>> Thanks for your work on this! Some comments inline: >>>> >>>>> Signed-off-by: Aman Karmani <aman@tmm1.net> >>>>> --- >>>>> libavfilter/metal/utils.h | 35 +++++++++++++++++++ >>>>> libavfilter/metal/utils.m | 73 >>>>> +++++++++++++++++++++++++++++++++++++++ >>>>> 2 files changed, 108 insertions(+) >>>>> create mode 100644 libavfilter/metal/utils.h >>>>> create mode 100644 libavfilter/metal/utils.m >>>>> >>>>> diff --git a/libavfilter/metal/utils.h b/libavfilter/metal/utils.h >>>>> new file mode 100644 >>>>> index 0000000000..bd0319f63c >>>>> --- /dev/null >>>>> +++ b/libavfilter/metal/utils.h >>>>> @@ -0,0 +1,35 @@ >>>>> +/* >>>>> + * 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 >>>>> + */ >>>>> + >>>>> +#ifndef AVFILTER_METAL_UTILS_H >>>>> +#define AVFILTER_METAL_UTILS_H >>>>> + >>>>> +#include <Metal/Metal.h> >>>>> +#include <CoreVideo/CoreVideo.h> >>>>> + >>>>> +void ff_metal_compute_encoder_dispatch(id<MTLDevice> device, >>>>> + id<MTLComputePipelineState> >>>>> pipeline, >>>>> + id<MTLComputeCommandEncoder> >>>>> encoder, >>>>> + NSUInteger width, NSUInteger >>>>> height); >>>>> + >>>>> +CVMetalTextureRef ff_metal_texture_from_pixbuf(void *avclass, >>>>> + >>>>> CVMetalTextureCacheRef >>>>> textureCache, >>>>> + CVPixelBufferRef >>>>> pixbuf, >>>>> + int plane, >>>>> + MTLPixelFormat >>>>> format); >>>>> +#endif /* AVFILTER_METAL_UTILS_H */ >>>>> diff --git a/libavfilter/metal/utils.m b/libavfilter/metal/utils.m >>>>> new file mode 100644 >>>>> index 0000000000..5df0ed600e >>>>> --- /dev/null >>>>> +++ b/libavfilter/metal/utils.m >>>>> @@ -0,0 +1,73 @@ >>>>> +/* >>>>> + * 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 "libavutil/log.h" >>>>> +#include <libavfilter/metal/utils.h> >>>>> + >>>>> +void ff_metal_compute_encoder_dispatch(id<MTLDevice> device, >>>>> + id<MTLComputePipelineState> >>>>> pipeline, >>>>> + id<MTLComputeCommandEncoder> >>>>> encoder, >>>>> + NSUInteger width, NSUInteger >>>>> height) >>>>> +{ >>>>> + [encoder setComputePipelineState:pipeline]; >>>>> + NSUInteger w = pipeline.threadExecutionWidth; >>>>> + NSUInteger h = pipeline.maxTotalThreadsPerThreadgroup / w; >>>>> + MTLSize threadsPerThreadgroup = MTLSizeMake(w, h, 1); >>>>> + BOOL fallback = YES; >>>>> + if (@available(macOS 10.15, iOS 11, tvOS 14.5, *)) { >>>>> + if ([device supportsFamily:MTLGPUFamilyCommon3]) { >>>>> + MTLSize threadsPerGrid = MTLSizeMake(width, height, 1); >>>>> + [encoder dispatchThreads:threadsPerGrid >>>>> threadsPerThreadgroup:threadsPerThreadgroup]; >>>>> + fallback = NO; >>>>> + } >>>>> + } >>>> >>>> Why not just do an else here instead of the fallback variable? >>>> >>> >>> Well there's two if statements, and we need to run the fallback only >>> when >>> both fail. So where would the else go? I would need to duplicate it >>> twice. >>> >> >> Oh, is it not possible to just add the [device >> supportsFamily:MTLGPUFamilyCommon3] >> after the @available check? Or does that not work, just like its is not >> possible to >> negate a @available for some reason? >> > > Indeed, my understanding is that the only way to use it is without any > negation or other conditionals. > > Here's what the compiler says when I try what you suggested: > > OBJCC libavfilter/metal/utils.o > libavfilter/metal/utils.m:31:9: warning: @available does not guard > availability here; use if (@available) instead > [-Wunsupported-availability-guard] > if (@available(macOS 10.15, iOS 11, tvOS 14.5, *) && [device > supportsFamily:MTLGPUFamilyCommon3]) { > ^ > 1 warning generated. > Ah, unfortunate… Nevermind then. > >>> >>>> >>>>> + if (fallback) { >>>>> + MTLSize threadgroups = MTLSizeMake((width + w - 1) / w, >>>>> + (height + h - 1) / h, >>>>> + 1); >>>>> + [encoder dispatchThreadgroups:threadgroups >>>>> threadsPerThreadgroup:threadsPerThreadgroup]; >>>>> + } >>>>> +} >>>>> + >>>>> +CVMetalTextureRef ff_metal_texture_from_pixbuf(void *ctx, >>>>> + >>>>> CVMetalTextureCacheRef >>>>> textureCache, >>>>> + CVPixelBufferRef >>>>> pixbuf, >>>>> + int plane, >>>>> + MTLPixelFormat >>>>> format) >>>>> +{ >>>>> + CVMetalTextureRef tex = NULL; >>>>> + CVReturn ret; >>>>> + >>>>> + ret = CVMetalTextureCacheCreateTextureFromImage( >>>>> + NULL, >>>>> + textureCache, >>>>> + pixbuf, >>>>> + NULL, >>>>> + format, >>>>> + CVPixelBufferGetWidthOfPlane(pixbuf, plane), >>>>> + CVPixelBufferGetHeightOfPlane(pixbuf, plane), >>>>> + plane, >>>>> + &tex >>>>> + ); >>>>> + if (ret != kCVReturnSuccess) { >>>>> + av_log(ctx, AV_LOG_ERROR, "Failed to create CVMetalTexture >>>>> from image: %d\n", ret); >>>>> + return NULL; >>>>> + } >>>>> + >>>>> + return tex; >>>>> +} >>>>> \ No newline at end of file >>>> >>>> Missing newline at end of file >>>> >>> >>> Fixed locally, thanks. >>> >>> >>>> >>>>> -- >>>>> 2.33.0 >>>>> >>>>> _______________________________________________ >>>>> ffmpeg-devel mailing list >>>>> ffmpeg-devel@ffmpeg.org >>>>> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel >>>>> >>>>> To unsubscribe, visit link above, or email >>>>> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". >>>> >> >> >> _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". ^ permalink raw reply [flat|nested] 12+ messages in thread
* [FFmpeg-devel] [PATCH v3 5/5] avfilter: add vf_deinterlace_videotoolbox 2021-12-16 20:28 [FFmpeg-devel] [PATCH v3 1/5] avfilter/vf_yadif_cuda: simplify filter definition Aman Karmani ` (2 preceding siblings ...) 2021-12-16 20:28 ` [FFmpeg-devel] [PATCH v3 4/5] avfilter: add metal utilities Aman Karmani @ 2021-12-16 20:28 ` Aman Karmani 2021-12-17 3:39 ` Philip Langdale 2021-12-17 3:30 ` [FFmpeg-devel] [PATCH v3 1/5] avfilter/vf_yadif_cuda: simplify filter definition Philip Langdale 4 siblings, 1 reply; 12+ messages in thread From: Aman Karmani @ 2021-12-16 20:28 UTC (permalink / raw) To: ffmpeg-devel; +Cc: philipl, Aman Karmani, kernrj From: Aman Karmani <aman@tmm1.net> deinterlaces CVPixelBuffers, i.e. AV_PIX_FMT_VIDEOTOOLBOX frames currently implements YADIF, but other algorithms could easily be added to the same filter. for example, an interlaced mpeg2 file can be decoded by avcodec, uploaded into a CVPixelBuffer, deinterlaced by metal, and then encoded to h264 by VideoToolbox as follows: ffmpeg \ -init_hw_device videotoolbox \ -i interlaced.ts \ -vf hwupload,deinterlace_videotoolbox=mode=send_field:deint=interlaced \ -c:v h264_videotoolbox \ -b:v 2000k \ -c:a copy \ -y progressive.ts (note that uploading AVFrame into CVPixelBuffer via hwupload requires 504c60660d3194758823ddd45ceddb86e35d806f) Signed-off-by: Aman Karmani <aman@tmm1.net> --- configure | 1 + libavfilter/Makefile | 4 + libavfilter/allfilters.c | 1 + .../metal/vf_deinterlace_videotoolbox.metal | 269 ++++++++++++ libavfilter/vf_deinterlace_videotoolbox.m | 400 ++++++++++++++++++ 5 files changed, 675 insertions(+) create mode 100644 libavfilter/metal/vf_deinterlace_videotoolbox.metal create mode 100644 libavfilter/vf_deinterlace_videotoolbox.m diff --git a/configure b/configure index ab00b2d7cb..cbaef21bbf 100755 --- a/configure +++ b/configure @@ -3620,6 +3620,7 @@ cover_rect_filter_deps="avcodec avformat gpl" cropdetect_filter_deps="gpl" deinterlace_qsv_filter_deps="libmfx" deinterlace_vaapi_filter_deps="vaapi" +deinterlace_videotoolbox_filter_deps="metal corevideo videotoolbox" delogo_filter_deps="gpl" denoise_vaapi_filter_deps="vaapi" derain_filter_select="dnn" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 2fe495df28..4812f88045 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -241,6 +241,10 @@ OBJS-$(CONFIG_DEFLATE_FILTER) += vf_neighbor.o OBJS-$(CONFIG_DEFLICKER_FILTER) += vf_deflicker.o OBJS-$(CONFIG_DEINTERLACE_QSV_FILTER) += vf_deinterlace_qsv.o OBJS-$(CONFIG_DEINTERLACE_VAAPI_FILTER) += vf_deinterlace_vaapi.o vaapi_vpp.o +OBJS-$(CONFIG_DEINTERLACE_VIDEOTOOLBOX_FILTER) += vf_deinterlace_videotoolbox.o \ + metal/vf_deinterlace_videotoolbox.metallib.o \ + metal/utils.o \ + yadif_common.o OBJS-$(CONFIG_DEJUDDER_FILTER) += vf_dejudder.o OBJS-$(CONFIG_DELOGO_FILTER) += vf_delogo.o OBJS-$(CONFIG_DENOISE_VAAPI_FILTER) += vf_misc_vaapi.o vaapi_vpp.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index ec57a2c49c..2ed3deb7dd 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -228,6 +228,7 @@ extern const AVFilter ff_vf_deflate; extern const AVFilter ff_vf_deflicker; extern const AVFilter ff_vf_deinterlace_qsv; extern const AVFilter ff_vf_deinterlace_vaapi; +extern const AVFilter ff_vf_deinterlace_videotoolbox; extern const AVFilter ff_vf_dejudder; extern const AVFilter ff_vf_delogo; extern const AVFilter ff_vf_denoise_vaapi; diff --git a/libavfilter/metal/vf_deinterlace_videotoolbox.metal b/libavfilter/metal/vf_deinterlace_videotoolbox.metal new file mode 100644 index 0000000000..50783f2ffe --- /dev/null +++ b/libavfilter/metal/vf_deinterlace_videotoolbox.metal @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2018 Philip Langdale <philipl@overt.org> + * 2020 Aman Karmani <aman@tmm1.net> + * 2020 Stefan Dyulgerov <stefan.dyulgerov@gmail.com> + * + * 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 <metal_stdlib> +#include <metal_integer> +#include <metal_texture> + +using namespace metal; + +/* + * Parameters + */ + +struct deintParams { + uint channels; + uint parity; + uint tff; + bool is_second_field; + bool skip_spatial_check; + int field_mode; +}; + +/* + * Texture access helpers + */ + +#define accesstype access::sample +const sampler s(coord::pixel); + +template <typename T> +T tex2D(texture2d<float, access::sample> tex, uint x, uint y) +{ + return tex.sample(s, float2(x, y)).x; +} + +template <> +float2 tex2D<float2>(texture2d<float, access::sample> tex, uint x, uint y) +{ + return tex.sample(s, float2(x, y)).xy; +} + +template <typename T> +T tex2D(texture2d<float, access::read> tex, uint x, uint y) +{ + return tex.read(uint2(x, y)).x; +} + +template <> +float2 tex2D<float2>(texture2d<float, access::read> tex, uint x, uint y) +{ + return tex.read(uint2(x, y)).xy; +} + +/* + * YADIF helpers + */ + +template<typename T> +T spatial_predictor(T a, T b, T c, T d, T e, T f, T g, + T h, T i, T j, T k, T l, T m, T n) +{ + T spatial_pred = (d + k)/2; + T spatial_score = abs(c - j) + abs(d - k) + abs(e - l); + + T score = abs(b - k) + abs(c - l) + abs(d - m); + if (score < spatial_score) { + spatial_pred = (c + l)/2; + spatial_score = score; + score = abs(a - l) + abs(b - m) + abs(c - n); + if (score < spatial_score) { + spatial_pred = (b + m)/2; + spatial_score = score; + } + } + score = abs(d - i) + abs(e - j) + abs(f - k); + if (score < spatial_score) { + spatial_pred = (e + j)/2; + spatial_score = score; + score = abs(e - h) + abs(f - i) + abs(g - j); + if (score < spatial_score) { + spatial_pred = (f + i)/2; + spatial_score = score; + } + } + return spatial_pred; +} + +template<typename T> +T temporal_predictor(T A, T B, T C, T D, T E, T F, + T G, T H, T I, T J, T K, T L, + T spatial_pred, bool skip_check) +{ + T p0 = (C + H) / 2; + T p1 = F; + T p2 = (D + I) / 2; + T p3 = G; + T p4 = (E + J) / 2; + + T tdiff0 = abs(D - I); + T tdiff1 = (abs(A - F) + abs(B - G)) / 2; + T tdiff2 = (abs(K - F) + abs(G - L)) / 2; + + T diff = max3(tdiff0, tdiff1, tdiff2); + + if (!skip_check) { + T maxi = max3(p2 - p3, p2 - p1, min(p0 - p1, p4 - p3)); + T mini = min3(p2 - p3, p2 - p1, max(p0 - p1, p4 - p3)); + diff = max3(diff, mini, -maxi); + } + + return clamp(spatial_pred, p2 - diff, p2 + diff); +} + +#define T float2 +template <> +T spatial_predictor<T>(T a, T b, T c, T d, T e, T f, T g, + T h, T i, T j, T k, T l, T m, T n) +{ + return T( + spatial_predictor(a.x, b.x, c.x, d.x, e.x, f.x, g.x, + h.x, i.x, j.x, k.x, l.x, m.x, n.x), + spatial_predictor(a.y, b.y, c.y, d.y, e.y, f.y, g.y, + h.y, i.y, j.y, k.y, l.y, m.y, n.y) + ); +} + +template <> +T temporal_predictor<T>(T A, T B, T C, T D, T E, T F, + T G, T H, T I, T J, T K, T L, + T spatial_pred, bool skip_check) +{ + return T( + temporal_predictor(A.x, B.x, C.x, D.x, E.x, F.x, + G.x, H.x, I.x, J.x, K.x, L.x, + spatial_pred.x, skip_check), + temporal_predictor(A.y, B.y, C.y, D.y, E.y, F.y, + G.y, H.y, I.y, J.y, K.y, L.y, + spatial_pred.y, skip_check) + ); +} +#undef T + +/* + * YADIF compute + */ + +template <typename T> +T yadif_compute_spatial( + texture2d<float, accesstype> cur, + uint2 pos) +{ + // Calculate spatial prediction + T a = tex2D<T>(cur, pos.x - 3, pos.y - 1); + T b = tex2D<T>(cur, pos.x - 2, pos.y - 1); + T c = tex2D<T>(cur, pos.x - 1, pos.y - 1); + T d = tex2D<T>(cur, pos.x - 0, pos.y - 1); + T e = tex2D<T>(cur, pos.x + 1, pos.y - 1); + T f = tex2D<T>(cur, pos.x + 2, pos.y - 1); + T g = tex2D<T>(cur, pos.x + 3, pos.y - 1); + + T h = tex2D<T>(cur, pos.x - 3, pos.y + 1); + T i = tex2D<T>(cur, pos.x - 2, pos.y + 1); + T j = tex2D<T>(cur, pos.x - 1, pos.y + 1); + T k = tex2D<T>(cur, pos.x - 0, pos.y + 1); + T l = tex2D<T>(cur, pos.x + 1, pos.y + 1); + T m = tex2D<T>(cur, pos.x + 2, pos.y + 1); + T n = tex2D<T>(cur, pos.x + 3, pos.y + 1); + + return spatial_predictor(a, b, c, d, e, f, g, + h, i, j, k, l, m, n); +} + +template <typename T> +T yadif_compute_temporal( + texture2d<float, accesstype> cur, + texture2d<float, accesstype> prev2, + texture2d<float, accesstype> prev1, + texture2d<float, accesstype> next1, + texture2d<float, accesstype> next2, + T spatial_pred, + bool skip_spatial_check, + uint2 pos) +{ + // Calculate temporal prediction + T A = tex2D<T>(prev2, pos.x, pos.y - 1); + T B = tex2D<T>(prev2, pos.x, pos.y + 1); + T C = tex2D<T>(prev1, pos.x, pos.y - 2); + T D = tex2D<T>(prev1, pos.x, pos.y + 0); + T E = tex2D<T>(prev1, pos.x, pos.y + 2); + T F = tex2D<T>(cur, pos.x, pos.y - 1); + T G = tex2D<T>(cur, pos.x, pos.y + 1); + T H = tex2D<T>(next1, pos.x, pos.y - 2); + T I = tex2D<T>(next1, pos.x, pos.y + 0); + T J = tex2D<T>(next1, pos.x, pos.y + 2); + T K = tex2D<T>(next2, pos.x, pos.y - 1); + T L = tex2D<T>(next2, pos.x, pos.y + 1); + + return temporal_predictor(A, B, C, D, E, F, G, H, I, J, K, L, + spatial_pred, skip_spatial_check); +} + +template <typename T> +T yadif( + texture2d<float, access::write> dst, + texture2d<float, accesstype> prev, + texture2d<float, accesstype> cur, + texture2d<float, accesstype> next, + constant deintParams& params, + uint2 pos) +{ + T spatial_pred = yadif_compute_spatial<T>(cur, pos); + + if (params.is_second_field) { + return yadif_compute_temporal(cur, prev, cur, next, next, spatial_pred, params.skip_spatial_check, pos); + } else { + return yadif_compute_temporal(cur, prev, prev, cur, next, spatial_pred, params.skip_spatial_check, pos); + } +} + +/* + * Kernel dispatch + */ + +kernel void deint( + texture2d<float, access::write> dst [[texture(0)]], + texture2d<float, accesstype> prev [[texture(1)]], + texture2d<float, accesstype> cur [[texture(2)]], + texture2d<float, accesstype> next [[texture(3)]], + constant deintParams& params [[buffer(4)]], + uint2 pos [[thread_position_in_grid]]) +{ + if ((pos.x >= dst.get_width()) || + (pos.y >= dst.get_height())) { + return; + } + + // Don't modify the primary field + if (pos.y % 2 == params.parity) { + float4 in = cur.read(pos); + dst.write(in, pos); + return; + } + + float2 pred; + if (params.channels == 1) + pred = float2(yadif<float>(dst, prev, cur, next, params, pos)); + else + pred = yadif<float2>(dst, prev, cur, next, params, pos); + dst.write(pred.xyyy, pos); +} diff --git a/libavfilter/vf_deinterlace_videotoolbox.m b/libavfilter/vf_deinterlace_videotoolbox.m new file mode 100644 index 0000000000..b18155277b --- /dev/null +++ b/libavfilter/vf_deinterlace_videotoolbox.m @@ -0,0 +1,400 @@ +/* + * Copyright (C) 2018 Philip Langdale <philipl@overt.org> + * 2020 Aman Karmani <aman@tmm1.net> + * + * 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 "internal.h" +#include "yadif.h" +#include <libavutil/avassert.h> +#include <libavutil/hwcontext.h> +#include <libavutil/objc.h> +#include <libavfilter/metal/utils.h> + +extern char ff_vf_deinterlace_videotoolbox_metallib_data[]; +extern unsigned int ff_vf_deinterlace_videotoolbox_metallib_len; + +typedef struct DeintVTContext { + YADIFContext yadif; + + AVBufferRef *device_ref; + AVBufferRef *input_frames_ref; + AVHWFramesContext *input_frames; + + id<MTLDevice> mtlDevice; + id<MTLLibrary> mtlLibrary; + id<MTLCommandQueue> mtlQueue; + id<MTLComputePipelineState> mtlPipeline; + id<MTLFunction> mtlFunction; + id<MTLBuffer> mtlParamsBuffer; + + CVMetalTextureCacheRef textureCache; +} DeintVTContext; + +struct mtlYadifParams { + uint channels; + uint parity; + uint tff; + bool is_second_field; + bool skip_spatial_check; + int field_mode; +}; + +static void call_kernel(AVFilterContext *ctx, + id<MTLTexture> dst, + id<MTLTexture> prev, + id<MTLTexture> cur, + id<MTLTexture> next, + int channels, + int parity, + int tff) +{ + DeintVTContext *s = ctx->priv; + id<MTLCommandBuffer> buffer = s->mtlQueue.commandBuffer; + id<MTLComputeCommandEncoder> encoder = buffer.computeCommandEncoder; + struct mtlYadifParams *params = (struct mtlYadifParams *)s->mtlParamsBuffer.contents; + *params = (struct mtlYadifParams){ + .channels = channels, + .parity = parity, + .tff = tff, + .is_second_field = !(parity ^ tff), + .skip_spatial_check = s->yadif.mode&2, + .field_mode = s->yadif.current_field + }; + + [encoder setTexture:dst atIndex:0]; + [encoder setTexture:prev atIndex:1]; + [encoder setTexture:cur atIndex:2]; + [encoder setTexture:next atIndex:3]; + [encoder setBuffer:s->mtlParamsBuffer offset:0 atIndex:4]; + ff_metal_compute_encoder_dispatch(s->mtlDevice, s->mtlPipeline, encoder, dst.width, dst.height); + [encoder endEncoding]; + + [buffer commit]; + [buffer waitUntilCompleted]; + + ff_objc_release(&encoder); + ff_objc_release(&buffer); +} + +static void filter(AVFilterContext *ctx, AVFrame *dst, + int parity, int tff) +{ + DeintVTContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + int i; + + for (i = 0; i < y->csp->nb_components; i++) { + int pixel_size, channels; + const AVComponentDescriptor *comp = &y->csp->comp[i]; + CVMetalTextureRef prev, cur, next, dest; + id<MTLTexture> tex_prev, tex_cur, tex_next, tex_dest; + MTLPixelFormat format; + + if (comp->plane < i) { + // We process planes as a whole, so don't reprocess + // them for additional components + continue; + } + + pixel_size = (comp->depth + comp->shift) / 8; + channels = comp->step / pixel_size; + if (pixel_size > 2 || channels > 2) { + av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n", y->csp->name); + goto exit; + } + switch (pixel_size) { + case 1: + format = channels == 1 ? MTLPixelFormatR8Unorm : MTLPixelFormatRG8Unorm; + break; + case 2: + format = channels == 1 ? MTLPixelFormatR16Unorm : MTLPixelFormatRG16Unorm; + break; + default: + av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n", y->csp->name); + goto exit; + } + av_log(ctx, AV_LOG_TRACE, + "Deinterlacing plane %d: pixel_size: %d channels: %d\n", + comp->plane, pixel_size, channels); + + prev = ff_metal_texture_from_pixbuf(ctx, s->textureCache, (CVPixelBufferRef)y->prev->data[3], i, format); + cur = ff_metal_texture_from_pixbuf(ctx, s->textureCache, (CVPixelBufferRef)y->cur->data[3], i, format); + next = ff_metal_texture_from_pixbuf(ctx, s->textureCache, (CVPixelBufferRef)y->next->data[3], i, format); + dest = ff_metal_texture_from_pixbuf(ctx, s->textureCache, (CVPixelBufferRef)dst->data[3], i, format); + + tex_prev = CVMetalTextureGetTexture(prev); + tex_cur = CVMetalTextureGetTexture(cur); + tex_next = CVMetalTextureGetTexture(next); + tex_dest = CVMetalTextureGetTexture(dest); + + call_kernel(ctx, tex_dest, tex_prev, tex_cur, tex_next, + channels, parity, tff); + + CFRelease(prev); + CFRelease(cur); + CFRelease(next); + CFRelease(dest); + } + + CVBufferPropagateAttachments((CVPixelBufferRef)y->cur->data[3], (CVPixelBufferRef)dst->data[3]); + + if (y->current_field == YADIF_FIELD_END) { + y->current_field = YADIF_FIELD_NORMAL; + } + +exit: + return; +} + +static av_cold int deint_videotoolbox_init(AVFilterContext *ctx) +{ + DeintVTContext *s = ctx->priv; + NSError *err = nil; + CVReturn ret; + + s->mtlDevice = MTLCreateSystemDefaultDevice(); + if (!s->mtlDevice) { + av_log(ctx, AV_LOG_ERROR, "Unable to find Metal device\n"); + return AVERROR_EXTERNAL; + } + + av_log(ctx, AV_LOG_INFO, "Using Metal device: %s\n", s->mtlDevice.name.UTF8String); + + dispatch_data_t libData = dispatch_data_create( + ff_vf_deinterlace_videotoolbox_metallib_data, + ff_vf_deinterlace_videotoolbox_metallib_len, + nil, + nil); + s->mtlLibrary = [s->mtlDevice + newLibraryWithData:libData + error:&err]; + dispatch_release(libData); + libData = nil; + if (err) { + av_log(ctx, AV_LOG_ERROR, "Failed to load Metal library: %s\n", err.description.UTF8String); + return AVERROR_EXTERNAL; + } + s->mtlFunction = [s->mtlLibrary newFunctionWithName:@"deint"]; + + s->mtlQueue = s->mtlDevice.newCommandQueue; + if (!s->mtlQueue) { + av_log(ctx, AV_LOG_ERROR, "Failed to create Metal command queue!\n"); + return AVERROR_EXTERNAL; + } + + s->mtlPipeline = [s->mtlDevice + newComputePipelineStateWithFunction:s->mtlFunction + error:&err]; + if (err) { + av_log(ctx, AV_LOG_ERROR, "Failed to create Metal compute pipeline: %s\n", err.description.UTF8String); + return AVERROR_EXTERNAL; + } + + s->mtlParamsBuffer = [s->mtlDevice + newBufferWithLength:sizeof(struct mtlYadifParams) + options:MTLResourceStorageModeShared]; + if (!s->mtlParamsBuffer) { + av_log(ctx, AV_LOG_ERROR, "Failed to create Metal buffer for parameters\n"); + return AVERROR_EXTERNAL; + } + + ret = CVMetalTextureCacheCreate( + NULL, + NULL, + s->mtlDevice, + NULL, + &s->textureCache + ); + if (ret != kCVReturnSuccess) { + av_log(ctx, AV_LOG_ERROR, "Failed to create CVMetalTextureCache: %d\n", ret); + return AVERROR_EXTERNAL; + } + + return 0; +} + +static av_cold void deint_videotoolbox_uninit(AVFilterContext *ctx) +{ + DeintVTContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + + av_frame_free(&y->prev); + av_frame_free(&y->cur); + av_frame_free(&y->next); + + av_buffer_unref(&s->device_ref); + av_buffer_unref(&s->input_frames_ref); + s->input_frames = NULL; + + ff_objc_release(&s->mtlParamsBuffer); + ff_objc_release(&s->mtlFunction); + ff_objc_release(&s->mtlPipeline); + ff_objc_release(&s->mtlQueue); + ff_objc_release(&s->mtlLibrary); + ff_objc_release(&s->mtlDevice); + + if (s->textureCache) { + CFRelease(s->textureCache); + s->textureCache = NULL; + } +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + DeintVTContext *s = ctx->priv; + + if (!inlink->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "A hardware frames reference is " + "required to associate the processing device.\n"); + return AVERROR(EINVAL); + } + + s->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx); + if (!s->input_frames_ref) { + av_log(ctx, AV_LOG_ERROR, "A input frames reference create " + "failed.\n"); + return AVERROR(ENOMEM); + } + s->input_frames = (AVHWFramesContext*)s->input_frames_ref->data; + + return 0; +} + +static int config_output(AVFilterLink *link) +{ + AVHWFramesContext *output_frames; + AVFilterContext *ctx = link->src; + DeintVTContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + int ret = 0; + + av_assert0(s->input_frames); + s->device_ref = av_buffer_ref(s->input_frames->device_ref); + if (!s->device_ref) { + av_log(ctx, AV_LOG_ERROR, "A device reference create " + "failed.\n"); + return AVERROR(ENOMEM); + } + + link->hw_frames_ctx = av_hwframe_ctx_alloc(s->device_ref); + if (!link->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "Failed to create HW frame context " + "for output.\n"); + ret = AVERROR(ENOMEM); + goto exit; + } + + output_frames = (AVHWFramesContext*)link->hw_frames_ctx->data; + + output_frames->format = AV_PIX_FMT_VIDEOTOOLBOX; + output_frames->sw_format = s->input_frames->sw_format; + output_frames->width = ctx->inputs[0]->w; + output_frames->height = ctx->inputs[0]->h; + + ret = ff_filter_init_hw_frames(ctx, link, 10); + if (ret < 0) + goto exit; + + ret = av_hwframe_ctx_init(link->hw_frames_ctx); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to initialise VideoToolbox frame " + "context for output: %d\n", ret); + goto exit; + } + + link->time_base.num = ctx->inputs[0]->time_base.num; + link->time_base.den = ctx->inputs[0]->time_base.den * 2; + link->w = ctx->inputs[0]->w; + link->h = ctx->inputs[0]->h; + + if(y->mode & 1) + link->frame_rate = av_mul_q(ctx->inputs[0]->frame_rate, + (AVRational){2, 1}); + + if (link->w < 3 || link->h < 3) { + av_log(ctx, AV_LOG_ERROR, "Video of less than 3 columns or lines is not supported\n"); + ret = AVERROR(EINVAL); + goto exit; + } + + y->csp = av_pix_fmt_desc_get(output_frames->sw_format); + y->filter = filter; + +exit: + return ret; +} + +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define CONST(name, help, val, unit) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, INT_MIN, INT_MAX, FLAGS, unit } + +static const AVOption deinterlace_videotoolbox_options[] = { + #define OFFSET(x) offsetof(YADIFContext, x) + { "mode", "specify the interlacing mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=YADIF_MODE_SEND_FRAME}, 0, 3, FLAGS, "mode"}, + CONST("send_frame", "send one frame for each frame", YADIF_MODE_SEND_FRAME, "mode"), + CONST("send_field", "send one frame for each field", YADIF_MODE_SEND_FIELD, "mode"), + CONST("send_frame_nospatial", "send one frame for each frame, but skip spatial interlacing check", YADIF_MODE_SEND_FRAME_NOSPATIAL, "mode"), + CONST("send_field_nospatial", "send one frame for each field, but skip spatial interlacing check", YADIF_MODE_SEND_FIELD_NOSPATIAL, "mode"), + + { "parity", "specify the assumed picture field parity", OFFSET(parity), AV_OPT_TYPE_INT, {.i64=YADIF_PARITY_AUTO}, -1, 1, FLAGS, "parity" }, + CONST("tff", "assume top field first", YADIF_PARITY_TFF, "parity"), + CONST("bff", "assume bottom field first", YADIF_PARITY_BFF, "parity"), + CONST("auto", "auto detect parity", YADIF_PARITY_AUTO, "parity"), + + { "deint", "specify which frames to deinterlace", OFFSET(deint), AV_OPT_TYPE_INT, {.i64=YADIF_DEINT_ALL}, 0, 1, FLAGS, "deint" }, + CONST("all", "deinterlace all frames", YADIF_DEINT_ALL, "deint"), + CONST("interlaced", "only deinterlace frames marked as interlaced", YADIF_DEINT_INTERLACED, "deint"), + #undef OFFSET + + { NULL } +}; + +AVFILTER_DEFINE_CLASS(deinterlace_videotoolbox); + +static const AVFilterPad deint_videotoolbox_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = ff_yadif_filter_frame, + .config_props = config_input, + }, +}; + +static const AVFilterPad deint_videotoolbox_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .request_frame = ff_yadif_request_frame, + .config_props = config_output, + }, +}; + +AVFilter ff_vf_deinterlace_videotoolbox = { + .name = "deinterlace_videotoolbox", + .description = NULL_IF_CONFIG_SMALL("Deinterlace VideoToolbox frames with Metal compute"), + .priv_size = sizeof(DeintVTContext), + .priv_class = &deinterlace_videotoolbox_class, + .init = deint_videotoolbox_init, + .uninit = deint_videotoolbox_uninit, + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VIDEOTOOLBOX), + FILTER_INPUTS(deint_videotoolbox_inputs), + FILTER_OUTPUTS(deint_videotoolbox_outputs), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; -- 2.33.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 5/5] avfilter: add vf_deinterlace_videotoolbox 2021-12-16 20:28 ` [FFmpeg-devel] [PATCH v3 5/5] avfilter: add vf_deinterlace_videotoolbox Aman Karmani @ 2021-12-17 3:39 ` Philip Langdale 0 siblings, 0 replies; 12+ messages in thread From: Philip Langdale @ 2021-12-17 3:39 UTC (permalink / raw) To: ffmpeg-devel On Thu, 16 Dec 2021 12:28:58 -0800 Aman Karmani <ffmpeg@tmm1.net> wrote: > From: Aman Karmani <aman@tmm1.net> > > deinterlaces CVPixelBuffers, i.e. AV_PIX_FMT_VIDEOTOOLBOX frames > > currently implements YADIF, but other algorithms could easily > be added to the same filter. > > for example, an interlaced mpeg2 file can be decoded by avcodec, > uploaded into a CVPixelBuffer, deinterlaced by metal, and then > encoded to h264 by VideoToolbox as follows: > > ffmpeg \ > -init_hw_device videotoolbox \ > -i interlaced.ts \ > -vf > hwupload,deinterlace_videotoolbox=mode=send_field:deint=interlaced \ > -c:v h264_videotoolbox \ -b:v 2000k \ > -c:a copy \ > -y progressive.ts > > (note that uploading AVFrame into CVPixelBuffer via hwupload > requires 504c60660d3194758823ddd45ceddb86e35d806f) > > Signed-off-by: Aman Karmani <aman@tmm1.net> Ignoring my lack of familiarity with the Apple specific parts, this looks reasonable, although I have the same question that Paul had about naming. I know that you're thinking that future metal accelerated algorithms could go in this filter, but the precedent in the codebase is that each algorithm is a separate filter, and so if you ever wanted to add a second one down the line, we'd be expecting it to be separate anyway. --phil _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCH v3 1/5] avfilter/vf_yadif_cuda: simplify filter definition 2021-12-16 20:28 [FFmpeg-devel] [PATCH v3 1/5] avfilter/vf_yadif_cuda: simplify filter definition Aman Karmani ` (3 preceding siblings ...) 2021-12-16 20:28 ` [FFmpeg-devel] [PATCH v3 5/5] avfilter: add vf_deinterlace_videotoolbox Aman Karmani @ 2021-12-17 3:30 ` Philip Langdale 4 siblings, 0 replies; 12+ messages in thread From: Philip Langdale @ 2021-12-17 3:30 UTC (permalink / raw) To: ffmpeg-devel On Thu, 16 Dec 2021 12:28:54 -0800 Aman Karmani <ffmpeg@tmm1.net> wrote: > From: Aman Karmani <aman@tmm1.net> > > Signed-off-by: Aman Karmani <aman@tmm1.net> > --- > libavfilter/vf_yadif_cuda.c | 19 +------------------ > 1 file changed, 1 insertion(+), 18 deletions(-) > > diff --git a/libavfilter/vf_yadif_cuda.c b/libavfilter/vf_yadif_cuda.c > index da1ab5a8ff..685b8a2035 100644 > --- a/libavfilter/vf_yadif_cuda.c > +++ b/libavfilter/vf_yadif_cuda.c > @@ -212,23 +212,6 @@ static av_cold void > deint_cuda_uninit(AVFilterContext *ctx) s->input_frames = NULL; > } > > -static int deint_cuda_query_formats(AVFilterContext *ctx) > -{ > - enum AVPixelFormat pix_fmts[] = { > - AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE, > - }; > - int ret; > - > - if ((ret = ff_formats_ref(ff_make_format_list(pix_fmts), > - &ctx->inputs[0]->outcfg.formats)) < 0) > - return ret; > - if ((ret = ff_formats_ref(ff_make_format_list(pix_fmts), > - &ctx->outputs[0]->incfg.formats)) < 0) > - return ret; > - > - return 0; > -} > - > static int config_input(AVFilterLink *inlink) > { > AVFilterContext *ctx = inlink->dst; > @@ -380,9 +363,9 @@ const AVFilter ff_vf_yadif_cuda = { > .priv_size = sizeof(DeintCUDAContext), > .priv_class = &yadif_cuda_class, > .uninit = deint_cuda_uninit, > + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_CUDA), > FILTER_INPUTS(deint_cuda_inputs), > FILTER_OUTPUTS(deint_cuda_outputs), > - FILTER_QUERY_FUNC(deint_cuda_query_formats), > .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, > .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, > }; LGTM. Thanks. --phil _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2021-12-17 19:52 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-12-16 20:28 [FFmpeg-devel] [PATCH v3 1/5] avfilter/vf_yadif_cuda: simplify filter definition Aman Karmani 2021-12-16 20:28 ` [FFmpeg-devel] [PATCH v3 2/5] build: detect Metal.framework and build .metal files Aman Karmani 2021-12-17 8:54 ` Martin Storsjö 2021-12-17 19:52 ` Aman Karmani 2021-12-16 20:28 ` [FFmpeg-devel] [PATCH v3 3/5] avutil: add obj-c helpers into header-only include Aman Karmani 2021-12-16 20:28 ` [FFmpeg-devel] [PATCH v3 4/5] avfilter: add metal utilities Aman Karmani 2021-12-16 22:45 ` Marvin Scholz [not found] ` <CAK=uwuwsNg+Ujk0rx_FXP4KEhEzZ9qXJFKCAJkQqgJ8fkNKOHQ@mail.gmail.com> 2021-12-16 23:13 ` Marvin Scholz [not found] ` <CAK=uwuxHQ28r6EOQKf7FE-QxRu2XYheLzg54S_YuLdLax=OjEA@mail.gmail.com> 2021-12-17 1:32 ` Marvin Scholz 2021-12-16 20:28 ` [FFmpeg-devel] [PATCH v3 5/5] avfilter: add vf_deinterlace_videotoolbox Aman Karmani 2021-12-17 3:39 ` Philip Langdale 2021-12-17 3:30 ` [FFmpeg-devel] [PATCH v3 1/5] avfilter/vf_yadif_cuda: simplify filter definition Philip Langdale
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git