diff --git a/debian/patches/0001-add-fixes-for-segment-muxer.patch b/debian/patches/0001-add-fixes-for-segment-muxer.patch index e9ba23203..f89faa6d5 100644 --- a/debian/patches/0001-add-fixes-for-segment-muxer.patch +++ b/debian/patches/0001-add-fixes-for-segment-muxer.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavformat/segment.c =================================================================== --- FFmpeg.orig/libavformat/segment.c +++ FFmpeg/libavformat/segment.c -@@ -88,6 +88,7 @@ typedef struct SegmentContext { +@@ -89,6 +89,7 @@ typedef struct SegmentContext { int64_t last_val; ///< remember last time for wrap around detection int cut_pending; int header_written; ///< whether we've already called avformat_write_header @@ -10,7 +10,7 @@ Index: FFmpeg/libavformat/segment.c char *entry_prefix; ///< prefix to add to list entry filenames int list_type; ///< set the list type -@@ -707,6 +708,7 @@ static int seg_init(AVFormatContext *s) +@@ -708,6 +709,7 @@ static int seg_init(AVFormatContext *s) if ((ret = parse_frames(s, &seg->frames, &seg->nb_frames, seg->frames_str)) < 0) return ret; } else { @@ -18,7 +18,7 @@ Index: FFmpeg/libavformat/segment.c if (seg->use_clocktime) { if (seg->time <= 0) { av_log(s, AV_LOG_ERROR, "Invalid negative segment_time with segment_atclocktime option set\n"); -@@ -890,7 +892,15 @@ calc_times: +@@ -891,7 +893,15 @@ calc_times: seg->cut_pending = 1; seg->last_val = wrapped_val; } else { diff --git a/debian/patches/0003-add-enhanced-cuda-pixfmt-converter-impl.patch b/debian/patches/0003-add-enhanced-cuda-pixfmt-converter-impl.patch index e383720ff..1467ac5f9 100644 --- a/debian/patches/0003-add-enhanced-cuda-pixfmt-converter-impl.patch +++ b/debian/patches/0003-add-enhanced-cuda-pixfmt-converter-impl.patch @@ -292,7 +292,7 @@ Index: FFmpeg/libavfilter/vf_scale_cuda.c #include "avfilter.h" +#include "dither_matrix.h" - #include "internal.h" + #include "filters.h" #include "scale_eval.h" #include "video.h" @@ -108,6 +110,9 @@ typedef struct CUDAScaleContext { @@ -300,8 +300,8 @@ Index: FFmpeg/libavfilter/vf_scale_cuda.c float param; + -+ CUdeviceptr ditherBuffer; -+ CUtexObject ditherTex; ++ CUdeviceptr dither_buffer; ++ CUtexObject dither_tex; } CUDAScaleContext; static av_cold int cudascale_init(AVFilterContext *ctx) @@ -317,13 +317,13 @@ Index: FFmpeg/libavfilter/vf_scale_cuda.c CHECK_CU(cu->cuCtxPushCurrent(s->hwctx->cuda_ctx)); - CHECK_CU(cu->cuModuleUnload(s->cu_module)); - s->cu_module = NULL; -+ if (s->ditherTex) { -+ CHECK_CU(cu->cuTexObjectDestroy(s->ditherTex)); -+ s->ditherTex = 0; ++ if (s->dither_tex) { ++ CHECK_CU(cu->cuTexObjectDestroy(s->dither_tex)); ++ s->dither_tex = 0; + } -+ if (s->ditherBuffer) { -+ CHECK_CU(cu->cuMemFree(s->ditherBuffer)); -+ s->ditherBuffer = 0; ++ if (s->dither_buffer) { ++ CHECK_CU(cu->cuMemFree(s->dither_buffer)); ++ s->dither_buffer = 0; + } + if (s->cu_module) { + CHECK_CU(cu->cuModuleUnload(s->cu_module)); @@ -332,7 +332,7 @@ Index: FFmpeg/libavfilter/vf_scale_cuda.c CHECK_CU(cu->cuCtxPopCurrent(&dummy)); } -@@ -273,6 +288,67 @@ static av_cold int init_processing_chain +@@ -275,6 +290,68 @@ static av_cold int init_processing_chain return 0; } @@ -340,7 +340,8 @@ Index: FFmpeg/libavfilter/vf_scale_cuda.c +{ + CUDAScaleContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; -+ AVHWFramesContext *frames_ctx = (AVHWFramesContext*)inlink->hw_frames_ctx->data; ++ FilterLink *inl = ff_filter_link(inlink); ++ AVHWFramesContext *frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data; + AVCUDADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; + CudaFunctions *cu = device_hwctx->internal->cuda_dl; + CUcontext dummy, cuda_ctx = device_hwctx->cuda_ctx; @@ -381,15 +382,15 @@ Index: FFmpeg/libavfilter/vf_scale_cuda.c + if ((ret = CHECK_CU(cu->cuCtxPushCurrent(cuda_ctx))) < 0) + return ret; + -+ if ((ret = CHECK_CU(cu->cuMemAlloc(&s->ditherBuffer, sizeof(ff_fruit_dither_matrix)))) < 0) ++ if ((ret = CHECK_CU(cu->cuMemAlloc(&s->dither_buffer, sizeof(ff_fruit_dither_matrix)))) < 0) + goto fail; + -+ res_desc.res.pitch2D.devPtr = cpy.dstDevice = s->ditherBuffer; ++ res_desc.res.pitch2D.devPtr = cpy.dstDevice = s->dither_buffer; + + if ((ret = CHECK_CU(cu->cuMemcpy2D(&cpy))) < 0) + goto fail; + -+ if ((ret = CHECK_CU(cu->cuTexObjectCreate(&s->ditherTex, &res_desc, &tex_desc, NULL))) < 0) ++ if ((ret = CHECK_CU(cu->cuTexObjectCreate(&s->dither_tex, &res_desc, &tex_desc, NULL))) < 0) + goto fail; + +fail: @@ -400,9 +401,9 @@ Index: FFmpeg/libavfilter/vf_scale_cuda.c static av_cold int cudascale_load_functions(AVFilterContext *ctx) { CUDAScaleContext *s = ctx->priv; -@@ -377,6 +453,11 @@ static av_cold int cudascale_config_prop - if (ret < 0) - return ret; +@@ -383,6 +460,11 @@ static av_cold int cudascale_config_prop + s->hwctx = device_hwctx; + s->cu_stream = s->hwctx->stream; + if (s->in_desc->comp[0].depth > s->out_desc->comp[0].depth) { + if ((ret = cudascale_setup_dither(ctx)) < 0) @@ -412,7 +413,7 @@ Index: FFmpeg/libavfilter/vf_scale_cuda.c if (inlink->sample_aspect_ratio.num) { outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h*inlink->w, outlink->w*inlink->h}, -@@ -412,11 +493,15 @@ static int call_resize_kernel(AVFilterCo +@@ -418,11 +500,15 @@ static int call_resize_kernel(AVFilterCo (CUdeviceptr)out_frame->data[2], (CUdeviceptr)out_frame->data[3] }; @@ -425,11 +426,11 @@ Index: FFmpeg/libavfilter/vf_scale_cuda.c &dst_width, &dst_height, &dst_pitch, - &src_width, &src_height, &s->param + &src_width, &src_height, &s->param, -+ &s->ditherTex, &dither_size, &dither_quantization ++ &s->dither_tex, &dither_size, &dither_quantization }; return CHECK_CU(cu->cuLaunchKernel(func, -@@ -440,6 +525,7 @@ static int scalecuda_resize(AVFilterCont +@@ -446,6 +532,7 @@ static int scalecuda_resize(AVFilterCont for (i = 0; i < s->in_planes; i++) { CUDA_TEXTURE_DESC tex_desc = { diff --git a/debian/patches/0004-add-cuda-tonemap-impl.patch b/debian/patches/0004-add-cuda-tonemap-impl.patch index 57c47e10c..d2e2c353c 100644 --- a/debian/patches/0004-add-cuda-tonemap-impl.patch +++ b/debian/patches/0004-add-cuda-tonemap-impl.patch @@ -2,7 +2,7 @@ Index: FFmpeg/configure =================================================================== --- FFmpeg.orig/configure +++ FFmpeg/configure -@@ -3291,6 +3291,8 @@ scale_cuda_filter_deps="ffnvcodec" +@@ -3312,6 +3312,8 @@ scale_cuda_filter_deps="ffnvcodec" scale_cuda_filter_deps_any="cuda_nvcc cuda_llvm" thumbnail_cuda_filter_deps="ffnvcodec" thumbnail_cuda_filter_deps_any="cuda_nvcc cuda_llvm" @@ -11,25 +11,31 @@ Index: FFmpeg/configure transpose_npp_filter_deps="ffnvcodec libnpp" overlay_cuda_filter_deps="ffnvcodec" overlay_cuda_filter_deps_any="cuda_nvcc cuda_llvm" -@@ -4082,7 +4084,7 @@ enable doc - enable faan faandct faanidct - enable large_tests - enable optimizations --enable ptx_compression -+disable ptx_compression - enable runtime_cpudetect - enable safe_bitstream_reader - enable static -@@ -4630,7 +4632,7 @@ if enabled cuda_nvcc; then +@@ -4690,8 +4692,10 @@ if enabled cuda_nvcc; then + nvcc_default="nvcc" nvccflags_default="-gencode arch=compute_30,code=sm_30 -O2" else ++ # clang-20 emits ptx60 instruction 'brx.idx' even for ptx32 target (llvm/llvm-project@ccc3127) ++ # default to ptx60/sm_30 to follow the changes made in clang-16+ (llvm/llvm-project@d677505) nvcc_default="clang" - nvccflags_default="--cuda-gpu-arch=sm_30 -O2" -+ nvccflags_default="--cuda-gpu-arch=sm_30 -O2 -ffast-math" ++ nvccflags_default="--cuda-feature=+ptx60 --cuda-gpu-arch=sm_30 -O2 -ffast-math" NVCC_C="" fi -@@ -6711,7 +6713,7 @@ fi +@@ -4701,6 +4705,11 @@ if enabled cuda_nvcc; then + if $nvcc $nvccflags_default 2>&1 | grep -qi unsupported; then + nvccflags_default="-gencode arch=compute_60,code=sm_60 -O2" + fi ++else ++ # '--cuda-feature=+ptx*' option is not available before clang-15 ++ if $nvcc $nvccflags_default 2>&1 | grep -qi unsupported; then ++ nvccflags_default="--cuda-gpu-arch=sm_30 -O2 -ffast-math" ++ fi + fi + + set_default arch cc cxx doxygen pkg_config ranlib strip sysinclude \ +@@ -6753,7 +6762,7 @@ fi if enabled cuda_nvcc; then nvccflags="$nvccflags -ptx" else @@ -54,12 +60,12 @@ Index: FFmpeg/libavfilter/Makefile =================================================================== --- FFmpeg.orig/libavfilter/Makefile +++ FFmpeg/libavfilter/Makefile -@@ -522,6 +522,8 @@ OBJS-$(CONFIG_TMEDIAN_FILTER) +@@ -524,6 +524,8 @@ OBJS-$(CONFIG_TMEDIAN_FILTER) OBJS-$(CONFIG_TMIDEQUALIZER_FILTER) += vf_tmidequalizer.o OBJS-$(CONFIG_TMIX_FILTER) += vf_mix.o framesync.o OBJS-$(CONFIG_TONEMAP_FILTER) += vf_tonemap.o +OBJS-$(CONFIG_TONEMAP_CUDA_FILTER) += vf_tonemap_cuda.o cuda/tonemap.ptx.o \ -+ cuda/host_util.o ++ cuda/host_util.o cuda/load_helper.o OBJS-$(CONFIG_TONEMAP_OPENCL_FILTER) += vf_tonemap_opencl.o opencl.o \ opencl/tonemap.o opencl/colorspace_common.o OBJS-$(CONFIG_TONEMAP_VAAPI_FILTER) += vf_tonemap_vaapi.o vaapi_vpp.o @@ -67,7 +73,7 @@ Index: FFmpeg/libavfilter/allfilters.c =================================================================== --- FFmpeg.orig/libavfilter/allfilters.c +++ FFmpeg/libavfilter/allfilters.c -@@ -493,6 +493,7 @@ extern const AVFilter ff_vf_tmedian; +@@ -494,6 +494,7 @@ extern const AVFilter ff_vf_tmedian; extern const AVFilter ff_vf_tmidequalizer; extern const AVFilter ff_vf_tmix; extern const AVFilter ff_vf_tonemap; @@ -814,6 +820,96 @@ Index: FFmpeg/libavfilter/cuda/host_util.h + FFCUDAFrame *dst, const AVFrame *src, const AVPixFmtDescriptor *src_desc); + +#endif /* AVFILTER_CUDA_HOST_UTIL_H */ +Index: FFmpeg/libavfilter/cuda/load_helper.c +=================================================================== +--- FFmpeg.orig/libavfilter/cuda/load_helper.c ++++ FFmpeg/libavfilter/cuda/load_helper.c +@@ -32,11 +32,9 @@ + + #define CHECK_CU(x) FF_CUDA_CHECK_DL(avctx, cu, x) + +-int ff_cuda_load_module(void *avctx, AVCUDADeviceContext *hwctx, CUmodule *cu_module, +- const unsigned char *data, const unsigned int length) ++static int decompress_cuda_ptx(void *avctx, uint8_t **data_out, uint64_t *length_out, ++ const unsigned char *data, const unsigned int length) + { +- CudaFunctions *cu = hwctx->internal->cuda_dl; +- + #if CONFIG_PTX_COMPRESSION + z_stream stream = { 0 }; + uint8_t *buf, *tmp; +@@ -88,10 +86,51 @@ int ff_cuda_load_module(void *avctx, AVC + + inflateEnd(&stream); + +- ret = CHECK_CU(cu->cuModuleLoadData(cu_module, buf)); +- av_free(buf); +- return ret; ++ *data_out = buf; ++ *length_out = stream.total_out; + #else +- return CHECK_CU(cu->cuModuleLoadData(cu_module, data)); ++ *data_out = NULL; ++ *length_out = 0; + #endif ++ return 0; ++} ++ ++int ff_cuda_load_module(void *avctx, AVCUDADeviceContext *hwctx, CUmodule *cu_module, ++ const unsigned char *data, const unsigned int length) ++{ ++ CudaFunctions *cu = hwctx->internal->cuda_dl; ++ uint8_t *data_out = NULL; ++ uint64_t length_out = 0; ++ int ret; ++ ++ if ((ret = decompress_cuda_ptx(avctx, &data_out, &length_out, data, length)) < 0) ++ goto exit; ++ ++ ret = CHECK_CU(cu->cuModuleLoadData(cu_module, (data_out ? data_out : data))); ++exit: ++ if (data_out) ++ av_free(data_out); ++ return ret; ++} ++ ++int ff_cuda_link_add_data(void *avctx, AVCUDADeviceContext *hwctx, ++ CUlinkState state, const char* name, ++ const unsigned char *data, const unsigned int length) ++{ ++ CudaFunctions *cu = hwctx->internal->cuda_dl; ++ uint8_t *data_out = NULL; ++ uint64_t length_out = 0; ++ int ret; ++ ++ if ((ret = decompress_cuda_ptx(avctx, &data_out, &length_out, data, length)) < 0) ++ goto exit; ++ ++ ret = CHECK_CU(cu->cuLinkAddData(state, CU_JIT_INPUT_PTX, ++ (void *)(data_out ? data_out : data), ++ (size_t)(data_out ? length_out : length), ++ name, 0, NULL, NULL)); ++exit: ++ if (data_out) ++ av_free(data_out); ++ return ret; + } +Index: FFmpeg/libavfilter/cuda/load_helper.h +=================================================================== +--- FFmpeg.orig/libavfilter/cuda/load_helper.h ++++ FFmpeg/libavfilter/cuda/load_helper.h +@@ -25,4 +25,11 @@ + int ff_cuda_load_module(void *avctx, AVCUDADeviceContext *hwctx, CUmodule *cu_module, + const unsigned char *data, const unsigned int length); + ++/** ++ * Adds a PTX data to a pending linker invocation and applies any decompression, if necessary. ++ */ ++int ff_cuda_link_add_data(void *avctx, AVCUDADeviceContext *hwctx, ++ CUlinkState state, const char* name, ++ const unsigned char *data, const unsigned int length); ++ + #endif /* AVFILTER_CUDA_LOAD_HELPER_H */ Index: FFmpeg/libavfilter/cuda/pixfmt.h =================================================================== --- /dev/null @@ -1648,7 +1744,7 @@ Index: FFmpeg/libavfilter/cuda/tonemap.cu +TONEMAP_VARIANT(_itp, _READER, , _YUV2RGB_S, _TONEMAP_ITP, _RGB2YUV_S, , _WRITER) +TONEMAP_VARIANT(_itp_d, _READER, , _YUV2RGB_S, _TONEMAP_ITP, _RGB2YUV_S, _DITHER, _WRITER) + -+TONEMAP_VARIANT(_dovi_max, _READER, _RESHAPE, _YCC2RGB, _TONEMAP_MAX, _RGB2YUV, , _WRITER) ++TONEMAP_VARIANT(_dovi_max, _READER, _RESHAPE, _YCC2RGB, _TONEMAP_MAX, _RGB2YUV, , _WRITER) +TONEMAP_VARIANT(_dovi_max_d, _READER, _RESHAPE, _YCC2RGB, _TONEMAP_MAX, _RGB2YUV, _DITHER, _WRITER) +TONEMAP_VARIANT(_dovi_rgb, _READER, _RESHAPE, _YCC2RGB, _TONEMAP_RGB, _RGB2YUV, , _WRITER) +TONEMAP_VARIANT(_dovi_rgb_d, _READER, _RESHAPE, _YCC2RGB, _TONEMAP_RGB, _RGB2YUV, _DITHER, _WRITER) @@ -1813,7 +1909,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c =================================================================== --- /dev/null +++ FFmpeg/libavfilter/vf_tonemap_cuda.c -@@ -0,0 +1,1174 @@ +@@ -0,0 +1,1233 @@ +/* + * This file is part of FFmpeg. + * @@ -1839,10 +1935,10 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/bprint.h" -+#include "libavutil/common.h" ++#include "libavutil/cuda_check.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_cuda_internal.h" -+#include "libavutil/cuda_check.h" ++#include "libavutil/mem.h" +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" @@ -1850,9 +1946,10 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c +#include "avfilter.h" +#include "colorspace.h" +#include "cuda/host_util.h" ++#include "cuda/load_helper.h" +#include "cuda/shared.h" +#include "cuda/tonemap.h" -+#include "internal.h" ++#include "formats.h" +#include "scale_eval.h" +#include "video.h" +#include "dither_matrix.h" @@ -1864,6 +1961,13 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + AV_PIX_FMT_P016 +}; + ++static const int colorspaces_out[] = { ++ AVCOL_SPC_UNSPECIFIED, ++ AVCOL_SPC_BT709, ++ AVCOL_SPC_BT2020_NCL, ++ -1 ++}; ++ +#define DIV_UP(a, b) ( ((a) + (b) - 1) / (b) ) +#define ALIGN_UP(a, b) (((a) + (b) - 1) & ~((b) - 1)) +#define NUM_BUFFERS 2 @@ -1903,8 +2007,8 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + CUfunction cu_func_dovi; + CUfunction cu_func_dovi_pq; + -+ CUdeviceptr ditherBuffer; -+ CUtexObject ditherTex; ++ CUdeviceptr dither_buffer; ++ CUtexObject dither_tex; + +#define params_cnt 8 +#define pivots_cnt (7+1) @@ -1914,7 +2018,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c +#define pivots_sz pivots_cnt*sizeof(float) +#define coeffs_sz coeffs_cnt*sizeof(float) +#define mmr_sz mmr_cnt*sizeof(float) -+ CUdeviceptr doviBuffer; ++ CUdeviceptr dovi_buffer; + struct DoviMetadata *dovi; + float *dovi_pbuf; + @@ -1963,7 +2067,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + return AVERROR(ENOMEM); + + s->dovi = NULL; -+ s->doviBuffer = 0; ++ s->dovi_buffer = 0; + + return 0; +} @@ -1978,9 +2082,9 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + + CHECK_CU(cu->cuCtxPushCurrent(cuda_ctx)); + -+ if (s->doviBuffer) { -+ CHECK_CU(cu->cuMemFree(s->doviBuffer)); -+ s->doviBuffer = 0; ++ if (s->dovi_buffer) { ++ CHECK_CU(cu->cuMemFree(s->dovi_buffer)); ++ s->dovi_buffer = 0; + } + + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); @@ -2004,13 +2108,13 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + + CHECK_CU(cu->cuCtxPushCurrent(cuda_ctx)); + -+ if (s->ditherTex) { -+ CHECK_CU(cu->cuTexObjectDestroy(s->ditherTex)); -+ s->ditherTex = 0; ++ if (s->dither_tex) { ++ CHECK_CU(cu->cuTexObjectDestroy(s->dither_tex)); ++ s->dither_tex = 0; + } -+ if (s->ditherBuffer) { -+ CHECK_CU(cu->cuMemFree(s->ditherBuffer)); -+ s->ditherBuffer = 0; ++ if (s->dither_buffer) { ++ CHECK_CU(cu->cuMemFree(s->dither_buffer)); ++ s->dither_buffer = 0; + } + if (s->cu_module) { + CHECK_CU(cu->cuModuleUnload(s->cu_module)); @@ -2040,7 +2144,8 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c +{ + TonemapCUDAContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; -+ AVHWFramesContext *frames_ctx = (AVHWFramesContext*)inlink->hw_frames_ctx->data; ++ FilterLink *inl = ff_filter_link(inlink); ++ AVHWFramesContext *frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data; + AVCUDADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; + CudaFunctions *cu = device_hwctx->internal->cuda_dl; + CUcontext dummy, cuda_ctx = device_hwctx->cuda_ctx; @@ -2081,15 +2186,15 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + if ((ret = CHECK_CU(cu->cuCtxPushCurrent(cuda_ctx))) < 0) + return ret; + -+ if ((ret = CHECK_CU(cu->cuMemAlloc(&s->ditherBuffer, sizeof(ff_fruit_dither_matrix)))) < 0) ++ if ((ret = CHECK_CU(cu->cuMemAlloc(&s->dither_buffer, sizeof(ff_fruit_dither_matrix)))) < 0) + goto fail; + -+ res_desc.res.pitch2D.devPtr = cpy.dstDevice = s->ditherBuffer; ++ res_desc.res.pitch2D.devPtr = cpy.dstDevice = s->dither_buffer; + + if ((ret = CHECK_CU(cu->cuMemcpy2D(&cpy))) < 0) + goto fail; + -+ if ((ret = CHECK_CU(cu->cuTexObjectCreate(&s->ditherTex, &res_desc, &tex_desc, NULL))) < 0) ++ if ((ret = CHECK_CU(cu->cuTexObjectCreate(&s->dither_tex, &res_desc, &tex_desc, NULL))) < 0) + goto fail; + +fail: @@ -2097,8 +2202,9 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + return ret; +} + -+static av_cold int init_stage(TonemapCUDAContext *s, AVBufferRef *device_ctx, -+ AVFilterLink *outlink) ++static av_cold int init_hwframe_ctx(TonemapCUDAContext *s, ++ AVBufferRef *device_ctx, ++ int out_width, int out_height) +{ + AVBufferRef *out_ref = NULL; + AVHWFramesContext *out_ctx; @@ -2111,8 +2217,8 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + + out_ctx->format = AV_PIX_FMT_CUDA; + out_ctx->sw_format = s->out_fmt; -+ out_ctx->width = FFALIGN(outlink->w, 32); -+ out_ctx->height = FFALIGN(outlink->h, 32); ++ out_ctx->width = FFALIGN(out_width, 32); ++ out_ctx->height = FFALIGN(out_height, 32); + + ret = av_hwframe_ctx_init(out_ref); + if (ret < 0) @@ -2123,8 +2229,8 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + if (ret < 0) + goto fail; + -+ s->frame->width = outlink->w; -+ s->frame->height = outlink->h; ++ s->frame->width = out_width; ++ s->frame->height = out_height; + + av_buffer_unref(&s->frames_ctx); + s->frames_ctx = out_ref; @@ -2145,9 +2251,12 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + return 0; +} + -+static av_cold int init_processing_chain(AVFilterContext *ctx, AVFilterLink *outlink) ++static av_cold int init_processing_chain(AVFilterContext *ctx, ++ int out_width, int out_height) +{ + TonemapCUDAContext *s = ctx->priv; ++ FilterLink *inl = ff_filter_link(ctx->inputs[0]); ++ FilterLink *outl = ff_filter_link(ctx->outputs[0]); + + AVHWFramesContext *in_frames_ctx; + @@ -2158,11 +2267,11 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + int ret; + + /* check that we have a hw context */ -+ if (!ctx->inputs[0]->hw_frames_ctx) { ++ if (!inl->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n"); + return AVERROR(EINVAL); + } -+ in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data; ++ in_frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data; + in_format = in_frames_ctx->sw_format; + out_format = (s->format == AV_PIX_FMT_NONE) ? in_format : s->format; + in_desc = av_pix_fmt_desc_get(in_format); @@ -2190,12 +2299,12 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + s->in_desc = in_desc; + s->out_desc = out_desc; + -+ ret = init_stage(s, in_frames_ctx->device_ref, outlink); ++ ret = init_hwframe_ctx(s, in_frames_ctx->device_ref, out_width, out_height); + if (ret < 0) + return ret; + -+ ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->frames_ctx); -+ if (!ctx->outputs[0]->hw_frames_ctx) ++ outl->hw_frames_ctx = av_buffer_ref(s->frames_ctx); ++ if (!outl->hw_frames_ctx) + return AVERROR(ENOMEM); + + return 0; @@ -2332,7 +2441,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + enum AVColorSpace in_spc = s->in_spc, out_spc = s->out_spc; + enum AVColorPrimaries in_pri = s->in_pri, out_pri = s->out_pri; + enum AVColorRange in_range = s->in_range, out_range = s->out_range; -+ int d = s->in_desc->comp[0].depth > s->out_desc->comp[0].depth && s->ditherTex; ++ int d = s->in_desc->comp[0].depth > s->out_desc->comp[0].depth && s->dither_tex; + float input_quantization_offset = 0.0f; + float output_quantization_offset = 0.0f; + float input_y_scale = 1.0f; @@ -2527,7 +2636,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + + if (s->dovi) { + s->dovi_pbuf = av_mallocz(3*(params_sz+pivots_sz+coeffs_sz+mmr_sz)); -+ ret = CHECK_CU(cu->cuMemAlloc(&s->doviBuffer, 3*(params_sz+pivots_sz+coeffs_sz+mmr_sz))); ++ ret = CHECK_CU(cu->cuMemAlloc(&s->dovi_buffer, 3*(params_sz+pivots_sz+coeffs_sz+mmr_sz))); + if (ret < 0) + goto fail; + } @@ -2594,8 +2703,8 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + if (ret < 0) + goto fail2; + -+ ret = CHECK_CU(cu->cuLinkAddData(link_state, CU_JIT_INPUT_PTX, (void *)ff_tonemap_ptx_data, -+ (size_t)ff_tonemap_ptx_len, "ff_tonemap_ptx_data", 0, NULL, NULL)); ++ ret = ff_cuda_link_add_data(ctx, s->hwctx, link_state, "ff_tonemap_ptx_data", ++ ff_tonemap_ptx_data, ff_tonemap_ptx_len); + if (ret < 0) + goto fail2; + @@ -2670,20 +2779,24 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c +{ + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = outlink->src->inputs[0]; -+ AVHWFramesContext *frames_ctx = (AVHWFramesContext*)inlink->hw_frames_ctx->data; -+ AVCUDADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; ++ FilterLink *inl = ff_filter_link(inlink); ++ AVHWFramesContext *frames_ctx; ++ AVCUDADeviceContext *device_hwctx; + TonemapCUDAContext *s = ctx->priv; + int ret; + -+ s->hwctx = device_hwctx; -+ + outlink->w = inlink->w; + outlink->h = inlink->h; + -+ ret = init_processing_chain(ctx, outlink); ++ ret = init_processing_chain(ctx, outlink->w, outlink->h); + if (ret < 0) + return ret; + ++ frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data; ++ device_hwctx = frames_ctx->device_ctx->hwctx; ++ ++ s->hwctx = device_hwctx; ++ + if (s->in_desc->comp[0].depth > s->out_desc->comp[0].depth) { + if ((ret = setup_dither(ctx)) < 0) + return ret; @@ -2700,7 +2813,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + TonemapCUDAContext *s = ctx->priv; + CudaFunctions *cu = s->hwctx->internal->cuda_dl; + FFCUDAFrame src, dst; -+ void *args[] = { &src, &dst, &s->ditherTex, &s->doviBuffer }; ++ void *args[] = { &src, &dst, &s->dither_tex, &s->dovi_buffer }; + int ret, pq_out = s->out_trc == AVCOL_TRC_SMPTE2084; + + ret = ff_make_cuda_frame(ctx, cu, 1, @@ -2727,6 +2840,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c +static int do_tonemap(AVFilterContext *ctx, AVFrame *out, AVFrame *in) +{ + TonemapCUDAContext *s = ctx->priv; ++ AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *src = in; + int ret; + @@ -2843,9 +2957,9 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + s->in_chroma_loc = in->chroma_location; + + s->out_trc = s->trc == -1 ? AVCOL_TRC_UNSPECIFIED : s->trc; -+ s->out_spc = s->spc == -1 ? AVCOL_SPC_UNSPECIFIED : s->spc; ++ s->out_spc = outlink->colorspace; + s->out_pri = s->pri == -1 ? AVCOL_PRI_UNSPECIFIED : s->pri; -+ s->out_range = s->range == -1 ? s->in_range : s->range; ++ s->out_range = outlink->color_range; + s->out_chroma_loc = s->in_chroma_loc; + + if ((ret = compile(link)) < 0) @@ -2861,7 +2975,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + if (s->dovi) { + update_dovi_buf(ctx); + -+ ret = CHECK_CU(cu->cuMemcpyHtoDAsync(s->doviBuffer, s->dovi_pbuf, ++ ret = CHECK_CU(cu->cuMemcpyHtoDAsync(s->dovi_buffer, s->dovi_pbuf, + 3*(params_sz+pivots_sz+coeffs_sz+mmr_sz), s->hwctx->stream)); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to update dovi buf.\n"); @@ -2897,6 +3011,47 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + return ret; +} + ++static int query_formats(AVFilterContext *avctx) ++{ ++ TonemapCUDAContext *s = avctx->priv; ++ AVFilterFormats *formats; ++ int ret; ++ const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE }; ++ ++ // single format ++ formats = ff_make_format_list(pix_fmts); ++ ret = ff_formats_ref(formats, &avctx->inputs[0]->outcfg.formats); ++ if (ret < 0) ++ return ret; ++ ++ ret = ff_formats_ref(formats, &avctx->outputs[0]->incfg.formats); ++ if (ret < 0) ++ return ret; ++ ++ // colorspaces and ranges ++ if ((ret = ff_formats_ref(ff_all_color_spaces(), ++ &avctx->inputs[0]->outcfg.color_spaces)) < 0) ++ return ret; ++ ++ if ((ret = ff_formats_ref(ff_all_color_ranges(), ++ &avctx->inputs[0]->outcfg.color_ranges)) < 0) ++ return ret; ++ ++ formats = s->spc != -1 ++ ? ff_make_formats_list_singleton(s->spc) ++ : ff_make_format_list(colorspaces_out); ++ if ((ret = ff_formats_ref(formats, &avctx->outputs[0]->incfg.color_spaces)) < 0) ++ return ret; ++ ++ formats = s->range != -1 ++ ? ff_make_formats_list_singleton(s->range) ++ : ff_all_color_ranges(); ++ if ((ret = ff_formats_ref(formats, &avctx->outputs[0]->incfg.color_ranges)) < 0) ++ return ret; ++ ++ return 0; ++} ++ +#define OFFSET(x) offsetof(TonemapCUDAContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption options[] = { @@ -2984,7 +3139,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_cuda.c + FILTER_INPUTS(tonemap_cuda_inputs), + FILTER_OUTPUTS(tonemap_cuda_outputs), + -+ FILTER_SINGLE_PIXFMT(AV_PIX_FMT_CUDA), ++ FILTER_QUERY_FUNC(query_formats), + + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff --git a/debian/patches/0005-add-amf-fixes-from-upstream-and-custom-tunings.patch b/debian/patches/0005-add-amf-fixes-from-upstream-and-custom-tunings.patch new file mode 100644 index 000000000..0e1ad6380 --- /dev/null +++ b/debian/patches/0005-add-amf-fixes-from-upstream-and-custom-tunings.patch @@ -0,0 +1,772 @@ +Index: FFmpeg/libavcodec/amfenc.c +=================================================================== +--- FFmpeg.orig/libavcodec/amfenc.c ++++ FFmpeg/libavcodec/amfenc.c +@@ -102,19 +102,6 @@ static int amf_save_hdr_metadata(AVCodec + + #define PTS_PROP L"PtsProp" + +-const enum AVPixelFormat ff_amf_pix_fmts[] = { +- AV_PIX_FMT_NV12, +- AV_PIX_FMT_YUV420P, +-#if CONFIG_D3D11VA +- AV_PIX_FMT_D3D11, +-#endif +-#if CONFIG_DXVA2 +- AV_PIX_FMT_DXVA2_VLD, +-#endif +- AV_PIX_FMT_P010, +- AV_PIX_FMT_NONE +-}; +- + typedef struct FormatMap { + enum AVPixelFormat av_format; + enum AMF_SURFACE_FORMAT amf_format; +@@ -125,7 +112,9 @@ static const FormatMap format_map[] = + { AV_PIX_FMT_NONE, AMF_SURFACE_UNKNOWN }, + { AV_PIX_FMT_NV12, AMF_SURFACE_NV12 }, + { AV_PIX_FMT_P010, AMF_SURFACE_P010 }, ++ { AV_PIX_FMT_BGRA, AMF_SURFACE_BGRA }, + { AV_PIX_FMT_BGR0, AMF_SURFACE_BGRA }, ++ { AV_PIX_FMT_RGBA, AMF_SURFACE_RGBA }, + { AV_PIX_FMT_RGB0, AMF_SURFACE_RGBA }, + { AV_PIX_FMT_GRAY8, AMF_SURFACE_GRAY8 }, + { AV_PIX_FMT_YUV420P, AMF_SURFACE_YUV420P }, +@@ -274,7 +263,6 @@ static int amf_init_context(AVCodecConte + av_unused int ret; + + ctx->hwsurfaces_in_queue = 0; +- ctx->hwsurfaces_in_queue_max = 16; + + // configure AMF logger + // the return of these functions indicates old state and do not affect behaviour +@@ -329,7 +317,7 @@ static int amf_init_context(AVCodecConte + return AVERROR(ENOMEM); + + if (frames_ctx->initial_pool_size > 0) +- ctx->hwsurfaces_in_queue_max = frames_ctx->initial_pool_size - 1; ++ ctx->hwsurfaces_in_queue_max = FFMIN(ctx->hwsurfaces_in_queue_max, frames_ctx->initial_pool_size - 1); + + } else if (avctx->hw_device_ctx) { + AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)avctx->hw_device_ctx->data; +@@ -415,10 +403,6 @@ static int amf_init_encoder(AVCodecConte + else + pix_fmt = avctx->pix_fmt; + +- if (pix_fmt == AV_PIX_FMT_P010) { +- AMF_RETURN_IF_FALSE(ctx, ctx->version >= AMF_MAKE_FULL_VERSION(1, 4, 32, 0), AVERROR_UNKNOWN, "10-bit encoder is not supported by AMD GPU drivers versions lower than 23.30.\n"); +- } +- + ctx->format = amf_av_to_amf_format(pix_fmt); + AMF_RETURN_IF_FALSE(ctx, ctx->format != AMF_SURFACE_UNKNOWN, AVERROR(EINVAL), + "Format %s is not supported\n", av_get_pix_fmt_name(pix_fmt)); +@@ -426,6 +410,8 @@ static int amf_init_encoder(AVCodecConte + res = ctx->factory->pVtbl->CreateComponent(ctx->factory, ctx->context, codec_id, &ctx->encoder); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_ENCODER_NOT_FOUND, "CreateComponent(%ls) failed with error %d\n", codec_id, res); + ++ ctx->submitted_frame = 0; ++ + return 0; + } + +@@ -541,7 +527,6 @@ static int amf_copy_buffer(AVCodecContex + if ((ctx->max_b_frames > 0 || ((ctx->pa_adaptive_mini_gop == 1) ? true : false)) && ctx->dts_delay == 0) { + int64_t timestamp_last = AV_NOPTS_VALUE; + size_t can_read = av_fifo_can_read(ctx->timestamp_list); +- + AMF_RETURN_IF_FALSE(ctx, can_read > 0, AVERROR_UNKNOWN, + "timestamp_list is empty while max_b_frames = %d\n", avctx->max_b_frames); + av_fifo_peek(ctx->timestamp_list, ×tamp_last, 1, can_read - 1); +@@ -766,11 +751,50 @@ int ff_amf_receive_packet(AVCodecContext + switch (avctx->codec->id) { + case AV_CODEC_ID_H264: + AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_AUD, !!ctx->aud); ++ switch (frame->pict_type) { ++ case AV_PICTURE_TYPE_I: ++ if (ctx->forced_idr) { ++ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_SPS, 1); ++ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_PPS, 1); ++ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_PICTURE_TYPE_IDR); ++ } else { ++ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_PICTURE_TYPE_I); ++ } ++ break; ++ case AV_PICTURE_TYPE_P: ++ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_PICTURE_TYPE_P); ++ break; ++ case AV_PICTURE_TYPE_B: ++ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_PICTURE_TYPE_B); ++ break; ++ } + break; + case AV_CODEC_ID_HEVC: + AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_AUD, !!ctx->aud); ++ switch (frame->pict_type) { ++ case AV_PICTURE_TYPE_I: ++ if (ctx->forced_idr) { ++ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_HEADER, 1); ++ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_IDR); ++ } else { ++ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_I); ++ } ++ break; ++ case AV_PICTURE_TYPE_P: ++ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_FORCE_PICTURE_TYPE, AMF_VIDEO_ENCODER_HEVC_PICTURE_TYPE_P); ++ break; ++ } ++ break; ++ case AV_CODEC_ID_AV1: ++ if (frame->pict_type == AV_PICTURE_TYPE_I) { ++ if (ctx->forced_idr) { ++ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_AV1_FORCE_INSERT_SEQUENCE_HEADER, 1); ++ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE, AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_KEY); ++ } else { ++ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE, AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_INTRA_ONLY); ++ } ++ } + break; +- //case AV_CODEC_ID_AV1 not supported + default: + break; + } +@@ -787,6 +811,13 @@ int ff_amf_receive_packet(AVCodecContext + + av_frame_unref(frame); + ret = av_fifo_write(ctx->timestamp_list, &pts, 1); ++ ++ if (ctx->submitted_frame == 0) ++ { ++ ctx->use_b_frame = (ctx->max_b_frames > 0 || ((ctx->pa_adaptive_mini_gop == 1) ? true : false)); ++ } ++ ctx->submitted_frame++; ++ + if (ret < 0) + return ret; + } +@@ -796,7 +827,7 @@ int ff_amf_receive_packet(AVCodecContext + do { + block_and_wait = 0; + // poll data +- if (!avpkt->data && !avpkt->buf) { ++ if (!avpkt->data && !avpkt->buf && (ctx->use_b_frame ? (ctx->submitted_frame >= 2) : true) ) { + res_query = ctx->encoder->pVtbl->QueryOutput(ctx->encoder, &data); + if (data) { + // copy data to packet +@@ -806,6 +837,7 @@ int ff_amf_receive_packet(AVCodecContext + data->pVtbl->QueryInterface(data, &guid, (void**)&buffer); // query for buffer interface + ret = amf_copy_buffer(avctx, avpkt, buffer); + ++ ctx->submitted_frame++; + buffer->pVtbl->Release(buffer); + + if (data->pVtbl->HasProperty(data, L"av_frame_ref")) { +@@ -845,6 +877,7 @@ int ff_amf_receive_packet(AVCodecContext + av_frame_unref(ctx->delayed_frame); + AMF_RETURN_IF_FALSE(ctx, res_resubmit == AMF_OK, AVERROR_UNKNOWN, "Repeated SubmitInput() failed with error %d\n", res_resubmit); + ++ ctx->submitted_frame++; + ret = av_fifo_write(ctx->timestamp_list, &pts, 1); + if (ret < 0) + return ret; +@@ -863,7 +896,12 @@ int ff_amf_receive_packet(AVCodecContext + if (query_output_data_flag == 0) { + if (res_resubmit == AMF_INPUT_FULL || ctx->delayed_drain || (ctx->eof && res_query != AMF_EOF) || (ctx->hwsurfaces_in_queue >= ctx->hwsurfaces_in_queue_max)) { + block_and_wait = 1; +- av_usleep(1000); ++ ++ // Only sleep if the driver doesn't support waiting in QueryOutput() ++ // or if we already have output data so we will skip calling it. ++ if (!ctx->query_timeout_supported || avpkt->data || avpkt->buf) { ++ av_usleep(1000); ++ } + } + } + } while (block_and_wait); +Index: FFmpeg/libavcodec/amfenc.h +=================================================================== +--- FFmpeg.orig/libavcodec/amfenc.h ++++ FFmpeg/libavcodec/amfenc.h +@@ -68,6 +68,7 @@ typedef struct AmfContext { + + int hwsurfaces_in_queue; + int hwsurfaces_in_queue_max; ++ int query_timeout_supported; + + // helpers to handle async calls + int delayed_drain; +@@ -77,6 +78,8 @@ typedef struct AmfContext { + // shift dts back by max_b_frames in timing + AVFifo *timestamp_list; + int64_t dts_delay; ++ int submitted_frame; ++ amf_bool use_b_frame; + + // common encoder option options + +@@ -114,6 +117,7 @@ typedef struct AmfContext { + int max_b_frames; + int qvbr_quality_level; + int hw_high_motion_quality_boost; ++ int forced_idr; + + // HEVC - specific options + +Index: FFmpeg/libavcodec/amfenc_av1.c +=================================================================== +--- FFmpeg.orig/libavcodec/amfenc_av1.c ++++ FFmpeg/libavcodec/amfenc_av1.c +@@ -28,6 +28,22 @@ + + #define OFFSET(x) offsetof(AmfContext, x) + #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM ++ ++static const enum AVPixelFormat ff_amfenc_av1_pix_fmts[] = { ++ AV_PIX_FMT_NV12, ++ AV_PIX_FMT_YUV420P, ++ AV_PIX_FMT_P010, ++ AV_PIX_FMT_BGRA, ++ AV_PIX_FMT_BGR0, ++#if CONFIG_D3D11VA ++ AV_PIX_FMT_D3D11, ++#endif ++#if CONFIG_DXVA2 ++ AV_PIX_FMT_DXVA2_VLD, ++#endif ++ AV_PIX_FMT_NONE ++}; ++ + static const AVOption options[] = { + + { "usage", "Set the encoding usage", OFFSET(usage), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_VIDEO_ENCODER_AV1_USAGE_LOW_LATENCY_HIGH_QUALITY, VE, .unit = "usage" }, +@@ -97,10 +113,16 @@ static const AVOption options[] = { + { "gop", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_GOP_ALIGNED }, 0, 0, VE, .unit = "hdrmode" }, + { "frame", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_KEY_FRAME_ALIGNED }, 0, 0, VE, .unit = "hdrmode" }, + ++ { "async_depth", "Set maximum encoding parallelism. Higher values increase output latency.", OFFSET(hwsurfaces_in_queue_max), AV_OPT_TYPE_INT, {.i64 = 16 }, 1, 16, VE }, ++ + { "preencode", "Enable preencode", OFFSET(preencode), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE}, + { "enforce_hrd", "Enforce HRD", OFFSET(enforce_hrd), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE}, + { "filler_data", "Filler Data Enable", OFFSET(filler_data), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE}, + ++ /// B-Frames ++ { "max_b_frames", "Maximum number of consecutive B Pictures", OFFSET(max_consecutive_b_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 3, VE }, ++ { "bf", "B Picture Pattern", OFFSET(max_b_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 3, VE }, ++ + { "high_motion_quality_boost_enable", "Enable High motion quality boost mode", OFFSET(hw_high_motion_quality_boost), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + + // min_qp_i -> min_qp_intra, min_qp_p -> min_qp_inter +@@ -116,6 +138,7 @@ static const AVOption options[] = { + { "none", "no adaptive quantization", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_AQ_MODE_NONE }, 0, 0, VE, .unit = "adaptive_quantisation_mode" }, + { "caq", "context adaptive quantization", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_AQ_MODE_CAQ }, 0, 0, VE, .unit = "adaptive_quantisation_mode" }, + ++ { "forced_idr", "Force I frames to be IDR frames", OFFSET(forced_idr), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, + + { "align", "alignment mode", OFFSET(align), AV_OPT_TYPE_INT, {.i64 = AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_NO_RESTRICTIONS }, AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_ONLY, AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_NO_RESTRICTIONS, VE, .unit = "align" }, + { "64x16", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_ONLY }, 0, 0, VE, .unit = "align" }, +@@ -169,6 +192,9 @@ static const AVOption options[] = { + { "pa_high_motion_quality_boost_mode", "Sets the PA high motion quality boost mode", OFFSET(pa_high_motion_quality_boost_mode), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_AUTO, VE , .unit = "high_motion_quality_boost_mode" }, + { "none", "no high motion quality boost", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_NONE }, 0, 0, VE, .unit = "high_motion_quality_boost_mode" }, + { "auto", "auto high motion quality boost", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_PA_HIGH_MOTION_QUALITY_BOOST_MODE_AUTO }, 0, 0, VE, .unit = "high_motion_quality_boost_mode" }, ++ ++ { "pa_adaptive_mini_gop", "Enable Adaptive B-frame", OFFSET(pa_adaptive_mini_gop), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, VE }, ++ + { NULL } + + }; +@@ -241,6 +267,12 @@ FF_ENABLE_DEPRECATION_WARNINGS + color_profile = ff_amf_get_color_profile(avctx); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PROFILE, color_profile); + ++#ifndef AMF_VIDEO_ENCODER_AV1_NOMINAL_RANGE // Not available before AMF 1.4.36.0 ++ #define AMF_VIDEO_ENCODER_AV1_NOMINAL_RANGE L"Av1NominalRange" ++#endif ++ /// Color Range ++ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_NOMINAL_RANGE, !!(avctx->color_range == AVCOL_RANGE_JPEG)); ++ + /// Color Depth + pix_fmt = avctx->hw_frames_ctx ? ((AVHWFramesContext*)avctx->hw_frames_ctx->data)->sw_format + : avctx->pix_fmt; +@@ -251,15 +283,10 @@ FF_ENABLE_DEPRECATION_WARNINGS + + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_COLOR_BIT_DEPTH, color_depth); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PROFILE, color_profile); +- if (color_depth == AMF_COLOR_BIT_DEPTH_8) { +- /// Color Transfer Characteristics (AMF matches ISO/IEC) +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_TRANSFER_CHARACTERISTIC, AMF_COLOR_TRANSFER_CHARACTERISTIC_BT709); +- /// Color Primaries (AMF matches ISO/IEC) +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PRIMARIES, AMF_COLOR_PRIMARIES_BT709); +- } else { +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_TRANSFER_CHARACTERISTIC, AMF_COLOR_TRANSFER_CHARACTERISTIC_SMPTE2084); +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PRIMARIES, AMF_COLOR_PRIMARIES_BT2020); +- } ++ /// Color Transfer Characteristics (AMF matches ISO/IEC) ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_TRANSFER_CHARACTERISTIC, avctx->color_trc); ++ /// Color Primaries (AMF matches ISO/IEC) ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PRIMARIES, avctx->color_primaries); + + profile_level = avctx->level; + if (profile_level == AV_LEVEL_UNKNOWN) { +@@ -280,7 +307,9 @@ FF_ENABLE_DEPRECATION_WARNINGS + } + + // Picture control properties +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_GOP_SIZE, avctx->gop_size); ++ if (avctx->gop_size != -1) { ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_GOP_SIZE, avctx->gop_size); ++ } + + // Setup header insertion mode only if this option was defined explicitly + if (ctx->header_insertion_mode != -1) { +@@ -367,7 +396,7 @@ FF_ENABLE_DEPRECATION_WARNINGS + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_PEAK_BITRATE, avctx->rc_max_rate); + } + else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) { +- av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); ++ av_log(ctx, AV_LOG_DEBUG, "rate control mode is vbr_peak but max_rate is not set, default max_rate will be applied.\n"); + } + if (avctx->bit_rate > 0) { + ctx->rate_control_mode = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR; +@@ -456,6 +485,9 @@ FF_ENABLE_DEPRECATION_WARNINGS + if (ctx->pa_taq_mode != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_TAQ_MODE, ctx->pa_taq_mode); + } ++ if (ctx->pa_adaptive_mini_gop != -1) { ++ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_ADAPTIVE_MINIGOP, ((ctx->pa_adaptive_mini_gop == 0) ? false : true)); ++ } + if (ctx->pa_ltr != -1) { + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_LTR_ENABLE, ((ctx->pa_ltr == 0) ? false : true)); + } +@@ -467,6 +499,67 @@ FF_ENABLE_DEPRECATION_WARNINGS + } + } + ++ // B-Frames ++ AMFVariantStruct is_adaptive_b_frames = { 0 }; ++ res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_AV1_ADAPTIVE_MINIGOP, &is_adaptive_b_frames); ++ if (ctx->max_consecutive_b_frames != -1 || ctx->max_b_frames != -1 || is_adaptive_b_frames.boolValue == true) { ++ ++ //Get the capability of encoder ++ AMFCaps *encoder_caps = NULL; ++ ctx->encoder->pVtbl->GetCaps(ctx->encoder, &encoder_caps); ++ if (encoder_caps != NULL) ++ { ++ res = encoder_caps->pVtbl->GetProperty(encoder_caps, AMF_VIDEO_ENCODER_AV1_CAP_BFRAMES, &var); ++ if (res == AMF_OK) { ++ ++ //encoder supports AV1 B-frame ++ if(var.boolValue == true){ ++ //adaptive b-frames is higher priority than max_b_frames ++ if (is_adaptive_b_frames.boolValue == true) ++ { ++ //force AMF_VIDEO_ENCODER_AV1_MAX_CONSECUTIVE_BPICTURES to 3 ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MAX_CONSECUTIVE_BPICTURES, 3); ++ ++ if(ctx->pa_lookahead_buffer_depth < 1) ++ { ++ //force AMF_PA_LOOKAHEAD_BUFFER_DEPTH to 1 if not set or smaller than 1 ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_LOOKAHEAD_BUFFER_DEPTH, 1); ++ } ++ } ++ else { ++ if (ctx->max_b_frames != -1) { ++ //in case user sets B-frames ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_B_PIC_PATTERN, ctx->max_b_frames); ++ if (res != AMF_OK) { ++ res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_AV1_B_PIC_PATTERN, &var); ++ av_log(ctx, AV_LOG_WARNING, "B-frames=%d is not supported by this GPU, switched to %d\n", ctx->max_b_frames, (int)var.int64Value); ++ ctx->max_b_frames = (int)var.int64Value; ++ } ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MAX_CONSECUTIVE_BPICTURES, ctx->max_b_frames); ++ } ++ } ++ ++ } ++ //encoder doesn't support AV1 B-frame ++ else { ++ av_log(ctx, AV_LOG_WARNING, "The current GPU in use does not support AV1 B-frame encoding, there will be no B-frame in bitstream.\n"); ++ } ++ } else { ++ //Can't get the capability of encoder ++ av_log(ctx, AV_LOG_WARNING, "Unable to get AV1 B-frame capability.\n"); ++ av_log(ctx, AV_LOG_WARNING, "There will be no B-frame in bitstream.\n"); ++ } ++ ++ encoder_caps->pVtbl->Release(encoder_caps); ++ encoder_caps = NULL; ++ } ++ } ++ ++ // Wait inside QueryOutput() if supported by the driver ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_QUERY_TIMEOUT, 1); ++ res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_AV1_QUERY_TIMEOUT, &var); ++ ctx->query_timeout_supported = res == AMF_OK && var.int64Value; ++ + // init encoder + res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); +@@ -628,8 +721,8 @@ const FFCodec ff_av1_amf_encoder = { + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, +- .p.pix_fmts = ff_amf_pix_fmts, +- .color_ranges = AVCOL_RANGE_MPEG, /* FIXME: implement tagging */ ++ .p.pix_fmts = ff_amfenc_av1_pix_fmts, ++ .color_ranges = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG, + .p.wrapper_name = "amf", + .hw_configs = ff_amfenc_hw_configs, + }; +Index: FFmpeg/libavcodec/amfenc_h264.c +=================================================================== +--- FFmpeg.orig/libavcodec/amfenc_h264.c ++++ FFmpeg/libavcodec/amfenc_h264.c +@@ -27,6 +27,20 @@ + #define OFFSET(x) offsetof(AmfContext, x) + #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM + ++static const enum AVPixelFormat ff_amfenc_h264_pix_fmts[] = { ++ AV_PIX_FMT_NV12, ++ AV_PIX_FMT_YUV420P, ++ AV_PIX_FMT_BGRA, ++ AV_PIX_FMT_BGR0, ++#if CONFIG_D3D11VA ++ AV_PIX_FMT_D3D11, ++#endif ++#if CONFIG_DXVA2 ++ AV_PIX_FMT_DXVA2_VLD, ++#endif ++ AV_PIX_FMT_NONE ++}; ++ + static const AVOption options[] = { + // Static + /// Usage +@@ -110,6 +124,9 @@ static const AVOption options[] = { + /// Header Insertion Spacing + { "header_spacing", "Header Insertion Spacing", OFFSET(header_spacing), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1000, VE }, + ++ /// Maximum queued frames ++ { "async_depth", "Set maximum encoding parallelism. Higher values increase output latency.", OFFSET(hwsurfaces_in_queue_max), AV_OPT_TYPE_INT, {.i64 = 16 }, 1, 16, VE }, ++ + /// B-Frames + // BPicturesPattern=bf + { "bf_delta_qp", "B-Picture Delta QP", OFFSET(b_frame_delta_qp), AV_OPT_TYPE_INT, { .i64 = 4 }, -10, 10, VE }, +@@ -133,6 +150,7 @@ static const AVOption options[] = { + { "me_half_pel", "Enable ME Half Pixel", OFFSET(me_half_pel), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, VE }, + { "me_quarter_pel", "Enable ME Quarter Pixel", OFFSET(me_quarter_pel),AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, VE }, + ++ { "forced_idr", "Force I frames to be IDR frames", OFFSET(forced_idr) , AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, + { "aud", "Inserts AU Delimiter NAL unit", OFFSET(aud) , AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, VE }, + + +@@ -360,7 +378,22 @@ FF_ENABLE_DEPRECATION_WARNINGS + if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MIN_QP, 0); + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_QP, 51); +- } else { ++ } else if (ctx->rate_control_mode != AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_QUALITY_VBR) { ++ /* Custom tuning */ ++ if (avctx->qmin == -1 && avctx->qmax == -1) { ++ switch (ctx->usage) { ++ case AMF_VIDEO_ENCODER_USAGE_TRANSCONDING: ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MIN_QP, 18); ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_QP, 46); ++ break; ++ case AMF_VIDEO_ENCODER_USAGE_ULTRA_LOW_LATENCY: ++ case AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY: ++ case AMF_VIDEO_ENCODER_USAGE_WEBCAM: ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MIN_QP, 22); ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_QP, 48); ++ break; ++ } ++ } + if (avctx->qmin != -1) { + int qval = avctx->qmin > 51 ? 51 : avctx->qmin; + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MIN_QP, qval); +@@ -391,7 +424,7 @@ FF_ENABLE_DEPRECATION_WARNINGS + if (avctx->rc_max_rate) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PEAK_BITRATE, avctx->rc_max_rate); + } else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) { +- av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); ++ av_log(ctx, AV_LOG_DEBUG, "rate control mode is vbr_peak but max_rate is not set, default max_rate will be applied.\n"); + } + + if (ctx->latency != -1) { +@@ -482,6 +515,21 @@ FF_ENABLE_DEPRECATION_WARNINGS + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_REF_B_PIC_DELTA_QP, ctx->ref_b_frame_delta_qp); + } + ++ if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) { ++ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENABLE_VBAQ, 0); ++ if (ctx->enable_vbaq) ++ av_log(ctx, AV_LOG_WARNING, "VBAQ is not supported by cqp Rate Control Method, automatically disabled\n"); ++ } else { ++ if (ctx->enable_vbaq != -1) { ++ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENABLE_VBAQ, !!ctx->enable_vbaq); ++ } ++ } ++ ++ // Wait inside QueryOutput() if supported by the driver ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QUERY_TIMEOUT, 1); ++ res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_QUERY_TIMEOUT, &var); ++ ctx->query_timeout_supported = res == AMF_OK && var.int64Value; ++ + // Initialize Encoder + res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); +@@ -499,19 +547,12 @@ FF_ENABLE_DEPRECATION_WARNINGS + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_SKIP_FRAME_ENABLE, ((ctx->skip_frame == 0) ? false : true)); + } + +- if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) { +- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENABLE_VBAQ, 0); +- if (ctx->enable_vbaq) +- av_log(ctx, AV_LOG_WARNING, "VBAQ is not supported by cqp Rate Control Method, automatically disabled\n"); +- } else { +- if (ctx->enable_vbaq != -1) { +- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENABLE_VBAQ, !!ctx->enable_vbaq); +- } +- } + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_DE_BLOCKING_FILTER, !!deblocking_filter); + + // Keyframe Interval +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_IDR_PERIOD, avctx->gop_size); ++ if (avctx->gop_size != -1) { ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_IDR_PERIOD, avctx->gop_size); ++ } + + // Header Insertion Spacing + if (ctx->header_spacing >= 0) +@@ -601,7 +642,7 @@ const FFCodec ff_h264_amf_encoder = { + AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +- .p.pix_fmts = ff_amf_pix_fmts, ++ .p.pix_fmts = ff_amfenc_h264_pix_fmts, + .color_ranges = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG, + .p.wrapper_name = "amf", + .hw_configs = ff_amfenc_hw_configs, +Index: FFmpeg/libavcodec/amfenc_hevc.c +=================================================================== +--- FFmpeg.orig/libavcodec/amfenc_hevc.c ++++ FFmpeg/libavcodec/amfenc_hevc.c +@@ -26,6 +26,21 @@ + #define OFFSET(x) offsetof(AmfContext, x) + #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM + ++static const enum AVPixelFormat ff_amfenc_hevc_pix_fmts[] = { ++ AV_PIX_FMT_NV12, ++ AV_PIX_FMT_YUV420P, ++ AV_PIX_FMT_P010, ++ AV_PIX_FMT_BGRA, ++ AV_PIX_FMT_BGR0, ++#if CONFIG_D3D11VA ++ AV_PIX_FMT_D3D11, ++#endif ++#if CONFIG_DXVA2 ++ AV_PIX_FMT_DXVA2_VLD, ++#endif ++ AV_PIX_FMT_NONE ++}; ++ + static const AVOption options[] = { + { "usage", "Set the encoding usage", OFFSET(usage), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY_HIGH_QUALITY, VE, .unit = "usage" }, + { "transcoding", "Generic Transcoding", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCODING }, 0, 0, VE, .unit = "usage" }, +@@ -83,6 +98,8 @@ static const AVOption options[] = { + { "gop", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_GOP_ALIGNED }, 0, 0, VE, .unit = "hdrmode" }, + { "idr", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED }, 0, 0, VE, .unit = "hdrmode" }, + ++ { "async_depth", "Set maximum encoding parallelism. Higher values increase output latency.", OFFSET(hwsurfaces_in_queue_max), AV_OPT_TYPE_INT, {.i64 = 16 }, 1, 16, VE }, ++ + { "high_motion_quality_boost_enable", "Enable High motion quality boost mode", OFFSET(hw_high_motion_quality_boost), AV_OPT_TYPE_BOOL, {.i64 = -1 }, -1, 1, VE }, + { "gops_per_idr", "GOPs per IDR 0-no IDR will be inserted", OFFSET(gops_per_idr), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, VE }, + { "preencode", "Enable preencode", OFFSET(preencode), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, VE}, +@@ -100,6 +117,7 @@ static const AVOption options[] = { + { "me_half_pel", "Enable ME Half Pixel", OFFSET(me_half_pel), AV_OPT_TYPE_BOOL,{ .i64 = -1 }, -1, 1, VE }, + { "me_quarter_pel", "Enable ME Quarter Pixel ", OFFSET(me_quarter_pel),AV_OPT_TYPE_BOOL,{ .i64 = -1 }, -1, 1, VE }, + ++ { "forced_idr", "Force I frames to be IDR frames", OFFSET(forced_idr) ,AV_OPT_TYPE_BOOL,{ .i64 = 1 }, 0, 1, VE }, + { "aud", "Inserts AU Delimiter NAL unit", OFFSET(aud) ,AV_OPT_TYPE_BOOL,{ .i64 = -1 }, -1, 1, VE }, + + +@@ -193,7 +211,7 @@ FF_ENABLE_DEPRECATION_WARNINGS + AMF_ASSIGN_PROPERTY_SIZE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FRAMESIZE, framesize); + + AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FRAMERATE, framerate); +- ++#if 0 + switch (avctx->profile) { + case AV_PROFILE_HEVC_MAIN: + profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN; +@@ -213,7 +231,7 @@ FF_ENABLE_DEPRECATION_WARNINGS + if (profile != 0) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PROFILE, profile); + } +- ++#endif + if (ctx->tier != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_TIER, ctx->tier); + } +@@ -247,29 +265,32 @@ FF_ENABLE_DEPRECATION_WARNINGS + AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_NOMINAL_RANGE, !!(avctx->color_range == AVCOL_RANGE_JPEG)); + /// Color Depth + color_depth = AMF_COLOR_BIT_DEPTH_8; ++ profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN; ++ avctx->profile = AV_PROFILE_HEVC_MAIN; + pix_fmt = avctx->hw_frames_ctx ? ((AVHWFramesContext*)avctx->hw_frames_ctx->data)->sw_format + : avctx->pix_fmt; + if (pix_fmt == AV_PIX_FMT_P010) { + color_depth = AMF_COLOR_BIT_DEPTH_10; ++ profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN_10; ++ avctx->profile = AV_PROFILE_HEVC_MAIN_10; + } + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_COLOR_BIT_DEPTH, color_depth); +- if (color_depth == AMF_COLOR_BIT_DEPTH_8) { +- /// Color Transfer Characteristics (AMF matches ISO/IEC) +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_TRANSFER_CHARACTERISTIC, AMF_COLOR_TRANSFER_CHARACTERISTIC_BT709); +- /// Color Primaries (AMF matches ISO/IEC) +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_COLOR_PRIMARIES, AMF_COLOR_PRIMARIES_BT709); +- } else { +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_TRANSFER_CHARACTERISTIC, AMF_COLOR_TRANSFER_CHARACTERISTIC_SMPTE2084); +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_COLOR_PRIMARIES, AMF_COLOR_PRIMARIES_BT2020); +- } ++ /// HEVC Profile ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PROFILE, profile); ++ /// Color Transfer Characteristics (AMF matches ISO/IEC) ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_TRANSFER_CHARACTERISTIC, avctx->color_trc); ++ /// Color Primaries (AMF matches ISO/IEC) ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_COLOR_PRIMARIES, avctx->color_primaries); + + // Picture control properties + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_NUM_GOPS_PER_IDR, ctx->gops_per_idr); +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_GOP_SIZE, avctx->gop_size); ++ if (avctx->gop_size != -1) { ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_GOP_SIZE, avctx->gop_size); ++ } + if (avctx->slices > 1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_SLICES_PER_FRAME, avctx->slices); + } +- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_DE_BLOCKING_FILTER_DISABLE, deblocking_filter); ++ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_DE_BLOCKING_FILTER_DISABLE, !deblocking_filter); + + if (ctx->header_insertion_mode != -1) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE, ctx->header_insertion_mode); +@@ -369,7 +390,7 @@ FF_ENABLE_DEPRECATION_WARNINGS + if (avctx->rc_max_rate) { + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE, avctx->rc_max_rate); + } else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) { +- av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); ++ av_log(ctx, AV_LOG_DEBUG, "rate control mode is vbr_peak but max_rate is not set, default max_rate will be applied.\n"); + } + + if (ctx->latency != -1) { +@@ -429,6 +450,11 @@ FF_ENABLE_DEPRECATION_WARNINGS + } + } + ++ // Wait inside QueryOutput() if supported by the driver ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QUERY_TIMEOUT, 1); ++ res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QUERY_TIMEOUT, &var); ++ ctx->query_timeout_supported = res == AMF_OK && var.int64Value; ++ + // init encoder + res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); + AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); +@@ -438,29 +464,56 @@ FF_ENABLE_DEPRECATION_WARNINGS + AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_AU_SIZE, ctx->max_au_size); + } + +- if (ctx->min_qp_i != -1) { +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, ctx->min_qp_i); +- } else if (avctx->qmin != -1) { +- int qval = avctx->qmin > 51 ? 51 : avctx->qmin; +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, qval); +- } +- if (ctx->max_qp_i != -1) { +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, ctx->max_qp_i); +- } else if (avctx->qmax != -1) { +- int qval = avctx->qmax > 51 ? 51 : avctx->qmax; +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, qval); +- } +- if (ctx->min_qp_p != -1) { +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, ctx->min_qp_p); +- } else if (avctx->qmin != -1) { +- int qval = avctx->qmin > 51 ? 51 : avctx->qmin; +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, qval); +- } +- if (ctx->max_qp_p != -1) { +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, ctx->max_qp_p); +- } else if (avctx->qmax != -1) { +- int qval = avctx->qmax > 51 ? 51 : avctx->qmax; +- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, qval); ++ if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP) { ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, 0); ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, 51); ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, 0); ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, 51); ++ } else { ++ if (ctx->min_qp_i != -1) { ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, ctx->min_qp_i); ++ } else if (avctx->qmin != -1) { ++ int qval = avctx->qmin > 51 ? 51 : avctx->qmin; ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, qval); ++ } ++ if (ctx->max_qp_i != -1) { ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, ctx->max_qp_i); ++ } else if (avctx->qmax != -1) { ++ int qval = avctx->qmax > 51 ? 51 : avctx->qmax; ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, qval); ++ } ++ if (ctx->min_qp_p != -1) { ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, ctx->min_qp_p); ++ } else if (avctx->qmin != -1) { ++ int qval = avctx->qmin > 51 ? 51 : avctx->qmin; ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, qval); ++ } ++ if (ctx->max_qp_p != -1) { ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, ctx->max_qp_p); ++ } else if (avctx->qmax != -1) { ++ int qval = avctx->qmax > 51 ? 51 : avctx->qmax; ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, qval); ++ } ++ /* Custom tuning */ ++ if (ctx->min_qp_i == -1 && ctx->max_qp_i == -1 && ctx->min_qp_p == -1 && ctx->max_qp_p == -1 && ++ avctx->qmin == -1 && avctx->qmax == -1) { ++ switch (ctx->usage) { ++ case AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING: ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, 18); ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, 46); ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, 18); ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, 46); ++ break; ++ case AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY: ++ case AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY: ++ case AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM: ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, 22); ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, 48); ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, 22); ++ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, 48); ++ break; ++ } ++ } + } + + if (ctx->qp_p != -1) { +@@ -511,6 +564,7 @@ static const FFCodecDefault defaults[] = + { "slices", "1" }, + { "qmin", "-1" }, + { "qmax", "-1" }, ++ { "flags", "+loop"}, + { NULL }, + }; + static const AVClass hevc_amf_class = { +@@ -535,8 +589,8 @@ const FFCodec ff_hevc_amf_encoder = { + AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +- .p.pix_fmts = ff_amf_pix_fmts, +- .color_ranges = AVCOL_RANGE_MPEG, /* FIXME: implement tagging */ ++ .p.pix_fmts = ff_amfenc_hevc_pix_fmts, ++ .color_ranges = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG, + .p.wrapper_name = "amf", + .hw_configs = ff_amfenc_hw_configs, + }; diff --git a/debian/patches/0005-add-amf-refactor-and-10bit-encoding.patch b/debian/patches/0005-add-amf-refactor-and-10bit-encoding.patch deleted file mode 100644 index 517575cfe..000000000 --- a/debian/patches/0005-add-amf-refactor-and-10bit-encoding.patch +++ /dev/null @@ -1,2584 +0,0 @@ -Index: FFmpeg/libavcodec/Makefile -=================================================================== ---- FFmpeg.orig/libavcodec/Makefile -+++ FFmpeg/libavcodec/Makefile -@@ -68,7 +68,7 @@ include $(SRC_PATH)/libavcodec/vvc/Makef - OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o - OBJS-$(CONFIG_AC3DSP) += ac3dsp.o ac3.o ac3tab.o - OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio_sample_rates.o --OBJS-$(CONFIG_AMF) += amfenc.o -+OBJS-$(CONFIG_AMF) += amfenc.o amf.o - OBJS-$(CONFIG_AUDIO_FRAME_QUEUE) += audio_frame_queue.o - OBJS-$(CONFIG_ATSC_A53) += atsc_a53.o - OBJS-$(CONFIG_AUDIODSP) += audiodsp.o -@@ -1261,7 +1261,7 @@ SKIPHEADERS + - bitstream_template.h \ - $(ARCH)/vpx_arith.h \ - --SKIPHEADERS-$(CONFIG_AMF) += amfenc.h -+SKIPHEADERS-$(CONFIG_AMF) += amfenc.h amf.h - SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h - SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h - SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h -Index: FFmpeg/libavcodec/amf.c -=================================================================== ---- /dev/null -+++ FFmpeg/libavcodec/amf.c -@@ -0,0 +1,345 @@ -+/* -+ * 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 "amf.h" -+ -+#define FFMPEG_AMF_WRITER_ID L"ffmpeg_amf" -+ -+const FormatMap format_map[] = -+{ -+ { AV_PIX_FMT_NONE, AMF_SURFACE_UNKNOWN }, -+ { AV_PIX_FMT_NV12, AMF_SURFACE_NV12 }, -+ { AV_PIX_FMT_P010, AMF_SURFACE_P010 }, -+ { AV_PIX_FMT_BGRA, AMF_SURFACE_BGRA }, -+ { AV_PIX_FMT_BGR0, AMF_SURFACE_BGRA }, -+ { AV_PIX_FMT_RGBA, AMF_SURFACE_RGBA }, -+ { AV_PIX_FMT_RGB0, AMF_SURFACE_RGBA }, -+ { AV_PIX_FMT_GRAY8, AMF_SURFACE_GRAY8 }, -+ { AV_PIX_FMT_YUV420P, AMF_SURFACE_YUV420P }, -+ { AV_PIX_FMT_YUYV422, AMF_SURFACE_YUY2 }, -+}; -+ -+enum AMF_SURFACE_FORMAT amf_av_to_amf_format(enum AVPixelFormat fmt) -+{ -+ int i; -+ for (i = 0; i < amf_countof(format_map); i++) { -+ if (format_map[i].av_format == fmt) { -+ return format_map[i].amf_format; -+ } -+ } -+ return AMF_SURFACE_UNKNOWN; -+} -+ -+enum AVPixelFormat amf_to_av_format(enum AMF_SURFACE_FORMAT fmt) -+{ -+ int i; -+ for (i = 0; i < amf_countof(format_map); i++) { -+ if (format_map[i].amf_format == fmt) { -+ return format_map[i].av_format; -+ } -+ } -+ return AMF_SURFACE_UNKNOWN; -+} -+ -+amf_int64 amf_av_to_amf_color_profile(AVCodecContext *avctx) -+{ -+ amf_int64 color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN; -+ if (avctx->color_range == AVCOL_RANGE_JPEG) { -+ // Color Space for Full (JPEG) Range -+ switch (avctx->colorspace) { -+ case AVCOL_SPC_SMPTE170M: -+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_601; -+ break; -+ case AVCOL_SPC_BT709: -+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_709; -+ break; -+ case AVCOL_SPC_BT2020_NCL: -+ case AVCOL_SPC_BT2020_CL: -+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_2020; -+ break; -+ } -+ } else { -+ // Color Space for Limited (MPEG) range -+ switch (avctx->colorspace) { -+ case AVCOL_SPC_SMPTE170M: -+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_601; -+ break; -+ case AVCOL_SPC_BT709: -+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_709; -+ break; -+ case AVCOL_SPC_BT2020_NCL: -+ case AVCOL_SPC_BT2020_CL: -+ color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020; -+ break; -+ } -+ } -+ return color_profile; -+} -+ -+static void AMF_CDECL_CALL AMFTraceWriter_Write(AMFTraceWriter *pThis, -+ const wchar_t *scope, const wchar_t *message) -+{ -+ AVAMFLogger *logger = (AVAMFLogger*)pThis; -+ av_log(logger->avcl, AV_LOG_DEBUG, "%ls: %ls", scope, message); -+} -+ -+static void AMF_CDECL_CALL AMFTraceWriter_Flush(AMFTraceWriter *pThis) {} -+ -+static AMFTraceWriterVtbl tracer_vtbl = -+{ -+ .Write = AMFTraceWriter_Write, -+ .Flush = AMFTraceWriter_Flush, -+}; -+ -+int amf_load_library(AVAMFContext *ctx) -+{ -+ AMFInit_Fn init_fun; -+ AMFQueryVersion_Fn version_fun; -+ AMF_RESULT res; -+ -+ ctx->library = dlopen(AMF_DLL_NAMEA, RTLD_NOW | RTLD_LOCAL); -+ AMF_RETURN_IF_FALSE(ctx->avclass, ctx->library != NULL, -+ AVERROR_UNKNOWN, "DLL %s failed to open\n", AMF_DLL_NAMEA); -+ -+ init_fun = (AMFInit_Fn)dlsym(ctx->library, AMF_INIT_FUNCTION_NAME); -+ AMF_RETURN_IF_FALSE(ctx->avclass, init_fun != NULL, -+ AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_INIT_FUNCTION_NAME); -+ -+ version_fun = (AMFQueryVersion_Fn)dlsym(ctx->library, AMF_QUERY_VERSION_FUNCTION_NAME); -+ AMF_RETURN_IF_FALSE(ctx->avclass, version_fun != NULL, -+ AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_QUERY_VERSION_FUNCTION_NAME); -+ -+ res = version_fun(&ctx->version); -+ AMF_RETURN_IF_FALSE(ctx->avclass, res == AMF_OK, -+ AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_QUERY_VERSION_FUNCTION_NAME, res); -+ -+ res = init_fun(AMF_FULL_VERSION, &ctx->factory); -+ AMF_RETURN_IF_FALSE(ctx->avclass, res == AMF_OK, -+ AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_INIT_FUNCTION_NAME, res); -+ -+ res = ctx->factory->pVtbl->GetTrace(ctx->factory, &ctx->trace); -+ AMF_RETURN_IF_FALSE(ctx->avclass, res == AMF_OK, -+ AVERROR_UNKNOWN, "GetTrace() failed with error %d\n", res); -+ -+ res = ctx->factory->pVtbl->GetDebug(ctx->factory, &ctx->debug); -+ AMF_RETURN_IF_FALSE(ctx->avclass, res == AMF_OK, -+ AVERROR_UNKNOWN, "GetDebug() failed with error %d\n", res); -+ -+ return 0; -+} -+ -+int amf_create_context(AVAMFContext *ctx) -+{ -+ AMF_RESULT res; -+ -+ // configure AMF logger -+ ctx->trace->pVtbl->EnableWriter(ctx->trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, !!ctx->log_to_dbg); -+ if (ctx->log_to_dbg) -+ ctx->trace->pVtbl->SetWriterLevel(ctx->trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, AMF_TRACE_TRACE); -+ ctx->trace->pVtbl->EnableWriter(ctx->trace, AMF_TRACE_WRITER_CONSOLE, 0); -+ ctx->trace->pVtbl->SetGlobalLevel(ctx->trace, AMF_TRACE_TRACE); -+ -+ // connect AMF logger to av_log -+ ctx->logger.vtbl = &tracer_vtbl; -+ ctx->logger.avcl = ctx->avclass; -+ ctx->trace->pVtbl->RegisterWriter(ctx->trace, FFMPEG_AMF_WRITER_ID, (AMFTraceWriter*)&ctx->logger, 1); -+ ctx->trace->pVtbl->SetWriterLevel(ctx->trace, FFMPEG_AMF_WRITER_ID, AMF_TRACE_TRACE); -+ -+ res = ctx->factory->pVtbl->CreateContext(ctx->factory, &ctx->context); -+ AMF_RETURN_IF_FALSE(ctx->avclass, res == AMF_OK, -+ AVERROR_UNKNOWN, "CreateContext() failed with error %d\n", res); -+ -+ return 0; -+} -+ -+void amf_unload_library(AVAMFContext *ctx) -+{ -+ if (ctx->context) { -+ ctx->context->pVtbl->Terminate(ctx->context); -+ ctx->context->pVtbl->Release(ctx->context); -+ ctx->context = NULL; -+ } -+ if (ctx->trace) { -+ ctx->trace->pVtbl->UnregisterWriter(ctx->trace, FFMPEG_AMF_WRITER_ID); -+ } -+ if (ctx->library) { -+ dlclose(ctx->library); -+ ctx->library = NULL; -+ } -+ ctx->trace = NULL; -+ ctx->debug = NULL; -+ ctx->factory = NULL; -+ ctx->version = 0; -+} -+ -+int amf_context_init_dx11(AVAMFContext *ctx) -+{ -+ AMF_RESULT res; -+ -+ res = ctx->context->pVtbl->InitDX11(ctx->context, NULL, AMF_DX11_1); -+ if (res != AMF_OK) { -+ res = ctx->context->pVtbl->InitDX11(ctx->context, NULL, AMF_DX11_0); -+ } -+ -+ if (res == AMF_OK) { -+ av_log(ctx->avclass, AV_LOG_VERBOSE, "AMF initialization succeeded via DX11\n"); -+ } else { -+ if (res == AMF_NOT_SUPPORTED) -+ av_log(ctx->avclass, AV_LOG_ERROR, "AMF via DX11 is not supported on the given device\n"); -+ else -+ av_log(ctx->avclass, AV_LOG_ERROR, "AMF failed to initialize on the default DX11 device: %d\n", res); -+ } -+ return res; -+} -+ -+int amf_context_init_dx9(AVAMFContext *ctx) -+{ -+ AMF_RESULT res; -+ -+ res = ctx->context->pVtbl->InitDX9(ctx->context, NULL); -+ if (res == AMF_OK) { -+ av_log(ctx->avclass, AV_LOG_VERBOSE, "AMF initialization succeeded via DX9\n"); -+ } else { -+ if (res == AMF_NOT_SUPPORTED) -+ av_log(ctx->avclass, AV_LOG_ERROR, "AMF via DX9 is not supported on the given device\n"); -+ else -+ av_log(ctx->avclass, AV_LOG_ERROR, "AMF failed to initialize on the default DX9 device: %d\n", res); -+ } -+ return res; -+} -+ -+int amf_context_init_vulkan(AVAMFContext *ctx) -+{ -+ AMF_RESULT res; -+ AMFContext1* context1 = NULL; -+ AMFGuid guid = IID_AMFContext1(); -+ -+ res = ctx->context->pVtbl->QueryInterface(ctx->context, &guid, (void**)&context1); -+ AMF_RETURN_IF_FALSE(ctx->avclass, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext1() failed with error %d\n", res); -+ -+ res = context1->pVtbl->InitVulkan(context1, NULL); -+ context1->pVtbl->Release(context1); -+ if (res == AMF_OK) { -+ av_log(ctx->avclass, AV_LOG_VERBOSE, "AMF initialization succeeded via Vulkan\n"); -+ } else { -+ if (res == AMF_NOT_SUPPORTED) -+ av_log(ctx->avclass, AV_LOG_ERROR, "AMF via Vulkan is not supported on the given device\n"); -+ else -+ av_log(ctx->avclass, AV_LOG_ERROR, "AMF failed to initialize on the default Vulkan device: %d\n", res); -+ } -+ return res; -+} -+ -+int amf_context_init_opencl(AVAMFContext *ctx) -+{ -+ AMF_RESULT res; -+ -+ res = ctx->context->pVtbl->InitOpenCL(ctx->context, NULL); -+ if (res == AMF_OK) { -+ av_log(ctx->avclass, AV_LOG_VERBOSE, "AMF initialization succeeded via OpenCL\n"); -+ } else { -+ if (res == AMF_NOT_SUPPORTED) -+ av_log(ctx->avclass, AV_LOG_ERROR, "AMF via OpenCL is not supported on the given device\n"); -+ else -+ av_log(ctx->avclass, AV_LOG_ERROR, "AMF failed to initialize on the default OpenCL device: %d\n", res); -+ } -+ return res; -+} -+ -+#if CONFIG_D3D11VA -+int amf_context_derive_dx11(AVAMFContext *ctx, AVD3D11VADeviceContext *hwctx) -+{ -+ AMF_RESULT res; -+ -+ res = ctx->context->pVtbl->InitDX11(ctx->context, hwctx->device, AMF_DX11_1); -+ if (res != AMF_OK) { -+ res = ctx->context->pVtbl->InitDX11(ctx->context, hwctx->device, AMF_DX11_0); -+ } -+ -+ if (res == AMF_OK) { -+ av_log(ctx->avclass, AV_LOG_VERBOSE, "AMF derived succeeded via DX11\n"); -+ } else { -+ if (res == AMF_NOT_SUPPORTED) -+ av_log(ctx->avclass, AV_LOG_ERROR, "AMF via DX11 is not supported on the given device\n"); -+ else -+ av_log(ctx->avclass, AV_LOG_ERROR, "AMF failed to derive from the given DX11 device: %d\n", res); -+ return AVERROR(ENODEV); -+ } -+ return res; -+} -+#endif -+ -+#if CONFIG_DXVA2 -+int amf_context_derive_dx9(AVAMFContext *ctx, AVDXVA2DeviceContext *hwctx) -+{ -+ AMF_RESULT res; -+ HRESULT hr; -+ HANDLE device_handle; -+ IDirect3DDevice9* device; -+ -+ hr = IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->devmgr, &device_handle); -+ if (FAILED(hr)) { -+ av_log(ctx->avclass, AV_LOG_ERROR, "Failed to open device handle for DX9 device: %lx\n", (unsigned long)hr); -+ return AVERROR_EXTERNAL; -+ } -+ -+ hr = IDirect3DDeviceManager9_LockDevice(hwctx->devmgr, device_handle, &device, FALSE); -+ if (SUCCEEDED(hr)) { -+ IDirect3DDeviceManager9_UnlockDevice(hwctx->devmgr, device_handle, FALSE); -+ } else { -+ av_log(ctx->avclass, AV_LOG_ERROR, "Failed to lock device handle for DX9 device: %lx\n", (unsigned long)hr); -+ return AVERROR_EXTERNAL; -+ } -+ -+ IDirect3DDeviceManager9_CloseDeviceHandle(hwctx->devmgr, device_handle); -+ -+ res = ctx->context->pVtbl->InitDX9(ctx->context, device); -+ -+ IDirect3DDevice9_Release(device); -+ -+ if (res == AMF_OK) { -+ av_log(ctx->avclass, AV_LOG_VERBOSE, "AMF derived succeeded via DX9\n"); -+ } else { -+ if (res == AMF_NOT_SUPPORTED) -+ av_log(ctx->avclass, AV_LOG_ERROR, "AMF via DX9 is not supported on the given device\n"); -+ else -+ av_log(ctx->avclass, AV_LOG_ERROR, "AMF failed to derive from the given DX9 device: %d\n", res); -+ return AVERROR(ENODEV); -+ } -+ return res; -+} -+#endif -+ -+#if CONFIG_OPENCL -+int amf_context_derive_opencl(AVAMFContext *ctx, AVOpenCLDeviceContext *hwctx) -+{ -+ AMF_RESULT res; -+ -+ res = ctx->context->pVtbl->InitOpenCL(ctx->context, hwctx->command_queue); -+ if (res == AMF_OK) { -+ av_log(ctx->avclass, AV_LOG_VERBOSE, "AMF derived succeeded via OpenCL\n"); -+ } else { -+ if (res == AMF_NOT_SUPPORTED) -+ av_log(ctx->avclass, AV_LOG_ERROR, "AMF via OpenCL is not supported on the given device\n"); -+ else -+ av_log(ctx->avclass, AV_LOG_ERROR, "AMF failed to derive from the given OpenCL device: %d\n", res); -+ return AVERROR(ENODEV); -+ } -+ return res; -+} -+#endif -Index: FFmpeg/libavcodec/amf.h -=================================================================== ---- /dev/null -+++ FFmpeg/libavcodec/amf.h -@@ -0,0 +1,133 @@ -+/* -+ * 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 AVCODEC_AMF_H -+#define AVCODEC_AMF_H -+ -+#include -+#include -+#include -+ -+#include "config.h" -+#include "avcodec.h" -+ -+#include "libavutil/pixdesc.h" -+ -+#if CONFIG_D3D11VA -+#include "libavutil/hwcontext_d3d11va.h" -+#endif -+ -+#if CONFIG_DXVA2 -+#define COBJMACROS -+#include "libavutil/hwcontext_dxva2.h" -+#endif -+ -+#if CONFIG_OPENCL -+#include "libavutil/hwcontext_opencl.h" -+#endif -+ -+#ifdef _WIN32 -+#include "compat/w32dlfcn.h" -+#else -+#include -+#endif -+ -+/** -+* Error handling helper -+*/ -+#define AMF_RETURN_IF_FALSE(avctx, exp, ret_value, /*message,*/ ...) \ -+ if (!(exp)) { \ -+ av_log(avctx, AV_LOG_ERROR, __VA_ARGS__); \ -+ return ret_value; \ -+ } -+ -+#define AMF_GOTO_FAIL_IF_FALSE(avctx, exp, ret_value, /*message,*/ ...) \ -+ if (!(exp)) { \ -+ av_log(avctx, AV_LOG_ERROR, __VA_ARGS__); \ -+ ret = ret_value; \ -+ goto fail; \ -+ } -+ -+/** -+* AMF trace writer callback class -+* Used to capture all AMF logging -+*/ -+typedef struct AVAMFLogger { -+ AMFTraceWriterVtbl *vtbl; -+ void *avcl; -+} AVAMFLogger; -+ -+typedef struct AVAMFContext { -+ void *avclass; -+ int log_to_dbg; -+ -+ // access to AMF runtime -+ amf_handle library; ///< handle to DLL library -+ AMFFactory *factory; ///< pointer to AMF factory -+ AMFDebug *debug; ///< pointer to AMF debug interface -+ AMFTrace *trace; ///< pointer to AMF trace interface -+ -+ amf_uint64 version; ///< version of AMF runtime -+ AVAMFLogger logger; ///< AMF writer registered with AMF -+ AMFContext *context; ///< AMF context -+} AVAMFContext; -+ -+/** -+* Surface/Pixel format -+*/ -+typedef struct FormatMap { -+ enum AVPixelFormat av_format; -+ enum AMF_SURFACE_FORMAT amf_format; -+} FormatMap; -+ -+extern const FormatMap format_map[]; -+enum AMF_SURFACE_FORMAT amf_av_to_amf_format(enum AVPixelFormat fmt); -+enum AVPixelFormat amf_to_av_format(enum AMF_SURFACE_FORMAT fmt); -+amf_int64 amf_av_to_amf_color_profile(AVCodecContext *avctx); -+ -+/** -+* Load AMFContext -+*/ -+int amf_load_library(AVAMFContext *ctx); -+int amf_create_context(AVAMFContext *ctx); -+void amf_unload_library(AVAMFContext *ctx); -+ -+/** -+* Init AMFContext standalone -+*/ -+int amf_context_init_dx11(AVAMFContext *ctx); -+int amf_context_init_dx9(AVAMFContext *ctx); -+int amf_context_init_vulkan(AVAMFContext *ctx); -+int amf_context_init_opencl(AVAMFContext *ctx); -+ -+/** -+* Derive AMFContext from builtin hwcontext -+*/ -+#if CONFIG_D3D11VA -+int amf_context_derive_dx11(AVAMFContext *ctx, AVD3D11VADeviceContext *hwctx); -+#endif -+ -+#if CONFIG_DXVA2 -+int amf_context_derive_dx9(AVAMFContext *ctx, AVDXVA2DeviceContext *hwctx); -+#endif -+ -+#if CONFIG_OPENCL -+int amf_context_derive_opencl(AVAMFContext *ctx, AVOpenCLDeviceContext *hwctx); -+#endif -+ -+#endif /* AVCODEC_AMF_H */ -Index: FFmpeg/libavcodec/amfenc.c -=================================================================== ---- FFmpeg.orig/libavcodec/amfenc.c -+++ FFmpeg/libavcodec/amfenc.c -@@ -16,229 +16,56 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - --#include "config.h" --#include "config_components.h" -- - #include "libavutil/avassert.h" --#include "libavutil/imgutils.h" - #include "libavutil/hwcontext.h" --#if CONFIG_D3D11VA --#include "libavutil/hwcontext_d3d11va.h" --#endif --#if CONFIG_DXVA2 --#define COBJMACROS --#include "libavutil/hwcontext_dxva2.h" --#endif -+#include "libavutil/imgutils.h" -+#include "libavutil/mastering_display_metadata.h" -+ - #include "libavutil/mem.h" --#include "libavutil/pixdesc.h" - #include "libavutil/time.h" - - #include "amfenc.h" - #include "encode.h" - #include "internal.h" - --#if CONFIG_D3D11VA --#include --#endif -- --#ifdef _WIN32 --#include "compat/w32dlfcn.h" --#else --#include --#endif -- --#define FFMPEG_AMF_WRITER_ID L"ffmpeg_amf" -- - #define PTS_PROP L"PtsProp" - --const enum AVPixelFormat ff_amf_pix_fmts[] = { -- AV_PIX_FMT_NV12, -- AV_PIX_FMT_YUV420P, --#if CONFIG_D3D11VA -- AV_PIX_FMT_D3D11, --#endif --#if CONFIG_DXVA2 -- AV_PIX_FMT_DXVA2_VLD, --#endif -- AV_PIX_FMT_NONE --}; -- --typedef struct FormatMap { -- enum AVPixelFormat av_format; -- enum AMF_SURFACE_FORMAT amf_format; --} FormatMap; -- --static const FormatMap format_map[] = --{ -- { AV_PIX_FMT_NONE, AMF_SURFACE_UNKNOWN }, -- { AV_PIX_FMT_NV12, AMF_SURFACE_NV12 }, -- { AV_PIX_FMT_BGR0, AMF_SURFACE_BGRA }, -- { AV_PIX_FMT_RGB0, AMF_SURFACE_RGBA }, -- { AV_PIX_FMT_GRAY8, AMF_SURFACE_GRAY8 }, -- { AV_PIX_FMT_YUV420P, AMF_SURFACE_YUV420P }, -- { AV_PIX_FMT_YUYV422, AMF_SURFACE_YUY2 }, --}; -- --static enum AMF_SURFACE_FORMAT amf_av_to_amf_format(enum AVPixelFormat fmt) --{ -- int i; -- for (i = 0; i < amf_countof(format_map); i++) { -- if (format_map[i].av_format == fmt) { -- return format_map[i].amf_format; -- } -- } -- return AMF_SURFACE_UNKNOWN; --} -- --static void AMF_CDECL_CALL AMFTraceWriter_Write(AMFTraceWriter *pThis, -- const wchar_t *scope, const wchar_t *message) --{ -- AmfTraceWriter *tracer = (AmfTraceWriter*)pThis; -- av_log(tracer->avctx, AV_LOG_DEBUG, "%ls: %ls", scope, message); // \n is provided from AMF --} -- --static void AMF_CDECL_CALL AMFTraceWriter_Flush(AMFTraceWriter *pThis) --{ --} -- --static AMFTraceWriterVtbl tracer_vtbl = -+static int amf_init_context(AVCodecContext *avctx) - { -- .Write = AMFTraceWriter_Write, -- .Flush = AMFTraceWriter_Flush, --}; -+ AMFEncContext *ctx = avctx->priv_data; -+ AVAMFContext *amfctx = NULL; -+ AMF_RESULT res; -+ int ret; - --static int amf_load_library(AVCodecContext *avctx) --{ -- AmfContext *ctx = avctx->priv_data; -- AMFInit_Fn init_fun; -- AMFQueryVersion_Fn version_fun; -- AMF_RESULT res; -+ ctx->dts_delay = 0; -+ ctx->hwsurfaces_in_queue = 0; -+ ctx->hwsurfaces_in_queue_max = 16; - - ctx->delayed_frame = av_frame_alloc(); -- if (!ctx->delayed_frame) { -+ if (!ctx->delayed_frame) - return AVERROR(ENOMEM); -- } -+ - // hardcoded to current HW queue size - will auto-realloc if too small - ctx->timestamp_list = av_fifo_alloc2(avctx->max_b_frames + 16, sizeof(int64_t), - AV_FIFO_FLAG_AUTO_GROW); -- if (!ctx->timestamp_list) { -+ if (!ctx->timestamp_list) - return AVERROR(ENOMEM); -- } -- ctx->dts_delay = 0; -- -- -- ctx->library = dlopen(AMF_DLL_NAMEA, RTLD_NOW | RTLD_LOCAL); -- AMF_RETURN_IF_FALSE(ctx, ctx->library != NULL, -- AVERROR_UNKNOWN, "DLL %s failed to open\n", AMF_DLL_NAMEA); -- -- init_fun = (AMFInit_Fn)dlsym(ctx->library, AMF_INIT_FUNCTION_NAME); -- AMF_RETURN_IF_FALSE(ctx, init_fun != NULL, AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_INIT_FUNCTION_NAME); -- -- version_fun = (AMFQueryVersion_Fn)dlsym(ctx->library, AMF_QUERY_VERSION_FUNCTION_NAME); -- AMF_RETURN_IF_FALSE(ctx, version_fun != NULL, AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_QUERY_VERSION_FUNCTION_NAME); -- -- res = version_fun(&ctx->version); -- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_QUERY_VERSION_FUNCTION_NAME, res); -- res = init_fun(AMF_FULL_VERSION, &ctx->factory); -- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_INIT_FUNCTION_NAME, res); -- res = ctx->factory->pVtbl->GetTrace(ctx->factory, &ctx->trace); -- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "GetTrace() failed with error %d\n", res); -- res = ctx->factory->pVtbl->GetDebug(ctx->factory, &ctx->debug); -- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "GetDebug() failed with error %d\n", res); -- return 0; --} -- --#if CONFIG_D3D11VA --static int amf_init_from_d3d11_device(AVCodecContext *avctx, AVD3D11VADeviceContext *hwctx) --{ -- AmfContext *ctx = avctx->priv_data; -- AMF_RESULT res; -- -- res = ctx->context->pVtbl->InitDX11(ctx->context, hwctx->device, AMF_DX11_1); -- if (res != AMF_OK) { -- if (res == AMF_NOT_SUPPORTED) -- av_log(avctx, AV_LOG_ERROR, "AMF via D3D11 is not supported on the given device.\n"); -- else -- av_log(avctx, AV_LOG_ERROR, "AMF failed to initialise on the given D3D11 device: %d.\n", res); -- return AVERROR(ENODEV); -- } -- -- return 0; --} --#endif -- --#if CONFIG_DXVA2 --static int amf_init_from_dxva2_device(AVCodecContext *avctx, AVDXVA2DeviceContext *hwctx) --{ -- AmfContext *ctx = avctx->priv_data; -- HANDLE device_handle; -- IDirect3DDevice9 *device; -- HRESULT hr; -- AMF_RESULT res; -- int ret; -- -- hr = IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->devmgr, &device_handle); -- if (FAILED(hr)) { -- av_log(avctx, AV_LOG_ERROR, "Failed to open device handle for Direct3D9 device: %lx.\n", (unsigned long)hr); -- return AVERROR_EXTERNAL; -- } - -- hr = IDirect3DDeviceManager9_LockDevice(hwctx->devmgr, device_handle, &device, FALSE); -- if (SUCCEEDED(hr)) { -- IDirect3DDeviceManager9_UnlockDevice(hwctx->devmgr, device_handle, FALSE); -- ret = 0; -- } else { -- av_log(avctx, AV_LOG_ERROR, "Failed to lock device handle for Direct3D9 device: %lx.\n", (unsigned long)hr); -- ret = AVERROR_EXTERNAL; -- } -+ amfctx = av_mallocz(sizeof(AVAMFContext)); -+ if (!amfctx) -+ return AVERROR(ENOMEM); - -- IDirect3DDeviceManager9_CloseDeviceHandle(hwctx->devmgr, device_handle); -+ ctx->amfctx = amfctx; -+ amfctx->avclass = avctx; -+ amfctx->log_to_dbg = ctx->log_to_dbg; - -+ ret = amf_load_library(amfctx); - if (ret < 0) - return ret; - -- res = ctx->context->pVtbl->InitDX9(ctx->context, device); -- -- IDirect3DDevice9_Release(device); -- -- if (res != AMF_OK) { -- if (res == AMF_NOT_SUPPORTED) -- av_log(avctx, AV_LOG_ERROR, "AMF via D3D9 is not supported on the given device.\n"); -- else -- av_log(avctx, AV_LOG_ERROR, "AMF failed to initialise on given D3D9 device: %d.\n", res); -- return AVERROR(ENODEV); -- } -- -- return 0; --} --#endif -- --static int amf_init_context(AVCodecContext *avctx) --{ -- AmfContext *ctx = avctx->priv_data; -- AMFContext1 *context1 = NULL; -- AMF_RESULT res; -- av_unused int ret; -- -- ctx->hwsurfaces_in_queue = 0; -- ctx->hwsurfaces_in_queue_max = 16; -- -- // configure AMF logger -- // the return of these functions indicates old state and do not affect behaviour -- ctx->trace->pVtbl->EnableWriter(ctx->trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, ctx->log_to_dbg != 0 ); -- if (ctx->log_to_dbg) -- ctx->trace->pVtbl->SetWriterLevel(ctx->trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, AMF_TRACE_TRACE); -- ctx->trace->pVtbl->EnableWriter(ctx->trace, AMF_TRACE_WRITER_CONSOLE, 0); -- ctx->trace->pVtbl->SetGlobalLevel(ctx->trace, AMF_TRACE_TRACE); -- -- // connect AMF logger to av_log -- ctx->tracer.vtbl = &tracer_vtbl; -- ctx->tracer.avctx = avctx; -- ctx->trace->pVtbl->RegisterWriter(ctx->trace, FFMPEG_AMF_WRITER_ID,(AMFTraceWriter*)&ctx->tracer, 1); -- ctx->trace->pVtbl->SetWriterLevel(ctx->trace, FFMPEG_AMF_WRITER_ID, AMF_TRACE_TRACE); -- -- res = ctx->factory->pVtbl->CreateContext(ctx->factory, &ctx->context); -- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext() failed with error %d\n", res); -+ ret = amf_create_context(amfctx); -+ if (ret < 0) -+ return ret; - - // If a device was passed to the encoder, try to initialise from that. - if (avctx->hw_frames_ctx) { -@@ -253,16 +80,16 @@ static int amf_init_context(AVCodecConte - switch (frames_ctx->device_ctx->type) { - #if CONFIG_D3D11VA - case AV_HWDEVICE_TYPE_D3D11VA: -- ret = amf_init_from_d3d11_device(avctx, frames_ctx->device_ctx->hwctx); -- if (ret < 0) -- return ret; -+ res = amf_context_derive_dx11(amfctx, frames_ctx->device_ctx->hwctx); -+ if (res != AMF_OK) -+ return res; - break; - #endif - #if CONFIG_DXVA2 - case AV_HWDEVICE_TYPE_DXVA2: -- ret = amf_init_from_dxva2_device(avctx, frames_ctx->device_ctx->hwctx); -- if (ret < 0) -- return ret; -+ res = amf_context_derive_dx9(amfctx, frames_ctx->device_ctx->hwctx); -+ if (res != AMF_OK) -+ return res; - break; - #endif - default: -@@ -284,16 +111,16 @@ static int amf_init_context(AVCodecConte - switch (device_ctx->type) { - #if CONFIG_D3D11VA - case AV_HWDEVICE_TYPE_D3D11VA: -- ret = amf_init_from_d3d11_device(avctx, device_ctx->hwctx); -- if (ret < 0) -- return ret; -+ res = amf_context_derive_dx11(amfctx, device_ctx->hwctx); -+ if (res != AMF_OK) -+ return res; - break; - #endif - #if CONFIG_DXVA2 - case AV_HWDEVICE_TYPE_DXVA2: -- ret = amf_init_from_dxva2_device(avctx, device_ctx->hwctx); -- if (ret < 0) -- return ret; -+ res = amf_context_derive_dx9(amfctx, device_ctx->hwctx); -+ if (res != AMF_OK) -+ return res; - break; - #endif - default: -@@ -307,40 +134,33 @@ static int amf_init_context(AVCodecConte - return AVERROR(ENOMEM); - - } else { -- res = ctx->context->pVtbl->InitDX11(ctx->context, NULL, AMF_DX11_1); -- if (res == AMF_OK) { -- av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D11.\n"); -- } else { -- res = ctx->context->pVtbl->InitDX9(ctx->context, NULL); -- if (res == AMF_OK) { -- av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via D3D9.\n"); -- } else { -- AMFGuid guid = IID_AMFContext1(); -- res = ctx->context->pVtbl->QueryInterface(ctx->context, &guid, (void**)&context1); -- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext1() failed with error %d\n", res); -- -- res = context1->pVtbl->InitVulkan(context1, NULL); -- context1->pVtbl->Release(context1); -+#ifdef _WIN32 -+ res = amf_context_init_dx11(amfctx); -+ if (res != AMF_OK) { -+ res = amf_context_init_dx9(amfctx); -+ if (res != AMF_OK) { -+#endif -+ res = amf_context_init_vulkan(amfctx); - if (res != AMF_OK) { -- if (res == AMF_NOT_SUPPORTED) -- av_log(avctx, AV_LOG_ERROR, "AMF via Vulkan is not supported on the given device.\n"); -- else -- av_log(avctx, AV_LOG_ERROR, "AMF failed to initialise on the given Vulkan device: %d.\n", res); -+ av_log(avctx, AV_LOG_ERROR, "AMF initialisation is not supported.\n"); - return AVERROR(ENOSYS); - } -- av_log(avctx, AV_LOG_VERBOSE, "AMF initialisation succeeded via Vulkan.\n"); -+#ifdef _WIN32 - } - } -+#endif - } -+ - return 0; - } - - static int amf_init_encoder(AVCodecContext *avctx) - { -- AmfContext *ctx = avctx->priv_data; -+ AMFEncContext *ctx = avctx->priv_data; -+ AVAMFContext *amfctx = ctx->amfctx; - const wchar_t *codec_id = NULL; -- AMF_RESULT res; - enum AVPixelFormat pix_fmt; -+ AMF_RESULT res; - - switch (avctx->codec->id) { - case AV_CODEC_ID_H264: -@@ -355,26 +175,26 @@ static int amf_init_encoder(AVCodecConte - default: - break; - } -- AMF_RETURN_IF_FALSE(ctx, codec_id != NULL, AVERROR(EINVAL), "Codec %d is not supported\n", avctx->codec->id); -+ AMF_RETURN_IF_FALSE(avctx, codec_id != NULL, -+ AVERROR(EINVAL), "Codec %d is not supported\n", avctx->codec->id); - -- if (ctx->hw_frames_ctx) -- pix_fmt = ((AVHWFramesContext*)ctx->hw_frames_ctx->data)->sw_format; -- else -- pix_fmt = avctx->pix_fmt; -+ pix_fmt = avctx->hw_frames_ctx ? ((AVHWFramesContext*)avctx->hw_frames_ctx->data)->sw_format : avctx->pix_fmt; - - ctx->format = amf_av_to_amf_format(pix_fmt); -- AMF_RETURN_IF_FALSE(ctx, ctx->format != AMF_SURFACE_UNKNOWN, AVERROR(EINVAL), -- "Format %s is not supported\n", av_get_pix_fmt_name(pix_fmt)); -+ AMF_RETURN_IF_FALSE(avctx, ctx->format != AMF_SURFACE_UNKNOWN, -+ AVERROR(EINVAL), "Format %s is not supported\n", av_get_pix_fmt_name(pix_fmt)); - -- res = ctx->factory->pVtbl->CreateComponent(ctx->factory, ctx->context, codec_id, &ctx->encoder); -- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_ENCODER_NOT_FOUND, "CreateComponent(%ls) failed with error %d\n", codec_id, res); -+ res = amfctx->factory->pVtbl->CreateComponent(amfctx->factory, amfctx->context, codec_id, &ctx->encoder); -+ AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, -+ AVERROR_ENCODER_NOT_FOUND, "CreateComponent(%ls) failed with error %d\n", codec_id, res); - - return 0; - } - --int av_cold ff_amf_encode_close(AVCodecContext *avctx) -+av_cold int ff_amf_encode_close(AVCodecContext *avctx) - { -- AmfContext *ctx = avctx->priv_data; -+ AMFEncContext *ctx = avctx->priv_data; -+ AVAMFContext *amfctx = ctx->amfctx; - - if (ctx->delayed_surface) { - ctx->delayed_surface->pVtbl->Release(ctx->delayed_surface); -@@ -387,34 +207,34 @@ int av_cold ff_amf_encode_close(AVCodecC - ctx->encoder = NULL; - } - -- if (ctx->context) { -- ctx->context->pVtbl->Terminate(ctx->context); -- ctx->context->pVtbl->Release(ctx->context); -- ctx->context = NULL; -- } -+ amf_unload_library(amfctx); -+ if (amfctx) -+ av_freep(&amfctx); -+ -+ ctx->delayed_drain = 0; - av_buffer_unref(&ctx->hw_device_ctx); - av_buffer_unref(&ctx->hw_frames_ctx); - -- if (ctx->trace) { -- ctx->trace->pVtbl->UnregisterWriter(ctx->trace, FFMPEG_AMF_WRITER_ID); -- } -- if (ctx->library) { -- dlclose(ctx->library); -- ctx->library = NULL; -- } -- ctx->trace = NULL; -- ctx->debug = NULL; -- ctx->factory = NULL; -- ctx->version = 0; -- ctx->delayed_drain = 0; - av_frame_free(&ctx->delayed_frame); - av_fifo_freep2(&ctx->timestamp_list); -- - return 0; - } - --static int amf_copy_surface(AVCodecContext *avctx, const AVFrame *frame, -- AMFSurface* surface) -+av_cold int ff_amf_encode_init(AVCodecContext *avctx) -+{ -+ int ret; -+ -+ if ((ret = amf_init_context(avctx)) == 0) -+ if ((ret = amf_init_encoder(avctx)) == 0) -+ return 0; -+ -+ ff_amf_encode_close(avctx); -+ return ret; -+} -+ -+static int amf_copy_surface(AVCodecContext *avctx, -+ const AVFrame *frame, -+ AMFSurface* surface) - { - AMFPlane *plane; - uint8_t *dst_data[4]; -@@ -430,38 +250,37 @@ static int amf_copy_surface(AVCodecConte - dst_data[i] = plane->pVtbl->GetNative(plane); - dst_linesize[i] = plane->pVtbl->GetHPitch(plane); - } -+ - av_image_copy2(dst_data, dst_linesize, - frame->data, frame->linesize, frame->format, - avctx->width, avctx->height); -- - return 0; - } - --static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buffer) -+static int amf_copy_buffer(AVCodecContext *avctx, -+ AVPacket *pkt, -+ AMFBuffer *buffer) - { -- AmfContext *ctx = avctx->priv_data; -+ AMFEncContext *ctx = avctx->priv_data; - int ret; -- AMFVariantStruct var = {0}; -+ AMFVariantStruct var = { 0 }; - int64_t timestamp = AV_NOPTS_VALUE; - int64_t size = buffer->pVtbl->GetSize(buffer); - -- if ((ret = ff_get_encode_buffer(avctx, pkt, size, 0)) < 0) { -+ if ((ret = ff_get_encode_buffer(avctx, pkt, size, 0)) < 0) - return ret; -- } - memcpy(pkt->data, buffer->pVtbl->GetNative(buffer), size); - - switch (avctx->codec->id) { - case AV_CODEC_ID_H264: - buffer->pVtbl->GetProperty(buffer, AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE, &var); -- if(var.int64Value == AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR) { -+ if (var.int64Value == AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR) - pkt->flags = AV_PKT_FLAG_KEY; -- } - break; - case AV_CODEC_ID_HEVC: - buffer->pVtbl->GetProperty(buffer, AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE, &var); -- if (var.int64Value == AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_IDR) { -+ if (var.int64Value == AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_IDR) - pkt->flags = AV_PKT_FLAG_KEY; -- } - break; - case AV_CODEC_ID_AV1: - buffer->pVtbl->GetProperty(buffer, AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE, &var); -@@ -476,7 +295,6 @@ static int amf_copy_buffer(AVCodecContex - - pkt->pts = var.int64Value; // original pts - -- - AMF_RETURN_IF_FALSE(ctx, av_fifo_read(ctx->timestamp_list, ×tamp, 1) >= 0, - AVERROR_UNKNOWN, "timestamp_list is empty\n"); - -@@ -486,34 +304,20 @@ static int amf_copy_buffer(AVCodecContex - size_t can_read = av_fifo_can_read(ctx->timestamp_list); - - AMF_RETURN_IF_FALSE(ctx, can_read > 0, AVERROR_UNKNOWN, -- "timestamp_list is empty while max_b_frames = %d\n", avctx->max_b_frames); -+ "timestamp_list is empty while max_b_frames = %d\n", avctx->max_b_frames); -+ - av_fifo_peek(ctx->timestamp_list, ×tamp_last, 1, can_read - 1); -- if (timestamp < 0 || timestamp_last < AV_NOPTS_VALUE) { -+ if (timestamp < 0 || timestamp_last < AV_NOPTS_VALUE) - return AVERROR(ERANGE); -- } - ctx->dts_delay = timestamp_last - timestamp; - } - pkt->dts = timestamp - ctx->dts_delay; - return 0; - } - --// amfenc API implementation --int ff_amf_encode_init(AVCodecContext *avctx) --{ -- int ret; -- -- if ((ret = amf_load_library(avctx)) == 0) { -- if ((ret = amf_init_context(avctx)) == 0) { -- if ((ret = amf_init_encoder(avctx)) == 0) { -- return 0; -- } -- } -- } -- ff_amf_encode_close(avctx); -- return ret; --} -- --static AMF_RESULT amf_set_property_buffer(AMFSurface *object, const wchar_t *name, AMFBuffer *val) -+static AMF_RESULT amf_set_property_buffer(AMFSurface *object, -+ const wchar_t *name, -+ AMFBuffer *val) - { - AMF_RESULT res; - AMFVariantStruct var; -@@ -527,15 +331,16 @@ static AMF_RESULT amf_set_property_buffe - res = AMFVariantAssignInterface(&var, amf_interface); - amf_interface->pVtbl->Release(amf_interface); - } -- if (res == AMF_OK) { -+ if (res == AMF_OK) - res = object->pVtbl->SetProperty(object, name, var); -- } - AMFVariantClear(&var); - } - return res; - } - --static AMF_RESULT amf_get_property_buffer(AMFData *object, const wchar_t *name, AMFBuffer **val) -+static AMF_RESULT amf_get_property_buffer(AMFData *object, -+ const wchar_t *name, -+ AMFBuffer **val) - { - AMF_RESULT res; - AMFVariantStruct var; -@@ -583,9 +388,60 @@ static void amf_release_buffer_with_fram - frame_ref_storage_buffer->pVtbl->Release(frame_ref_storage_buffer); - } - -+static int amf_save_hdr_metadata(AVCodecContext *avctx, const AVFrame *frame, AMFHDRMetadata *hdrmeta) -+{ -+ AVFrameSideData *sd_display; -+ AVFrameSideData *sd_light; -+ AVMasteringDisplayMetadata *display_meta; -+ AVContentLightMetadata *light_meta; -+ -+ sd_display = av_frame_get_side_data(frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); -+ if (sd_display) { -+ display_meta = (AVMasteringDisplayMetadata *)sd_display->data; -+ if (display_meta->has_luminance) { -+ const unsigned int luma_den = 10000; -+ hdrmeta->maxMasteringLuminance = -+ (amf_uint32)(luma_den * av_q2d(display_meta->max_luminance)); -+ hdrmeta->minMasteringLuminance = -+ FFMIN((amf_uint32)(luma_den * av_q2d(display_meta->min_luminance)), hdrmeta->maxMasteringLuminance); -+ } -+ if (display_meta->has_primaries) { -+ const unsigned int chroma_den = 50000; -+ hdrmeta->redPrimary[0] = -+ FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[0][0])), chroma_den); -+ hdrmeta->redPrimary[1] = -+ FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[0][1])), chroma_den); -+ hdrmeta->greenPrimary[0] = -+ FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[1][0])), chroma_den); -+ hdrmeta->greenPrimary[1] = -+ FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[1][1])), chroma_den); -+ hdrmeta->bluePrimary[0] = -+ FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[2][0])), chroma_den); -+ hdrmeta->bluePrimary[1] = -+ FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->display_primaries[2][1])), chroma_den); -+ hdrmeta->whitePoint[0] = -+ FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->white_point[0])), chroma_den); -+ hdrmeta->whitePoint[1] = -+ FFMIN((amf_uint16)(chroma_den * av_q2d(display_meta->white_point[1])), chroma_den); -+ } -+ -+ sd_light = av_frame_get_side_data(frame, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); -+ if (sd_light) { -+ light_meta = (AVContentLightMetadata *)sd_light->data; -+ if (light_meta) { -+ hdrmeta->maxContentLightLevel = (amf_uint16)light_meta->MaxCLL; -+ hdrmeta->maxFrameAverageLightLevel = (amf_uint16)light_meta->MaxFALL; -+ } -+ } -+ return 0; -+ } -+ return 1; -+} -+ - int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) - { -- AmfContext *ctx = avctx->priv_data; -+ AMFEncContext *ctx = avctx->priv_data; -+ AVAMFContext *amfctx = ctx->amfctx; - AMFSurface *surface; - AMF_RESULT res; - int ret; -@@ -614,10 +470,9 @@ int ff_amf_receive_packet(AVCodecContext - if (res == AMF_INPUT_FULL) { - ctx->delayed_drain = 1; // input queue is full: resubmit Drain() in ff_amf_receive_packet - } else { -- if (res == AMF_OK) { -+ if (res == AMF_OK) - ctx->eof = 1; // drain started -- } -- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Drain() failed with error %d\n", res); -+ AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "Drain() failed with error %d\n", res); - } - } - } -@@ -633,13 +488,10 @@ int ff_amf_receive_packet(AVCodecContext - ID3D11Texture2D *texture = (ID3D11Texture2D*)frame->data[0]; // actual texture - int index = (intptr_t)frame->data[1]; // index is a slice in texture array is - set to tell AMF which slice to use - -- av_assert0(frame->hw_frames_ctx && ctx->hw_frames_ctx && -- frame->hw_frames_ctx->data == ctx->hw_frames_ctx->data); -- - texture->lpVtbl->SetPrivateData(texture, &AMFTextureArrayIndexGUID, sizeof(index), &index); - -- res = ctx->context->pVtbl->CreateSurfaceFromDX11Native(ctx->context, texture, &surface, NULL); // wrap to AMF surface -- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX11Native() failed with error %d\n", res); -+ res = amfctx->context->pVtbl->CreateSurfaceFromDX11Native(amfctx->context, texture, &surface, NULL); // wrap to AMF surface -+ AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX11Native() failed with error %d\n", res); - - hw_surface = 1; - } -@@ -650,8 +502,8 @@ int ff_amf_receive_packet(AVCodecContext - { - IDirect3DSurface9 *texture = (IDirect3DSurface9 *)frame->data[3]; // actual texture - -- res = ctx->context->pVtbl->CreateSurfaceFromDX9Native(ctx->context, texture, &surface, NULL); // wrap to AMF surface -- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX9Native() failed with error %d\n", res); -+ res = amfctx->context->pVtbl->CreateSurfaceFromDX9Native(amfctx->context, texture, &surface, NULL); // wrap to AMF surface -+ AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX9Native() failed with error %d\n", res); - - hw_surface = 1; - } -@@ -659,8 +511,8 @@ int ff_amf_receive_packet(AVCodecContext - #endif - default: - { -- res = ctx->context->pVtbl->AllocSurface(ctx->context, AMF_MEMORY_HOST, ctx->format, avctx->width, avctx->height, &surface); -- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "AllocSurface() failed with error %d\n", res); -+ res = amfctx->context->pVtbl->AllocSurface(amfctx->context, AMF_MEMORY_HOST, ctx->format, avctx->width, avctx->height, &surface); -+ AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR(ENOMEM), "AllocSurface() failed with error %d\n", res); - amf_copy_surface(avctx, frame, surface); - } - break; -@@ -672,28 +524,49 @@ int ff_amf_receive_packet(AVCodecContext - // input HW surfaces can be vertically aligned by 16; tell AMF the real size - surface->pVtbl->SetCrop(surface, 0, 0, frame->width, frame->height); - -- frame_ref_storage_buffer = amf_create_buffer_with_frame_ref(frame, ctx->context); -- AMF_RETURN_IF_FALSE(ctx, frame_ref_storage_buffer != NULL, AVERROR(ENOMEM), "create_buffer_with_frame_ref() returned NULL\n"); -+ frame_ref_storage_buffer = amf_create_buffer_with_frame_ref(frame, amfctx->context); -+ AMF_RETURN_IF_FALSE(avctx, frame_ref_storage_buffer != NULL, AVERROR(ENOMEM), "create_buffer_with_frame_ref() returned NULL\n"); - - res = amf_set_property_buffer(surface, L"av_frame_ref", frame_ref_storage_buffer); -- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "SetProperty failed for \"av_frame_ref\" with error %d\n", res); -+ AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "SetProperty failed for \"av_frame_ref\" with error %d\n", res); -+ - ctx->hwsurfaces_in_queue++; - frame_ref_storage_buffer->pVtbl->Release(frame_ref_storage_buffer); - } - -+ // HDR10 metadata -+ if (frame->color_trc == AVCOL_TRC_SMPTE2084) { -+ AMFBuffer *hdrmeta_buffer = NULL; -+ res = amfctx->context->pVtbl->AllocBuffer(amfctx->context, AMF_MEMORY_HOST, sizeof(AMFHDRMetadata), &hdrmeta_buffer); -+ if (res == AMF_OK) { -+ AMFHDRMetadata *hdrmeta = (AMFHDRMetadata *)hdrmeta_buffer->pVtbl->GetNative(hdrmeta_buffer); -+ if (amf_save_hdr_metadata(avctx, frame, hdrmeta) == 0) { -+ switch (avctx->codec->id) { -+ case AV_CODEC_ID_H264: -+ AMF_ASSIGN_PROPERTY_INTERFACE(res, ctx->encoder, AMF_VIDEO_ENCODER_INPUT_HDR_METADATA, hdrmeta_buffer); break; -+ case AV_CODEC_ID_HEVC: -+ AMF_ASSIGN_PROPERTY_INTERFACE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_INPUT_HDR_METADATA, hdrmeta_buffer); break; -+ case AV_CODEC_ID_AV1: -+ AMF_ASSIGN_PROPERTY_INTERFACE(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_INPUT_HDR_METADATA, hdrmeta_buffer); break; -+ } -+ res = amf_set_property_buffer(surface, L"av_frame_hdrmeta", hdrmeta_buffer); -+ AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "SetProperty failed for \"av_frame_hdrmeta\" with error %d\n", res); -+ } -+ hdrmeta_buffer->pVtbl->Release(hdrmeta_buffer); -+ } -+ } -+ - surface->pVtbl->SetPts(surface, frame->pts); - AMF_ASSIGN_PROPERTY_INT64(res, surface, PTS_PROP, frame->pts); - - switch (avctx->codec->id) { - case AV_CODEC_ID_H264: -- AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_AUD, !!ctx->aud); -- break; -+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_SPS, 1); -+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_PPS, 1); -+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_AUD, !!ctx->aud); break; - case AV_CODEC_ID_HEVC: -- AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_AUD, !!ctx->aud); -- break; -+ AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_AUD, !!ctx->aud); break; - //case AV_CODEC_ID_AV1 not supported -- default: -- break; - } - - // submit surface -@@ -704,7 +577,7 @@ int ff_amf_receive_packet(AVCodecContext - } else { - int64_t pts = frame->pts; - surface->pVtbl->Release(surface); -- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "SubmitInput() failed with error %d\n", res); -+ AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "SubmitInput() failed with error %d\n", res); - - av_frame_unref(frame); - ret = av_fifo_write(ctx->timestamp_list, &pts, 1); -@@ -713,7 +586,6 @@ int ff_amf_receive_packet(AVCodecContext - } - } - -- - do { - block_and_wait = 0; - // poll data -@@ -732,25 +604,39 @@ int ff_amf_receive_packet(AVCodecContext - if (data->pVtbl->HasProperty(data, L"av_frame_ref")) { - AMFBuffer* frame_ref_storage_buffer; - res = amf_get_property_buffer(data, L"av_frame_ref", &frame_ref_storage_buffer); -- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "GetProperty failed for \"av_frame_ref\" with error %d\n", res); -+ AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "GetProperty failed for \"av_frame_ref\" with error %d\n", res); - amf_release_buffer_with_frame_ref(frame_ref_storage_buffer); - ctx->hwsurfaces_in_queue--; - } - - data->pVtbl->Release(data); - -- AMF_RETURN_IF_FALSE(ctx, ret >= 0, ret, "amf_copy_buffer() failed with error %d\n", ret); -+ AMF_RETURN_IF_FALSE(avctx, ret >= 0, ret, "amf_copy_buffer() failed with error %d\n", ret); - } - } - res_resubmit = AMF_OK; - if (ctx->delayed_surface != NULL) { // try to resubmit frame -+ if (ctx->delayed_surface->pVtbl->HasProperty(ctx->delayed_surface, L"av_frame_hdrmeta")) { -+ AMFBuffer * hdrmeta_buffer = NULL; -+ res = amf_get_property_buffer((AMFData *)ctx->delayed_surface, L"av_frame_hdrmeta", &hdrmeta_buffer); -+ AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "GetProperty failed for \"av_frame_hdrmeta\" with error %d\n", res); -+ switch (avctx->codec->id) { -+ case AV_CODEC_ID_H264: -+ AMF_ASSIGN_PROPERTY_INTERFACE(res, ctx->encoder, AMF_VIDEO_ENCODER_INPUT_HDR_METADATA, hdrmeta_buffer); break; -+ case AV_CODEC_ID_HEVC: -+ AMF_ASSIGN_PROPERTY_INTERFACE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_INPUT_HDR_METADATA, hdrmeta_buffer); break; -+ case AV_CODEC_ID_AV1: -+ AMF_ASSIGN_PROPERTY_INTERFACE(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_INPUT_HDR_METADATA, hdrmeta_buffer); break; -+ } -+ hdrmeta_buffer->pVtbl->Release(hdrmeta_buffer); -+ } - res_resubmit = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)ctx->delayed_surface); - if (res_resubmit != AMF_INPUT_FULL) { - int64_t pts = ctx->delayed_surface->pVtbl->GetPts(ctx->delayed_surface); - ctx->delayed_surface->pVtbl->Release(ctx->delayed_surface); - ctx->delayed_surface = NULL; - av_frame_unref(ctx->delayed_frame); -- AMF_RETURN_IF_FALSE(ctx, res_resubmit == AMF_OK, AVERROR_UNKNOWN, "Repeated SubmitInput() failed with error %d\n", res_resubmit); -+ AMF_RETURN_IF_FALSE(avctx, res_resubmit == AMF_OK, AVERROR_UNKNOWN, "Repeated SubmitInput() failed with error %d\n", res_resubmit); - - ret = av_fifo_write(ctx->timestamp_list, &pts, 1); - if (ret < 0) -@@ -761,7 +647,7 @@ int ff_amf_receive_packet(AVCodecContext - if (res != AMF_INPUT_FULL) { - ctx->delayed_drain = 0; - ctx->eof = 1; // drain started -- AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Repeated Drain() failed with error %d\n", res); -+ AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "Repeated Drain() failed with error %d\n", res); - } else { - av_log(avctx, AV_LOG_WARNING, "Data acquired but delayed drain submission got AMF_INPUT_FULL- should not happen\n"); - } -@@ -775,13 +661,12 @@ int ff_amf_receive_packet(AVCodecContext - } - } while (block_and_wait); - -- if (res_query == AMF_EOF) { -+ if (res_query == AMF_EOF) - ret = AVERROR_EOF; -- } else if (data == NULL) { -+ else if (data == NULL) - ret = AVERROR(EAGAIN); -- } else { -+ else - ret = 0; -- } - return ret; - } - -Index: FFmpeg/libavcodec/amfenc.h -=================================================================== ---- FFmpeg.orig/libavcodec/amfenc.h -+++ FFmpeg/libavcodec/amfenc.h -@@ -1,63 +1,44 @@ - /* --* 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 --*/ -+ * 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 AVCODEC_AMFENC_H - #define AVCODEC_AMFENC_H - --#include -- - #include - #include - #include -+#include - - #include "libavutil/fifo.h" - --#include "avcodec.h" -+#include "amf.h" - #include "hwconfig.h" - --#define MAX_LOOKAHEAD_DEPTH 41 -- --/** --* AMF trace writer callback class --* Used to capture all AMF logging --*/ -- --typedef struct AmfTraceWriter { -- AMFTraceWriterVtbl *vtbl; -- AVCodecContext *avctx; --} AmfTraceWriter; -+#define MAX_LOOKAHEAD_DEPTH 41 - - /** - * AMF encoder context - */ -+typedef struct AMFEncContext { -+ void *avclass; -+ void *amfctx; - --typedef struct AmfContext { -- AVClass *avclass; -- // access to AMF runtime -- amf_handle library; ///< handle to DLL library -- AMFFactory *factory; ///< pointer to AMF factory -- AMFDebug *debug; ///< pointer to AMF debug interface -- AMFTrace *trace; ///< pointer to AMF trace interface -- -- amf_uint64 version; ///< version of AMF runtime -- AmfTraceWriter tracer; ///< AMF writer registered with AMF -- AMFContext *context; ///< AMF context -- //encoder -+ // encoder - AMFComponent *encoder; ///< AMF encoder object - amf_bool eof; ///< flag indicating EOF happened - AMF_SURFACE_FORMAT format; ///< AMF surface format -@@ -78,7 +59,6 @@ typedef struct AmfContext { - int64_t dts_delay; - - // common encoder option options -- - int log_to_dbg; - - // Static options, have to be set before Init() call -@@ -91,7 +71,6 @@ typedef struct AmfContext { - int ref_b_frame_delta_qp; - - // Dynamic options, can be set after Init() call -- - int rate_control_mode; - int enforce_hrd; - int filler_data; -@@ -114,7 +93,6 @@ typedef struct AmfContext { - int hw_high_motion_quality_boost; - - // HEVC - specific options -- - int gops_per_idr; - int header_insertion_mode; - int min_qp_i; -@@ -124,11 +102,9 @@ typedef struct AmfContext { - int tier; - - // AV1 - specific options -- - enum AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_ENUM align; - - // Preanalysis - specific options -- - int preanalysis; - int pa_activity_type; - int pa_scene_change_detection; -@@ -145,9 +121,7 @@ typedef struct AmfContext { - int pa_taq_mode; - int pa_high_motion_quality_boost_mode; - int pa_adaptive_mini_gop; -- -- --} AmfContext; -+} AMFEncContext; - - extern const AVCodecHWConfigInternal *const ff_amfenc_hw_configs[]; - -@@ -165,18 +139,4 @@ int ff_amf_encode_close(AVCodecContext * - */ - int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); - --/** --* Supported formats --*/ --extern const enum AVPixelFormat ff_amf_pix_fmts[]; -- --/** --* Error handling helper --*/ --#define AMF_RETURN_IF_FALSE(avctx, exp, ret_value, /*message,*/ ...) \ -- if (!(exp)) { \ -- av_log(avctx, AV_LOG_ERROR, __VA_ARGS__); \ -- return ret_value; \ -- } -- --#endif //AVCODEC_AMFENC_H -+#endif /* AVCODEC_AMFENC_H */ -Index: FFmpeg/libavcodec/amfenc_av1.c -=================================================================== ---- FFmpeg.orig/libavcodec/amfenc_av1.c -+++ FFmpeg/libavcodec/amfenc_av1.c -@@ -22,8 +22,24 @@ - #include "codec_internal.h" - #include "internal.h" - --#define OFFSET(x) offsetof(AmfContext, x) -+#define OFFSET(x) offsetof(AMFEncContext, x) - #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM -+ -+static const enum AVPixelFormat ff_amfenc_av1_pix_fmts[] = { -+ AV_PIX_FMT_NV12, -+ AV_PIX_FMT_YUV420P, -+ AV_PIX_FMT_P010, -+ AV_PIX_FMT_BGRA, -+ AV_PIX_FMT_BGR0, -+#if CONFIG_D3D11VA -+ AV_PIX_FMT_D3D11, -+#endif -+#if CONFIG_DXVA2 -+ AV_PIX_FMT_DXVA2_VLD, -+#endif -+ AV_PIX_FMT_NONE -+}; -+ - static const AVOption options[] = { - { "usage", "Set the encoding usage", OFFSET(usage), AV_OPT_TYPE_INT, {.i64 = AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING }, AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING, AMF_VIDEO_ENCODER_AV1_USAGE_LOW_LATENCY, VE, .unit = "usage" }, - { "transcoding", "", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING }, 0, 0, VE, .unit = "usage" }, -@@ -157,20 +173,19 @@ static av_cold int amf_encode_init_av1(A - { - int ret = 0; - AMF_RESULT res = AMF_OK; -- AmfContext* ctx = avctx->priv_data; -+ AMFEncContext *ctx = avctx->priv_data; - AMFVariantStruct var = { 0 }; - amf_int64 profile = 0; - amf_int64 profile_level = 0; -- AMFBuffer* buffer; -+ AMFBuffer *buffer; - AMFGuid guid; - AMFRate framerate; - AMFSize framesize = AMFConstructSize(avctx->width, avctx->height); -+ amf_int64 color_profile; -+ enum AVPixelFormat pix_fmt; - -- -- -- if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { -+ if (avctx->framerate.num > 0 && avctx->framerate.den > 0) - framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); -- } - else { - FF_DISABLE_DEPRECATION_WARNINGS - framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num -@@ -184,7 +199,7 @@ FF_ENABLE_DEPRECATION_WARNINGS - if ((ret = ff_amf_encode_init(avctx)) < 0) - return ret; - -- // init static parameters -+ // Init static parameters - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_USAGE, ctx->usage); - - AMF_ASSIGN_PROPERTY_SIZE(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_FRAMESIZE, framesize); -@@ -198,18 +213,17 @@ FF_ENABLE_DEPRECATION_WARNINGS - default: - break; - } -- if (profile == 0) { -+ if (profile == 0) - profile = ctx->profile; -- } - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_PROFILE, profile); - - profile_level = avctx->level; -- if (profile_level == AV_LEVEL_UNKNOWN) { -+ if (profile_level == FF_LEVEL_UNKNOWN) - profile_level = ctx->level; -- } - if (profile_level != 0) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_LEVEL, profile_level); - } -+ - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET, ctx->quality); - - // Maximum Reference Frames -@@ -225,7 +239,7 @@ FF_ENABLE_DEPRECATION_WARNINGS - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE, ctx->header_insertion_mode); - - // Rate control -- // autodetect rate control method -+ // Autodetect rate control method - if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN) { - if (ctx->min_qp_i != -1 || ctx->max_qp_i != -1 || - ctx->min_qp_p != -1 || ctx->max_qp_p != -1 || -@@ -248,8 +262,7 @@ FF_ENABLE_DEPRECATION_WARNINGS - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_PREENCODE, 0); - if (ctx->preencode) - av_log(ctx, AV_LOG_WARNING, "Preencode is not supported by cqp Rate Control Method, automatically disabled\n"); -- } -- else { -+ } else { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_PREENCODE, ctx->preencode); - } - -@@ -260,7 +273,7 @@ FF_ENABLE_DEPRECATION_WARNINGS - } - - if (ctx->hw_high_motion_quality_boost != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_HIGH_MOTION_QUALITY_BOOST, ((ctx->hw_high_motion_quality_boost == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_HIGH_MOTION_QUALITY_BOOST, !!ctx->hw_high_motion_quality_boost); - } - - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD, ctx->rate_control_mode); -@@ -275,7 +288,7 @@ FF_ENABLE_DEPRECATION_WARNINGS - } - } - -- // init dynamic rate control params -+ // Dynamic rate control params - if (ctx->max_au_size) - ctx->enforce_hrd = 1; - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_ENFORCE_HRD, ctx->enforce_hrd); -@@ -288,32 +301,27 @@ FF_ENABLE_DEPRECATION_WARNINGS - } - if (avctx->rc_max_rate) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_PEAK_BITRATE, avctx->rc_max_rate); -- } -- else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) { -+ } else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) { - av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); - } -+ - if (avctx->bit_rate > 0) { - ctx->rate_control_mode = AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR; - av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CBR\n"); - } - -- switch (ctx->align) -- { -+ switch (ctx->align) { - case AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_ONLY: -- if (avctx->width / 64 * 64 != avctx->width || avctx->height / 16 * 16 != avctx->height) -- { -+ if (avctx->width / 64 * 64 != avctx->width || avctx->height / 16 * 16 != avctx->height) { - res = AMF_NOT_SUPPORTED; - av_log(ctx, AV_LOG_ERROR, "Resolution incorrect for alignment mode\n"); - return AVERROR_EXIT; - } - break; - case AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_1080P_CODED_1082: -- if ((avctx->width / 64 * 64 == avctx->width && avctx->height / 16 * 16 == avctx->height) || (avctx->width == 1920 && avctx->height == 1080)) -- { -+ if ((avctx->width / 64 * 64 == avctx->width && avctx->height / 16 * 16 == avctx->height) || (avctx->width == 1920 && avctx->height == 1080)) { - res = AMF_OK; -- } -- else -- { -+ } else { - res = AMF_NOT_SUPPORTED; - av_log(ctx, AV_LOG_ERROR, "Resolution incorrect for alignment mode\n"); - return AVERROR_EXIT; -@@ -329,24 +337,35 @@ FF_ENABLE_DEPRECATION_WARNINGS - } - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE, ctx->align); - -+ // Output color depth, profile, transfer and primaries -+ pix_fmt = avctx->hw_frames_ctx ? ((AVHWFramesContext*)avctx->hw_frames_ctx->data)->sw_format : avctx->pix_fmt; -+ if (pix_fmt == AV_PIX_FMT_P010) { -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_COLOR_BIT_DEPTH, AMF_COLOR_BIT_DEPTH_10); -+ } else { -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_COLOR_BIT_DEPTH, AMF_COLOR_BIT_DEPTH_8); -+ } -+ color_profile = amf_av_to_amf_color_profile(avctx); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PROFILE, color_profile); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_TRANSFER_CHARACTERISTIC, (amf_int64)avctx->color_trc); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PRIMARIES, (amf_int64)avctx->color_primaries); -+ - if (ctx->preanalysis != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_PRE_ANALYSIS_ENABLE, !!((ctx->preanalysis == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_PRE_ANALYSIS_ENABLE, !!ctx->preanalysis); - } - - res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_AV1_PRE_ANALYSIS_ENABLE, &var); -- if ((int)var.int64Value) -- { -+ if ((int)var.int64Value) { - if (ctx->pa_activity_type != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_ACTIVITY_TYPE, ctx->pa_activity_type); - } - if (ctx->pa_scene_change_detection != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_SCENE_CHANGE_DETECTION_ENABLE, ((ctx->pa_scene_change_detection == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_SCENE_CHANGE_DETECTION_ENABLE, !!ctx->pa_scene_change_detection); - } - if (ctx->pa_scene_change_detection_sensitivity != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY, ctx->pa_scene_change_detection_sensitivity); - } - if (ctx->pa_static_scene_detection != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_STATIC_SCENE_DETECTION_ENABLE, ((ctx->pa_static_scene_detection == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_STATIC_SCENE_DETECTION_ENABLE, !!ctx->pa_static_scene_detection); - } - if (ctx->pa_static_scene_detection_sensitivity != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY, ctx->pa_static_scene_detection_sensitivity); -@@ -361,7 +380,7 @@ FF_ENABLE_DEPRECATION_WARNINGS - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_CAQ_STRENGTH, ctx->pa_caq_strength); - } - if (ctx->pa_frame_sad != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_FRAME_SAD_ENABLE, ((ctx->pa_frame_sad == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_FRAME_SAD_ENABLE, !!ctx->pa_frame_sad); - } - if (ctx->pa_paq_mode != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_PAQ_MODE, ctx->pa_paq_mode); -@@ -370,7 +389,7 @@ FF_ENABLE_DEPRECATION_WARNINGS - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_TAQ_MODE, ctx->pa_taq_mode); - } - if (ctx->pa_ltr != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_LTR_ENABLE, ((ctx->pa_ltr == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_LTR_ENABLE, !!ctx->pa_ltr); - } - if (ctx->pa_lookahead_buffer_depth != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_LOOKAHEAD_BUFFER_DEPTH, ctx->pa_lookahead_buffer_depth); -@@ -380,40 +399,35 @@ FF_ENABLE_DEPRECATION_WARNINGS - } - } - -- // init encoder -+ // Init encoder - res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); - -- // init dynamic picture control params -+ // Init dynamic picture control params - if (ctx->min_qp_i != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTRA, ctx->min_qp_i); -- } -- else if (avctx->qmin != -1) { -+ } else if (avctx->qmin != -1) { - int qval = avctx->qmin > 255 ? 255 : avctx->qmin; - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTRA, qval); - } - if (ctx->max_qp_i != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTRA, ctx->max_qp_i); -- } -- else if (avctx->qmax != -1) { -+ } else if (avctx->qmax != -1) { - int qval = avctx->qmax > 255 ? 255 : avctx->qmax; - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTRA, qval); - } - if (ctx->min_qp_p != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTER, ctx->min_qp_p); -- } -- else if (avctx->qmin != -1) { -+ } else if (avctx->qmin != -1) { - int qval = avctx->qmin > 255 ? 255 : avctx->qmin; - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTER, qval); - } - if (ctx->max_qp_p != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTER, ctx->max_qp_p); -- } -- else if (avctx->qmax != -1) { -+ } else if (avctx->qmax != -1) { - int qval = avctx->qmax > 255 ? 255 : avctx->qmax; - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTER, qval); - } -- - if (ctx->qp_p != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_Q_INDEX_INTER, ctx->qp_p); - } -@@ -422,7 +436,7 @@ FF_ENABLE_DEPRECATION_WARNINGS - } - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_SKIP_FRAME, ctx->skip_frame); - -- // fill extradata -+ // Fill extradata - res = AMFVariantInit(&var); - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "AMFVariantInit() failed with error %d\n", res); - -@@ -433,9 +447,8 @@ FF_ENABLE_DEPRECATION_WARNINGS - guid = IID_AMFBuffer(); - - res = var.pInterface->pVtbl->QueryInterface(var.pInterface, &guid, (void**)&buffer); // query for buffer interface -- if (res != AMF_OK) { -+ if (res != AMF_OK) - var.pInterface->pVtbl->Release(var.pInterface); -- } - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "QueryInterface(IID_AMFBuffer) failed with error %d\n", res); - - avctx->extradata_size = (int)buffer->pVtbl->GetSize(buffer); -@@ -471,20 +484,21 @@ static const AVClass av1_amf_class = { - }; - - const FFCodec ff_av1_amf_encoder = { -- .p.name = "av1_amf", -+ .p.name = "av1_amf", - CODEC_LONG_NAME("AMD AMF AV1 encoder"), -- .p.type = AVMEDIA_TYPE_VIDEO, -- .p.id = AV_CODEC_ID_AV1, -+ .p.type = AVMEDIA_TYPE_VIDEO, -+ .p.id = AV_CODEC_ID_AV1, - .init = amf_encode_init_av1, - FF_CODEC_RECEIVE_PACKET_CB(ff_amf_receive_packet), - .close = ff_amf_encode_close, -- .priv_data_size = sizeof(AmfContext), -- .p.priv_class = &av1_amf_class, -+ .priv_data_size = sizeof(AMFEncContext), -+ .p.priv_class = &av1_amf_class, - .defaults = defaults, -- .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | -+ .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_DR1, -- .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, -- .p.pix_fmts = ff_amf_pix_fmts, -- .p.wrapper_name = "amf", -+ .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | -+ FF_CODEC_CAP_INIT_CLEANUP, -+ .p.pix_fmts = ff_amfenc_av1_pix_fmts, -+ .p.wrapper_name = "amf", - .hw_configs = ff_amfenc_hw_configs, - }; -Index: FFmpeg/libavcodec/amfenc_h264.c -=================================================================== ---- FFmpeg.orig/libavcodec/amfenc_h264.c -+++ FFmpeg/libavcodec/amfenc_h264.c -@@ -16,17 +16,29 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -- - #include "libavutil/internal.h" - #include "libavutil/opt.h" - #include "amfenc.h" - #include "codec_internal.h" - #include "internal.h" --#include - --#define OFFSET(x) offsetof(AmfContext, x) -+#define OFFSET(x) offsetof(AMFEncContext, x) - #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM - -+static const enum AVPixelFormat ff_amfenc_h264_pix_fmts[] = { -+ AV_PIX_FMT_NV12, -+ AV_PIX_FMT_YUV420P, -+ AV_PIX_FMT_BGRA, -+ AV_PIX_FMT_BGR0, -+#if CONFIG_D3D11VA -+ AV_PIX_FMT_D3D11, -+#endif -+#if CONFIG_DXVA2 -+ AV_PIX_FMT_DXVA2_VLD, -+#endif -+ AV_PIX_FMT_NONE -+}; -+ - static const AVOption options[] = { - // Static - /// Usage -@@ -190,7 +202,7 @@ static av_cold int amf_encode_init_h264( - { - int ret = 0; - AMF_RESULT res = AMF_OK; -- AmfContext *ctx = avctx->priv_data; -+ AMFEncContext *ctx = avctx->priv_data; - AMFVariantStruct var = { 0 }; - amf_int64 profile = 0; - amf_int64 profile_level = 0; -@@ -199,10 +211,12 @@ static av_cold int amf_encode_init_h264( - AMFRate framerate; - AMFSize framesize = AMFConstructSize(avctx->width, avctx->height); - int deblocking_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0; -+ amf_int64 color_profile; -+ enum AVPixelFormat pix_fmt; - -- if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { -+ if (avctx->framerate.num > 0 && avctx->framerate.den > 0) - framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); -- } else { -+ else { - FF_DISABLE_DEPRECATION_WARNINGS - framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num - #if FF_API_TICKS_PER_FRAME -@@ -239,40 +253,32 @@ FF_ENABLE_DEPRECATION_WARNINGS - profile = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_HIGH; - break; - } -- if (profile == 0) { -+ if (profile == 0) - profile = ctx->profile; -- } - - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PROFILE, profile); - - profile_level = avctx->level; -- if (profile_level == AV_LEVEL_UNKNOWN) { -+ if (profile_level == FF_LEVEL_UNKNOWN) - profile_level = ctx->level; -- } - if (profile_level != 0) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PROFILE_LEVEL, profile_level); - } - - // Maximum Reference Frames -- if (avctx->refs != -1) { -+ if (avctx->refs != -1) - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_NUM_REFRAMES, avctx->refs); -- } - if (avctx->sample_aspect_ratio.den && avctx->sample_aspect_ratio.num) { - AMFRatio ratio = AMFConstructRatio(avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den); - AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_ASPECT_RATIO, ratio); - } - -- /// Color Range (Partial/TV/MPEG or Full/PC/JPEG) -- if (avctx->color_range == AVCOL_RANGE_JPEG) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, 1); -- } -- -- // autodetect rate control method -+ // Autodetect rate control method - if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN) { - if (ctx->qp_i != -1 || ctx->qp_p != -1 || ctx->qp_b != -1) { - ctx->rate_control_mode = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP; - av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CQP\n"); -- } else if (avctx->rc_max_rate > 0 ) { -+ } else if (avctx->rc_max_rate > 0) { - ctx->rate_control_mode = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR; - av_log(ctx, AV_LOG_DEBUG, "Rate control turned to Peak VBR\n"); - } else { -@@ -281,10 +287,11 @@ FF_ENABLE_DEPRECATION_WARNINGS - } - } - -+ // Pre-Pass, Pre-Analysis, Two-Pass - if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PREENCODE_ENABLE, AMF_VIDEO_ENCODER_PREENCODE_DISABLED); - if (ctx->preencode) -- av_log(ctx, AV_LOG_WARNING, "Preencode is not supported by cqp Rate Control Method, automatically disabled\n"); -+ av_log(ctx, AV_LOG_WARNING, "Pre-Encode is not supported by CQP rate control method, automatically disabled\n"); - } else { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PREENCODE_ENABLE, ctx->preencode); - } -@@ -296,15 +303,16 @@ FF_ENABLE_DEPRECATION_WARNINGS - } - - if (ctx->hw_high_motion_quality_boost != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HIGH_MOTION_QUALITY_BOOST_ENABLE, ((ctx->hw_high_motion_quality_boost == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HIGH_MOTION_QUALITY_BOOST_ENABLE, !!ctx->hw_high_motion_quality_boost); - } - -+ // Quality preset - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QUALITY_PRESET, ctx->quality); - - // Dynamic parmaters - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD, ctx->rate_control_mode); - -- /// VBV Buffer -+ // VBV Buffer - if (avctx->rc_buffer_size != 0) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_VBV_BUFFER_SIZE, avctx->rc_buffer_size); - if (avctx->rc_initial_buffer_occupancy != 0) { -@@ -314,7 +322,8 @@ FF_ENABLE_DEPRECATION_WARNINGS - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_INITIAL_VBV_BUFFER_FULLNESS, amf_buffer_fullness); - } - } -- /// Maximum Access Unit Size -+ -+ // Maximum Access Unit Size - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_AU_SIZE, ctx->max_au_size); - - if (ctx->max_au_size) -@@ -324,7 +333,21 @@ FF_ENABLE_DEPRECATION_WARNINGS - if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MIN_QP, 0); - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_QP, 51); -- } else { -+ } else if (ctx->rate_control_mode != AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_QUALITY_VBR) { -+ if (avctx->qmin == -1 && avctx->qmax == -1) { -+ switch (ctx->usage) { -+ case AMF_VIDEO_ENCODER_USAGE_TRANSCONDING: -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MIN_QP, 18); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_QP, 46); -+ break; -+ case AMF_VIDEO_ENCODER_USAGE_ULTRA_LOW_LATENCY: -+ case AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY: -+ case AMF_VIDEO_ENCODER_USAGE_WEBCAM: -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MIN_QP, 22); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_QP, 48); -+ break; -+ } -+ } - if (avctx->qmin != -1) { - int qval = avctx->qmin > 51 ? 51 : avctx->qmin; - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MIN_QP, qval); -@@ -335,42 +358,56 @@ FF_ENABLE_DEPRECATION_WARNINGS - } - } - // QP Values -- if (ctx->qp_i != -1) -+ if (ctx->qp_i != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QP_I, ctx->qp_i); -- if (ctx->qp_p != -1) -+ } -+ if (ctx->qp_p != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QP_P, ctx->qp_p); -- if (ctx->qp_b != -1) -+ } -+ if (ctx->qp_b != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QP_B, ctx->qp_b); -+ } - - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_TARGET_BITRATE, avctx->bit_rate); - - if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PEAK_BITRATE, avctx->bit_rate); - } -+ - if (avctx->rc_max_rate) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PEAK_BITRATE, avctx->rc_max_rate); - } else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) { -- av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); -+ av_log(ctx, AV_LOG_WARNING, "Rate control method is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); - } - -+ pix_fmt = avctx->hw_frames_ctx ? ((AVHWFramesContext*)avctx->hw_frames_ctx->data)->sw_format : avctx->pix_fmt; -+ AMF_RETURN_IF_FALSE(ctx, pix_fmt != AV_PIX_FMT_P010, AVERROR_INVALIDDATA, "10-bit input video is not supported by AMF H264 encoder\n"); -+ -+ // Output color depth, profile, transfer and primaries -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_COLOR_BIT_DEPTH, AMF_COLOR_BIT_DEPTH_8); -+ color_profile = amf_av_to_amf_color_profile(avctx); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_COLOR_PROFILE, color_profile); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, !!(avctx->color_range == AVCOL_RANGE_JPEG)); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_TRANSFER_CHARACTERISTIC, (amf_int64)avctx->color_trc); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_OUTPUT_COLOR_PRIMARIES, (amf_int64)avctx->color_primaries); -+ - if (ctx->preanalysis != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_PRE_ANALYSIS_ENABLE, !!((ctx->preanalysis == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_PRE_ANALYSIS_ENABLE, !!ctx->preanalysis); - } - - res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_PRE_ANALYSIS_ENABLE, &var); -- if ((int)var.int64Value) -- { -+ if ((int)var.int64Value) { - if (ctx->pa_activity_type != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_ACTIVITY_TYPE, ctx->pa_activity_type); - } - if (ctx->pa_scene_change_detection != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_SCENE_CHANGE_DETECTION_ENABLE, ((ctx->pa_scene_change_detection == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_SCENE_CHANGE_DETECTION_ENABLE, !!ctx->pa_scene_change_detection); - } - if (ctx->pa_scene_change_detection_sensitivity != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY, ctx->pa_scene_change_detection_sensitivity); - } - if (ctx->pa_static_scene_detection != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_STATIC_SCENE_DETECTION_ENABLE, ((ctx->pa_static_scene_detection == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_STATIC_SCENE_DETECTION_ENABLE, !!ctx->pa_static_scene_detection); - } - if (ctx->pa_static_scene_detection_sensitivity != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY, ctx->pa_static_scene_detection_sensitivity); -@@ -385,7 +422,7 @@ FF_ENABLE_DEPRECATION_WARNINGS - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_CAQ_STRENGTH, ctx->pa_caq_strength); - } - if (ctx->pa_frame_sad != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_FRAME_SAD_ENABLE, ((ctx->pa_frame_sad == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_FRAME_SAD_ENABLE, !!ctx->pa_frame_sad); - } - if (ctx->pa_paq_mode != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_PAQ_MODE, ctx->pa_paq_mode); -@@ -394,10 +431,10 @@ FF_ENABLE_DEPRECATION_WARNINGS - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_TAQ_MODE, ctx->pa_taq_mode); - } - if (ctx->pa_adaptive_mini_gop != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ADAPTIVE_MINIGOP, ((ctx->pa_adaptive_mini_gop == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ADAPTIVE_MINIGOP, !!ctx->pa_adaptive_mini_gop); - } - if (ctx->pa_ltr != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_LTR_ENABLE, ((ctx->pa_ltr == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_LTR_ENABLE, !!ctx->pa_ltr); - } - if (ctx->pa_lookahead_buffer_depth != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_LOOKAHEAD_BUFFER_DEPTH, ctx->pa_lookahead_buffer_depth); -@@ -422,8 +459,7 @@ FF_ENABLE_DEPRECATION_WARNINGS - av_log(ctx, AVERROR_BUG, "Maxium B frames needs to be greater than the specified B frame count.\n"); - } - } -- } -- else { -+ } else { - if (ctx->max_b_frames != -1) { - av_log(ctx, AVERROR_BUG, "Maxium number of B frames needs to be specified.\n"); - } -@@ -439,41 +475,49 @@ FF_ENABLE_DEPRECATION_WARNINGS - res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); - -- // Enforce HRD, Filler Data, VBAQ, Frame Skipping, Deblocking Filter -+ // Enforce HRD, Filler Data, Frame Skipping, Deblocking Filter - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENFORCE_HRD, !!ctx->enforce_hrd); - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FILLER_DATA_ENABLE, !!ctx->filler_data); - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_SKIP_FRAME_ENABLE, !!ctx->skip_frame); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_DE_BLOCKING_FILTER, !!deblocking_filter); -+ -+ // VBAQ - if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) { - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENABLE_VBAQ, 0); -- if (ctx->enable_vbaq) -+ if (ctx->enable_vbaq) { -+ ctx->enable_vbaq = 0; - av_log(ctx, AV_LOG_WARNING, "VBAQ is not supported by cqp Rate Control Method, automatically disabled\n"); -+ } - } else { - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENABLE_VBAQ, !!ctx->enable_vbaq); - } -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_DE_BLOCKING_FILTER, !!deblocking_filter); - - // Keyframe Interval - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_IDR_PERIOD, avctx->gop_size); - - // Header Insertion Spacing -- if (ctx->header_spacing >= 0) -+ if (ctx->header_spacing >= 0) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEADER_INSERTION_SPACING, ctx->header_spacing); -+ } - - // Intra-Refresh, Slicing -- if (ctx->intra_refresh_mb > 0) -+ if (ctx->intra_refresh_mb > 0) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_INTRA_REFRESH_NUM_MBS_PER_SLOT, ctx->intra_refresh_mb); -- if (avctx->slices > 1) -+ } -+ if (avctx->slices > 1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_SLICES_PER_FRAME, avctx->slices); -+ } - - // Coding -- if (ctx->coding_mode != 0) -+ if (ctx->coding_mode != 0) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_CABAC_ENABLE, ctx->coding_mode); -+ } - - // Motion Estimation - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_MOTION_HALF_PIXEL, !!ctx->me_half_pel); - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_MOTION_QUARTERPIXEL, !!ctx->me_quarter_pel); - -- // fill extradata -+ // Fill extradata - res = AMFVariantInit(&var); - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "AMFVariantInit() failed with error %d\n", res); - -@@ -484,9 +528,8 @@ FF_ENABLE_DEPRECATION_WARNINGS - guid = IID_AMFBuffer(); - - res = var.pInterface->pVtbl->QueryInterface(var.pInterface, &guid, (void**)&buffer); // query for buffer interface -- if (res != AMF_OK) { -+ if (res != AMF_OK) - var.pInterface->pVtbl->Release(var.pInterface); -- } - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "QueryInterface(IID_AMFBuffer) failed with error %d\n", res); - - avctx->extradata_size = (int)buffer->pVtbl->GetSize(buffer); -@@ -505,15 +548,15 @@ FF_ENABLE_DEPRECATION_WARNINGS - } - - static const FFCodecDefault defaults[] = { -- { "refs", "-1" }, -- { "aspect", "0" }, -- { "qmin", "-1" }, -- { "qmax", "-1" }, -- { "b", "2M" }, -- { "g", "250" }, -- { "slices", "1" }, -- { "flags", "+loop"}, -- { NULL }, -+ { "refs", "-1" }, -+ { "aspect", "0" }, -+ { "qmin", "-1" }, -+ { "qmax", "-1" }, -+ { "b", "2M" }, -+ { "g", "250" }, -+ { "slices", "1" }, -+ { "flags", "+loop" }, -+ { NULL }, - }; - - static const AVClass h264_amf_class = { -@@ -531,14 +574,14 @@ const FFCodec ff_h264_amf_encoder = { - .init = amf_encode_init_h264, - FF_CODEC_RECEIVE_PACKET_CB(ff_amf_receive_packet), - .close = ff_amf_encode_close, -- .priv_data_size = sizeof(AmfContext), -+ .priv_data_size = sizeof(AMFEncContext), - .p.priv_class = &h264_amf_class, - .defaults = defaults, - .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | - FF_CODEC_CAP_INIT_CLEANUP, -- .p.pix_fmts = ff_amf_pix_fmts, -+ .p.pix_fmts = ff_amfenc_h264_pix_fmts, - .p.wrapper_name = "amf", - .hw_configs = ff_amfenc_hw_configs, - }; -Index: FFmpeg/libavcodec/amfenc_hevc.c -=================================================================== ---- FFmpeg.orig/libavcodec/amfenc_hevc.c -+++ FFmpeg/libavcodec/amfenc_hevc.c -@@ -21,10 +21,25 @@ - #include "amfenc.h" - #include "codec_internal.h" - #include "internal.h" --#include - --#define OFFSET(x) offsetof(AmfContext, x) -+#define OFFSET(x) offsetof(AMFEncContext, x) - #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM -+ -+static const enum AVPixelFormat ff_amfenc_hevc_pix_fmts[] = { -+ AV_PIX_FMT_NV12, -+ AV_PIX_FMT_YUV420P, -+ AV_PIX_FMT_P010, -+ AV_PIX_FMT_BGRA, -+ AV_PIX_FMT_BGR0, -+#if CONFIG_D3D11VA -+ AV_PIX_FMT_D3D11, -+#endif -+#if CONFIG_DXVA2 -+ AV_PIX_FMT_DXVA2_VLD, -+#endif -+ AV_PIX_FMT_NONE -+}; -+ - static const AVOption options[] = { - { "usage", "Set the encoding usage", OFFSET(usage), AV_OPT_TYPE_INT, {.i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCODING }, AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCODING, AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY_HIGH_QUALITY, VE, .unit = "usage" }, - { "transcoding", "Generic Transcoding", 0, AV_OPT_TYPE_CONST, {.i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCODING }, 0, 0, VE, .unit = "usage" }, -@@ -151,8 +166,8 @@ static av_cold int amf_encode_init_hevc( - { - int ret = 0; - AMF_RESULT res = AMF_OK; -- AmfContext *ctx = avctx->priv_data; -- AMFVariantStruct var = {0}; -+ AMFEncContext *ctx = avctx->priv_data; -+ AMFVariantStruct var = { 0 }; - amf_int64 profile = 0; - amf_int64 profile_level = 0; - AMFBuffer *buffer; -@@ -160,10 +175,12 @@ static av_cold int amf_encode_init_hevc( - AMFRate framerate; - AMFSize framesize = AMFConstructSize(avctx->width, avctx->height); - int deblocking_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0; -+ amf_int64 color_profile; -+ enum AVPixelFormat pix_fmt; - -- if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { -+ if (avctx->framerate.num > 0 && avctx->framerate.den > 0) - framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den); -- } else { -+ else { - FF_DISABLE_DEPRECATION_WARNINGS - framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num - #if FF_API_TICKS_PER_FRAME -@@ -176,7 +193,7 @@ FF_ENABLE_DEPRECATION_WARNINGS - if ((ret = ff_amf_encode_init(avctx)) < 0) - return ret; - -- // init static parameters -+ // Static parameters - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_USAGE, ctx->usage); - - AMF_ASSIGN_PROPERTY_SIZE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FRAMESIZE, framesize); -@@ -187,23 +204,25 @@ FF_ENABLE_DEPRECATION_WARNINGS - case AV_PROFILE_HEVC_MAIN: - profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN; - break; -+ case AV_PROFILE_HEVC_MAIN_10: -+ profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN_10; -+ break; - default: - break; - } -- if (profile == 0) { -+ if (profile == 0) - profile = ctx->profile; -- } - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PROFILE, profile); - - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_TIER, ctx->tier); - - profile_level = avctx->level; -- if (profile_level == AV_LEVEL_UNKNOWN) { -+ if (profile_level == FF_LEVEL_UNKNOWN) - profile_level = ctx->level; -- } - if (profile_level != 0) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PROFILE_LEVEL, profile_level); - } -+ - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET, ctx->quality); - // Maximum Reference Frames - if (avctx->refs != -1) { -@@ -224,30 +243,12 @@ FF_ENABLE_DEPRECATION_WARNINGS - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_DE_BLOCKING_FILTER_DISABLE, deblocking_filter); - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE, ctx->header_insertion_mode); - -- // Rate control -- // autodetect rate control method -- if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN) { -- if (ctx->min_qp_i != -1 || ctx->max_qp_i != -1 || -- ctx->min_qp_p != -1 || ctx->max_qp_p != -1 || -- ctx->qp_i !=-1 || ctx->qp_p != -1) { -- ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP; -- av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CQP\n"); -- } else if (avctx->rc_max_rate > 0) { -- ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR; -- av_log(ctx, AV_LOG_DEBUG, "Rate control turned to Peak VBR\n"); -- } else { -- ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR; -- av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CBR\n"); -- } -- } -- - // Pre-Pass, Pre-Analysis, Two-Pass - if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PREENCODE_ENABLE, 0); - if (ctx->preencode) - av_log(ctx, AV_LOG_WARNING, "Preencode is not supported by cqp Rate Control Method, automatically disabled\n"); -- } -- else { -+ } else { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PREENCODE_ENABLE, ctx->preencode); - } - -@@ -258,7 +259,24 @@ FF_ENABLE_DEPRECATION_WARNINGS - } - - if (ctx->hw_high_motion_quality_boost != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_HIGH_MOTION_QUALITY_BOOST_ENABLE, ((ctx->hw_high_motion_quality_boost == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_HIGH_MOTION_QUALITY_BOOST_ENABLE, !!ctx->hw_high_motion_quality_boost); -+ } -+ -+ // Rate control properties -+ // Auto detect rate control method -+ if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN) { -+ if (ctx->min_qp_i != -1 || ctx->max_qp_i != -1 || -+ ctx->min_qp_p != -1 || ctx->max_qp_p != -1 || -+ ctx->qp_i !=-1 || ctx->qp_p != -1) { -+ ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP; -+ av_log(ctx, AV_LOG_DEBUG, "Rate control method turned to CQP\n"); -+ } else if (avctx->rc_max_rate > 0) { -+ ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR; -+ av_log(ctx, AV_LOG_DEBUG, "Rate control method turned to Peak VBR\n"); -+ } else { -+ ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR; -+ av_log(ctx, AV_LOG_DEBUG, "Rate control method turned to CBR\n"); -+ } - } - - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD, ctx->rate_control_mode); -@@ -273,17 +291,22 @@ FF_ENABLE_DEPRECATION_WARNINGS - } - } - -+ // VBAQ - if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ, false); -- if (ctx->enable_vbaq) -- av_log(ctx, AV_LOG_WARNING, "VBAQ is not supported by cqp Rate Control Method, automatically disabled\n"); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ, 0); -+ if (ctx->enable_vbaq) { -+ ctx->enable_vbaq = 0; -+ av_log(ctx, AV_LOG_WARNING, "VBAQ is not supported by CQP rate control method, automatically disabled\n"); -+ } - } else { - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ, !!ctx->enable_vbaq); - } -+ -+ // Motion estimation - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MOTION_HALF_PIXEL, ctx->me_half_pel); - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MOTION_QUARTERPIXEL, ctx->me_quarter_pel); - -- // init dynamic rate control params -+ // Dynamic rate control params - if (ctx->max_au_size) - ctx->enforce_hrd = 1; - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENFORCE_HRD, ctx->enforce_hrd); -@@ -297,27 +320,39 @@ FF_ENABLE_DEPRECATION_WARNINGS - if (avctx->rc_max_rate) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE, avctx->rc_max_rate); - } else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) { -- av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); -+ av_log(ctx, AV_LOG_WARNING, "Rate control method is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n"); -+ } -+ -+ // Output color depth, profile, transfer and primaries -+ pix_fmt = avctx->hw_frames_ctx ? ((AVHWFramesContext*)avctx->hw_frames_ctx->data)->sw_format : avctx->pix_fmt; -+ if (pix_fmt == AV_PIX_FMT_P010) { -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_COLOR_BIT_DEPTH, AMF_COLOR_BIT_DEPTH_10); -+ } else { -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_COLOR_BIT_DEPTH, AMF_COLOR_BIT_DEPTH_8); - } -+ color_profile = amf_av_to_amf_color_profile(avctx); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_COLOR_PROFILE, color_profile); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_NOMINAL_RANGE, !!(avctx->color_range == AVCOL_RANGE_JPEG)); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_TRANSFER_CHARACTERISTIC, (amf_int64)avctx->color_trc); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_OUTPUT_COLOR_PRIMARIES, (amf_int64)avctx->color_primaries); - - if (ctx->preanalysis != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PRE_ANALYSIS_ENABLE, !!((ctx->preanalysis == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PRE_ANALYSIS_ENABLE, !!ctx->preanalysis); - } - - res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PRE_ANALYSIS_ENABLE, &var); -- if ((int)var.int64Value) -- { -+ if ((int)var.int64Value) { - if (ctx->pa_activity_type != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_ACTIVITY_TYPE, ctx->pa_activity_type); - } - if (ctx->pa_scene_change_detection != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_SCENE_CHANGE_DETECTION_ENABLE, ((ctx->pa_scene_change_detection == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_SCENE_CHANGE_DETECTION_ENABLE, !!ctx->pa_scene_change_detection); - } - if (ctx->pa_scene_change_detection_sensitivity != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_SCENE_CHANGE_DETECTION_SENSITIVITY, ctx->pa_scene_change_detection_sensitivity); - } - if (ctx->pa_static_scene_detection != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_STATIC_SCENE_DETECTION_ENABLE, ((ctx->pa_static_scene_detection == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_STATIC_SCENE_DETECTION_ENABLE, !!ctx->pa_static_scene_detection); - } - if (ctx->pa_static_scene_detection_sensitivity != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_STATIC_SCENE_DETECTION_SENSITIVITY, ctx->pa_static_scene_detection_sensitivity); -@@ -332,7 +367,7 @@ FF_ENABLE_DEPRECATION_WARNINGS - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_CAQ_STRENGTH, ctx->pa_caq_strength); - } - if (ctx->pa_frame_sad != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_FRAME_SAD_ENABLE, ((ctx->pa_frame_sad == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_FRAME_SAD_ENABLE, !!ctx->pa_frame_sad); - } - if (ctx->pa_paq_mode != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_PAQ_MODE, ctx->pa_paq_mode); -@@ -341,7 +376,7 @@ FF_ENABLE_DEPRECATION_WARNINGS - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_TAQ_MODE, ctx->pa_taq_mode); - } - if (ctx->pa_ltr != -1) { -- AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_LTR_ENABLE, ((ctx->pa_ltr == 0) ? false : true)); -+ AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_PA_LTR_ENABLE, !!ctx->pa_ltr); - } - if (ctx->pa_lookahead_buffer_depth != -1) { - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_PA_LOOKAHEAD_BUFFER_DEPTH, ctx->pa_lookahead_buffer_depth); -@@ -351,36 +386,63 @@ FF_ENABLE_DEPRECATION_WARNINGS - } - } - -- // init encoder -+ // Init encoder - res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height); - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res); - -- // init dynamic picture control params -+ // Dynamic picture control params - AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_AU_SIZE, ctx->max_au_size); - -- if (ctx->min_qp_i != -1) { -- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, ctx->min_qp_i); -- } else if (avctx->qmin != -1) { -- int qval = avctx->qmin > 51 ? 51 : avctx->qmin; -- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, qval); -- } -- if (ctx->max_qp_i != -1) { -- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, ctx->max_qp_i); -- } else if (avctx->qmax != -1) { -- int qval = avctx->qmax > 51 ? 51 : avctx->qmax; -- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, qval); -- } -- if (ctx->min_qp_p != -1) { -- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, ctx->min_qp_p); -- } else if (avctx->qmin != -1) { -- int qval = avctx->qmin > 51 ? 51 : avctx->qmin; -- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, qval); -- } -- if (ctx->max_qp_p != -1) { -- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, ctx->max_qp_p); -- } else if (avctx->qmax != -1) { -- int qval = avctx->qmax > 51 ? 51 : avctx->qmax; -- AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, qval); -+ // QP Minimum / Maximum -+ if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP) { -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, 0); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, 51); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, 0); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, 51); -+ } else { -+ if (ctx->min_qp_i != -1) { -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, ctx->min_qp_i); -+ } else if (avctx->qmin != -1) { -+ int qval = avctx->qmin > 51 ? 51 : avctx->qmin; -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, qval); -+ } -+ if (ctx->max_qp_i != -1) { -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, ctx->max_qp_i); -+ } else if (avctx->qmax != -1) { -+ int qval = avctx->qmax > 51 ? 51 : avctx->qmax; -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, qval); -+ } -+ if (ctx->min_qp_p != -1) { -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, ctx->min_qp_p); -+ } else if (avctx->qmin != -1) { -+ int qval = avctx->qmin > 51 ? 51 : avctx->qmin; -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, qval); -+ } -+ if (ctx->max_qp_p != -1) { -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, ctx->max_qp_p); -+ } else if (avctx->qmax != -1) { -+ int qval = avctx->qmax > 51 ? 51 : avctx->qmax; -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, qval); -+ } -+ if (ctx->min_qp_i == -1 && ctx->max_qp_i == -1 && ctx->min_qp_p == -1 && ctx->max_qp_p == -1 && -+ avctx->qmin == -1 && avctx->qmax == -1) { -+ switch (ctx->usage) { -+ case AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING: -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, 18); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, 46); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, 18); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, 46); -+ break; -+ case AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY: -+ case AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY: -+ case AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM: -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, 22); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, 48); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, 22); -+ AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, 48); -+ break; -+ } -+ } - } - - if (ctx->qp_p != -1) { -@@ -391,7 +453,7 @@ FF_ENABLE_DEPRECATION_WARNINGS - } - AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_SKIP_FRAME_ENABLE, ctx->skip_frame); - -- // fill extradata -+ // Fill extradata - res = AMFVariantInit(&var); - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "AMFVariantInit() failed with error %d\n", res); - -@@ -402,9 +464,8 @@ FF_ENABLE_DEPRECATION_WARNINGS - guid = IID_AMFBuffer(); - - res = var.pInterface->pVtbl->QueryInterface(var.pInterface, &guid, (void**)&buffer); // query for buffer interface -- if (res != AMF_OK) { -+ if (res != AMF_OK) - var.pInterface->pVtbl->Release(var.pInterface); -- } - AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "QueryInterface(IID_AMFBuffer) failed with error %d\n", res); - - avctx->extradata_size = (int)buffer->pVtbl->GetSize(buffer); -@@ -421,6 +482,7 @@ FF_ENABLE_DEPRECATION_WARNINGS - - return 0; - } -+ - static const FFCodecDefault defaults[] = { - { "refs", "-1" }, - { "aspect", "0" }, -@@ -431,6 +493,7 @@ static const FFCodecDefault defaults[] = - { "qmax", "-1" }, - { NULL }, - }; -+ - static const AVClass hevc_amf_class = { - .class_name = "hevc_amf", - .item_name = av_default_item_name, -@@ -446,14 +509,14 @@ const FFCodec ff_hevc_amf_encoder = { - .init = amf_encode_init_hevc, - FF_CODEC_RECEIVE_PACKET_CB(ff_amf_receive_packet), - .close = ff_amf_encode_close, -- .priv_data_size = sizeof(AmfContext), -+ .priv_data_size = sizeof(AMFEncContext), - .p.priv_class = &hevc_amf_class, - .defaults = defaults, - .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | - AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | - FF_CODEC_CAP_INIT_CLEANUP, -- .p.pix_fmts = ff_amf_pix_fmts, -+ .p.pix_fmts = ff_amfenc_hevc_pix_fmts, - .p.wrapper_name = "amf", - .hw_configs = ff_amfenc_hw_configs, - }; diff --git a/debian/patches/0006-add-opencl-scaler-and-pixfmt-converter-impl.patch b/debian/patches/0006-add-opencl-scaler-and-pixfmt-converter-impl.patch index 51482286b..02eaab276 100644 --- a/debian/patches/0006-add-opencl-scaler-and-pixfmt-converter-impl.patch +++ b/debian/patches/0006-add-opencl-scaler-and-pixfmt-converter-impl.patch @@ -2,7 +2,7 @@ Index: FFmpeg/configure =================================================================== --- FFmpeg.orig/configure +++ FFmpeg/configure -@@ -3889,6 +3889,7 @@ rubberband_filter_deps="librubberband" +@@ -3935,6 +3935,7 @@ rubberband_filter_deps="librubberband" sab_filter_deps="gpl swscale" scale2ref_filter_deps="swscale" scale_filter_deps="swscale" @@ -14,7 +14,7 @@ Index: FFmpeg/libavfilter/Makefile =================================================================== --- FFmpeg.orig/libavfilter/Makefile +++ FFmpeg/libavfilter/Makefile -@@ -459,6 +459,7 @@ OBJS-$(CONFIG_SCALE_FILTER) +@@ -461,6 +461,7 @@ OBJS-$(CONFIG_SCALE_FILTER) OBJS-$(CONFIG_SCALE_CUDA_FILTER) += vf_scale_cuda.o scale_eval.o \ vf_scale_cuda.ptx.o cuda/load_helper.o OBJS-$(CONFIG_SCALE_NPP_FILTER) += vf_scale_npp.o scale_eval.o @@ -26,7 +26,7 @@ Index: FFmpeg/libavfilter/allfilters.c =================================================================== --- FFmpeg.orig/libavfilter/allfilters.c +++ FFmpeg/libavfilter/allfilters.c -@@ -432,6 +432,7 @@ extern const AVFilter ff_vf_sab; +@@ -433,6 +433,7 @@ extern const AVFilter ff_vf_sab; extern const AVFilter ff_vf_scale; extern const AVFilter ff_vf_scale_cuda; extern const AVFilter ff_vf_scale_npp; @@ -331,7 +331,7 @@ Index: FFmpeg/libavfilter/vf_scale_opencl.c =================================================================== --- /dev/null +++ FFmpeg/libavfilter/vf_scale_opencl.c -@@ -0,0 +1,777 @@ +@@ -0,0 +1,779 @@ +/* + * Copyright (c) 2018 Gabriel Machado + * Copyright (c) 2021 NyanMisaka @@ -354,13 +354,13 @@ Index: FFmpeg/libavfilter/vf_scale_opencl.c + */ + +#include "libavutil/avassert.h" -+#include "libavutil/common.h" +#include "libavutil/imgutils.h" ++#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avfilter.h" -+#include "internal.h" ++#include "filters.h" +#include "opencl.h" +#include "opencl_source.h" +#include "scale_eval.h" @@ -762,8 +762,10 @@ Index: FFmpeg/libavfilter/vf_scale_opencl.c + +static int scale_opencl_config_output(AVFilterLink *outlink) +{ ++ FilterLink *outl = ff_filter_link(outlink); + AVFilterContext *avctx = outlink->src; + AVFilterLink *inlink = avctx->inputs[0]; ++ FilterLink *inl = ff_filter_link(inlink); + ScaleOpenCLContext *ctx = avctx->priv; + AVHWFramesContext *in_frames_ctx; + enum AVPixelFormat in_format; @@ -772,9 +774,9 @@ Index: FFmpeg/libavfilter/vf_scale_opencl.c + const AVPixFmtDescriptor *out_desc; + int ret; + -+ if (!inlink->hw_frames_ctx) ++ if (!inl->hw_frames_ctx) + return AVERROR(EINVAL); -+ in_frames_ctx = (AVHWFramesContext*)inlink->hw_frames_ctx->data; ++ in_frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data; + in_format = in_frames_ctx->sw_format; + out_format = (ctx->format == AV_PIX_FMT_NONE) ? in_format : ctx->format; + in_desc = av_pix_fmt_desc_get(in_format); @@ -818,9 +820,9 @@ Index: FFmpeg/libavfilter/vf_scale_opencl.c + ctx->ocf.output_height = ctx->dst_h; + + if (ctx->passthrough && ctx->src_w == ctx->dst_w && ctx->src_h == ctx->dst_h && ctx->in_fmt == ctx->out_fmt) { -+ av_buffer_unref(&outlink->hw_frames_ctx); -+ outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx); -+ if (!outlink->hw_frames_ctx) ++ av_buffer_unref(&outl->hw_frames_ctx); ++ outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx); ++ if (!outl->hw_frames_ctx) + return AVERROR(ENOMEM); + return 0; + } else { diff --git a/debian/patches/0007-add-bt2390-eetf-and-code-refactor-to-opencl-tonemap.patch b/debian/patches/0007-add-bt2390-eetf-and-code-refactor-to-opencl-tonemap.patch index e4c6c8bb8..659e2ab1c 100644 --- a/debian/patches/0007-add-bt2390-eetf-and-code-refactor-to-opencl-tonemap.patch +++ b/debian/patches/0007-add-bt2390-eetf-and-code-refactor-to-opencl-tonemap.patch @@ -2,16 +2,89 @@ Index: FFmpeg/libavfilter/opencl.c =================================================================== --- FFmpeg.orig/libavfilter/opencl.c +++ FFmpeg/libavfilter/opencl.c -@@ -169,7 +169,7 @@ int ff_opencl_filter_load_program(AVFilt +@@ -19,6 +19,7 @@ + #include + #include + ++#include "libavutil/avassert.h" + #include "libavutil/file_open.h" + #include "libavutil/mem.h" + #include "libavutil/pixdesc.h" +@@ -156,6 +157,29 @@ void ff_opencl_filter_uninit(AVFilterCon + av_buffer_unref(&ctx->device_ref); + } + ++#if ARCH_AARCH64 && (defined(__linux__) || defined(__ANDROID__)) ++static char *check_opencl_device_str(cl_device_id device_id, ++ cl_device_info key) ++{ ++ char *str; ++ size_t size; ++ cl_int cle; ++ cle = clGetDeviceInfo(device_id, key, 0, NULL, &size); ++ if (cle != CL_SUCCESS) ++ return NULL; ++ str = av_malloc(size); ++ if (!str) ++ return NULL; ++ cle = clGetDeviceInfo(device_id, key, size, str, &size); ++ if (cle != CL_SUCCESS) { ++ av_free(str); ++ return NULL; ++ } ++ av_assert0(strlen(str) + 1== size); ++ return str; ++} ++#endif ++ + int ff_opencl_filter_load_program(AVFilterContext *avctx, + const char **program_source_array, + int nb_strings) +@@ -171,8 +195,42 @@ int ff_opencl_filter_load_program(AVFilt + return AVERROR(EIO); } ++#if ARCH_AARCH64 && (defined(__linux__) || defined(__ANDROID__)) ++ /* Try aggressive heuristics for the kernel vectorizer & unroller on libMali */ ++ { ++ char *device_vendor = check_opencl_device_str(ctx->hwctx->device_id, CL_DEVICE_VENDOR); ++ char *device_name = check_opencl_device_str(ctx->hwctx->device_id, CL_DEVICE_NAME); ++ ++ if (strstr(device_vendor, "ARM") && ++ (strstr(device_name, "Mali") || strstr(device_name, "Immortalis"))) { ++ av_free(device_vendor); ++ av_free(device_name); ++ ++ cle = clBuildProgram(ctx->program, 1, &ctx->hwctx->device_id, ++ "-cl-finite-math-only -cl-unsafe-math-optimizations " ++ "-fkernel-vectorizer -fkernel-unroller", NULL, NULL); ++ if (cle == CL_SUCCESS) ++ return 0; ++ ++ /* Fall-back to standard build options */ ++ clReleaseProgram(ctx->program); ++ ctx->program = clCreateProgramWithSource(ctx->hwctx->context, nb_strings, ++ program_source_array, ++ NULL, &cle); ++ if (!ctx->program) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to create program: %d.\n", cle); ++ return AVERROR(EIO); ++ } ++ } ++ if (device_vendor) ++ av_free(device_vendor); ++ if (device_name) ++ av_free(device_name); ++ } ++#endif ++ cle = clBuildProgram(ctx->program, 1, &ctx->hwctx->device_id, - NULL, NULL, NULL); + "-cl-finite-math-only -cl-unsafe-math-optimizations", NULL, NULL); if (cle != CL_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "Failed to build program: %d.\n", cle); -@@ -330,7 +330,7 @@ void ff_opencl_print_const_matrix_3x3(AV +@@ -333,7 +391,7 @@ void ff_opencl_print_const_matrix_3x3(AV av_bprintf(buf, "__constant float %s[9] = {\n", name_str); for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) @@ -84,7 +157,7 @@ Index: FFmpeg/libavfilter/opencl/colorspace_common.cl #if chroma_loc == 1 #define chroma_sample(a,b,c,d) (((a) + (c)) * 0.5f) -@@ -33,88 +43,134 @@ +@@ -33,88 +43,128 @@ #define chroma_sample(a,b,c,d) (((a) + (b) + (c) + (d)) * 0.25f) #endif @@ -213,8 +286,10 @@ Index: FFmpeg/libavfilter/opencl/colorspace_common.cl + +float inverse_ootf_1_2(float x) { + return x > 0.0f ? native_powr(x, 1.0f / 1.2f) : x; -+} -+ + } + +-float inverse_eotf_bt1886(float c) { +- return c < 0.0f ? 0.0f : powr(c, 1.0f / 2.4f); +float oetf_arib_b67(float x) { + x = fmax(x, 0.0f); + return x <= (1.0f / 12.0f) @@ -222,15 +297,6 @@ Index: FFmpeg/libavfilter/opencl/colorspace_common.cl + : (ARIB_B67_A * native_log(12.0f * x - ARIB_B67_B) + ARIB_B67_C); } --float inverse_eotf_bt1886(float c) { -- return c < 0.0f ? 0.0f : powr(c, 1.0f / 2.4f); -+float inverse_oetf_arib_b67(float x) { -+ x = fmax(x, 0.0f); -+ return x <= 0.5f -+ ? (x * x) * (1.0f / 3.0f) -+ : (native_exp((x - ARIB_B67_C) / ARIB_B67_A) + ARIB_B67_B) * (1.0f / 12.0f); - } - -float oetf_bt709(float c) { - c = c < 0.0f ? 0.0f : c; - float r1 = 4.5f * c; @@ -241,11 +307,18 @@ Index: FFmpeg/libavfilter/opencl/colorspace_common.cl - float r1 = c / 4.5f; - float r2 = powr((c + 0.099f) / 1.099f, 1.0f / 0.45f); - return c < 0.081f ? r1 : r2; ++float inverse_oetf_arib_b67(float x) { ++ x = fmax(x, 0.0f); ++ return x <= 0.5f ++ ? (x * x) * (1.0f / 3.0f) ++ : (native_exp((x - ARIB_B67_C) / ARIB_B67_A) + ARIB_B67_B) * (1.0f / 12.0f); ++} ++ +// linearizer for HLG/ARIB-B67 +float eotf_arib_b67(float x) { + return ootf_1_2(inverse_oetf_arib_b67(x)) * 5.0f; - } - ++} ++ +// delinearizer for HLG/ARIB-B67 +float inverse_eotf_arib_b67(float x) { + return oetf_arib_b67(inverse_ootf_1_2(x / 5.0f)); @@ -254,14 +327,8 @@ Index: FFmpeg/libavfilter/opencl/colorspace_common.cl +// delinearizer for BT709, BT2020-10 +float inverse_eotf_bt1886(float x) { + return x > 0.0f ? native_powr(x, 1.0f / 2.4f) : 0.0f; -+} -+ -+#ifdef LUT_TRC -+float linearize_lut(float x) { -+ return lin_lut[clamp((int)(x * LUT_TRC), 0, LUT_TRC)]; -+} -+#endif -+ + } + float3 yuv2rgb(float y, float u, float v) { -#ifdef FULL_RANGE_IN - u -= 0.5f; v -= 0.5f; @@ -280,7 +347,7 @@ Index: FFmpeg/libavfilter/opencl/colorspace_common.cl #endif float r = y * rgb_matrix[0] + u * rgb_matrix[1] + v * rgb_matrix[2]; float g = y * rgb_matrix[3] + u * rgb_matrix[4] + v * rgb_matrix[5]; -@@ -138,19 +194,35 @@ float3 rgb2yuv(float r, float g, float b +@@ -138,19 +188,35 @@ float3 rgb2yuv(float r, float g, float b float y = r*yuv_matrix[0] + g*yuv_matrix[1] + b*yuv_matrix[2]; float u = r*yuv_matrix[3] + g*yuv_matrix[4] + b*yuv_matrix[5]; float v = r*yuv_matrix[6] + g*yuv_matrix[7] + b*yuv_matrix[8]; @@ -322,7 +389,7 @@ Index: FFmpeg/libavfilter/opencl/colorspace_common.cl return y; } -@@ -188,18 +260,101 @@ float3 lrgb2lrgb(float3 c) { +@@ -188,18 +254,101 @@ float3 lrgb2lrgb(float3 c) { #endif } @@ -526,7 +593,7 @@ Index: FFmpeg/libavfilter/opencl/tonemap.cl float j = tone_param; float a, b; -@@ -71,202 +85,611 @@ float mobius(float s, float peak) { +@@ -71,202 +85,618 @@ float mobius(float s, float peak) { return s; a = -j * j * (peak - 1.0f) / (j * j - 2.0f * j + peak); @@ -769,10 +836,8 @@ Index: FFmpeg/libavfilter/opencl/tonemap.cl + float3 c = yuv2lrgb(yuv); +#endif + return c; - } - --float3 map_one_pixel_rgb(float3 rgb, float peak, float average) { -- float sig = max(max(rgb.x, max(rgb.y, rgb.z)), 1e-6f); ++} ++ +// Map from source space YUV to destination space RGB +float3 map_to_dst_space_from_yuv(float3 yuv) { +#ifdef DOVI_RESHAPE @@ -785,8 +850,10 @@ Index: FFmpeg/libavfilter/opencl/tonemap.cl + c = lrgb2lrgb(c); +#endif + return c; -+} -+ + } + +-float3 map_one_pixel_rgb(float3 rgb, float peak, float average) { +- float sig = max(max(rgb.x, max(rgb.y, rgb.z)), 1e-6f); +#ifdef DOVI_RESHAPE +float reshape_poly(float s, float4 coeffs) { + return (coeffs.z * s + coeffs.y) * s + coeffs.x; @@ -1072,7 +1139,7 @@ Index: FFmpeg/libavfilter/opencl/tonemap.cl + c1 = lrgb2lrgb(c1); + c2 = lrgb2lrgb(c2); + c3 = lrgb2lrgb(c3); -+ #if !defined(RGB2RGB_PASSTHROUGH) && !defined(DOVI_PERF_TRADEOFF) ++ #if !defined(RGB2RGB_PASSTHROUGH) + c0 = gamut_compress(c0); + c1 = gamut_compress(c1); + c2 = gamut_compress(c2); @@ -1123,6 +1190,8 @@ Index: FFmpeg/libavfilter/opencl/tonemap.cl + +float3 apply_lut3d(__global float3 *lut, float3 color) +{ ++ color = clamp(color, 0.0f, 1.0f); ++ + // Scale the color to the LUT grid. + float3 pos = color * (float)(LUT_SIZE - 1); + @@ -1132,17 +1201,22 @@ Index: FFmpeg/libavfilter/opencl/tonemap.cl + float3 f = pos - convert_float3(base); + + // Compute the base linear index. -+ int baseIndex = base.x + base.y * LUT_SIZE + base.z * LUT_SIZE * LUT_SIZE; ++ unsigned base_idx = base.x + base.y * LUT_SIZE + base.z * LUT_SIZE * LUT_SIZE; ++ ++#define LUT_IDX_MAX (LUT_SIZE * LUT_SIZE * LUT_SIZE - 1) ++#define LUT_IDX_OFFSET_MAX (1 + LUT_SIZE + LUT_SIZE * LUT_SIZE) ++ ++ base_idx = min(base_idx, (unsigned)(LUT_IDX_MAX - LUT_IDX_OFFSET_MAX)); + + // Fetch the eight corner values of the current cube cell. -+ float3 c000 = lut[baseIndex]; -+ float3 c100 = lut[baseIndex + 1]; -+ float3 c010 = lut[baseIndex + LUT_SIZE]; -+ float3 c110 = lut[baseIndex + 1 + LUT_SIZE]; -+ float3 c001 = lut[baseIndex + LUT_SIZE * LUT_SIZE]; -+ float3 c101 = lut[baseIndex + 1 + LUT_SIZE * LUT_SIZE]; -+ float3 c011 = lut[baseIndex + LUT_SIZE + LUT_SIZE * LUT_SIZE]; -+ float3 c111 = lut[baseIndex + 1 + LUT_SIZE + LUT_SIZE * LUT_SIZE]; ++ float3 c000 = lut[base_idx]; ++ float3 c100 = lut[base_idx + 1]; ++ float3 c010 = lut[base_idx + LUT_SIZE]; ++ float3 c110 = lut[base_idx + 1 + LUT_SIZE]; ++ float3 c001 = lut[base_idx + LUT_SIZE * LUT_SIZE]; ++ float3 c101 = lut[base_idx + 1 + LUT_SIZE * LUT_SIZE]; ++ float3 c011 = lut[base_idx + LUT_SIZE + LUT_SIZE * LUT_SIZE]; ++ float3 c111 = lut[base_idx + 1 + LUT_SIZE + LUT_SIZE * LUT_SIZE]; + + // Determine the tetrahedron within the cube cell. + // The tetrahedron selection is based on the ordering of the fractional parts. @@ -1264,7 +1338,7 @@ Index: FFmpeg/libavfilter/opencl/tonemap.cl +#endif +} + -+__kernel void build_lut(__global float3* lut, float peak) ++__kernel void build_lut(__global float3 *lut, float peak) +{ + const int total_entries = LUT_SIZE * LUT_SIZE * LUT_SIZE; + int idx = get_global_id(0); @@ -1313,7 +1387,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or -@@ -15,8 +15,15 @@ +@@ -15,27 +15,46 @@ * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -1327,32 +1401,46 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c +#endif + #include "libavutil/avassert.h" - #include "libavutil/common.h" +-#include "libavutil/common.h" #include "libavutil/imgutils.h" -@@ -29,13 +36,17 @@ ++#include "libavutil/mem.h" + #include "libavutil/opt.h" + #include "libavutil/pixdesc.h" + + #include "avfilter.h" + #include "filters.h" ++#include "formats.h" + #include "opencl.h" #include "opencl_source.h" #include "video.h" #include "colorspace.h" +#include "dither_matrix.h" ++ ++#define OPENCL_SOURCE_NB 3 -// TODO: -// - separate peak-detection from tone-mapping kernel to solve -// one-frame-delay issue. -// - more format support -+#define OPENCL_SOURCE_NB 3 - --#define DETECTION_FRAMES 63 +static const enum AVPixelFormat supported_formats[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV420P16, + AV_PIX_FMT_NV12, + AV_PIX_FMT_P010, + AV_PIX_FMT_P016, ++}; + +-#define DETECTION_FRAMES 63 ++static const int colorspaces_out[] = { ++ AVCOL_SPC_UNSPECIFIED, ++ AVCOL_SPC_BT709, ++ AVCOL_SPC_BT2020_NCL, ++ -1 +}; enum TonemapAlgorithm { TONEMAP_NONE, -@@ -45,7 +56,17 @@ enum TonemapAlgorithm { +@@ -45,7 +64,17 @@ enum TonemapAlgorithm { TONEMAP_REINHARD, TONEMAP_HABLE, TONEMAP_MOBIUS, @@ -1371,7 +1459,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c }; typedef struct TonemapOpenCLContext { -@@ -56,23 +77,44 @@ typedef struct TonemapOpenCLContext { +@@ -56,23 +85,45 @@ typedef struct TonemapOpenCLContext { enum AVColorPrimaries primaries, primaries_in, primaries_out; enum AVColorRange range, range_in, range_out; enum AVChromaLocation chroma_loc; @@ -1389,6 +1477,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c +#define mmr_sz mmr_cnt*sizeof(float) + struct DoviMetadata *dovi; + cl_mem dovi_buf; ++ int is_pure_dovi; enum TonemapAlgorithm tonemap; + enum TonemapMode tonemap_mode; @@ -1420,7 +1509,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c }; static const char *const delinearize_funcs[AVCOL_TRC_NB] = { -@@ -80,7 +122,7 @@ static const char *const delinearize_fun +@@ -80,7 +131,7 @@ static const char *const delinearize_fun [AVCOL_TRC_BT2020_10] = "inverse_eotf_bt1886", }; @@ -1429,26 +1518,26 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c [TONEMAP_NONE] = "direct", [TONEMAP_LINEAR] = "linear", [TONEMAP_GAMMA] = "gamma", -@@ -88,8 +130,18 @@ static const char *const tonemap_func[TO +@@ -88,8 +139,18 @@ static const char *const tonemap_func[TO [TONEMAP_REINHARD] = "reinhard", [TONEMAP_HABLE] = "hable", [TONEMAP_MOBIUS] = "mobius", + [TONEMAP_BT2390] = "bt2390", - }; - ++}; ++ +static const double dovi_lms2rgb_matrix[3][3] = +{ + { 3.06441879, -2.16597676, 0.10155818}, + {-0.65612108, 1.78554118, -0.12943749}, + { 0.01736321, -0.04725154, 1.03004253}, -+}; -+ + }; + +#define LUT_SIZE (65 * 65 * 65) + static int get_rgb2rgb_matrix(enum AVColorPrimaries in, enum AVColorPrimaries out, double rgb2rgb[3][3]) { double rgb2xyz[3][3], xyz2rgb[3][3]; -@@ -108,90 +160,361 @@ static int get_rgb2rgb_matrix(enum AVCol +@@ -108,90 +169,368 @@ static int get_rgb2rgb_matrix(enum AVCol return 0; } @@ -1466,7 +1555,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c + cl_int cle; + + pbuf = (float *)clEnqueueMapBuffer(ctx->command_queue, ctx->dovi_buf, -+ CL_TRUE, CL_MAP_WRITE, 0, ++ CL_TRUE, CL_MAP_WRITE_INVALIDATE_REGION, 0, + 3*(params_sz+pivots_sz+coeffs_sz+mmr_sz), + 0, NULL, NULL, &cle); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to map dovi buf: %d.\n", cle); @@ -1600,7 +1689,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c - const char *opencl_sources[OPENCL_SOURCE_NB]; - - av_bprint_init(&header, 1024, AV_BPRINT_SIZE_AUTOMATIC); -+ cl_mem_flags dovi_buf_flags = CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR; ++ cl_mem_flags dovi_buf_flags = CL_MEM_ALLOC_HOST_PTR | CL_MEM_HOST_WRITE_ONLY | CL_MEM_READ_ONLY; + char *device_vendor = NULL; + char *device_name = NULL; + char *device_exts = NULL; @@ -1705,6 +1794,13 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c + ctx->tonemap_mode = TONEMAP_MODE_ITP; + } + ++ // for low perf device, only do reshaping for pure dovi ++ if (ctx->tradeoff && ctx->dovi && !ctx->is_pure_dovi) { ++ av_freep(&ctx->dovi); ++ ctx->dovi = NULL; ++ ctx->apply_dovi = 0; ++ } ++ + av_log(ctx, AV_LOG_DEBUG, "Tonemapping transfer from %s to %s\n", av_color_transfer_name(ctx->trc_in), av_color_transfer_name(ctx->trc_out)); @@ -1840,7 +1936,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c av_bprintf(&header, "#define chroma_loc %d\n", (int)ctx->chroma_loc); if (rgb2rgb_passthrough) -@@ -199,19 +522,41 @@ static int tonemap_opencl_init(AVFilterC +@@ -199,19 +538,41 @@ static int tonemap_opencl_init(AVFilterC else ff_opencl_print_const_matrix_3x3(&header, "rgb2rgb", rgb2rgb); @@ -1889,7 +1985,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c ctx->colorspace_out, av_color_space_name(ctx->colorspace_out)); goto fail; } -@@ -219,24 +564,13 @@ static int tonemap_opencl_init(AVFilterC +@@ -219,24 +580,13 @@ static int tonemap_opencl_init(AVFilterC ff_fill_rgb2yuv_table(luma_dst, rgb2yuv); ff_opencl_print_const_matrix_3x3(&header, "yuv_matrix", rgb2yuv); @@ -1919,7 +2015,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c av_log(avctx, AV_LOG_DEBUG, "Generated OpenCL header:\n%s\n", header.str); opencl_sources[0] = header.str; -@@ -254,46 +588,213 @@ static int tonemap_opencl_init(AVFilterC +@@ -254,46 +604,216 @@ static int tonemap_opencl_init(AVFilterC CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to create OpenCL " "command queue %d.\n", cle); @@ -1973,7 +2069,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c + ctx->lut_generation_kernel = clCreateKernel(ctx->ocf.program, "build_lut", &cle); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to create kernel %d.\n", cle); + -+ CL_CREATE_BUFFER_FLAGS(ctx, lut_buffer, CL_MEM_READ_WRITE, lut_buffer_size, NULL); ++ CL_CREATE_BUFFER_FLAGS(ctx, lut_buffer, CL_MEM_HOST_NO_ACCESS | CL_MEM_READ_WRITE, lut_buffer_size, NULL); + CL_SET_KERNEL_ARG(ctx->lut_generation_kernel, 0, cl_mem, &ctx->lut_buffer); + CL_SET_KERNEL_ARG(ctx->lut_generation_kernel, 1, cl_float, &peak); + @@ -1982,6 +2078,8 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c + 0, NULL, NULL); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to enqueue build_lut kernel: %d.\n", cle); + ++ cle = clFinish(ctx->command_queue); ++ CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to finish command queue: %d.\n", cle); + + ctx->kernel = clCreateKernel(ctx->ocf.program, "tonemap_lut", &cle); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to create kernel %d.\n", cle); @@ -2080,12 +2178,12 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c + ctx->initialised = 0; +} + -+ static av_cold int tonemap_opencl_preinit(AVFilterContext *avctx) -+ { -+ TonemapOpenCLContext *ctx = avctx->priv; -+ ctx->final_param = NAN; -+ return 0; -+ } ++static av_cold int tonemap_opencl_preinit(AVFilterContext *avctx) ++{ ++ TonemapOpenCLContext *ctx = avctx->priv; ++ ctx->final_param = NAN; ++ return 0; ++} + +static int format_is_supported(enum AVPixelFormat fmt) +{ @@ -2101,6 +2199,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c - TonemapOpenCLContext *s = avctx->priv; + AVFilterContext *avctx = outlink->src; + AVFilterLink *inlink = avctx->inputs[0]; ++ FilterLink *inl = ff_filter_link(inlink); + TonemapOpenCLContext *ctx = avctx->priv; + AVHWFramesContext *in_frames_ctx; + enum AVPixelFormat in_format; @@ -2116,10 +2215,10 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c - av_log(avctx, AV_LOG_ERROR, "unsupported output format," - "only p010/nv12 supported now\n"); + -+ if (!inlink->hw_frames_ctx) ++ if (!inl->hw_frames_ctx) return AVERROR(EINVAL); - } -+ in_frames_ctx = (AVHWFramesContext*)inlink->hw_frames_ctx->data; ++ in_frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data; + in_format = in_frames_ctx->sw_format; + out_format = (ctx->format == AV_PIX_FMT_NONE) ? in_format : ctx->format; + in_desc = av_pix_fmt_desc_get(in_format); @@ -2134,13 +2233,14 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c + av_log(ctx, AV_LOG_ERROR, "Unsupported output format: %s\n", + av_get_pix_fmt_name(out_format)); + return AVERROR(ENOSYS); - } ++ } + if (in_desc->comp[0].depth != 10 && in_desc->comp[0].depth != 16) { + av_log(ctx, AV_LOG_ERROR, "Unsupported input format depth: %d\n", + in_desc->comp[0].depth); + return AVERROR(ENOSYS); -+ } -+ + } + +- s->ocf.output_format = s->format == AV_PIX_FMT_NONE ? AV_PIX_FMT_NV12 : s->format; + ctx->in_fmt = in_format; + ctx->out_fmt = out_format; + ctx->in_desc = in_desc; @@ -2148,23 +2248,16 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c + ctx->in_planes = av_pix_fmt_count_planes(in_format); + ctx->out_planes = av_pix_fmt_count_planes(out_format); + ctx->ocf.output_format = out_format; - -- s->ocf.output_format = s->format == AV_PIX_FMT_NONE ? AV_PIX_FMT_NV12 : s->format; ++ ret = ff_opencl_filter_config_output(outlink); if (ret < 0) return ret; -@@ -308,13 +809,49 @@ static int launch_kernel(AVFilterContext +@@ -308,13 +828,49 @@ static int launch_kernel(AVFilterContext size_t global_work[2]; size_t local_work[2]; cl_int cle; + int idx_arg; - -- CL_SET_KERNEL_ARG(kernel, 0, cl_mem, &output->data[0]); -- CL_SET_KERNEL_ARG(kernel, 1, cl_mem, &input->data[0]); -- CL_SET_KERNEL_ARG(kernel, 2, cl_mem, &output->data[1]); -- CL_SET_KERNEL_ARG(kernel, 3, cl_mem, &input->data[1]); -- CL_SET_KERNEL_ARG(kernel, 4, cl_mem, &ctx->util_mem); -- CL_SET_KERNEL_ARG(kernel, 5, cl_float, &peak); ++ + if (!output->data[0] || !input->data[0] || !output->data[1] || !input->data[1]) { + err = AVERROR(EIO); + goto fail; @@ -2204,12 +2297,18 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c + if (ctx->dovi_buf) { + CL_SET_KERNEL_ARG(kernel, idx_arg++, cl_mem, &ctx->dovi_buf); + } -+ + +- CL_SET_KERNEL_ARG(kernel, 0, cl_mem, &output->data[0]); +- CL_SET_KERNEL_ARG(kernel, 1, cl_mem, &input->data[0]); +- CL_SET_KERNEL_ARG(kernel, 2, cl_mem, &output->data[1]); +- CL_SET_KERNEL_ARG(kernel, 3, cl_mem, &input->data[1]); +- CL_SET_KERNEL_ARG(kernel, 4, cl_mem, &ctx->util_mem); +- CL_SET_KERNEL_ARG(kernel, 5, cl_float, &peak); + CL_SET_KERNEL_ARG(kernel, idx_arg++, cl_float, &peak); local_work[0] = 16; local_work[1] = 16; -@@ -338,13 +875,10 @@ static int tonemap_opencl_filter_frame(A +@@ -338,12 +894,10 @@ static int tonemap_opencl_filter_frame(A AVFilterContext *avctx = inlink->dst; AVFilterLink *outlink = avctx->outputs[0]; TonemapOpenCLContext *ctx = avctx->priv; @@ -2219,12 +2318,19 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c int err; - double peak = ctx->peak; - -- AVHWFramesContext *input_frames_ctx = -- (AVHWFramesContext*)input->hw_frames_ctx->data; +- AVHWFramesContext *input_frames_ctx; av_log(ctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n", av_get_pix_fmt_name(input->format), -@@ -363,8 +897,49 @@ static int tonemap_opencl_filter_frame(A +@@ -351,7 +905,6 @@ static int tonemap_opencl_filter_frame(A + + if (!input->hw_frames_ctx) + return AVERROR(EINVAL); +- input_frames_ctx = (AVHWFramesContext*)input->hw_frames_ctx->data; + + output = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!output) { +@@ -363,17 +916,59 @@ static int tonemap_opencl_filter_frame(A if (err < 0) goto fail; @@ -2265,18 +2371,32 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c + if (!ctx->dovi) + goto fail; + ++ ctx->is_pure_dovi = rpu->vdr_rpu_profile == 0; ++ + ff_map_dovi_metadata(ctx->dovi, metadata); + output->color_trc = input->color_trc = AVCOL_TRC_SMPTE2084; + output->colorspace = input->colorspace = AVCOL_SPC_BT2020_NCL; + output->color_primaries = input->color_primaries = AVCOL_PRI_BT2020; + if (rpu->bl_video_full_range_flag) -+ output->color_range = input->color_range = AVCOL_RANGE_JPEG; ++ input->color_range = AVCOL_RANGE_JPEG; + } + } if (ctx->trc != -1) output->color_trc = ctx->trc; -@@ -385,72 +960,50 @@ static int tonemap_opencl_filter_frame(A + if (ctx->primaries != -1) + output->color_primaries = ctx->primaries; +- if (ctx->colorspace != -1) +- output->colorspace = ctx->colorspace; +- if (ctx->range != -1) +- output->color_range = ctx->range; ++ ++ output->colorspace = outlink->colorspace; ++ output->color_range = outlink->color_range; + + ctx->trc_in = input->color_trc; + ctx->trc_out = output->color_trc; +@@ -385,72 +980,50 @@ static int tonemap_opencl_filter_frame(A ctx->range_out = output->color_range; ctx->chroma_loc = output->chroma_location; @@ -2372,13 +2492,24 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c av_frame_free(&input); av_frame_free(&output); return err; -@@ -458,24 +1011,9 @@ fail: +@@ -458,62 +1031,101 @@ fail: static av_cold void tonemap_opencl_uninit(AVFilterContext *avctx) { -- TonemapOpenCLContext *ctx = avctx->priv; -- cl_int cle; + tonemap_opencl_uninit_common(avctx); ++ ++ tonemap_opencl_uninit_dovi(avctx); ++ ++ ff_opencl_filter_uninit(avctx); ++} ++ ++static int tonemap_opencl_query_formats(AVFilterContext *avctx) ++{ + TonemapOpenCLContext *ctx = avctx->priv; +- cl_int cle; ++ AVFilterFormats *formats; ++ int ret; ++ const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_OPENCL, AV_PIX_FMT_NONE }; - if (ctx->util_mem) - clReleaseMemObject(ctx->util_mem); @@ -2388,18 +2519,47 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c - av_log(avctx, AV_LOG_ERROR, "Failed to release " - "kernel: %d.\n", cle); - } -- ++ // single format ++ formats = ff_make_format_list(pix_fmts); ++ ret = ff_formats_ref(formats, &avctx->inputs[0]->outcfg.formats); ++ if (ret < 0) ++ return ret; + - if (ctx->command_queue) { - cle = clReleaseCommandQueue(ctx->command_queue); - if (cle != CL_SUCCESS) - av_log(avctx, AV_LOG_ERROR, "Failed to release " - "command queue: %d.\n", cle); - } -+ tonemap_opencl_uninit_dovi(avctx); ++ ret = ff_formats_ref(formats, &avctx->outputs[0]->incfg.formats); ++ if (ret < 0) ++ return ret; - ff_opencl_filter_uninit(avctx); +- ff_opencl_filter_uninit(avctx); ++ // colorspaces and ranges ++ if ((ret = ff_formats_ref(ff_all_color_spaces(), ++ &avctx->inputs[0]->outcfg.color_spaces)) < 0) ++ return ret; ++ ++ if ((ret = ff_formats_ref(ff_all_color_ranges(), ++ &avctx->inputs[0]->outcfg.color_ranges)) < 0) ++ return ret; ++ ++ formats = ctx->colorspace != -1 ++ ? ff_make_formats_list_singleton(ctx->colorspace) ++ : ff_make_format_list(colorspaces_out); ++ if ((ret = ff_formats_ref(formats, &avctx->outputs[0]->incfg.color_spaces)) < 0) ++ return ret; ++ ++ formats = ctx->range != -1 ++ ? ff_make_formats_list_singleton(ctx->range) ++ : ff_all_color_ranges(); ++ if ((ret = ff_formats_ref(formats, &avctx->outputs[0]->incfg.color_ranges)) < 0) ++ return ret; ++ ++ return 0; } -@@ -483,37 +1021,50 @@ static av_cold void tonemap_opencl_unini + #define OFFSET(x) offsetof(TonemapOpenCLContext, x) #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) static const AVOption tonemap_opencl_options[] = { @@ -2481,7 +2641,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c { NULL } }; -@@ -541,6 +1092,7 @@ const AVFilter ff_vf_tonemap_opencl = { +@@ -541,11 +1153,12 @@ const AVFilter ff_vf_tonemap_opencl = { .description = NULL_IF_CONFIG_SMALL("Perform HDR to SDR conversion with tonemapping."), .priv_size = sizeof(TonemapOpenCLContext), .priv_class = &tonemap_opencl_class, @@ -2489,3 +2649,9 @@ Index: FFmpeg/libavfilter/vf_tonemap_opencl.c .init = &ff_opencl_filter_init, .uninit = &tonemap_opencl_uninit, FILTER_INPUTS(tonemap_opencl_inputs), + FILTER_OUTPUTS(tonemap_opencl_outputs), +- FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), ++ FILTER_QUERY_FUNC(tonemap_opencl_query_formats), + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .flags = AVFILTER_FLAG_HWDEVICE, + }; diff --git a/debian/patches/0008-add-pgs-support-to-opencl-overlay.patch b/debian/patches/0008-add-pgs-support-to-opencl-overlay.patch index 56d0301c2..91568f821 100644 --- a/debian/patches/0008-add-pgs-support-to-opencl-overlay.patch +++ b/debian/patches/0008-add-pgs-support-to-opencl-overlay.patch @@ -453,12 +453,12 @@ Index: FFmpeg/libavfilter/vf_overlay_opencl.c - (AVHWFramesContext*)input_overlay->hw_frames_ctx->data; + if (!input_main) + return AVERROR_BUG; -+ -+ if (!input_overlay) -+ passthrough = 1; - err = overlay_opencl_load(avctx, main_fc->sw_format, - overlay_fc->sw_format); ++ if (!input_overlay) ++ passthrough = 1; ++ + if (!ctx->initialised) { + err = overlay_opencl_load(avctx); if (err < 0) @@ -532,16 +532,18 @@ Index: FFmpeg/libavfilter/vf_overlay_opencl.c av_frame_free(&output); return err; } -@@ -224,8 +330,49 @@ static int overlay_opencl_config_output( +@@ -224,8 +330,51 @@ static int overlay_opencl_config_output( { AVFilterContext *avctx = outlink->src; OverlayOpenCLContext *ctx = avctx->priv; + + AVFilterLink *inlink = avctx->inputs[0]; -+ AVHWFramesContext *frames_ctx_main = (AVHWFramesContext*)inlink->hw_frames_ctx->data; ++ FilterLink *inl = ff_filter_link(inlink); ++ AVHWFramesContext *frames_ctx_main = (AVHWFramesContext*)inl->hw_frames_ctx->data; + + AVFilterLink *inlink_overlay = avctx->inputs[1]; -+ AVHWFramesContext *frames_ctx_overlay = (AVHWFramesContext*)inlink_overlay->hw_frames_ctx->data; ++ FilterLink *inl_overlay = ff_filter_link(inlink_overlay); ++ AVHWFramesContext *frames_ctx_overlay = (AVHWFramesContext*)inl_overlay->hw_frames_ctx->data; + int err; @@ -582,7 +584,7 @@ Index: FFmpeg/libavfilter/vf_overlay_opencl.c err = ff_opencl_filter_config_output(outlink); if (err < 0) return err; -@@ -234,6 +381,11 @@ static int overlay_opencl_config_output( +@@ -234,6 +383,11 @@ static int overlay_opencl_config_output( if (err < 0) return err; @@ -594,7 +596,7 @@ Index: FFmpeg/libavfilter/vf_overlay_opencl.c return ff_framesync_configure(&ctx->fs); } -@@ -265,6 +417,20 @@ static av_cold void overlay_opencl_unini +@@ -265,6 +419,20 @@ static av_cold void overlay_opencl_unini "kernel: %d.\n", cle); } @@ -615,7 +617,7 @@ Index: FFmpeg/libavfilter/vf_overlay_opencl.c if (ctx->command_queue) { cle = clReleaseCommandQueue(ctx->command_queue); if (cle != CL_SUCCESS) -@@ -279,11 +445,20 @@ static av_cold void overlay_opencl_unini +@@ -279,11 +447,20 @@ static av_cold void overlay_opencl_unini #define OFFSET(x) offsetof(OverlayOpenCLContext, x) #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) diff --git a/debian/patches/0010-add-a-hack-for-opencl-reverse-mapping.patch b/debian/patches/0010-add-a-hack-for-opencl-reverse-mapping.patch index 83bc8cff9..9eb9b4abc 100644 --- a/debian/patches/0010-add-a-hack-for-opencl-reverse-mapping.patch +++ b/debian/patches/0010-add-a-hack-for-opencl-reverse-mapping.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavfilter/avfilter.h =================================================================== --- FFmpeg.orig/libavfilter/avfilter.h +++ FFmpeg/libavfilter/avfilter.h -@@ -564,6 +564,8 @@ struct AVFilterLink { +@@ -579,6 +579,8 @@ struct AVFilterLink { enum AVColorSpace colorspace; ///< agreed upon YUV color space enum AVColorRange color_range; ///< agreed upon YUV color range @@ -15,7 +15,7 @@ Index: FFmpeg/libavfilter/opencl.c =================================================================== --- FFmpeg.orig/libavfilter/opencl.c +++ FFmpeg/libavfilter/opencl.c -@@ -75,6 +75,9 @@ int ff_opencl_filter_config_input(AVFilt +@@ -77,6 +77,9 @@ int ff_opencl_filter_config_input(AVFilt if (!ctx->output_height) ctx->output_height = inlink->h; @@ -25,7 +25,7 @@ Index: FFmpeg/libavfilter/opencl.c return 0; } -@@ -123,6 +126,9 @@ int ff_opencl_filter_config_output(AVFil +@@ -126,6 +129,9 @@ int ff_opencl_filter_config_output(AVFil outlink->w = ctx->output_width; outlink->h = ctx->output_height; @@ -48,9 +48,9 @@ Index: FFmpeg/libavfilter/vf_hwmap.c +#endif + #include "avfilter.h" + #include "filters.h" #include "formats.h" - #include "internal.h" -@@ -122,6 +126,12 @@ static int hwmap_config_output(AVFilterL +@@ -124,6 +128,12 @@ static int hwmap_config_output(AVFilterL goto fail; } @@ -63,7 +63,7 @@ Index: FFmpeg/libavfilter/vf_hwmap.c } else if (inlink->format == hwfc->format && (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) && ctx->reverse) { -@@ -131,6 +141,9 @@ static int hwmap_config_output(AVFilterL +@@ -133,6 +143,9 @@ static int hwmap_config_output(AVFilterL // mapped from that back to the source type. AVBufferRef *source; AVHWFramesContext *frames; @@ -73,7 +73,7 @@ Index: FFmpeg/libavfilter/vf_hwmap.c ctx->hwframes_ref = av_hwframe_ctx_alloc(device); if (!ctx->hwframes_ref) { -@@ -144,8 +157,19 @@ static int hwmap_config_output(AVFilterL +@@ -146,8 +159,19 @@ static int hwmap_config_output(AVFilterL frames->width = hwfc->width; frames->height = hwfc->height; @@ -84,8 +84,8 @@ Index: FFmpeg/libavfilter/vf_hwmap.c + + if (frames->initial_pool_size == 0) { + // Dynamic allocation. -+ } else if (avctx->extra_hw_frames) { -+ frames->initial_pool_size += avctx->extra_hw_frames; ++ } else { ++ frames->initial_pool_size += (avctx->extra_hw_frames > 2 ? avctx->extra_hw_frames : 2); + } + +#if HAVE_OPENCL_D3D11 @@ -108,10 +108,10 @@ Index: FFmpeg/libavfilter/vf_hwupload.c +#endif + #include "avfilter.h" + #include "filters.h" #include "formats.h" - #include "internal.h" -@@ -110,6 +114,9 @@ static int hwupload_config_output(AVFilt - AVFilterLink *inlink = avctx->inputs[0]; +@@ -112,6 +116,9 @@ static int hwupload_config_output(AVFilt + FilterLink *inl = ff_filter_link(inlink); HWUploadContext *ctx = avctx->priv; int err; +#if HAVE_OPENCL_D3D11 @@ -120,7 +120,7 @@ Index: FFmpeg/libavfilter/vf_hwupload.c av_buffer_unref(&ctx->hwframes_ref); -@@ -151,6 +158,11 @@ static int hwupload_config_output(AVFilt +@@ -153,6 +160,11 @@ static int hwupload_config_output(AVFilt if (avctx->extra_hw_frames >= 0) ctx->hwframes->initial_pool_size = 2 + avctx->extra_hw_frames; @@ -136,7 +136,7 @@ Index: FFmpeg/libavutil/hwcontext_d3d11va.c =================================================================== --- FFmpeg.orig/libavutil/hwcontext_d3d11va.c +++ FFmpeg/libavutil/hwcontext_d3d11va.c -@@ -227,7 +227,7 @@ static AVBufferRef *d3d11va_alloc_single +@@ -229,7 +229,7 @@ static AVBufferRef *d3d11va_alloc_single .ArraySize = 1, .Usage = D3D11_USAGE_DEFAULT, .BindFlags = hwctx->BindFlags, @@ -145,7 +145,7 @@ Index: FFmpeg/libavutil/hwcontext_d3d11va.c }; hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &tex); -@@ -291,9 +291,17 @@ static int d3d11va_frames_init(AVHWFrame +@@ -293,9 +293,17 @@ static int d3d11va_frames_init(AVHWFrame .ArraySize = ctx->initial_pool_size, .Usage = D3D11_USAGE_DEFAULT, .BindFlags = hwctx->BindFlags, diff --git a/debian/patches/0011-add-fixes-for-mapping-from-qsv-source-device.patch b/debian/patches/0011-add-fixes-for-mapping-from-qsv-source-device.patch index 61519153e..c1f5dbde9 100644 --- a/debian/patches/0011-add-fixes-for-mapping-from-qsv-source-device.patch +++ b/debian/patches/0011-add-fixes-for-mapping-from-qsv-source-device.patch @@ -145,7 +145,7 @@ Index: FFmpeg/libavutil/hwcontext_qsv.c =================================================================== --- FFmpeg.orig/libavutil/hwcontext_qsv.c +++ FFmpeg/libavutil/hwcontext_qsv.c -@@ -369,7 +369,7 @@ static void qsv_frames_uninit(AVHWFrames +@@ -379,7 +379,7 @@ static void qsv_frames_uninit(AVHWFrames av_buffer_unref(&s->child_frames_ref); } @@ -154,7 +154,7 @@ Index: FFmpeg/libavutil/hwcontext_qsv.c { } -@@ -382,7 +382,7 @@ static AVBufferRef *qsv_pool_alloc(void +@@ -417,7 +417,7 @@ static AVBufferRef *qsv_fixed_pool_alloc if (s->nb_surfaces_used < hwctx->nb_surfaces) { s->nb_surfaces_used++; return av_buffer_create((uint8_t*)(s->surfaces_internal + s->nb_surfaces_used - 1), @@ -163,7 +163,7 @@ Index: FFmpeg/libavutil/hwcontext_qsv.c } return NULL; -@@ -2272,8 +2272,17 @@ static int qsv_device_create(AVHWDeviceC +@@ -2617,8 +2617,17 @@ static int qsv_device_create(AVHWDeviceC child_device = (AVHWDeviceContext*)priv->child_device_ctx->data; impl = choose_implementation(device, child_device_type); diff --git a/debian/patches/0013-add-vendor-id-option-for-d3d11.patch b/debian/patches/0013-add-vendor-id-option-for-d3d11.patch index bfecc49d0..9a22a1ecd 100644 --- a/debian/patches/0013-add-vendor-id-option-for-d3d11.patch +++ b/debian/patches/0013-add-vendor-id-option-for-d3d11.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavutil/hwcontext_d3d11va.c =================================================================== --- FFmpeg.orig/libavutil/hwcontext_d3d11va.c +++ FFmpeg/libavutil/hwcontext_d3d11va.c -@@ -638,6 +638,8 @@ static int d3d11va_device_create(AVHWDev +@@ -640,6 +640,8 @@ static int d3d11va_device_create(AVHWDev adapter = atoi(device); } else { AVDictionaryEntry *e = av_dict_get(opts, "vendor_id", NULL, 0); diff --git a/debian/patches/0014-add-vaapi-hwupload-filter.patch b/debian/patches/0014-add-vaapi-hwupload-filter.patch index 812a3819f..54ac20a45 100644 --- a/debian/patches/0014-add-vaapi-hwupload-filter.patch +++ b/debian/patches/0014-add-vaapi-hwupload-filter.patch @@ -2,19 +2,19 @@ Index: FFmpeg/configure =================================================================== --- FFmpeg.orig/configure +++ FFmpeg/configure -@@ -3840,6 +3840,7 @@ gblur_vulkan_filter_deps="vulkan spirv_c +@@ -3884,6 +3884,7 @@ gblur_vulkan_filter_deps="vulkan spirv_c hflip_vulkan_filter_deps="vulkan spirv_compiler" histeq_filter_deps="gpl" hqdn3d_filter_deps="gpl" +hwupload_vaapi_filter_deps="vaapi" iccdetect_filter_deps="lcms2" iccgen_filter_deps="lcms2" - interlace_filter_deps="gpl" + identity_filter_select="scene_sad" Index: FFmpeg/libavfilter/Makefile =================================================================== --- FFmpeg.orig/libavfilter/Makefile +++ FFmpeg/libavfilter/Makefile -@@ -346,6 +346,7 @@ OBJS-$(CONFIG_HUESATURATION_FILTER) +@@ -347,6 +347,7 @@ OBJS-$(CONFIG_HUESATURATION_FILTER) OBJS-$(CONFIG_HWDOWNLOAD_FILTER) += vf_hwdownload.o OBJS-$(CONFIG_HWMAP_FILTER) += vf_hwmap.o OBJS-$(CONFIG_HWUPLOAD_CUDA_FILTER) += vf_hwupload_cuda.o @@ -38,7 +38,7 @@ Index: FFmpeg/libavfilter/vf_hwupload_vaapi.c =================================================================== --- /dev/null +++ FFmpeg/libavfilter/vf_hwupload_vaapi.c -@@ -0,0 +1,193 @@ +@@ -0,0 +1,195 @@ +/* + * This file is part of FFmpeg. + * @@ -63,8 +63,8 @@ Index: FFmpeg/libavfilter/vf_hwupload_vaapi.c +#include "libavutil/opt.h" + +#include "avfilter.h" ++#include "filters.h" +#include "formats.h" -+#include "internal.h" +#include "video.h" + +typedef struct VaapiUploadContext { @@ -123,8 +123,10 @@ Index: FFmpeg/libavfilter/vf_hwupload_vaapi.c + +static int vaapiupload_config_output(AVFilterLink *outlink) +{ ++ FilterLink *outl = ff_filter_link(outlink); + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = ctx->inputs[0]; ++ FilterLink *inl = ff_filter_link(inlink); + VaapiUploadContext *s = ctx->priv; + + AVHWFramesContext *hwframe_ctx; @@ -137,8 +139,8 @@ Index: FFmpeg/libavfilter/vf_hwupload_vaapi.c + + hwframe_ctx = (AVHWFramesContext*)s->hwframe->data; + hwframe_ctx->format = AV_PIX_FMT_VAAPI; -+ if (inlink->hw_frames_ctx) { -+ AVHWFramesContext *in_hwframe_ctx = (AVHWFramesContext*)inlink->hw_frames_ctx->data; ++ if (inl->hw_frames_ctx) { ++ AVHWFramesContext *in_hwframe_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data; + hwframe_ctx->sw_format = in_hwframe_ctx->sw_format; + } else { + hwframe_ctx->sw_format = inlink->format; @@ -150,8 +152,8 @@ Index: FFmpeg/libavfilter/vf_hwupload_vaapi.c + if (ret < 0) + return ret; + -+ outlink->hw_frames_ctx = av_buffer_ref(s->hwframe); -+ if (!outlink->hw_frames_ctx) ++ outl->hw_frames_ctx = av_buffer_ref(s->hwframe); ++ if (!outl->hw_frames_ctx) + return AVERROR(ENOMEM); + + return 0; diff --git a/debian/patches/0015-disable-the-premultiplied-alpha-in-vaapi-overlay.patch b/debian/patches/0015-disable-the-premultiplied-alpha-in-vaapi-overlay.patch index a4bd5fc03..5b8535b3c 100644 --- a/debian/patches/0015-disable-the-premultiplied-alpha-in-vaapi-overlay.patch +++ b/debian/patches/0015-disable-the-premultiplied-alpha-in-vaapi-overlay.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavfilter/vf_overlay_vaapi.c =================================================================== --- FFmpeg.orig/libavfilter/vf_overlay_vaapi.c +++ FFmpeg/libavfilter/vf_overlay_vaapi.c -@@ -311,8 +311,12 @@ static int overlay_vaapi_config_input_ov +@@ -312,8 +312,12 @@ static int overlay_vaapi_config_input_ov ctx->blend_alpha = ctx->alpha; } diff --git a/debian/patches/0016-add-fixes-and-hdr2hdr-for-vaapi-tonemap.patch b/debian/patches/0016-add-fixes-and-hdr2hdr-for-vaapi-tonemap.patch deleted file mode 100644 index df7c99543..000000000 --- a/debian/patches/0016-add-fixes-and-hdr2hdr-for-vaapi-tonemap.patch +++ /dev/null @@ -1,311 +0,0 @@ -Index: FFmpeg/libavfilter/vf_tonemap_vaapi.c -=================================================================== ---- FFmpeg.orig/libavfilter/vf_tonemap_vaapi.c -+++ FFmpeg/libavfilter/vf_tonemap_vaapi.c -@@ -39,7 +39,11 @@ typedef struct HDRVAAPIContext { - enum AVColorTransferCharacteristic color_transfer; - enum AVColorSpace color_matrix; - -+ char *mastering_display; -+ char *content_light; -+ - VAHdrMetaDataHDR10 in_metadata; -+ VAHdrMetaDataHDR10 out_metadata; - - AVFrameSideData *src_display; - AVFrameSideData *src_light; -@@ -52,7 +56,7 @@ static int tonemap_vaapi_save_metadata(A - AVContentLightMetadata *light_meta; - - if (input_frame->color_trc != AVCOL_TRC_SMPTE2084) { -- av_log(avctx, AV_LOG_WARNING, "Only support HDR10 as input for vaapi tone-mapping\n"); -+ av_log(avctx, AV_LOG_DEBUG, "Only support HDR10 as input for vaapi tone-mapping\n"); - } - - ctx->src_display = av_frame_get_side_data(input_frame, -@@ -60,8 +64,7 @@ static int tonemap_vaapi_save_metadata(A - if (ctx->src_display) { - hdr_meta = (AVMasteringDisplayMetadata *)ctx->src_display->data; - if (!hdr_meta) { -- av_log(avctx, AV_LOG_ERROR, "No mastering display data\n"); -- return AVERROR(EINVAL); -+ av_log(avctx, AV_LOG_DEBUG, "No mastering display data\n"); - } - - if (hdr_meta->has_luminance) { -@@ -118,8 +121,7 @@ static int tonemap_vaapi_save_metadata(A - ctx->in_metadata.white_point_y); - } - } else { -- av_log(avctx, AV_LOG_ERROR, "No mastering display data from input\n"); -- return AVERROR(EINVAL); -+ av_log(avctx, AV_LOG_DEBUG, "No mastering display data from input\n"); - } - - ctx->src_light = av_frame_get_side_data(input_frame, -@@ -127,8 +129,7 @@ static int tonemap_vaapi_save_metadata(A - if (ctx->src_light) { - light_meta = (AVContentLightMetadata *)ctx->src_light->data; - if (!light_meta) { -- av_log(avctx, AV_LOG_ERROR, "No light metadata\n"); -- return AVERROR(EINVAL); -+ av_log(avctx, AV_LOG_DEBUG, "No light metadata\n"); - } - - ctx->in_metadata.max_content_light_level = light_meta->MaxCLL; -@@ -146,6 +147,87 @@ static int tonemap_vaapi_save_metadata(A - return 0; - } - -+static int tonemap_vaapi_update_sidedata(AVFilterContext *avctx, AVFrame *output_frame) -+{ -+ HDRVAAPIContext *ctx = avctx->priv; -+ AVFrameSideData *metadata; -+ AVMasteringDisplayMetadata *hdr_meta; -+ AVFrameSideData *metadata_lt; -+ AVContentLightMetadata *hdr_meta_lt; -+ int i; -+ const int mapping[3] = {1, 2, 0}; //green, blue, red -+ const int chroma_den = 50000; -+ const int luma_den = 10000; -+ -+ metadata = av_frame_new_side_data(output_frame, -+ AV_FRAME_DATA_MASTERING_DISPLAY_METADATA, -+ sizeof(AVMasteringDisplayMetadata)); -+ if (!metadata) -+ return AVERROR(ENOMEM); -+ -+ hdr_meta = (AVMasteringDisplayMetadata *)metadata->data; -+ -+ for (i = 0; i < 3; i++) { -+ const int j = mapping[i]; -+ hdr_meta->display_primaries[j][0].num = ctx->out_metadata.display_primaries_x[i]; -+ hdr_meta->display_primaries[j][0].den = chroma_den; -+ -+ hdr_meta->display_primaries[j][1].num = ctx->out_metadata.display_primaries_y[i]; -+ hdr_meta->display_primaries[j][1].den = chroma_den; -+ } -+ -+ hdr_meta->white_point[0].num = ctx->out_metadata.white_point_x; -+ hdr_meta->white_point[0].den = chroma_den; -+ -+ hdr_meta->white_point[1].num = ctx->out_metadata.white_point_y; -+ hdr_meta->white_point[1].den = chroma_den; -+ hdr_meta->has_primaries = 1; -+ -+ hdr_meta->max_luminance.num = ctx->out_metadata.max_display_mastering_luminance; -+ hdr_meta->max_luminance.den = luma_den; -+ -+ hdr_meta->min_luminance.num = ctx->out_metadata.min_display_mastering_luminance; -+ hdr_meta->min_luminance.den = luma_den; -+ hdr_meta->has_luminance = 1; -+ -+ av_log(avctx, AV_LOG_DEBUG, -+ "Mastering display colour volume(out):\n"); -+ av_log(avctx, AV_LOG_DEBUG, -+ "G(%u,%u) B(%u,%u) R(%u,%u) WP(%u,%u)\n", -+ ctx->out_metadata.display_primaries_x[0], -+ ctx->out_metadata.display_primaries_y[0], -+ ctx->out_metadata.display_primaries_x[1], -+ ctx->out_metadata.display_primaries_y[1], -+ ctx->out_metadata.display_primaries_x[2], -+ ctx->out_metadata.display_primaries_y[2], -+ ctx->out_metadata.white_point_x, -+ ctx->out_metadata.white_point_y); -+ av_log(avctx, AV_LOG_DEBUG, -+ "max_display_mastering_luminance=%u, min_display_mastering_luminance=%u\n", -+ ctx->out_metadata.max_display_mastering_luminance, -+ ctx->out_metadata.min_display_mastering_luminance); -+ -+ metadata_lt = av_frame_new_side_data(output_frame, -+ AV_FRAME_DATA_CONTENT_LIGHT_LEVEL, -+ sizeof(AVContentLightMetadata)); -+ if (!metadata_lt) -+ return AVERROR(ENOMEM); -+ -+ hdr_meta_lt = (AVContentLightMetadata *)metadata_lt->data; -+ -+ hdr_meta_lt->MaxCLL = FFMIN(ctx->out_metadata.max_content_light_level, 65535); -+ hdr_meta_lt->MaxFALL = FFMIN(ctx->out_metadata.max_pic_average_light_level, 65535); -+ -+ av_log(avctx, AV_LOG_DEBUG, -+ "Content light level information(out):\n"); -+ av_log(avctx, AV_LOG_DEBUG, -+ "MaxCLL(%u) MaxFALL(%u)\n", -+ ctx->out_metadata.max_content_light_level, -+ ctx->out_metadata.max_pic_average_light_level); -+ -+ return 0; -+} -+ - static int tonemap_vaapi_set_filter_params(AVFilterContext *avctx, AVFrame *input_frame) - { - VAAPIVPPContext *vpp_ctx = avctx->priv; -@@ -208,15 +290,26 @@ static int tonemap_vaapi_build_filter_pa - return AVERROR(EINVAL); - } - -- for (i = 0; i < num_query_caps; i++) { -- if (VA_TONE_MAPPING_HDR_TO_SDR & hdr_cap[i].caps_flag) -- break; -- } -- -- if (i >= num_query_caps) { -- av_log(avctx, AV_LOG_ERROR, -- "VAAPI driver doesn't support HDR to SDR\n"); -- return AVERROR(EINVAL); -+ if (ctx->mastering_display) { -+ for (i = 0; i < num_query_caps; i++) { -+ if (VA_TONE_MAPPING_HDR_TO_HDR & hdr_cap[i].caps_flag) -+ break; -+ } -+ if (i >= num_query_caps) { -+ av_log(avctx, AV_LOG_ERROR, -+ "VAAPI driver doesn't support HDR to HDR\n"); -+ return AVERROR(EINVAL); -+ } -+ } else { -+ for (i = 0; i < num_query_caps; i++) { -+ if (VA_TONE_MAPPING_HDR_TO_SDR & hdr_cap[i].caps_flag) -+ break; -+ } -+ if (i >= num_query_caps) { -+ av_log(avctx, AV_LOG_ERROR, -+ "VAAPI driver doesn't support HDR to SDR\n"); -+ return AVERROR(EINVAL); -+ } - } - - hdrtm_param.type = VAProcFilterHighDynamicRangeToneMapping; -@@ -241,6 +334,8 @@ static int tonemap_vaapi_filter_frame(AV - VAProcPipelineParameterBuffer params; - int err; - -+ VAHdrMetaData out_hdr_metadata; -+ - av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n", - av_get_pix_fmt_name(input_frame->format), - input_frame->width, input_frame->height, input_frame->pts); -@@ -278,22 +373,43 @@ static int tonemap_vaapi_filter_frame(AV - if (err < 0) - goto fail; - -+ av_frame_remove_side_data(output_frame, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); -+ av_frame_remove_side_data(output_frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); -+ -+ if (!ctx->mastering_display) { -+ /* Use BT709 by default for HDR to SDR output frame */ -+ output_frame->color_primaries = AVCOL_PRI_BT709; -+ output_frame->color_trc = AVCOL_TRC_BT709; -+ output_frame->colorspace = AVCOL_SPC_BT709; -+ } -+ - if (ctx->color_primaries != AVCOL_PRI_UNSPECIFIED) - output_frame->color_primaries = ctx->color_primaries; - - if (ctx->color_transfer != AVCOL_TRC_UNSPECIFIED) - output_frame->color_trc = ctx->color_transfer; -- else -- output_frame->color_trc = AVCOL_TRC_BT709; - - if (ctx->color_matrix != AVCOL_SPC_UNSPECIFIED) - output_frame->colorspace = ctx->color_matrix; - -+ if (ctx->mastering_display) { -+ err = tonemap_vaapi_update_sidedata(avctx, output_frame); -+ if (err < 0) -+ goto fail; -+ } -+ - err = ff_vaapi_vpp_init_params(avctx, ¶ms, - input_frame, output_frame); - if (err < 0) - goto fail; - -+ if (ctx->mastering_display) { -+ out_hdr_metadata.metadata_type = VAProcHighDynamicRangeMetadataHDR10; -+ out_hdr_metadata.metadata = &ctx->out_metadata; -+ out_hdr_metadata.metadata_size = sizeof(VAHdrMetaDataHDR10); -+ params.output_hdr_metadata = &out_hdr_metadata; -+ } -+ - if (vpp_ctx->nb_filter_buffers) { - params.filters = &vpp_ctx->filter_buffers[0]; - params.num_filters = vpp_ctx->nb_filter_buffers; -@@ -309,9 +425,6 @@ static int tonemap_vaapi_filter_frame(AV - av_get_pix_fmt_name(output_frame->format), - output_frame->width, output_frame->height, output_frame->pts); - -- av_frame_remove_side_data(output_frame, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); -- av_frame_remove_side_data(output_frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); -- - return ff_filter_frame(outlink, output_frame); - - fail: -@@ -332,8 +445,13 @@ static av_cold int tonemap_vaapi_init(AV - if (ctx->output_format_string) { - vpp_ctx->output_format = av_get_pix_fmt(ctx->output_format_string); - } else { -- vpp_ctx->output_format = AV_PIX_FMT_NV12; -- av_log(avctx, AV_LOG_WARNING, "Output format not set, use default format NV12\n"); -+ if (ctx->mastering_display) { -+ vpp_ctx->output_format = AV_PIX_FMT_P010; -+ av_log(avctx, AV_LOG_VERBOSE, "Output format not set, use default format P010 for HDR to HDR tone mapping.\n"); -+ } else { -+ vpp_ctx->output_format = AV_PIX_FMT_NV12; -+ av_log(avctx, AV_LOG_VERBOSE, "Output format not set, use default format NV12 for HDR to SDR tone mapping.\n"); -+ } - } - - #define STRING_OPTION(var_name, func_name, default_value) do { \ -@@ -353,6 +471,37 @@ static av_cold int tonemap_vaapi_init(AV - STRING_OPTION(color_transfer, color_transfer, AVCOL_TRC_UNSPECIFIED); - STRING_OPTION(color_matrix, color_space, AVCOL_SPC_UNSPECIFIED); - -+ if (ctx->mastering_display) { -+ if (10 != sscanf(ctx->mastering_display, -+ "%hu %hu|%hu %hu|%hu %hu|%hu %hu|%u %u", -+ &ctx->out_metadata.display_primaries_x[0], -+ &ctx->out_metadata.display_primaries_y[0], -+ &ctx->out_metadata.display_primaries_x[1], -+ &ctx->out_metadata.display_primaries_y[1], -+ &ctx->out_metadata.display_primaries_x[2], -+ &ctx->out_metadata.display_primaries_y[2], -+ &ctx->out_metadata.white_point_x, -+ &ctx->out_metadata.white_point_y, -+ &ctx->out_metadata.min_display_mastering_luminance, -+ &ctx->out_metadata.max_display_mastering_luminance)) { -+ av_log(avctx, AV_LOG_ERROR, -+ "Option mastering-display input invalid\n"); -+ return AVERROR(EINVAL); -+ } -+ -+ if (!ctx->content_light) { -+ ctx->out_metadata.max_content_light_level = 0; -+ ctx->out_metadata.max_pic_average_light_level = 0; -+ } else if (2 != sscanf(ctx->content_light, -+ "%hu %hu", -+ &ctx->out_metadata.max_content_light_level, -+ &ctx->out_metadata.max_pic_average_light_level)) { -+ av_log(avctx, AV_LOG_ERROR, -+ "Option content-light input invalid\n"); -+ return AVERROR(EINVAL); -+ } -+ } -+ - return 0; - } - -@@ -378,6 +527,12 @@ static const AVOption tonemap_vaapi_opti - { "t", "Output color transfer characteristics set", - OFFSET(color_transfer_string), AV_OPT_TYPE_STRING, - { .str = NULL }, .flags = FLAGS, .unit = "transfer" }, -+ { "display", "set mastering display colour volume", -+ OFFSET(mastering_display), AV_OPT_TYPE_STRING, -+ { .str = NULL }, .flags = FLAGS }, -+ { "light", "set content light level information", -+ OFFSET(content_light), AV_OPT_TYPE_STRING, -+ { .str = NULL }, .flags = FLAGS }, - { NULL } - }; - diff --git a/debian/patches/0017-add-fixes-for-nvdec-exceed-32-surfaces-error.patch b/debian/patches/0016-add-fixes-for-nvdec-exceed-32-surfaces-error.patch similarity index 92% rename from debian/patches/0017-add-fixes-for-nvdec-exceed-32-surfaces-error.patch rename to debian/patches/0016-add-fixes-for-nvdec-exceed-32-surfaces-error.patch index a58020b4a..5357db056 100644 --- a/debian/patches/0017-add-fixes-for-nvdec-exceed-32-surfaces-error.patch +++ b/debian/patches/0016-add-fixes-for-nvdec-exceed-32-surfaces-error.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavcodec/nvdec.c =================================================================== --- FFmpeg.orig/libavcodec/nvdec.c +++ FFmpeg/libavcodec/nvdec.c -@@ -299,8 +299,10 @@ static int nvdec_init_hwframes(AVCodecCo +@@ -300,8 +300,10 @@ static int nvdec_init_hwframes(AVCodecCo frames_ctx = (AVHWFramesContext*)(*out_frames_ref)->data; if (dummy) { diff --git a/debian/patches/0017-backport-fixes-for-vaapi-from-upstream.patch b/debian/patches/0017-backport-fixes-for-vaapi-from-upstream.patch new file mode 100644 index 000000000..d222e98e4 --- /dev/null +++ b/debian/patches/0017-backport-fixes-for-vaapi-from-upstream.patch @@ -0,0 +1,116 @@ +Index: FFmpeg/libavcodec/vaapi_encode.c +=================================================================== +--- FFmpeg.orig/libavcodec/vaapi_encode.c ++++ FFmpeg/libavcodec/vaapi_encode.c +@@ -1133,6 +1133,68 @@ fail: + return err; + } + ++static av_cold int vaapi_encode_surface_alignment(av_unused AVCodecContext *avctx) ++{ ++#if VA_CHECK_VERSION(1, 21, 0) ++ VAAPIEncodeContext *ctx = avctx->priv_data; ++ VASurfaceAttrib *attr_list = NULL; ++ unsigned int attr_count = 0; ++ VAConfigID va_config; ++ VAStatus vas; ++ int err = 0; ++ ++ vas = vaCreateConfig(ctx->hwctx->display, ++ ctx->va_profile, ctx->va_entrypoint, ++ NULL, 0, &va_config); ++ if (vas != VA_STATUS_SUCCESS) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to create temp encode pipeline " ++ "configuration: %d (%s).\n", vas, vaErrorStr(vas)); ++ return AVERROR(EIO); ++ } ++ ++ vas = vaQuerySurfaceAttributes(ctx->hwctx->display, va_config, ++ 0, &attr_count); ++ if (vas != VA_STATUS_SUCCESS) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to query surface attributes: " ++ "%d (%s).\n", vas, vaErrorStr(vas)); ++ err = AVERROR_EXTERNAL; ++ goto fail; ++ } ++ ++ attr_list = av_malloc(attr_count * sizeof(*attr_list)); ++ if (!attr_list) { ++ err = AVERROR(ENOMEM); ++ goto fail; ++ } ++ ++ vas = vaQuerySurfaceAttributes(ctx->hwctx->display, va_config, ++ attr_list, &attr_count); ++ if (vas != VA_STATUS_SUCCESS) { ++ av_log(avctx, AV_LOG_ERROR, "Failed to query surface attributes: " ++ "%d (%s).\n", vas, vaErrorStr(vas)); ++ err = AVERROR_EXTERNAL; ++ goto fail; ++ } ++ ++ for (unsigned int i = 0; i < attr_count; i++) { ++ if (attr_list[i].type == VASurfaceAttribAlignmentSize) { ++ ctx->surface_alignment_width = ++ 1 << (attr_list[i].value.value.i & 0xf); ++ ctx->surface_alignment_height = ++ 1 << ((attr_list[i].value.value.i & 0xf0) >> 4); ++ break; ++ } ++ } ++ ++fail: ++ av_freep(&attr_list); ++ vaDestroyConfig(ctx->hwctx->display, va_config); ++ return err; ++#else ++ return 0; ++#endif ++} ++ + static const VAAPIEncodeRCMode vaapi_encode_rc_modes[] = { + // Bitrate Quality + // | Maxrate | HRD/VBV +@@ -2111,6 +2173,10 @@ av_cold int ff_vaapi_encode_init(AVCodec + if (err < 0) + goto fail; + ++ err = vaapi_encode_surface_alignment(avctx); ++ if (err < 0) ++ goto fail; ++ + if (ctx->codec->get_encoder_caps) { + err = ctx->codec->get_encoder_caps(avctx); + if (err < 0) +Index: FFmpeg/libavcodec/vaapi_encode.h +=================================================================== +--- FFmpeg.orig/libavcodec/vaapi_encode.h ++++ FFmpeg/libavcodec/vaapi_encode.h +@@ -260,6 +260,10 @@ typedef struct VAAPIEncodeContext { + * This is a RefStruct reference. + */ + VABufferID *coded_buffer_ref; ++ ++ // Surface alignment required by driver. ++ int surface_alignment_width; ++ int surface_alignment_height; + } VAAPIEncodeContext; + + typedef struct VAAPIEncodeType { +Index: FFmpeg/libavcodec/vaapi_encode_h265.c +=================================================================== +--- FFmpeg.orig/libavcodec/vaapi_encode_h265.c ++++ FFmpeg/libavcodec/vaapi_encode_h265.c +@@ -951,8 +951,10 @@ static av_cold int vaapi_encode_h265_get + "min CB size %dx%d.\n", priv->ctu_size, priv->ctu_size, + priv->min_cb_size, priv->min_cb_size); + +- base_ctx->surface_width = FFALIGN(avctx->width, priv->min_cb_size); +- base_ctx->surface_height = FFALIGN(avctx->height, priv->min_cb_size); ++ base_ctx->surface_width = FFALIGN(avctx->width, ++ FFMAX(priv->min_cb_size, priv->common.surface_alignment_width)); ++ base_ctx->surface_height = FFALIGN(avctx->height, ++ FFMAX(priv->min_cb_size, priv->common.surface_alignment_height)); + + base_ctx->slice_block_width = base_ctx->slice_block_height = priv->ctu_size; + diff --git a/debian/patches/0018-backport-fixes-for-qsv-from-upstream.patch b/debian/patches/0018-backport-fixes-for-qsv-from-upstream.patch new file mode 100644 index 000000000..652dd86d9 --- /dev/null +++ b/debian/patches/0018-backport-fixes-for-qsv-from-upstream.patch @@ -0,0 +1,55 @@ +Index: FFmpeg/libavfilter/qsvvpp.c +=================================================================== +--- FFmpeg.orig/libavfilter/qsvvpp.c ++++ FFmpeg/libavfilter/qsvvpp.c +@@ -471,7 +471,8 @@ static QSVFrame *submit_frame(QSVVPPCont + } + + /* get the output surface */ +-static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink, const AVFrame *in) ++static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink, const AVFrame *in, ++ const AVFrame *propref) + { + FilterLink *l = ff_filter_link(outlink); + AVFilterContext *ctx = outlink->src; +@@ -513,6 +514,15 @@ static QSVFrame *query_frame(QSVVPPConte + return NULL; + } + ++ if (propref) { ++ ret = av_frame_copy_props(out_frame->frame, propref); ++ if (ret < 0) { ++ av_frame_free(&out_frame->frame); ++ av_log(ctx, AV_LOG_ERROR, "Failed to copy metadata fields from src to dst.\n"); ++ return NULL; ++ } ++ } ++ + if (l->frame_rate.num && l->frame_rate.den) + out_frame->frame->duration = av_rescale_q(1, av_inv_q(l->frame_rate), outlink->time_base); + else +@@ -985,7 +995,7 @@ int ff_qsvvpp_filter_frame(QSVVPPContext + } + + do { +- out_frame = query_frame(s, outlink, in_frame->frame); ++ out_frame = query_frame(s, outlink, in_frame->frame, propref); + if (!out_frame) { + av_log(ctx, AV_LOG_ERROR, "Failed to query an output frame.\n"); + return AVERROR(ENOMEM); +@@ -1009,15 +1019,6 @@ int ff_qsvvpp_filter_frame(QSVVPPContext + break; + } + +- if (propref) { +- ret1 = av_frame_copy_props(out_frame->frame, propref); +- if (ret1 < 0) { +- av_frame_free(&out_frame->frame); +- av_log(ctx, AV_LOG_ERROR, "Failed to copy metadata fields from src to dst.\n"); +- return ret1; +- } +- } +- + out_frame->frame->pts = av_rescale_q(out_frame->surface.Data.TimeStamp, + default_tb, outlink->time_base); + diff --git a/debian/patches/0018-backport-fixes-for-vaapi-from-upstream.patch b/debian/patches/0018-backport-fixes-for-vaapi-from-upstream.patch deleted file mode 100644 index d4288ab60..000000000 --- a/debian/patches/0018-backport-fixes-for-vaapi-from-upstream.patch +++ /dev/null @@ -1,607 +0,0 @@ -Index: FFmpeg/libavcodec/vaapi_av1.c -=================================================================== ---- FFmpeg.orig/libavcodec/vaapi_av1.c -+++ FFmpeg/libavcodec/vaapi_av1.c -@@ -19,6 +19,7 @@ - */ - - #include "libavutil/frame.h" -+#include "libavutil/mem.h" - #include "hwaccel_internal.h" - #include "vaapi_decode.h" - #include "internal.h" -@@ -42,6 +43,9 @@ typedef struct VAAPIAV1DecContext { - */ - VAAPIAV1FrameRef ref_tab[AV1_NUM_REF_FRAMES]; - AVFrame *tmp_frame; -+ -+ int nb_slice_params; -+ VASliceParameterBufferAV1 *slice_params; - } VAAPIAV1DecContext; - - static VASurfaceID vaapi_av1_surface_id(AV1Frame *vf) -@@ -97,6 +101,8 @@ static int vaapi_av1_decode_uninit(AVCod - for (int i = 0; i < FF_ARRAY_ELEMS(ctx->ref_tab); i++) - av_frame_free(&ctx->ref_tab[i].frame); - -+ av_freep(&ctx->slice_params); -+ - return ff_vaapi_decode_uninit(avctx); - } - -@@ -393,13 +399,25 @@ static int vaapi_av1_decode_slice(AVCode - { - const AV1DecContext *s = avctx->priv_data; - VAAPIDecodePicture *pic = s->cur_frame.hwaccel_picture_private; -- VASliceParameterBufferAV1 slice_param; -- int err = 0; -+ VAAPIAV1DecContext *ctx = avctx->internal->hwaccel_priv_data; -+ int err, nb_params; - -- for (int i = s->tg_start; i <= s->tg_end; i++) { -- memset(&slice_param, 0, sizeof(VASliceParameterBufferAV1)); -+ nb_params = s->tg_end - s->tg_start + 1; -+ if (ctx->nb_slice_params < nb_params) { -+ VASliceParameterBufferAV1 *tmp = av_realloc_array(ctx->slice_params, -+ nb_params, -+ sizeof(*ctx->slice_params)); -+ if (!tmp) { -+ ctx->nb_slice_params = 0; -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ ctx->slice_params = tmp; -+ ctx->nb_slice_params = nb_params; -+ } - -- slice_param = (VASliceParameterBufferAV1) { -+ for (int i = s->tg_start; i <= s->tg_end; i++) { -+ ctx->slice_params[i - s->tg_start] = (VASliceParameterBufferAV1) { - .slice_data_size = s->tile_group_info[i].tile_size, - .slice_data_offset = s->tile_group_info[i].tile_offset, - .slice_data_flag = VA_SLICE_DATA_FLAG_ALL, -@@ -408,18 +426,20 @@ static int vaapi_av1_decode_slice(AVCode - .tg_start = s->tg_start, - .tg_end = s->tg_end, - }; -- -- err = ff_vaapi_decode_make_slice_buffer(avctx, pic, &slice_param, -- sizeof(VASliceParameterBufferAV1), -- buffer, -- size); -- if (err) { -- ff_vaapi_decode_cancel(avctx, pic); -- return err; -- } - } - -+ err = ff_vaapi_decode_make_slice_buffer(avctx, pic, ctx->slice_params, nb_params, -+ sizeof(VASliceParameterBufferAV1), -+ buffer, -+ size); -+ if (err) -+ goto fail; -+ - return 0; -+ -+fail: -+ ff_vaapi_decode_cancel(avctx, pic); -+ return err; - } - - const FFHWAccel ff_av1_vaapi_hwaccel = { -Index: FFmpeg/libavcodec/vaapi_decode.c -=================================================================== ---- FFmpeg.orig/libavcodec/vaapi_decode.c -+++ FFmpeg/libavcodec/vaapi_decode.c -@@ -62,6 +62,7 @@ int ff_vaapi_decode_make_param_buffer(AV - int ff_vaapi_decode_make_slice_buffer(AVCodecContext *avctx, - VAAPIDecodePicture *pic, - const void *params_data, -+ int nb_params, - size_t params_size, - const void *slice_data, - size_t slice_size) -@@ -72,13 +73,14 @@ int ff_vaapi_decode_make_slice_buffer(AV - - av_assert0(pic->nb_slices <= pic->slices_allocated); - if (pic->nb_slices == pic->slices_allocated) { -- pic->slice_buffers = -+ VABufferID *tmp = - av_realloc_array(pic->slice_buffers, - pic->slices_allocated ? pic->slices_allocated * 2 : 64, - 2 * sizeof(*pic->slice_buffers)); -- if (!pic->slice_buffers) -+ if (!tmp) - return AVERROR(ENOMEM); - -+ pic->slice_buffers = tmp; - pic->slices_allocated = pic->slices_allocated ? pic->slices_allocated * 2 : 64; - } - av_assert0(pic->nb_slices + 1 <= pic->slices_allocated); -@@ -87,7 +89,7 @@ int ff_vaapi_decode_make_slice_buffer(AV - - vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, - VASliceParameterBufferType, -- params_size, 1, (void*)params_data, -+ params_size, nb_params, (void*)params_data, - &pic->slice_buffers[index]); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to create slice " -@@ -155,6 +157,11 @@ int ff_vaapi_decode_issue(AVCodecContext - VAStatus vas; - int err; - -+ if (pic->nb_slices <= 0) { -+ err = AVERROR(EINVAL); -+ goto fail; -+ } -+ - av_log(avctx, AV_LOG_DEBUG, "Decode to surface %#x.\n", - pic->output_surface); - -@@ -598,22 +605,26 @@ static int vaapi_decode_make_config(AVCo - if (err < 0) - goto fail; - -- frames->initial_pool_size = 1; -- // Add per-codec number of surfaces used for storing reference frames. -- switch (avctx->codec_id) { -- case AV_CODEC_ID_H264: -- case AV_CODEC_ID_HEVC: -- case AV_CODEC_ID_AV1: -- frames->initial_pool_size += 16; -- break; -- case AV_CODEC_ID_VP9: -- frames->initial_pool_size += 8; -- break; -- case AV_CODEC_ID_VP8: -- frames->initial_pool_size += 3; -- break; -- default: -- frames->initial_pool_size += 2; -+ if (CONFIG_VAAPI_1) -+ frames->initial_pool_size = 0; -+ else { -+ frames->initial_pool_size = 1; -+ // Add per-codec number of surfaces used for storing reference frames. -+ switch (avctx->codec_id) { -+ case AV_CODEC_ID_H264: -+ case AV_CODEC_ID_HEVC: -+ case AV_CODEC_ID_AV1: -+ frames->initial_pool_size += 16; -+ break; -+ case AV_CODEC_ID_VP9: -+ frames->initial_pool_size += 8; -+ break; -+ case AV_CODEC_ID_VP8: -+ frames->initial_pool_size += 3; -+ break; -+ default: -+ frames->initial_pool_size += 2; -+ } - } - } - -Index: FFmpeg/libavcodec/vaapi_decode.h -=================================================================== ---- FFmpeg.orig/libavcodec/vaapi_decode.h -+++ FFmpeg/libavcodec/vaapi_decode.h -@@ -73,6 +73,7 @@ int ff_vaapi_decode_make_param_buffer(AV - int ff_vaapi_decode_make_slice_buffer(AVCodecContext *avctx, - VAAPIDecodePicture *pic, - const void *params_data, -+ int nb_params, - size_t params_size, - const void *slice_data, - size_t slice_size); -Index: FFmpeg/libavcodec/vaapi_encode_av1.c -=================================================================== ---- FFmpeg.orig/libavcodec/vaapi_encode_av1.c -+++ FFmpeg/libavcodec/vaapi_encode_av1.c -@@ -23,6 +23,7 @@ - - #include "libavutil/pixdesc.h" - #include "libavutil/opt.h" -+#include "libavutil/mastering_display_metadata.h" - - #include "cbs_av1.h" - #include "put_bits.h" -@@ -41,6 +42,8 @@ typedef struct VAAPIEncodeAV1Context { - VAAPIEncodeContext common; - AV1RawOBU sh; /**< sequence header.*/ - AV1RawOBU fh; /**< frame header.*/ -+ AV1RawOBU mh[4]; /**< metadata header.*/ -+ int nb_mh; - CodedBitstreamContext *cbc; - CodedBitstreamFragment current_obu; - VAConfigAttribValEncAV1 attr; -@@ -155,6 +158,8 @@ static av_cold int vaapi_encode_av1_conf - priv->q_idx_idr = priv->q_idx_p = priv->q_idx_b = 128; - } - -+ ctx->roi_quant_range = AV1_MAX_QUANT; -+ - return 0; - } - -@@ -657,6 +662,68 @@ static int vaapi_encode_av1_init_picture - 2 : 1)); - } - -+ priv->nb_mh = 0; -+ -+ if (pic->type == PICTURE_TYPE_IDR) { -+ AVFrameSideData *sd = -+ av_frame_get_side_data(pic->input_image, -+ AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); -+ if (sd) { -+ AVMasteringDisplayMetadata *mdm = -+ (AVMasteringDisplayMetadata *)sd->data; -+ if (mdm->has_primaries && mdm->has_luminance) { -+ AV1RawOBU *obu = &priv->mh[priv->nb_mh++]; -+ AV1RawMetadata *md = &obu->obu.metadata; -+ AV1RawMetadataHDRMDCV *mdcv = &md->metadata.hdr_mdcv; -+ const int chroma_den = 1 << 16; -+ const int max_luma_den = 1 << 8; -+ const int min_luma_den = 1 << 14; -+ -+ memset(obu, 0, sizeof(*obu)); -+ obu->header.obu_type = AV1_OBU_METADATA; -+ md->metadata_type = AV1_METADATA_TYPE_HDR_MDCV; -+ -+ for (i = 0; i < 3; i++) { -+ mdcv->primary_chromaticity_x[i] = -+ av_rescale(mdm->display_primaries[i][0].num, chroma_den, -+ mdm->display_primaries[i][0].den); -+ mdcv->primary_chromaticity_y[i] = -+ av_rescale(mdm->display_primaries[i][1].num, chroma_den, -+ mdm->display_primaries[i][1].den); -+ } -+ -+ mdcv->white_point_chromaticity_x = -+ av_rescale(mdm->white_point[0].num, chroma_den, -+ mdm->white_point[0].den); -+ mdcv->white_point_chromaticity_y = -+ av_rescale(mdm->white_point[1].num, chroma_den, -+ mdm->white_point[1].den); -+ -+ mdcv->luminance_max = -+ av_rescale(mdm->max_luminance.num, max_luma_den, -+ mdm->max_luminance.den); -+ mdcv->luminance_min = -+ av_rescale(mdm->min_luminance.num, min_luma_den, -+ mdm->min_luminance.den); -+ } -+ } -+ -+ sd = av_frame_get_side_data(pic->input_image, -+ AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); -+ if (sd) { -+ AVContentLightMetadata *cllm = (AVContentLightMetadata *)sd->data; -+ AV1RawOBU *obu = &priv->mh[priv->nb_mh++]; -+ AV1RawMetadata *md = &obu->obu.metadata; -+ AV1RawMetadataHDRCLL *cll = &md->metadata.hdr_cll; -+ -+ memset(obu, 0, sizeof(*obu)); -+ obu->header.obu_type = AV1_OBU_METADATA; -+ md->metadata_type = AV1_METADATA_TYPE_HDR_CLL; -+ cll->max_cll = cllm->MaxCLL; -+ cll->max_fall = cllm->MaxFALL; -+ } -+ } -+ - end: - ff_cbs_fragment_reset(obu); - return ret; -@@ -733,6 +800,39 @@ end: - return ret; - } - -+static int vaapi_encode_av1_write_extra_header(AVCodecContext *avctx, -+ VAAPIEncodePicture *pic, -+ int index, int *type, -+ char *data, size_t *data_len) -+{ -+ VAAPIEncodeAV1Context *priv = avctx->priv_data; -+ CodedBitstreamFragment *obu = &priv->current_obu; -+ AV1RawOBU *mh_obu; -+ char mh_data[MAX_PARAM_BUFFER_SIZE]; -+ size_t mh_data_len; -+ int ret = 0; -+ -+ if (index >= priv->nb_mh) -+ return AVERROR_EOF; -+ -+ mh_obu = &priv->mh[index]; -+ ret = vaapi_encode_av1_add_obu(avctx, obu, AV1_OBU_METADATA, mh_obu); -+ if (ret < 0) -+ goto end; -+ -+ ret = vaapi_encode_av1_write_obu(avctx, mh_data, &mh_data_len, obu); -+ if (ret < 0) -+ goto end; -+ -+ memcpy(data, mh_data, MAX_PARAM_BUFFER_SIZE * sizeof(char)); -+ *data_len = mh_data_len; -+ *type = VAEncPackedHeaderRawData; -+ -+end: -+ ff_cbs_fragment_reset(obu); -+ return ret; -+} -+ - static const VAAPIEncodeProfile vaapi_encode_av1_profiles[] = { - { AV_PROFILE_AV1_MAIN, 8, 3, 1, 1, VAProfileAV1Profile0 }, - { AV_PROFILE_AV1_MAIN, 10, 3, 1, 1, VAProfileAV1Profile0 }, -@@ -760,6 +860,8 @@ static const VAAPIEncodeType vaapi_encod - - .slice_params_size = sizeof(VAEncTileGroupBufferAV1), - .init_slice_params = &vaapi_encode_av1_init_slice_params, -+ -+ .write_extra_header = &vaapi_encode_av1_write_extra_header, - }; - - static av_cold int vaapi_encode_av1_init(AVCodecContext *avctx) -@@ -774,7 +876,8 @@ static av_cold int vaapi_encode_av1_init - - ctx->desired_packed_headers = - VA_ENC_PACKED_HEADER_SEQUENCE | -- VA_ENC_PACKED_HEADER_PICTURE; -+ VA_ENC_PACKED_HEADER_PICTURE | -+ VA_ENC_PACKED_HEADER_MISC; // Metadata - - if (avctx->profile == AV_PROFILE_UNKNOWN) - avctx->profile = priv->profile; -Index: FFmpeg/libavcodec/vaapi_encode_h264.c -=================================================================== ---- FFmpeg.orig/libavcodec/vaapi_encode_h264.c -+++ FFmpeg/libavcodec/vaapi_encode_h264.c -@@ -759,7 +759,7 @@ static int vaapi_encode_h264_init_pictur - vpic->frame_num = hpic->frame_num; - - vpic->pic_fields.bits.idr_pic_flag = (pic->type == PICTURE_TYPE_IDR); -- vpic->pic_fields.bits.reference_pic_flag = (pic->type != PICTURE_TYPE_B); -+ vpic->pic_fields.bits.reference_pic_flag = pic->is_reference; - - return 0; - } -Index: FFmpeg/libavcodec/vaapi_encode_h265.c -=================================================================== ---- FFmpeg.orig/libavcodec/vaapi_encode_h265.c -+++ FFmpeg/libavcodec/vaapi_encode_h265.c -@@ -945,26 +945,23 @@ static int vaapi_encode_h265_init_pictur - - vpic->nal_unit_type = hpic->slice_nal_unit; - -+ vpic->pic_fields.bits.reference_pic_flag = pic->is_reference; - switch (pic->type) { - case PICTURE_TYPE_IDR: - vpic->pic_fields.bits.idr_pic_flag = 1; - vpic->pic_fields.bits.coding_type = 1; -- vpic->pic_fields.bits.reference_pic_flag = 1; - break; - case PICTURE_TYPE_I: - vpic->pic_fields.bits.idr_pic_flag = 0; - vpic->pic_fields.bits.coding_type = 1; -- vpic->pic_fields.bits.reference_pic_flag = 1; - break; - case PICTURE_TYPE_P: - vpic->pic_fields.bits.idr_pic_flag = 0; - vpic->pic_fields.bits.coding_type = 2; -- vpic->pic_fields.bits.reference_pic_flag = 1; - break; - case PICTURE_TYPE_B: - vpic->pic_fields.bits.idr_pic_flag = 0; - vpic->pic_fields.bits.coding_type = 3; -- vpic->pic_fields.bits.reference_pic_flag = 0; - break; - default: - av_assert0(0 && "invalid picture type"); -Index: FFmpeg/libavcodec/vaapi_h264.c -=================================================================== ---- FFmpeg.orig/libavcodec/vaapi_h264.c -+++ FFmpeg/libavcodec/vaapi_h264.c -@@ -93,14 +93,19 @@ typedef struct DPB { - */ - static int dpb_add(DPB *dpb, const H264Picture *pic) - { -- int i; -+ int i, pic_frame_idx, merged = 0; - - if (dpb->size >= dpb->max_size) - return -1; - -+ pic_frame_idx = pic->long_ref ? pic->pic_id : pic->frame_num; -+ - for (i = 0; i < dpb->size; i++) { - VAPictureH264 * const va_pic = &dpb->va_pics[i]; -- if (va_pic->picture_id == ff_vaapi_get_surface_id(pic->f)) { -+ int va_pic_long_ref = !!(va_pic->flags & VA_PICTURE_H264_LONG_TERM_REFERENCE); -+ if (va_pic->picture_id == ff_vaapi_get_surface_id(pic->f) && -+ va_pic_long_ref == pic->long_ref && -+ va_pic->frame_idx == pic_frame_idx) { - VAPictureH264 temp_va_pic; - fill_vaapi_pic(&temp_va_pic, pic, 0); - -@@ -112,11 +117,14 @@ static int dpb_add(DPB *dpb, const H264P - } else { - va_pic->BottomFieldOrderCnt = temp_va_pic.BottomFieldOrderCnt; - } -+ merged = 1; - } -- return 0; - } - } - -+ if (merged) -+ return 0; -+ - fill_vaapi_pic(&dpb->va_pics[dpb->size++], pic, 0); - return 0; - } -@@ -375,7 +383,7 @@ static int vaapi_h264_decode_slice(AVCod - slice_param.chroma_offset_l1); - - err = ff_vaapi_decode_make_slice_buffer(avctx, pic, -- &slice_param, sizeof(slice_param), -+ &slice_param, 1, sizeof(slice_param), - buffer, size); - if (err) { - ff_vaapi_decode_cancel(avctx, pic); -Index: FFmpeg/libavcodec/vaapi_hevc.c -=================================================================== ---- FFmpeg.orig/libavcodec/vaapi_hevc.c -+++ FFmpeg/libavcodec/vaapi_hevc.c -@@ -353,7 +353,7 @@ static int vaapi_hevc_end_frame(AVCodecC - if (pic->last_size) { - last_slice_param->LongSliceFlags.fields.LastSliceOfPic = 1; - ret = ff_vaapi_decode_make_slice_buffer(avctx, &pic->pic, -- &pic->last_slice_param, slice_param_size, -+ &pic->last_slice_param, 1, slice_param_size, - pic->last_buffer, pic->last_size); - if (ret < 0) - goto fail; -@@ -471,7 +471,7 @@ static int vaapi_hevc_decode_slice(AVCod - - if (!sh->first_slice_in_pic_flag) { - err = ff_vaapi_decode_make_slice_buffer(avctx, &pic->pic, -- &pic->last_slice_param, slice_param_size, -+ &pic->last_slice_param, 1, slice_param_size, - pic->last_buffer, pic->last_size); - pic->last_buffer = NULL; - pic->last_size = 0; -Index: FFmpeg/libavcodec/vaapi_mjpeg.c -=================================================================== ---- FFmpeg.orig/libavcodec/vaapi_mjpeg.c -+++ FFmpeg/libavcodec/vaapi_mjpeg.c -@@ -131,7 +131,7 @@ static int vaapi_mjpeg_decode_slice(AVCo - sp.components[i].ac_table_selector = s->ac_index[i]; - } - -- err = ff_vaapi_decode_make_slice_buffer(avctx, pic, &sp, sizeof(sp), buffer, size); -+ err = ff_vaapi_decode_make_slice_buffer(avctx, pic, &sp, 1, sizeof(sp), buffer, size); - if (err) - goto fail; - -Index: FFmpeg/libavcodec/vaapi_mpeg2.c -=================================================================== ---- FFmpeg.orig/libavcodec/vaapi_mpeg2.c -+++ FFmpeg/libavcodec/vaapi_mpeg2.c -@@ -162,7 +162,7 @@ static int vaapi_mpeg2_decode_slice(AVCo - }; - - err = ff_vaapi_decode_make_slice_buffer(avctx, pic, -- &slice_param, sizeof(slice_param), -+ &slice_param, 1, sizeof(slice_param), - buffer, size); - if (err < 0) { - ff_vaapi_decode_cancel(avctx, pic); -Index: FFmpeg/libavcodec/vaapi_mpeg4.c -=================================================================== ---- FFmpeg.orig/libavcodec/vaapi_mpeg4.c -+++ FFmpeg/libavcodec/vaapi_mpeg4.c -@@ -169,7 +169,7 @@ static int vaapi_mpeg4_decode_slice(AVCo - }; - - err = ff_vaapi_decode_make_slice_buffer(avctx, pic, -- &slice_param, sizeof(slice_param), -+ &slice_param, 1, sizeof(slice_param), - buffer, size); - if (err < 0) { - ff_vaapi_decode_cancel(avctx, pic); -Index: FFmpeg/libavcodec/vaapi_vc1.c -=================================================================== ---- FFmpeg.orig/libavcodec/vaapi_vc1.c -+++ FFmpeg/libavcodec/vaapi_vc1.c -@@ -489,7 +489,7 @@ static int vaapi_vc1_decode_slice(AVCode - }; - - err = ff_vaapi_decode_make_slice_buffer(avctx, pic, -- &slice_param, sizeof(slice_param), -+ &slice_param, 1, sizeof(slice_param), - buffer, size); - if (err < 0) { - ff_vaapi_decode_cancel(avctx, pic); -Index: FFmpeg/libavcodec/vaapi_vp8.c -=================================================================== ---- FFmpeg.orig/libavcodec/vaapi_vp8.c -+++ FFmpeg/libavcodec/vaapi_vp8.c -@@ -209,7 +209,7 @@ static int vaapi_vp8_decode_slice(AVCode - for (i = 0; i < 8; i++) - sp.partition_size[i+1] = s->coeff_partition_size[i]; - -- err = ff_vaapi_decode_make_slice_buffer(avctx, pic, &sp, sizeof(sp), data, data_size); -+ err = ff_vaapi_decode_make_slice_buffer(avctx, pic, &sp, 1, sizeof(sp), data, data_size); - if (err) - goto fail; - -Index: FFmpeg/libavcodec/vaapi_vp9.c -=================================================================== ---- FFmpeg.orig/libavcodec/vaapi_vp9.c -+++ FFmpeg/libavcodec/vaapi_vp9.c -@@ -158,7 +158,7 @@ static int vaapi_vp9_decode_slice(AVCode - } - - err = ff_vaapi_decode_make_slice_buffer(avctx, pic, -- &slice_param, sizeof(slice_param), -+ &slice_param, 1, sizeof(slice_param), - buffer, size); - if (err) { - ff_vaapi_decode_cancel(avctx, pic); -Index: FFmpeg/libavfilter/vaapi_vpp.c -=================================================================== ---- FFmpeg.orig/libavfilter/vaapi_vpp.c -+++ FFmpeg/libavfilter/vaapi_vpp.c -@@ -203,7 +203,10 @@ int ff_vaapi_vpp_config_output(AVFilterL - output_frames->width = ctx->output_width; - output_frames->height = ctx->output_height; - -- output_frames->initial_pool_size = 4; -+ if (CONFIG_VAAPI_1) -+ output_frames->initial_pool_size = 0; -+ else -+ output_frames->initial_pool_size = 4; - - err = ff_filter_init_hw_frames(avctx, outlink, 10); - if (err < 0) -@@ -219,6 +222,8 @@ int ff_vaapi_vpp_config_output(AVFilterL - va_frames = output_frames->hwctx; - - av_assert0(ctx->va_context == VA_INVALID_ID); -+ av_assert0(output_frames->initial_pool_size || -+ (va_frames->surface_ids == NULL && va_frames->nb_surfaces == 0)); - vas = vaCreateContext(ctx->hwctx->display, ctx->va_config, - ctx->output_width, ctx->output_height, - VA_PROGRESSIVE, -Index: FFmpeg/libavutil/hwcontext_vaapi.c -=================================================================== ---- FFmpeg.orig/libavutil/hwcontext_vaapi.c -+++ FFmpeg/libavutil/hwcontext_vaapi.c -@@ -809,6 +809,9 @@ static int vaapi_map_frame(AVHWFramesCon - VAStatus vas; - void *address = NULL; - int err, i; -+#if VA_CHECK_VERSION(1, 21, 0) -+ uint32_t vaflags = 0; -+#endif - - surface_id = (VASurfaceID)(uintptr_t)src->data[3]; - av_log(hwfc, AV_LOG_DEBUG, "Map surface %#x.\n", surface_id); -@@ -892,7 +895,16 @@ static int vaapi_map_frame(AVHWFramesCon - } - } - -+#if VA_CHECK_VERSION(1, 21, 0) -+ if (flags & AV_HWFRAME_MAP_READ) -+ vaflags |= VA_MAPBUFFER_FLAG_READ; -+ if (flags & AV_HWFRAME_MAP_WRITE) -+ vaflags |= VA_MAPBUFFER_FLAG_WRITE; -+ // On drivers not implementing vaMapBuffer2 libva calls vaMapBuffer instead. -+ vas = vaMapBuffer2(hwctx->display, map->image.buf, &address, vaflags); -+#else - vas = vaMapBuffer(hwctx->display, map->image.buf, &address); -+#endif - if (vas != VA_STATUS_SUCCESS) { - av_log(hwfc, AV_LOG_ERROR, "Failed to map image from surface " - "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas)); diff --git a/debian/patches/0020-backport-fixes-for-qsv-from-cartwheel.patch b/debian/patches/0019-backport-fixes-for-qsv-from-cartwheel.patch similarity index 97% rename from debian/patches/0020-backport-fixes-for-qsv-from-cartwheel.patch rename to debian/patches/0019-backport-fixes-for-qsv-from-cartwheel.patch index 26c3811f9..593e798ad 100644 --- a/debian/patches/0020-backport-fixes-for-qsv-from-cartwheel.patch +++ b/debian/patches/0019-backport-fixes-for-qsv-from-cartwheel.patch @@ -205,7 +205,7 @@ Index: FFmpeg/libavcodec/qsvdec.c frame->pts = MFX_PTS_TO_PTS(outsurf->Data.TimeStamp, avctx->pkt_timebase); #if QSV_VERSION_ATLEAST(1, 34) if ((avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) && -@@ -985,6 +1138,8 @@ static void qsv_decode_close_qsvcontext( +@@ -986,6 +1139,8 @@ static void qsv_decode_close_qsvcontext( av_buffer_unref(&q->frames_ctx.hw_frames_ctx); ff_refstruct_unref(&q->frames_ctx.mids); av_buffer_pool_uninit(&q->pool); @@ -300,7 +300,7 @@ Index: FFmpeg/libavcodec/qsvenc.h =================================================================== --- FFmpeg.orig/libavcodec/qsvenc.h +++ FFmpeg/libavcodec/qsvenc.h -@@ -177,6 +177,7 @@ typedef struct QSVEncContext { +@@ -175,6 +175,7 @@ typedef struct QSVEncContext { mfxExtMultiFrameControl extmfc; #endif mfxExtHEVCTiles exthevctiles; @@ -308,7 +308,7 @@ Index: FFmpeg/libavcodec/qsvenc.h mfxExtVP9Param extvp9param; #if QSV_HAVE_EXT_AV1_PARAM mfxExtAV1TileParam extav1tileparam; -@@ -193,7 +194,7 @@ typedef struct QSVEncContext { +@@ -191,7 +192,7 @@ typedef struct QSVEncContext { mfxExtVideoSignalInfo extvsi; @@ -317,7 +317,7 @@ Index: FFmpeg/libavcodec/qsvenc.h int nb_extparam_internal; mfxExtBuffer **extparam_str; -@@ -321,6 +322,9 @@ typedef struct QSVEncContext { +@@ -319,6 +320,9 @@ typedef struct QSVEncContext { int dual_gfx; AVDictionary *qsv_params; @@ -331,7 +331,7 @@ Index: FFmpeg/libavcodec/qsvenc_hevc.c =================================================================== --- FFmpeg.orig/libavcodec/qsvenc_hevc.c +++ FFmpeg/libavcodec/qsvenc_hevc.c -@@ -363,6 +363,9 @@ static const AVOption options[] = { +@@ -365,6 +365,9 @@ static const AVOption options[] = { { "int_ref_qp_delta", "QP difference for the refresh MBs", OFFSET(qsv.int_ref_qp_delta), AV_OPT_TYPE_INT, { .i64 = INT16_MIN }, INT16_MIN, INT16_MAX, VE }, { "int_ref_cycle_dist", "Distance between the beginnings of the intra-refresh cycles in frames", OFFSET(qsv.int_ref_cycle_dist), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT16_MAX, VE }, diff --git a/debian/patches/0019-backport-fixes-for-qsv-from-upstream.patch b/debian/patches/0019-backport-fixes-for-qsv-from-upstream.patch deleted file mode 100644 index 61d8daa80..000000000 --- a/debian/patches/0019-backport-fixes-for-qsv-from-upstream.patch +++ /dev/null @@ -1,1662 +0,0 @@ -Index: FFmpeg/configure -=================================================================== ---- FFmpeg.orig/configure -+++ FFmpeg/configure -@@ -2485,6 +2485,7 @@ TYPES_LIST=" - struct_sockaddr_storage - struct_stat_st_mtim_tv_nsec - struct_v4l2_frmivalenum_discrete -+ struct_mfxConfigInterface - " - - HAVE_LIST=" -@@ -6902,6 +6903,7 @@ elif enabled libvpl; then - check_pkg_config libmfx "vpl >= 2.6" "mfxvideo.h mfxdispatcher.h" MFXLoad || \ - die "ERROR: libvpl >= 2.6 not found" - add_cflags -DMFX_DEPRECATED_OFF -+ check_type "vpl/mfxdefs.h vpl/mfxvideo.h" "struct mfxConfigInterface" - fi - - if enabled libmfx; then -Index: FFmpeg/libavcodec/qsv.c -=================================================================== ---- FFmpeg.orig/libavcodec/qsv.c -+++ FFmpeg/libavcodec/qsv.c -@@ -34,6 +34,7 @@ - - #include "avcodec.h" - #include "qsv_internal.h" -+#include "refstruct.h" - - #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl)) - #define QSV_HAVE_USER_PLUGIN !QSV_ONEVPL -@@ -741,20 +742,19 @@ int ff_qsv_init_internal_session(AVCodec - return 0; - } - --static void mids_buf_free(void *opaque, uint8_t *data) -+static void mids_buf_free(FFRefStructOpaque opaque, void *obj) - { -- AVBufferRef *hw_frames_ref = opaque; -+ AVBufferRef *hw_frames_ref = opaque.nc; - av_buffer_unref(&hw_frames_ref); -- av_freep(&data); - } - --static AVBufferRef *qsv_create_mids(AVBufferRef *hw_frames_ref) -+static QSVMid *qsv_create_mids(AVBufferRef *hw_frames_ref) - { - AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ref->data; - AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; - int nb_surfaces = frames_hwctx->nb_surfaces; - -- AVBufferRef *mids_buf, *hw_frames_ref1; -+ AVBufferRef *hw_frames_ref1; - QSVMid *mids; - int i; - -@@ -762,35 +762,27 @@ static AVBufferRef *qsv_create_mids(AVBu - if (!hw_frames_ref1) - return NULL; - -- mids = av_calloc(nb_surfaces, sizeof(*mids)); -+ mids = ff_refstruct_alloc_ext(nb_surfaces * sizeof(*mids), 0, -+ hw_frames_ref1, mids_buf_free); - if (!mids) { - av_buffer_unref(&hw_frames_ref1); - return NULL; - } - -- mids_buf = av_buffer_create((uint8_t*)mids, nb_surfaces * sizeof(*mids), -- mids_buf_free, hw_frames_ref1, 0); -- if (!mids_buf) { -- av_buffer_unref(&hw_frames_ref1); -- av_freep(&mids); -- return NULL; -- } -- - for (i = 0; i < nb_surfaces; i++) { - QSVMid *mid = &mids[i]; - mid->handle_pair = (mfxHDLPair*)frames_hwctx->surfaces[i].Data.MemId; - mid->hw_frames_ref = hw_frames_ref1; - } - -- return mids_buf; -+ return mids; - } - - static int qsv_setup_mids(mfxFrameAllocResponse *resp, AVBufferRef *hw_frames_ref, -- AVBufferRef *mids_buf) -+ QSVMid *mids) - { - AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ref->data; - AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; -- QSVMid *mids = (QSVMid*)mids_buf->data; - int nb_surfaces = frames_hwctx->nb_surfaces; - int i; - -@@ -811,12 +803,7 @@ static int qsv_setup_mids(mfxFrameAllocR - return AVERROR(ENOMEM); - } - -- resp->mids[resp->NumFrameActual + 1] = av_buffer_ref(mids_buf); -- if (!resp->mids[resp->NumFrameActual + 1]) { -- av_buffer_unref((AVBufferRef**)&resp->mids[resp->NumFrameActual]); -- av_freep(&resp->mids); -- return AVERROR(ENOMEM); -- } -+ resp->mids[resp->NumFrameActual + 1] = ff_refstruct_ref(mids); - - return 0; - } -@@ -839,8 +826,16 @@ static mfxStatus qsv_frame_alloc(mfxHDL - AVHWFramesContext *frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data; - AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; - mfxFrameInfo *i = &req->Info; -- mfxFrameInfo *i1 = &frames_hwctx->surfaces[0].Info; -+ mfxFrameInfo *i1; - -+ if (!frames_hwctx->nb_surfaces) { -+ av_log(ctx->logctx, AV_LOG_DEBUG, -+ "Dynamic frame pools, no frame is pre-allocated\n"); -+ -+ return MFX_ERR_NONE; -+ } -+ -+ i1 = &frames_hwctx->surfaces[0].Info; - if (i->Width > i1->Width || i->Height > i1->Height || - i->FourCC != i1->FourCC || i->ChromaFormat != i1->ChromaFormat) { - av_log(ctx->logctx, AV_LOG_ERROR, "Mismatching surface properties in an " -@@ -850,7 +845,7 @@ static mfxStatus qsv_frame_alloc(mfxHDL - return MFX_ERR_UNSUPPORTED; - } - -- ret = qsv_setup_mids(resp, ctx->hw_frames_ctx, ctx->mids_buf); -+ ret = qsv_setup_mids(resp, ctx->hw_frames_ctx, ctx->mids); - if (ret < 0) { - av_log(ctx->logctx, AV_LOG_ERROR, - "Error filling an external frame allocation request\n"); -@@ -859,12 +854,17 @@ static mfxStatus qsv_frame_alloc(mfxHDL - } else if (req->Type & MFX_MEMTYPE_INTERNAL_FRAME) { - /* internal frames -- allocate a new hw frames context */ - AVHWFramesContext *ext_frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data; -+ AVQSVFramesContext *ext_frames_hwctx = ext_frames_ctx->hwctx; - mfxFrameInfo *i = &req->Info; - -- AVBufferRef *frames_ref, *mids_buf; -+ AVBufferRef *frames_ref; -+ QSVMid *mids; - AVHWFramesContext *frames_ctx; - AVQSVFramesContext *frames_hwctx; - -+ if (!ext_frames_hwctx->nb_surfaces) -+ return MFX_ERR_UNSUPPORTED; -+ - frames_ref = av_hwframe_ctx_alloc(ext_frames_ctx->device_ref); - if (!frames_ref) - return MFX_ERR_MEMORY_ALLOC; -@@ -889,14 +889,14 @@ static mfxStatus qsv_frame_alloc(mfxHDL - return MFX_ERR_MEMORY_ALLOC; - } - -- mids_buf = qsv_create_mids(frames_ref); -- if (!mids_buf) { -+ mids = qsv_create_mids(frames_ref); -+ if (!mids) { - av_buffer_unref(&frames_ref); - return MFX_ERR_MEMORY_ALLOC; - } - -- ret = qsv_setup_mids(resp, frames_ref, mids_buf); -- av_buffer_unref(&mids_buf); -+ ret = qsv_setup_mids(resp, frames_ref, mids); -+ ff_refstruct_unref(&mids); - av_buffer_unref(&frames_ref); - if (ret < 0) { - av_log(ctx->logctx, AV_LOG_ERROR, -@@ -912,19 +912,31 @@ static mfxStatus qsv_frame_alloc(mfxHDL - - static mfxStatus qsv_frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp) - { -+ if (!resp->mids) -+ return MFX_ERR_NONE; -+ - av_buffer_unref((AVBufferRef**)&resp->mids[resp->NumFrameActual]); -- av_buffer_unref((AVBufferRef**)&resp->mids[resp->NumFrameActual + 1]); -+ ff_refstruct_unref(&resp->mids[resp->NumFrameActual + 1]); - av_freep(&resp->mids); - return MFX_ERR_NONE; - } - - static mfxStatus qsv_frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) - { -- QSVMid *qsv_mid = mid; -- AVHWFramesContext *hw_frames_ctx = (AVHWFramesContext*)qsv_mid->hw_frames_ref->data; -- AVQSVFramesContext *hw_frames_hwctx = hw_frames_ctx->hwctx; -+ QSVFramesContext *ctx = (QSVFramesContext *)pthis; -+ AVHWFramesContext *frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data; -+ AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; -+ QSVMid *qsv_mid; -+ AVHWFramesContext *hw_frames_ctx; -+ AVQSVFramesContext *hw_frames_hwctx; - int ret; - -+ if (!frames_hwctx->nb_surfaces) -+ return MFX_ERR_UNSUPPORTED; -+ -+ qsv_mid = mid; -+ hw_frames_ctx = (AVHWFramesContext*)qsv_mid->hw_frames_ref->data; -+ hw_frames_hwctx = hw_frames_ctx->hwctx; - if (qsv_mid->locked_frame) - return MFX_ERR_UNDEFINED_BEHAVIOR; - -@@ -977,8 +989,15 @@ fail: - - static mfxStatus qsv_frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr) - { -- QSVMid *qsv_mid = mid; -+ QSVFramesContext *ctx = (QSVFramesContext *)pthis; -+ AVHWFramesContext *frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data; -+ AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; -+ QSVMid *qsv_mid; -+ -+ if (!frames_hwctx->nb_surfaces) -+ return MFX_ERR_UNSUPPORTED; - -+ qsv_mid = mid; - av_frame_free(&qsv_mid->locked_frame); - av_frame_free(&qsv_mid->hw_frame); - -@@ -987,9 +1006,18 @@ static mfxStatus qsv_frame_unlock(mfxHDL - - static mfxStatus qsv_frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl) - { -- QSVMid *qsv_mid = (QSVMid*)mid; -+ QSVFramesContext *ctx = (QSVFramesContext *)pthis; -+ AVHWFramesContext *frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data; -+ AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; - mfxHDLPair *pair_dst = (mfxHDLPair*)hdl; -- mfxHDLPair *pair_src = (mfxHDLPair*)qsv_mid->handle_pair; -+ mfxHDLPair *pair_src; -+ -+ if (frames_hwctx->nb_surfaces) { -+ QSVMid *qsv_mid = (QSVMid*)mid; -+ pair_src = (mfxHDLPair*)qsv_mid->handle_pair; -+ } else { -+ pair_src = (mfxHDLPair*)mid; -+ } - - pair_dst->first = pair_src->first; - -@@ -1103,14 +1131,17 @@ int ff_qsv_init_session_frames(AVCodecCo - - if (!opaque) { - qsv_frames_ctx->logctx = avctx; -+ qsv_frames_ctx->mids = NULL; -+ qsv_frames_ctx->nb_mids = 0; - - /* allocate the memory ids for the external frames */ -- av_buffer_unref(&qsv_frames_ctx->mids_buf); -- qsv_frames_ctx->mids_buf = qsv_create_mids(qsv_frames_ctx->hw_frames_ctx); -- if (!qsv_frames_ctx->mids_buf) -- return AVERROR(ENOMEM); -- qsv_frames_ctx->mids = (QSVMid*)qsv_frames_ctx->mids_buf->data; -- qsv_frames_ctx->nb_mids = frames_hwctx->nb_surfaces; -+ if (frames_hwctx->nb_surfaces) { -+ ff_refstruct_unref(&qsv_frames_ctx->mids); -+ qsv_frames_ctx->mids = qsv_create_mids(qsv_frames_ctx->hw_frames_ctx); -+ if (!qsv_frames_ctx->mids) -+ return AVERROR(ENOMEM); -+ qsv_frames_ctx->nb_mids = frames_hwctx->nb_surfaces; -+ } - - err = MFXVideoCORE_SetFrameAllocator(session, &frame_allocator); - if (err != MFX_ERR_NONE) -Index: FFmpeg/libavcodec/qsv_internal.h -=================================================================== ---- FFmpeg.orig/libavcodec/qsv_internal.h -+++ FFmpeg/libavcodec/qsv_internal.h -@@ -115,11 +115,12 @@ typedef struct QSVFramesContext { - AVBufferRef *hw_frames_ctx; - void *logctx; - -- /* The memory ids for the external frames. -- * Refcounted, since we need one reference owned by the QSVFramesContext -- * (i.e. by the encoder/decoder) and another one given to the MFX session -- * from the frame allocator. */ -- AVBufferRef *mids_buf; -+ /** -+ * The memory ids for the external frames. -+ * Refcounted (via the RefStruct API), since we need one reference -+ * owned by the QSVFramesContext (i.e. by the encoder/decoder) and -+ * another one given to the MFX session from the frame allocator. -+ */ - QSVMid *mids; - int nb_mids; - } QSVFramesContext; -Index: FFmpeg/libavcodec/qsvdec.c -=================================================================== ---- FFmpeg.orig/libavcodec/qsvdec.c -+++ FFmpeg/libavcodec/qsvdec.c -@@ -42,6 +42,7 @@ - #include "libavutil/imgutils.h" - #include "libavutil/film_grain_params.h" - #include "libavutil/mastering_display_metadata.h" -+#include "libavutil/avassert.h" - - #include "avcodec.h" - #include "codec_internal.h" -@@ -50,6 +51,7 @@ - #include "hwconfig.h" - #include "qsv.h" - #include "qsv_internal.h" -+#include "refstruct.h" - - #if QSV_ONEVPL - #include -@@ -67,6 +69,8 @@ static const AVRational mfx_tb = { 1, 90 - AV_NOPTS_VALUE : pts_tb.num ? \ - av_rescale_q(mfx_pts, mfx_tb, pts_tb) : mfx_pts) - -+#define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl)) -+ - typedef struct QSVAsyncFrame { - mfxSyncPoint *sync; - QSVFrame *frame; -@@ -76,6 +80,7 @@ typedef struct QSVContext { - // the session used for decoding - mfxSession session; - mfxVersion ver; -+ mfxHandleType handle_type; - - // the session we allocated internally, in case the caller did not provide - // one -@@ -132,26 +137,26 @@ static int qsv_get_continuous_buffer(AVC - if (ret < 0) - return ret; - -- frame->width = avctx->width; -- frame->height = avctx->height; -+ frame->width = avctx->coded_width; -+ frame->height = avctx->coded_height; - - switch (avctx->pix_fmt) { - case AV_PIX_FMT_NV12: -- frame->linesize[0] = FFALIGN(avctx->width, 128); -+ frame->linesize[0] = FFALIGN(avctx->coded_width, 128); - break; - case AV_PIX_FMT_P010: - case AV_PIX_FMT_P012: - case AV_PIX_FMT_YUYV422: -- frame->linesize[0] = 2 * FFALIGN(avctx->width, 128); -+ frame->linesize[0] = 2 * FFALIGN(avctx->coded_width, 128); - break; - case AV_PIX_FMT_Y210: - case AV_PIX_FMT_VUYX: - case AV_PIX_FMT_XV30: - case AV_PIX_FMT_Y212: -- frame->linesize[0] = 4 * FFALIGN(avctx->width, 128); -+ frame->linesize[0] = 4 * FFALIGN(avctx->coded_width, 128); - break; - case AV_PIX_FMT_XV36: -- frame->linesize[0] = 8 * FFALIGN(avctx->width, 128); -+ frame->linesize[0] = 8 * FFALIGN(avctx->coded_width, 128); - break; - default: - av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format.\n"); -@@ -168,7 +173,7 @@ static int qsv_get_continuous_buffer(AVC - avctx->pix_fmt == AV_PIX_FMT_P012) { - frame->linesize[1] = frame->linesize[0]; - frame->data[1] = frame->data[0] + -- frame->linesize[0] * FFALIGN(avctx->height, 64); -+ frame->linesize[0] * FFALIGN(avctx->coded_height, 64); - } - - ret = ff_attach_decode_data(frame); -@@ -182,6 +187,7 @@ static int qsv_init_session(AVCodecConte - AVBufferRef *hw_frames_ref, AVBufferRef *hw_device_ref) - { - int ret; -+ mfxIMPL impl; - - if (q->gpu_copy == MFX_GPUCOPY_ON && - !(q->iopattern & MFX_IOPATTERN_OUT_SYSTEM_MEMORY)) { -@@ -239,27 +245,52 @@ static int qsv_init_session(AVCodecConte - q->session = q->internal_qs.session; - } - -- if (MFXQueryVersion(q->session, &q->ver) != MFX_ERR_NONE) { -- av_log(avctx, AV_LOG_ERROR, "Error querying the session version. \n"); -- q->session = NULL; -+ if (MFXQueryIMPL(q->session, &impl) == MFX_ERR_NONE) { -+ switch (MFX_IMPL_VIA_MASK(impl)) { -+ case MFX_IMPL_VIA_VAAPI: -+ q->handle_type = MFX_HANDLE_VA_DISPLAY; -+ break; -+ -+ case MFX_IMPL_VIA_D3D11: -+ q->handle_type = MFX_HANDLE_D3D11_DEVICE; -+ break; -+ -+ case MFX_IMPL_VIA_D3D9: -+ q->handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER; -+ break; - -- if (q->internal_qs.session) { -- MFXClose(q->internal_qs.session); -- q->internal_qs.session = NULL; -- } -- -- if (q->internal_qs.loader) { -- MFXUnload(q->internal_qs.loader); -- q->internal_qs.loader = NULL; -+ default: -+ av_assert0(!"should not reach here"); - } -+ } else { -+ av_log(avctx, AV_LOG_ERROR, "Error querying the implementation. \n"); -+ goto fail; -+ } - -- return AVERROR_EXTERNAL; -+ if (MFXQueryVersion(q->session, &q->ver) != MFX_ERR_NONE) { -+ av_log(avctx, AV_LOG_ERROR, "Error querying the session version. \n"); -+ goto fail; - } - - /* make sure the decoder is uninitialized */ - MFXVideoDECODE_Close(q->session); - - return 0; -+ -+fail: -+ q->session = NULL; -+ -+ if (q->internal_qs.session) { -+ MFXClose(q->internal_qs.session); -+ q->internal_qs.session = NULL; -+ } -+ -+ if (q->internal_qs.loader) { -+ MFXUnload(q->internal_qs.loader); -+ q->internal_qs.loader = NULL; -+ } -+ -+ return AVERROR_EXTERNAL; - } - - static int qsv_decode_preinit(AVCodecContext *avctx, QSVContext *q, enum AVPixelFormat pix_fmt, mfxVideoParam *param) -@@ -309,7 +340,10 @@ static int qsv_decode_preinit(AVCodecCon - hwframes_ctx->height = FFALIGN(avctx->coded_height, 32); - hwframes_ctx->format = AV_PIX_FMT_QSV; - hwframes_ctx->sw_format = avctx->sw_pix_fmt; -- hwframes_ctx->initial_pool_size = q->suggest_pool_size + 16 + avctx->extra_hw_frames; -+ if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 2, 9) && q->handle_type != MFX_HANDLE_D3D9_DEVICE_MANAGER) -+ hwframes_ctx->initial_pool_size = 0; -+ else -+ hwframes_ctx->initial_pool_size = q->suggest_pool_size + 16 + avctx->extra_hw_frames; - frames_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; - - ret = av_hwframe_ctx_init(avctx->hw_frames_ctx); -@@ -379,7 +413,7 @@ static int qsv_decode_init_context(AVCod - q->frame_info = param->mfx.FrameInfo; - - if (!avctx->hw_frames_ctx) { -- ret = av_image_get_buffer_size(avctx->pix_fmt, FFALIGN(avctx->width, 128), FFALIGN(avctx->height, 64), 1); -+ ret = av_image_get_buffer_size(avctx->pix_fmt, FFALIGN(avctx->coded_width, 128), FFALIGN(avctx->coded_height, 64), 1); - if (ret < 0) - return ret; - q->pool = av_buffer_pool_init(ret, av_buffer_allocz); -@@ -443,6 +477,11 @@ static int qsv_decode_header(AVCodecCont - param->ExtParam = q->ext_buffers; - param->NumExtParam = q->nb_ext_buffers; - -+ if (param->mfx.FrameInfo.FrameRateExtN == 0 || param->mfx.FrameInfo.FrameRateExtD == 0) { -+ param->mfx.FrameInfo.FrameRateExtN = 25; -+ param->mfx.FrameInfo.FrameRateExtD = 1; -+ } -+ - #if QSV_VERSION_ATLEAST(1, 34) - if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 34) && avctx->codec_id == AV_CODEC_ID_AV1) - param->mfx.FilmGrain = (avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) ? 0 : param->mfx.FilmGrain; -@@ -499,7 +538,8 @@ static int alloc_frame(AVCodecContext *a - #endif - - #if QSV_VERSION_ATLEAST(1, 35) -- if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 35) && avctx->codec_id == AV_CODEC_ID_HEVC) { -+ if ((QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 35) && avctx->codec_id == AV_CODEC_ID_HEVC) || -+ (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 2, 9) && avctx->codec_id == AV_CODEC_ID_AV1)) { - frame->mdcv.Header.BufferId = MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME; - frame->mdcv.Header.BufferSz = sizeof(frame->mdcv); - // The data in mdcv is valid when this flag is 1 -@@ -703,6 +743,45 @@ static int qsv_export_hdr_side_data(AVCo - return 0; - } - -+static int qsv_export_hdr_side_data_av1(AVCodecContext *avctx, mfxExtMasteringDisplayColourVolume *mdcv, -+ mfxExtContentLightLevelInfo *clli, AVFrame *frame) -+{ -+ if (mdcv->InsertPayloadToggle) { -+ AVMasteringDisplayMetadata *mastering = av_mastering_display_metadata_create_side_data(frame); -+ const int chroma_den = 1 << 16; -+ const int max_luma_den = 1 << 8; -+ const int min_luma_den = 1 << 14; -+ -+ if (!mastering) -+ return AVERROR(ENOMEM); -+ -+ for (int i = 0; i < 3; i++) { -+ mastering->display_primaries[i][0] = av_make_q(mdcv->DisplayPrimariesX[i], chroma_den); -+ mastering->display_primaries[i][1] = av_make_q(mdcv->DisplayPrimariesY[i], chroma_den); -+ } -+ -+ mastering->white_point[0] = av_make_q(mdcv->WhitePointX, chroma_den); -+ mastering->white_point[1] = av_make_q(mdcv->WhitePointY, chroma_den); -+ -+ mastering->max_luminance = av_make_q(mdcv->MaxDisplayMasteringLuminance, max_luma_den); -+ mastering->min_luminance = av_make_q(mdcv->MinDisplayMasteringLuminance, min_luma_den); -+ -+ mastering->has_luminance = 1; -+ mastering->has_primaries = 1; -+ } -+ -+ if (clli->InsertPayloadToggle) { -+ AVContentLightMetadata *light = av_content_light_metadata_create_side_data(frame); -+ if (!light) -+ return AVERROR(ENOMEM); -+ -+ light->MaxCLL = clli->MaxContentLightLevel; -+ light->MaxFALL = clli->MaxPicAverageLightLevel; -+ } -+ -+ return 0; -+} -+ - #endif - - static int qsv_decode(AVCodecContext *avctx, QSVContext *q, -@@ -835,6 +914,12 @@ static int qsv_decode(AVCodecContext *av - if (ret < 0) - return ret; - } -+ -+ if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 2, 9) && avctx->codec_id == AV_CODEC_ID_AV1) { -+ ret = qsv_export_hdr_side_data_av1(avctx, &aframe.frame->mdcv, &aframe.frame->clli, frame); -+ if (ret < 0) -+ return ret; -+ } - #endif - - frame->repeat_pict = -@@ -846,13 +931,23 @@ static int qsv_decode(AVCodecContext *av - frame->flags |= AV_FRAME_FLAG_INTERLACED * - !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE); - frame->pict_type = ff_qsv_map_pictype(aframe.frame->dec_info.FrameType); -- //Key frame is IDR frame is only suitable for H264. For HEVC, IRAPs are key frames. -- if (avctx->codec_id == AV_CODEC_ID_H264) { -+ -+ if (avctx->codec_id == AV_CODEC_ID_H264 || -+ avctx->codec_id == AV_CODEC_ID_HEVC) { - if (aframe.frame->dec_info.FrameType & MFX_FRAMETYPE_IDR) - frame->flags |= AV_FRAME_FLAG_KEY; - else - frame->flags &= ~AV_FRAME_FLAG_KEY; -+ } else { -+ if (aframe.frame->dec_info.FrameType & MFX_FRAMETYPE_I) -+ frame->flags |= AV_FRAME_FLAG_KEY; -+ else -+ frame->flags &= ~AV_FRAME_FLAG_KEY; - } -+ frame->crop_left = outsurf->Info.CropX; -+ frame->crop_top = outsurf->Info.CropY; -+ frame->crop_right = outsurf->Info.Width - (outsurf->Info.CropX + outsurf->Info.CropW); -+ frame->crop_bottom = outsurf->Info.Height - (outsurf->Info.CropY + outsurf->Info.CropH); - - /* update the surface properties */ - if (avctx->pix_fmt == AV_PIX_FMT_QSV) -@@ -888,7 +983,7 @@ static void qsv_decode_close_qsvcontext( - ff_qsv_close_internal_session(&q->internal_qs); - - av_buffer_unref(&q->frames_ctx.hw_frames_ctx); -- av_buffer_unref(&q->frames_ctx.mids_buf); -+ ff_refstruct_unref(&q->frames_ctx.mids); - av_buffer_pool_uninit(&q->pool); - } - -@@ -1142,7 +1237,7 @@ const FFCodec ff_##x##_qsv_decoder = { \ - .p.priv_class = &x##_qsv_class, \ - .hw_configs = qsv_hw_configs, \ - .p.wrapper_name = "qsv", \ -- .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE, \ -+ .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING, \ - }; \ - - #define DEFINE_QSV_DECODER(x, X, bsf_name) DEFINE_QSV_DECODER_WITH_OPTION(x, X, bsf_name, options) -Index: FFmpeg/libavcodec/qsvenc.c -=================================================================== ---- FFmpeg.orig/libavcodec/qsvenc.c -+++ FFmpeg/libavcodec/qsvenc.c -@@ -31,6 +31,7 @@ - #include "libavutil/hwcontext_qsv.h" - #include "libavutil/mem.h" - #include "libavutil/log.h" -+#include "libavutil/dict.h" - #include "libavutil/time.h" - #include "libavutil/imgutils.h" - -@@ -41,6 +42,7 @@ - #include "qsv.h" - #include "qsv_internal.h" - #include "qsvenc.h" -+#include "refstruct.h" - - struct profile_names { - mfxU16 profile; -@@ -743,8 +745,9 @@ static int init_video_param_jpeg(AVCodec - if (avctx->hw_frames_ctx) { - AVHWFramesContext *frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data; - AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; -- q->param.mfx.FrameInfo.Width = frames_hwctx->surfaces[0].Info.Width; -- q->param.mfx.FrameInfo.Height = frames_hwctx->surfaces[0].Info.Height; -+ mfxFrameInfo *info = frames_hwctx->nb_surfaces ? &frames_hwctx->surfaces[0].Info : frames_hwctx->info; -+ q->param.mfx.FrameInfo.Width = info->Width; -+ q->param.mfx.FrameInfo.Height = info->Height; - } - - if (avctx->framerate.den > 0 && avctx->framerate.num > 0) { -@@ -867,8 +870,9 @@ static int init_video_param(AVCodecConte - if (avctx->hw_frames_ctx) { - AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; - AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; -- q->param.mfx.FrameInfo.Width = frames_hwctx->surfaces[0].Info.Width; -- q->param.mfx.FrameInfo.Height = frames_hwctx->surfaces[0].Info.Height; -+ mfxFrameInfo *info = frames_hwctx->nb_surfaces ? &frames_hwctx->surfaces[0].Info : frames_hwctx->info; -+ q->param.mfx.FrameInfo.Width = info->Width; -+ q->param.mfx.FrameInfo.Height = info->Height; - } - - if (avctx->framerate.den > 0 && avctx->framerate.num > 0) { -@@ -1633,6 +1637,12 @@ int ff_qsv_enc_init(AVCodecContext *avct - int iopattern = 0; - int opaque_alloc = 0; - int ret; -+ void *tmp; -+#if HAVE_STRUCT_MFXCONFIGINTERFACE -+ mfxExtBuffer ext_buf; -+ mfxConfigInterface *iface = NULL; -+ const AVDictionaryEntry *param = NULL; -+#endif - - q->param.AsyncDepth = q->async_depth; - -@@ -1693,35 +1703,92 @@ int ff_qsv_enc_init(AVCodecContext *avct - if (ret < 0) - return ret; - -+ tmp = av_realloc_array(q->extparam, q->nb_extparam_internal, sizeof(*q->extparam)); -+ if (!tmp) -+ return AVERROR(ENOMEM); -+ -+ q->extparam = tmp; -+ q->nb_extparam = q->nb_extparam_internal; -+ memcpy(q->extparam, q->extparam_internal, q->nb_extparam * sizeof(*q->extparam)); -+ - if (avctx->hwaccel_context) { - AVQSVContext *qsv = avctx->hwaccel_context; - int i, j; - -- q->extparam = av_calloc(qsv->nb_ext_buffers + q->nb_extparam_internal, -- sizeof(*q->extparam)); -- if (!q->extparam) -- return AVERROR(ENOMEM); -- -- q->param.ExtParam = q->extparam; -- for (i = 0; i < qsv->nb_ext_buffers; i++) -- q->param.ExtParam[i] = qsv->ext_buffers[i]; -- q->param.NumExtParam = qsv->nb_ext_buffers; -- -- for (i = 0; i < q->nb_extparam_internal; i++) { -- for (j = 0; j < qsv->nb_ext_buffers; j++) { -- if (qsv->ext_buffers[j]->BufferId == q->extparam_internal[i]->BufferId) -+ for (i = 0; i < qsv->nb_ext_buffers; i++) { -+ for (j = 0; j < q->nb_extparam_internal; j++) { -+ if (qsv->ext_buffers[i]->BufferId == q->extparam_internal[j]->BufferId) { -+ q->extparam[j] = qsv->ext_buffers[i]; - break; -+ } - } -- if (j < qsv->nb_ext_buffers) -- continue; - -- q->param.ExtParam[q->param.NumExtParam++] = q->extparam_internal[i]; -+ if (j == q->nb_extparam_internal) { -+ tmp = av_realloc_array(q->extparam, q->nb_extparam + 1, sizeof(*q->extparam)); -+ if (!tmp) -+ return AVERROR(ENOMEM); -+ -+ q->extparam = tmp; -+ q->extparam[q->nb_extparam++] = qsv->ext_buffers[i]; -+ } - } -- } else { -- q->param.ExtParam = q->extparam_internal; -- q->param.NumExtParam = q->nb_extparam_internal; - } - -+ q->param.ExtParam = q->extparam; -+ q->param.NumExtParam = q->nb_extparam; -+ -+#if HAVE_STRUCT_MFXCONFIGINTERFACE -+ ret = MFXVideoCORE_GetHandle(q->session, MFX_HANDLE_CONFIG_INTERFACE, (mfxHDL *)(&iface)); -+ if (ret < 0) -+ return ff_qsv_print_error(avctx, ret, -+ "Error getting mfx config interface handle"); -+ -+ while ((param = av_dict_get(q->qsv_params, "", param, AV_DICT_IGNORE_SUFFIX))) { -+ const char *param_key = param->key; -+ const char *param_value = param->value; -+ mfxExtBuffer *new_ext_buf; -+ void *tmp; -+ -+ av_log(avctx, AV_LOG_VERBOSE, "Parameter key: %s, value: %s\n", param_key, param_value); -+ -+ // Set encoding parameters using MFXSetParameter -+ for (int i = 0; i < 2; i++) { -+ ret = iface->SetParameter(iface, (mfxU8*)param_key, (mfxU8*)param_value, MFX_STRUCTURE_TYPE_VIDEO_PARAM, &q->param, &ext_buf); -+ if (ret == MFX_ERR_NONE) { -+ break; -+ } else if (i == 0 && ret == MFX_ERR_MORE_EXTBUFFER) { -+ tmp = av_realloc_array(q->extparam_str, q->nb_extparam_str + 1, sizeof(*q->extparam_str)); -+ if (!tmp) -+ return AVERROR(ENOMEM); -+ q->extparam_str = tmp; -+ -+ tmp = av_realloc_array(q->extparam, q->nb_extparam + 1, sizeof(*q->extparam)); -+ if (!tmp) -+ return AVERROR(ENOMEM); -+ q->extparam = tmp; -+ -+ new_ext_buf = (mfxExtBuffer*)av_mallocz(ext_buf.BufferSz); -+ if (!new_ext_buf) -+ return AVERROR(ENOMEM); -+ -+ new_ext_buf->BufferId = ext_buf.BufferId; -+ new_ext_buf->BufferSz = ext_buf.BufferSz; -+ q->extparam_str[q->nb_extparam_str++] = new_ext_buf; -+ q->extparam[q->nb_extparam++] = new_ext_buf; -+ q->param.ExtParam = q->extparam; -+ q->param.NumExtParam = q->nb_extparam; -+ } else { -+ av_log(avctx, AV_LOG_ERROR, "Failed to set parameter: %s\n", param_key); -+ return AVERROR_UNKNOWN; -+ } -+ } -+ } -+#else -+ if (q->qsv_params) { -+ av_log(avctx, AV_LOG_WARNING, "MFX string API is not supported, ignore qsv_params option\n"); -+ } -+#endif -+ - ret = MFXVideoENCODE_Query(q->session, &q->param, &q->param); - if (ret == MFX_WRN_PARTIAL_ACCELERATION) { - av_log(avctx, AV_LOG_WARNING, "Encoder will work with partial HW acceleration\n"); -@@ -2415,7 +2482,7 @@ static int encode_frame(AVCodecContext * - - if (frame->pict_type == AV_PICTURE_TYPE_I) { - enc_ctrl->FrameType = MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF; -- if (q->forced_idr) -+ if ((frame->flags & AV_FRAME_FLAG_KEY) || q->forced_idr) - enc_ctrl->FrameType |= MFX_FRAMETYPE_IDR; - } - } -@@ -2649,7 +2716,7 @@ int ff_qsv_enc_close(AVCodecContext *avc - ff_qsv_close_internal_session(&q->internal_qs); - - av_buffer_unref(&q->frames_ctx.hw_frames_ctx); -- av_buffer_unref(&q->frames_ctx.mids_buf); -+ ff_refstruct_unref(&q->frames_ctx.mids); - - cur = q->work_frames; - while (cur) { -@@ -2681,6 +2748,10 @@ int ff_qsv_enc_close(AVCodecContext *avc - av_buffer_unref(&q->opaque_alloc_buf); - #endif - -+ for (int i = 0; i < q->nb_extparam_str; i++) -+ av_free(q->extparam_str[i]); -+ -+ av_freep(&q->extparam_str); - av_freep(&q->extparam); - - return 0; -Index: FFmpeg/libavcodec/qsvenc.h -=================================================================== ---- FFmpeg.orig/libavcodec/qsvenc.h -+++ FFmpeg/libavcodec/qsvenc.h -@@ -64,7 +64,8 @@ - { "slower", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_2 }, INT_MIN, INT_MAX, VE, .unit = "preset" }, \ - { "veryslow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_QUALITY }, INT_MIN, INT_MAX, VE, .unit = "preset" }, \ - { "forced_idr", "Forcing I frames as IDR frames", OFFSET(qsv.forced_idr), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE }, \ --{ "low_power", "enable low power mode(experimental: many limitations by mfx version, BRC modes, etc.)", OFFSET(qsv.low_power), AV_OPT_TYPE_BOOL, { .i64 = -1}, -1, 1, VE}, -+{ "low_power", "enable low power mode(experimental: many limitations by mfx version, BRC modes, etc.)", OFFSET(qsv.low_power), AV_OPT_TYPE_BOOL, { .i64 = -1}, -1, 1, VE},\ -+{ "qsv_params", "Set QSV encoder parameters as key1=value1:key2=value2:...", OFFSET(qsv.qsv_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE }, - - #if QSV_HAVE_HE - #define QSV_HE_OPTIONS \ -@@ -195,7 +196,11 @@ typedef struct QSVEncContext { - mfxExtBuffer *extparam_internal[5 + (QSV_HAVE_MF * 2) + (QSV_HAVE_EXT_AV1_PARAM * 2) + QSV_HAVE_HE]; - int nb_extparam_internal; - -+ mfxExtBuffer **extparam_str; -+ int nb_extparam_str; -+ - mfxExtBuffer **extparam; -+ int nb_extparam; - - AVFifo *async_fifo; - -@@ -314,6 +319,8 @@ typedef struct QSVEncContext { - int skip_frame; - // This is used for Hyper Encode - int dual_gfx; -+ -+ AVDictionary *qsv_params; - } QSVEncContext; - - int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q); -Index: FFmpeg/libavcodec/qsvenc_av1.c -=================================================================== ---- FFmpeg.orig/libavcodec/qsvenc_av1.c -+++ FFmpeg/libavcodec/qsvenc_av1.c -@@ -25,6 +25,8 @@ - #include - - #include "libavutil/common.h" -+#include "libavutil/mastering_display_metadata.h" -+#include "libavutil/mem.h" - #include "libavutil/opt.h" - - #include "avcodec.h" -@@ -39,6 +41,75 @@ typedef struct QSVAV1EncContext { - QSVEncContext qsv; - } QSVAV1EncContext; - -+static int qsv_av1_set_encode_ctrl(AVCodecContext *avctx, -+ const AVFrame *frame, mfxEncodeCtrl *enc_ctrl) -+{ -+ QSVAV1EncContext *q = avctx->priv_data; -+ AVFrameSideData *sd; -+ -+ if (!frame || !QSV_RUNTIME_VERSION_ATLEAST(q->qsv.ver, 2, 11)) -+ return 0; -+ -+ sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); -+ if (sd) { -+ AVMasteringDisplayMetadata *mdm = (AVMasteringDisplayMetadata *)sd->data; -+ if (mdm->has_primaries && mdm->has_luminance) { -+ const int chroma_den = 1 << 16; -+ const int max_luma_den = 1 << 8; -+ const int min_luma_den = 1 << 14; -+ mfxExtMasteringDisplayColourVolume *mdcv = av_mallocz(sizeof(*mdcv)); -+ if (!mdcv) -+ return AVERROR(ENOMEM); -+ -+ mdcv->Header.BufferId = MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME; -+ mdcv->Header.BufferSz = sizeof(*mdcv); -+ -+ for (int i = 0; i < 3; i++) { -+ mdcv->DisplayPrimariesX[i] = -+ av_rescale(mdm->display_primaries[i][0].num, chroma_den, -+ mdm->display_primaries[i][0].den); -+ mdcv->DisplayPrimariesY[i] = -+ av_rescale(mdm->display_primaries[i][1].num, chroma_den, -+ mdm->display_primaries[i][1].den); -+ } -+ -+ mdcv->WhitePointX = -+ av_rescale(mdm->white_point[0].num, chroma_den, -+ mdm->white_point[0].den); -+ mdcv->WhitePointY = -+ av_rescale(mdm->white_point[1].num, chroma_den, -+ mdm->white_point[1].den); -+ -+ mdcv->MaxDisplayMasteringLuminance = -+ av_rescale(mdm->max_luminance.num, max_luma_den, -+ mdm->max_luminance.den); -+ mdcv->MinDisplayMasteringLuminance = -+ av_rescale(mdm->min_luminance.num, min_luma_den, -+ mdm->min_luminance.den); -+ -+ enc_ctrl->ExtParam[enc_ctrl->NumExtParam++] = (mfxExtBuffer *)mdcv; -+ } -+ } -+ -+ sd = av_frame_get_side_data(frame, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); -+ if (sd) { -+ AVContentLightMetadata *clm = (AVContentLightMetadata *)sd->data; -+ mfxExtContentLightLevelInfo *clli = av_mallocz(sizeof(*clli)); -+ if (!clli) -+ return AVERROR(ENOMEM); -+ -+ clli->Header.BufferId = MFX_EXTBUFF_CONTENT_LIGHT_LEVEL_INFO; -+ clli->Header.BufferSz = sizeof(*clli); -+ -+ clli->MaxContentLightLevel = clm->MaxCLL; -+ clli->MaxPicAverageLightLevel = clm->MaxFALL; -+ -+ enc_ctrl->ExtParam[enc_ctrl->NumExtParam++] = (mfxExtBuffer *)clli; -+ } -+ -+ return 0; -+} -+ - static av_cold int qsv_enc_init(AVCodecContext *avctx) - { - QSVAV1EncContext *q = avctx->priv_data; -@@ -61,6 +132,8 @@ static av_cold int qsv_enc_init(AVCodecC - return ret; - } - -+ q->qsv.set_encode_ctrl_cb = qsv_av1_set_encode_ctrl; -+ - return ff_qsv_enc_init(avctx, &q->qsv); - } - -Index: FFmpeg/libavfilter/qsvvpp.c -=================================================================== ---- FFmpeg.orig/libavfilter/qsvvpp.c -+++ FFmpeg/libavfilter/qsvvpp.c -@@ -307,7 +307,7 @@ static int fill_frameinfo_by_link(mfxFra - - frames_ctx = (AVHWFramesContext *)link->hw_frames_ctx->data; - frames_hwctx = frames_ctx->hwctx; -- *frameinfo = frames_hwctx->surfaces[0].Info; -+ *frameinfo = frames_hwctx->nb_surfaces ? frames_hwctx->surfaces[0].Info : *frames_hwctx->info; - } else { - pix_fmt = link->format; - desc = av_pix_fmt_desc_get(pix_fmt); -@@ -440,11 +440,6 @@ static QSVFrame *submit_frame(QSVVPPCont - av_frame_free(&qsv_frame->frame); - return NULL; - } -- -- if (av_frame_copy_props(qsv_frame->frame, picref) < 0) { -- av_frame_free(&qsv_frame->frame); -- return NULL; -- } - } else - qsv_frame->frame = av_frame_clone(picref); - -@@ -493,12 +488,6 @@ static QSVFrame *query_frame(QSVVPPConte - if (!out_frame->frame) - return NULL; - -- ret = av_frame_copy_props(out_frame->frame, in); -- if (ret < 0) { -- av_log(ctx, AV_LOG_ERROR, "Failed to copy metadata fields from src to dst.\n"); -- return NULL; -- } -- - ret = av_hwframe_get_buffer(outlink->hw_frames_ctx, out_frame->frame, 0); - if (ret < 0) { - av_log(ctx, AV_LOG_ERROR, "Can't allocate a surface.\n"); -@@ -515,12 +504,6 @@ static QSVFrame *query_frame(QSVVPPConte - if (!out_frame->frame) - return NULL; - -- ret = av_frame_copy_props(out_frame->frame, in); -- if (ret < 0) { -- av_log(ctx, AV_LOG_ERROR, "Failed to copy metadata fields from src to dst.\n"); -- return NULL; -- } -- - ret = map_frame_to_surface(out_frame->frame, - &out_frame->surface); - if (ret < 0) -@@ -603,6 +586,26 @@ static int init_vpp_session(AVFilterCont - device_ctx = (AVHWDeviceContext *)device_ref->data; - device_hwctx = device_ctx->hwctx; - -+ /* extract the properties of the "master" session given to us */ -+ ret = MFXQueryIMPL(device_hwctx->session, &impl); -+ if (ret == MFX_ERR_NONE) -+ ret = MFXQueryVersion(device_hwctx->session, &ver); -+ if (ret != MFX_ERR_NONE) { -+ av_log(avctx, AV_LOG_ERROR, "Error querying the session attributes\n"); -+ return AVERROR_UNKNOWN; -+ } -+ -+ if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) { -+ handle_type = MFX_HANDLE_VA_DISPLAY; -+ } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) { -+ handle_type = MFX_HANDLE_D3D11_DEVICE; -+ } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) { -+ handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER; -+ } else { -+ av_log(avctx, AV_LOG_ERROR, "Error unsupported handle type\n"); -+ return AVERROR_UNKNOWN; -+ } -+ - if (outlink->format == AV_PIX_FMT_QSV) { - AVHWFramesContext *out_frames_ctx; - AVBufferRef *out_frames_ref = av_hwframe_ctx_alloc(device_ref); -@@ -624,9 +627,15 @@ static int init_vpp_session(AVFilterCont - out_frames_ctx->width = FFALIGN(outlink->w, 32); - out_frames_ctx->height = FFALIGN(outlink->h, 32); - out_frames_ctx->sw_format = s->out_sw_format; -- out_frames_ctx->initial_pool_size = 64; -- if (avctx->extra_hw_frames > 0) -- out_frames_ctx->initial_pool_size += avctx->extra_hw_frames; -+ -+ if (QSV_RUNTIME_VERSION_ATLEAST(ver, 2, 9) && handle_type != MFX_HANDLE_D3D9_DEVICE_MANAGER) -+ out_frames_ctx->initial_pool_size = 0; -+ else { -+ out_frames_ctx->initial_pool_size = 64; -+ if (avctx->extra_hw_frames > 0) -+ out_frames_ctx->initial_pool_size += avctx->extra_hw_frames; -+ } -+ - out_frames_hwctx->frame_type = s->out_mem_mode; - - ret = av_hwframe_ctx_init(out_frames_ref); -@@ -652,26 +661,6 @@ static int init_vpp_session(AVFilterCont - } else - s->out_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY; - -- /* extract the properties of the "master" session given to us */ -- ret = MFXQueryIMPL(device_hwctx->session, &impl); -- if (ret == MFX_ERR_NONE) -- ret = MFXQueryVersion(device_hwctx->session, &ver); -- if (ret != MFX_ERR_NONE) { -- av_log(avctx, AV_LOG_ERROR, "Error querying the session attributes\n"); -- return AVERROR_UNKNOWN; -- } -- -- if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) { -- handle_type = MFX_HANDLE_VA_DISPLAY; -- } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) { -- handle_type = MFX_HANDLE_D3D11_DEVICE; -- } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) { -- handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER; -- } else { -- av_log(avctx, AV_LOG_ERROR, "Error unsupported handle type\n"); -- return AVERROR_UNKNOWN; -- } -- - ret = MFXVideoCORE_GetHandle(device_hwctx->session, handle_type, &handle); - if (ret < 0) - return ff_qsvvpp_print_error(avctx, ret, "Error getting the session handle"); -@@ -957,7 +946,7 @@ int ff_qsvvpp_close(AVFilterContext *avc - return 0; - } - --int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picref) -+int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picref, AVFrame *propref) - { - AVFilterContext *ctx = inlink->dst; - AVFilterLink *outlink = ctx->outputs[0]; -@@ -1014,6 +1003,16 @@ int ff_qsvvpp_filter_frame(QSVVPPContext - return AVERROR(EAGAIN); - break; - } -+ -+ if (propref) { -+ ret1 = av_frame_copy_props(out_frame->frame, propref); -+ if (ret1 < 0) { -+ av_frame_free(&out_frame->frame); -+ av_log(ctx, AV_LOG_ERROR, "Failed to copy metadata fields from src to dst.\n"); -+ return ret1; -+ } -+ } -+ - out_frame->frame->pts = av_rescale_q(out_frame->surface.Data.TimeStamp, - default_tb, outlink->time_base); - -@@ -1099,11 +1098,6 @@ int ff_qsvvpp_create_mfx_session(void *c - if (sts < 0) - return ff_qsvvpp_print_error(ctx, sts, - "Error creating a MFX session"); -- else if (sts > 0) { -- ff_qsvvpp_print_warning(ctx, sts, -- "Warning in MFX session creation"); -- return AVERROR_UNKNOWN; -- } - - *psession = session; - -Index: FFmpeg/libavfilter/qsvvpp.h -=================================================================== ---- FFmpeg.orig/libavfilter/qsvvpp.h -+++ FFmpeg/libavfilter/qsvvpp.h -@@ -131,7 +131,7 @@ int ff_qsvvpp_init(AVFilterContext *avct - int ff_qsvvpp_close(AVFilterContext *avctx); - - /* vpp filter frame and call the cb if needed */ --int ff_qsvvpp_filter_frame(QSVVPPContext *vpp, AVFilterLink *inlink, AVFrame *frame); -+int ff_qsvvpp_filter_frame(QSVVPPContext *vpp, AVFilterLink *inlink, AVFrame *frame, AVFrame *propref); - - int ff_qsvvpp_print_iopattern(void *log_ctx, int mfx_iopattern, - const char *extra_string); -Index: FFmpeg/libavfilter/vf_overlay_qsv.c -=================================================================== ---- FFmpeg.orig/libavfilter/vf_overlay_qsv.c -+++ FFmpeg/libavfilter/vf_overlay_qsv.c -@@ -230,13 +230,16 @@ static int process_frame(FFFrameSync *fs - { - AVFilterContext *ctx = fs->parent; - QSVVPPContext *qsv = fs->opaque; -- AVFrame *frame = NULL; -+ AVFrame *frame = NULL, *propref = NULL; - int ret = 0, i; - - for (i = 0; i < ctx->nb_inputs; i++) { - ret = ff_framesync_get_frame(fs, i, &frame, 0); -- if (ret == 0) -- ret = ff_qsvvpp_filter_frame(qsv, ctx->inputs[i], frame); -+ if (ret == 0) { -+ if (i == 0) -+ propref = frame; -+ ret = ff_qsvvpp_filter_frame(qsv, ctx->inputs[i], frame, propref); -+ } - if (ret < 0 && ret != AVERROR(EAGAIN)) - break; - } -Index: FFmpeg/libavfilter/vf_stack_qsv.c -=================================================================== ---- FFmpeg.orig/libavfilter/vf_stack_qsv.c -+++ FFmpeg/libavfilter/vf_stack_qsv.c -@@ -70,13 +70,16 @@ static int process_frame(FFFrameSync *fs - { - AVFilterContext *ctx = fs->parent; - QSVVPPContext *qsv = fs->opaque; -- AVFrame *frame = NULL; -+ AVFrame *frame = NULL, *propref = NULL; - int ret = 0; - - for (int i = 0; i < ctx->nb_inputs; i++) { - ret = ff_framesync_get_frame(fs, i, &frame, 0); -- if (ret == 0) -- ret = ff_qsvvpp_filter_frame(qsv, ctx->inputs[i], frame); -+ if (ret == 0) { -+ if (i == 0) -+ propref = frame; -+ ret = ff_qsvvpp_filter_frame(qsv, ctx->inputs[i], frame, propref); -+ } - if (ret < 0 && ret != AVERROR(EAGAIN)) - break; - } -Index: FFmpeg/libavfilter/vf_vpp_qsv.c -=================================================================== ---- FFmpeg.orig/libavfilter/vf_vpp_qsv.c -+++ FFmpeg/libavfilter/vf_vpp_qsv.c -@@ -748,7 +748,7 @@ static int activate(AVFilterContext *ctx - - if (qsv->session) { - if (in || qsv->eof) { -- ret = ff_qsvvpp_filter_frame(qsv, inlink, in); -+ ret = ff_qsvvpp_filter_frame(qsv, inlink, in, in); - av_frame_free(&in); - if (ret == AVERROR(EAGAIN)) - goto not_ready; -Index: FFmpeg/libavutil/hwcontext_qsv.c -=================================================================== ---- FFmpeg.orig/libavutil/hwcontext_qsv.c -+++ FFmpeg/libavutil/hwcontext_qsv.c -@@ -119,8 +119,15 @@ typedef struct QSVFramesContext { - #endif - AVFrame realigned_upload_frame; - AVFrame realigned_download_frame; -+ -+ mfxFrameInfo frame_info; - } QSVFramesContext; - -+typedef struct QSVSurface { -+ mfxFrameSurface1 mfx_surface; -+ AVFrame *child_frame; -+} QSVSurface; -+ - static const struct { - enum AVPixelFormat pix_fmt; - uint32_t fourcc; -@@ -166,6 +173,8 @@ extern int ff_qsv_get_surface_base_handl - enum AVHWDeviceType base_dev_type, - void **base_handle); - -+static int qsv_init_surface(AVHWFramesContext *ctx, mfxFrameSurface1 *surf); -+ - /** - * Caller needs to allocate enough space for base_handle pointer. - **/ -@@ -374,7 +383,32 @@ static void qsv_release_dummy(void *opaq - { - } - --static AVBufferRef *qsv_pool_alloc(void *opaque, size_t size) -+static void qsv_pool_release(void *opaque, uint8_t *data) -+{ -+ AVHWFramesContext *ctx = (AVHWFramesContext*)opaque; -+ QSVFramesContext *s = ctx->hwctx; -+ QSVSurface *qsv_surface = (QSVSurface *)data; -+ mfxHDLPair *hdl_pair = (mfxHDLPair *)qsv_surface->mfx_surface.Data.MemId; -+ AVHWFramesContext *child_frames_ctx; -+ -+ if (!s->child_frames_ref) -+ return; -+ -+ child_frames_ctx = (AVHWFramesContext*)s->child_frames_ref->data; -+ if (!child_frames_ctx->device_ctx) -+ return; -+ -+#if CONFIG_VAAPI -+ if (child_frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_VAAPI) -+ av_freep(&hdl_pair->first); -+#endif -+ -+ av_freep(&hdl_pair); -+ av_frame_free(&qsv_surface->child_frame); -+ av_freep(&qsv_surface); -+} -+ -+static AVBufferRef *qsv_fixed_pool_alloc(void *opaque, size_t size) - { - AVHWFramesContext *ctx = (AVHWFramesContext*)opaque; - QSVFramesContext *s = ctx->hwctx; -@@ -389,6 +423,104 @@ static AVBufferRef *qsv_pool_alloc(void - return NULL; - } - -+static AVBufferRef *qsv_dynamic_pool_alloc(void *opaque, size_t size) -+{ -+ AVHWFramesContext *ctx = (AVHWFramesContext*)opaque; -+ QSVFramesContext *s = ctx->hwctx; -+ AVHWFramesContext *child_frames_ctx; -+ QSVSurface *qsv_surface = NULL; -+ mfxHDLPair *handle_pairs_internal = NULL; -+ int ret; -+ -+ if (!s->child_frames_ref) -+ goto fail; -+ -+ child_frames_ctx = (AVHWFramesContext*)s->child_frames_ref->data; -+ if (!child_frames_ctx->device_ctx) -+ goto fail; -+ -+#if CONFIG_DXVA2 -+ if (child_frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) { -+ av_log(ctx, AV_LOG_ERROR, -+ "QSV on dxva2 requires a fixed frame pool size\n"); -+ goto fail; -+ } -+#endif -+ -+ qsv_surface = av_calloc(1, sizeof(*qsv_surface)); -+ if (!qsv_surface) -+ goto fail; -+ -+ qsv_surface->child_frame = av_frame_alloc(); -+ if (!qsv_surface->child_frame) -+ goto fail; -+ -+ ret = av_hwframe_get_buffer(s->child_frames_ref, qsv_surface->child_frame, 0); -+ if (ret < 0) -+ goto fail; -+ -+ handle_pairs_internal = av_calloc(1, sizeof(*handle_pairs_internal)); -+ if (!handle_pairs_internal) -+ goto fail; -+ -+ ret = qsv_init_surface(ctx, &qsv_surface->mfx_surface); -+ if (ret < 0) -+ goto fail; -+ -+#if CONFIG_VAAPI -+ if (child_frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_VAAPI) { -+ VASurfaceID *surface_id_internal; -+ -+ surface_id_internal = av_calloc(1, sizeof(*surface_id_internal)); -+ if (!surface_id_internal) -+ goto fail; -+ -+ *surface_id_internal = (VASurfaceID)(uintptr_t)qsv_surface->child_frame->data[3]; -+ handle_pairs_internal->first = (mfxHDL)surface_id_internal; -+ handle_pairs_internal->second = (mfxMemId)MFX_INFINITE; -+ } -+#endif -+ -+#if CONFIG_D3D11VA -+ if (child_frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { -+ AVD3D11VAFramesContext *child_frames_hwctx = child_frames_ctx->hwctx; -+ handle_pairs_internal->first = (mfxMemId)qsv_surface->child_frame->data[0]; -+ -+ if (child_frames_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) -+ handle_pairs_internal->second = (mfxMemId)MFX_INFINITE; -+ else -+ handle_pairs_internal->second = (mfxMemId)qsv_surface->child_frame->data[1]; -+ -+ } -+#endif -+ -+ qsv_surface->mfx_surface.Data.MemId = (mfxMemId)handle_pairs_internal; -+ return av_buffer_create((uint8_t *)qsv_surface, sizeof(*qsv_surface), -+ qsv_pool_release, ctx, 0); -+ -+fail: -+ if (qsv_surface) { -+ av_frame_free(&qsv_surface->child_frame); -+ } -+ -+ av_freep(&qsv_surface); -+ av_freep(&handle_pairs_internal); -+ -+ return NULL; -+} -+ -+static AVBufferRef *qsv_pool_alloc(void *opaque, size_t size) -+{ -+ AVHWFramesContext *ctx = (AVHWFramesContext*)opaque; -+ AVQSVFramesContext *hwctx = ctx->hwctx; -+ -+ if (hwctx->nb_surfaces == 0) { -+ return qsv_dynamic_pool_alloc(opaque, size); -+ } else { -+ return qsv_fixed_pool_alloc(opaque, size); -+ } -+} -+ - static int qsv_init_child_ctx(AVHWFramesContext *ctx) - { - QSVDeviceContext *device_priv = ctx->device_ctx->hwctx; -@@ -577,9 +709,28 @@ static int qsv_init_pool(AVHWFramesConte - - int i, ret = 0; - -- if (ctx->initial_pool_size <= 0) { -- av_log(ctx, AV_LOG_ERROR, "QSV requires a fixed frame pool size\n"); -+ if (ctx->initial_pool_size < 0) { -+ av_log(ctx, AV_LOG_ERROR, "Invalid frame pool size\n"); - return AVERROR(EINVAL); -+ } else if (ctx->initial_pool_size == 0) { -+ mfxFrameSurface1 mfx_surf1; -+ -+ ret = qsv_init_child_ctx(ctx); -+ if (ret < 0) -+ return ret; -+ -+ ffhwframesctx(ctx)->pool_internal = av_buffer_pool_init2(sizeof(mfxFrameSurface1), -+ ctx, qsv_pool_alloc, NULL); -+ if (!ffhwframesctx(ctx)->pool_internal) -+ return AVERROR(ENOMEM); -+ -+ memset(&mfx_surf1, 0, sizeof(mfx_surf1)); -+ qsv_init_surface(ctx, &mfx_surf1); -+ s->frame_info = mfx_surf1.Info; -+ frames_hwctx->info = &s->frame_info; -+ frames_hwctx->nb_surfaces = 0; -+ -+ return 0; - } - - s->handle_pairs_internal = av_calloc(ctx->initial_pool_size, -@@ -628,7 +779,7 @@ static mfxStatus frame_alloc(mfxHDL pthi - QSVFramesContext *s = ctx->hwctx; - AVQSVFramesContext *hwctx = &s->p; - mfxFrameInfo *i = &req->Info; -- mfxFrameInfo *i1 = &hwctx->surfaces[0].Info; -+ mfxFrameInfo *i1 = hwctx->nb_surfaces ? &hwctx->surfaces[0].Info : hwctx->info; - - if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) || - !(req->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) || -@@ -1223,7 +1374,7 @@ static int qsv_init_internal_session(AVH - MFX_IOPATTERN_OUT_SYSTEM_MEMORY; - par.AsyncDepth = 1; - -- par.vpp.In = frames_hwctx->surfaces[0].Info; -+ par.vpp.In = frames_hwctx->nb_surfaces ? frames_hwctx->surfaces[0].Info : *frames_hwctx->info; - - /* Apparently VPP requires the frame rate to be set to some value, otherwise - * init will fail (probably for the framerate conversion filter). Since we -@@ -1398,8 +1549,11 @@ static int qsv_frames_derive_from(AVHWFr - dst_hwctx->texture_infos[i].texture = (ID3D11Texture2D*)pair->first; - dst_hwctx->texture_infos[i].index = pair->second == (mfxMemId)MFX_INFINITE ? (intptr_t)0 : (intptr_t)pair->second; - } -- ID3D11Texture2D_GetDesc(dst_hwctx->texture_infos[0].texture, &texDesc); -- dst_hwctx->BindFlags = texDesc.BindFlags; -+ if (src_hwctx->nb_surfaces) { -+ ID3D11Texture2D_GetDesc(dst_hwctx->texture_infos[0].texture, &texDesc); -+ dst_hwctx->BindFlags = texDesc.BindFlags; -+ } else -+ dst_hwctx->BindFlags = qsv_get_d3d11va_bind_flags(src_hwctx->frame_type); - } - break; - #endif -@@ -1838,18 +1992,52 @@ static int qsv_transfer_data_to(AVHWFram - return 0; - } - --static int qsv_frames_derive_to(AVHWFramesContext *dst_ctx, -- AVHWFramesContext *src_ctx, int flags) -+static int qsv_dynamic_frames_derive_to(AVHWFramesContext *dst_ctx, -+ AVHWFramesContext *src_ctx, int flags) - { - QSVFramesContext *s = dst_ctx->hwctx; - AVQSVFramesContext *dst_hwctx = &s->p; -- int i; -+ mfxFrameSurface1 mfx_surf1; - -- if (src_ctx->initial_pool_size == 0) { -- av_log(dst_ctx, AV_LOG_ERROR, "Only fixed-size pools can be " -- "mapped to QSV frames.\n"); -- return AVERROR(EINVAL); -+ switch (src_ctx->device_ctx->type) { -+#if CONFIG_VAAPI -+ case AV_HWDEVICE_TYPE_VAAPI: -+ dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; -+ break; -+#endif -+ -+#if CONFIG_D3D11VA -+ case AV_HWDEVICE_TYPE_D3D11VA: -+ { -+ AVD3D11VAFramesContext *src_hwctx = src_ctx->hwctx; -+ -+ if (src_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) { -+ dst_hwctx->frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET; -+ } else { -+ dst_hwctx->frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; -+ } - } -+ break; -+#endif -+ -+ default: -+ return AVERROR(ENOSYS); -+ } -+ -+ memset(&mfx_surf1, 0, sizeof(mfx_surf1)); -+ qsv_init_surface(dst_ctx, &mfx_surf1); -+ s->frame_info = mfx_surf1.Info; -+ dst_hwctx->info = &s->frame_info; -+ dst_hwctx->nb_surfaces = 0; -+ return 0; -+} -+ -+static int qsv_fixed_frames_derive_to(AVHWFramesContext *dst_ctx, -+ AVHWFramesContext *src_ctx, int flags) -+{ -+ QSVFramesContext *s = dst_ctx->hwctx; -+ AVQSVFramesContext *dst_hwctx = &s->p; -+ int i; - - switch (src_ctx->device_ctx->type) { - #if CONFIG_VAAPI -@@ -1941,8 +2129,21 @@ static int qsv_frames_derive_to(AVHWFram - return 0; - } - --static int qsv_map_to(AVHWFramesContext *dst_ctx, -- AVFrame *dst, const AVFrame *src, int flags) -+static int qsv_frames_derive_to(AVHWFramesContext *dst_ctx, -+ AVHWFramesContext *src_ctx, int flags) -+{ -+ if (src_ctx->initial_pool_size < 0) { -+ av_log(dst_ctx, AV_LOG_ERROR, "Invalid src frame pool. \n"); -+ return AVERROR(EINVAL); -+ } else if (src_ctx->initial_pool_size == 0) { -+ return qsv_dynamic_frames_derive_to(dst_ctx, src_ctx, flags); -+ } else { -+ return qsv_fixed_frames_derive_to(dst_ctx, src_ctx, flags); -+ } -+} -+ -+static int qsv_fixed_pool_map_to(AVHWFramesContext *dst_ctx, -+ AVFrame *dst, const AVFrame *src, int flags) - { - AVQSVFramesContext *hwctx = dst_ctx->hwctx; - int i, err, index = -1; -@@ -2001,6 +2202,133 @@ static int qsv_map_to(AVHWFramesContext - return 0; - } - -+static void qsv_dynamic_pool_unmap(AVHWFramesContext *ctx, HWMapDescriptor *hwmap) -+{ -+ mfxFrameSurface1 *surfaces_internal = (mfxFrameSurface1 *)hwmap->priv; -+ mfxHDLPair *handle_pairs_internal = (mfxHDLPair *)surfaces_internal->Data.MemId; -+ AVHWFramesContext *src_ctx = (AVHWFramesContext *)ffhwframesctx(ctx)->source_frames->data; -+ -+ switch (src_ctx->format) { -+#if CONFIG_VAAPI -+ case AV_PIX_FMT_VAAPI: -+ { -+ av_freep(&handle_pairs_internal->first); -+ -+ break; -+ } -+#endif -+ -+#if CONFIG_D3D11VA -+ case AV_PIX_FMT_D3D11: -+ { -+ /* Do nothing */ -+ break; -+ } -+#endif -+ default: -+ av_log(ctx, AV_LOG_ERROR, "Should not reach here. \n"); -+ break; -+ } -+ -+ av_freep(&handle_pairs_internal); -+ av_freep(&surfaces_internal); -+} -+ -+static int qsv_dynamic_pool_map_to(AVHWFramesContext *dst_ctx, -+ AVFrame *dst, const AVFrame *src, int flags) -+{ -+ mfxFrameSurface1 *surfaces_internal = NULL; -+ mfxHDLPair *handle_pairs_internal = NULL; -+ int ret = 0; -+ -+ surfaces_internal = av_calloc(1, sizeof(*surfaces_internal)); -+ if (!surfaces_internal) { -+ ret = AVERROR(ENOMEM); -+ goto fail; -+ } -+ -+ handle_pairs_internal = av_calloc(1, sizeof(*handle_pairs_internal)); -+ if (!handle_pairs_internal) { -+ ret = AVERROR(ENOMEM); -+ goto fail; -+ } -+ -+ ret = qsv_init_surface(dst_ctx, surfaces_internal); -+ if (ret < 0) -+ goto fail; -+ -+ switch (src->format) { -+#if CONFIG_VAAPI -+ case AV_PIX_FMT_VAAPI: -+ { -+ VASurfaceID *surface_id_internal; -+ -+ surface_id_internal = av_calloc(1, sizeof(*surface_id_internal)); -+ if (!surface_id_internal) { -+ ret =AVERROR(ENOMEM); -+ goto fail; -+ } -+ -+ *surface_id_internal = (VASurfaceID)(uintptr_t)src->data[3]; -+ handle_pairs_internal->first = (mfxHDL)surface_id_internal; -+ handle_pairs_internal->second = (mfxMemId)MFX_INFINITE; -+ -+ break; -+ } -+#endif -+ -+#if CONFIG_D3D11VA -+ case AV_PIX_FMT_D3D11: -+ { -+ AVHWFramesContext *src_ctx = (AVHWFramesContext*)src->hw_frames_ctx->data; -+ AVD3D11VAFramesContext *src_hwctx = src_ctx->hwctx; -+ -+ handle_pairs_internal->first = (mfxMemId)src->data[0]; -+ -+ if (src_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) { -+ handle_pairs_internal->second = (mfxMemId)MFX_INFINITE; -+ } else { -+ handle_pairs_internal->second = (mfxMemId)src->data[1]; -+ } -+ -+ break; -+ } -+#endif -+ default: -+ ret = AVERROR(ENOSYS); -+ goto fail; -+ } -+ -+ surfaces_internal->Data.MemId = (mfxMemId)handle_pairs_internal; -+ -+ ret = ff_hwframe_map_create(dst->hw_frames_ctx, -+ dst, src, qsv_dynamic_pool_unmap, surfaces_internal); -+ if (ret) -+ goto fail; -+ -+ dst->width = src->width; -+ dst->height = src->height; -+ dst->data[3] = (uint8_t*)surfaces_internal; -+ -+ return 0; -+ -+fail: -+ av_freep(&handle_pairs_internal); -+ av_freep(&surfaces_internal); -+ return ret; -+} -+ -+static int qsv_map_to(AVHWFramesContext *dst_ctx, -+ AVFrame *dst, const AVFrame *src, int flags) -+{ -+ AVQSVFramesContext *hwctx = dst_ctx->hwctx; -+ -+ if (hwctx->nb_surfaces) -+ return qsv_fixed_pool_map_to(dst_ctx, dst, src, flags); -+ else -+ return qsv_dynamic_pool_map_to(dst_ctx, dst, src, flags); -+} -+ - static int qsv_frames_get_constraints(AVHWDeviceContext *ctx, - const void *hwconfig, - AVHWFramesConstraints *constraints) -Index: FFmpeg/libavutil/hwcontext_qsv.h -=================================================================== ---- FFmpeg.orig/libavutil/hwcontext_qsv.h -+++ FFmpeg/libavutil/hwcontext_qsv.h -@@ -25,8 +25,8 @@ - * @file - * An API-specific header for AV_HWDEVICE_TYPE_QSV. - * -- * This API does not support dynamic frame pools. AVHWFramesContext.pool must -- * contain AVBufferRefs whose data pointer points to an mfxFrameSurface1 struct. -+ * AVHWFramesContext.pool must contain AVBufferRefs whose data pointer points -+ * to a mfxFrameSurface1 struct. - */ - - /** -@@ -51,13 +51,36 @@ typedef struct AVQSVDeviceContext { - * This struct is allocated as AVHWFramesContext.hwctx - */ - typedef struct AVQSVFramesContext { -+ /** -+ * A pointer to a mfxFrameSurface1 struct -+ * -+ * It is available when nb_surfaces is non-zero. -+ */ - mfxFrameSurface1 *surfaces; -+ -+ /** -+ * Number of frames in the pool -+ * -+ * It is 0 for dynamic frame pools or AVHWFramesContext.initial_pool_size -+ * for fixed frame pools. -+ * -+ * Note only oneVPL GPU runtime 2.9+ can support dynamic frame pools -+ * on d3d11va or vaapi -+ */ - int nb_surfaces; - - /** - * A combination of MFX_MEMTYPE_* describing the frame pool. - */ - int frame_type; -+ -+ /** -+ * A pointer to a mfxFrameInfo struct -+ * -+ * It is available when nb_surfaces is 0, all buffers allocated from the -+ * pool have the same mfxFrameInfo. -+ */ -+ mfxFrameInfo *info; - } AVQSVFramesContext; - - #endif /* AVUTIL_HWCONTEXT_QSV_H */ diff --git a/debian/patches/0021-add-fixes-for-qsv-vpp-filters.patch b/debian/patches/0020-add-fixes-for-qsv-vpp-filters.patch similarity index 74% rename from debian/patches/0021-add-fixes-for-qsv-vpp-filters.patch rename to debian/patches/0020-add-fixes-for-qsv-vpp-filters.patch index 96d71cde5..879eff6d3 100644 --- a/debian/patches/0021-add-fixes-for-qsv-vpp-filters.patch +++ b/debian/patches/0020-add-fixes-for-qsv-vpp-filters.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavfilter/qsvvpp.c =================================================================== --- FFmpeg.orig/libavfilter/qsvvpp.c +++ FFmpeg/libavfilter/qsvvpp.c -@@ -167,7 +167,7 @@ int ff_qsvvpp_print_warning(void *log_ct +@@ -168,7 +168,7 @@ int ff_qsvvpp_print_warning(void *log_ct const char *desc; int ret; ret = qsv_map_error(err, &desc); @@ -11,7 +11,7 @@ Index: FFmpeg/libavfilter/qsvvpp.c return ret; } -@@ -458,8 +458,12 @@ static QSVFrame *submit_frame(QSVVPPCont +@@ -460,8 +460,12 @@ static QSVFrame *submit_frame(QSVVPPCont !(qsv_frame->frame->flags & AV_FRAME_FLAG_INTERLACED) ? MFX_PICSTRUCT_PROGRESSIVE : ((qsv_frame->frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? MFX_PICSTRUCT_FIELD_TFF : MFX_PICSTRUCT_FIELD_BFF); @@ -25,51 +25,27 @@ Index: FFmpeg/libavfilter/qsvvpp.c else if (qsv_frame->frame->repeat_pict == 2) qsv_frame->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING; else if (qsv_frame->frame->repeat_pict == 4) -@@ -986,6 +990,23 @@ int ff_qsvvpp_filter_frame(QSVVPPContext - return AVERROR(ENOMEM); - } +@@ -913,8 +917,13 @@ static int qsvvpp_init_vpp_session(AVFil -+ /* Copy metadata before initializing vpp session, -+ * which contains callback to drop the HDR metadata */ -+ if (propref) { -+ int flags = out_frame->frame->flags; -+ int64_t duration = out_frame->frame->duration; -+ -+ ret1 = av_frame_copy_props(out_frame->frame, propref); -+ if (ret1 < 0) { -+ av_frame_free(&out_frame->frame); -+ av_log(ctx, AV_LOG_ERROR, "Failed to copy metadata fields from src to dst.\n"); -+ return ret1; -+ } -+ -+ out_frame->frame->flags = flags; -+ out_frame->frame->duration = duration; + /* Query VPP params again, including params for frame */ + ret = MFXVideoVPP_Query(s->session, &s->vpp_param, &s->vpp_param); +- if (ret < 0) +- return ff_qsvvpp_print_error(avctx, ret, "Error querying VPP params"); ++ if (ret < 0) { ++ /* Wa a PicStruct validation issue in VPL/MSDK RT */ ++ if (s->vpp_param.vpp.In.PicStruct != in->surface.Info.PicStruct) ++ s->vpp_param.vpp.In.PicStruct = in->surface.Info.PicStruct; ++ else ++ return ff_qsvvpp_print_error(avctx, ret, "Error querying VPP params"); + } -+ - ret = qsvvpp_init_vpp_session(ctx, s, in_frame, out_frame); - if (ret) - return ret; -@@ -1004,15 +1025,6 @@ int ff_qsvvpp_filter_frame(QSVVPPContext - break; - } - -- if (propref) { -- ret1 = av_frame_copy_props(out_frame->frame, propref); -- if (ret1 < 0) { -- av_frame_free(&out_frame->frame); -- av_log(ctx, AV_LOG_ERROR, "Failed to copy metadata fields from src to dst.\n"); -- return ret1; -- } -- } -- - out_frame->frame->pts = av_rescale_q(out_frame->surface.Data.TimeStamp, - default_tb, outlink->time_base); + else if (ret > 0) + ff_qsvvpp_print_warning(avctx, ret, "Warning When querying VPP params"); Index: FFmpeg/libavfilter/vf_overlay_qsv.c =================================================================== --- FFmpeg.orig/libavfilter/vf_overlay_qsv.c +++ FFmpeg/libavfilter/vf_overlay_qsv.c -@@ -228,43 +228,47 @@ static int config_overlay_input(AVFilter +@@ -227,43 +227,47 @@ static int config_overlay_input(AVFilter static int process_frame(FFFrameSync *fs) { @@ -145,11 +121,19 @@ Index: FFmpeg/libavfilter/vf_overlay_qsv.c return ff_framesync_configure(&s->fs); } -@@ -285,12 +289,6 @@ static int config_output(AVFilterLink *o +@@ -275,7 +279,6 @@ static int config_output(AVFilterLink *o + AVFilterLink *in0 = ctx->inputs[0]; + AVFilterLink *in1 = ctx->inputs[1]; + FilterLink *l0 = ff_filter_link(in0); +- FilterLink *l1 = ff_filter_link(in1); + FilterLink *ol = ff_filter_link(outlink); + int ret; + +@@ -287,12 +290,6 @@ static int config_output(AVFilterLink *o return AVERROR(EINVAL); } else if (in0->format == AV_PIX_FMT_QSV) { - AVHWFramesContext *hw_frame0 = (AVHWFramesContext *)in0->hw_frames_ctx->data; -- AVHWFramesContext *hw_frame1 = (AVHWFramesContext *)in1->hw_frames_ctx->data; + AVHWFramesContext *hw_frame0 = (AVHWFramesContext *)l0->hw_frames_ctx->data; +- AVHWFramesContext *hw_frame1 = (AVHWFramesContext *)l1->hw_frames_ctx->data; - - if (hw_frame0->device_ctx != hw_frame1->device_ctx) { - av_log(ctx, AV_LOG_ERROR, "Inputs with different underlying QSV devices are forbidden.\n"); @@ -158,7 +142,7 @@ Index: FFmpeg/libavfilter/vf_overlay_qsv.c vpp->qsv_param.out_sw_format = hw_frame0->sw_format; } -@@ -372,6 +370,7 @@ static int overlay_qsv_query_formats(AVF +@@ -374,6 +371,7 @@ static int overlay_qsv_query_formats(AVF static const enum AVPixelFormat main_in_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NV12, @@ -166,7 +150,7 @@ Index: FFmpeg/libavfilter/vf_overlay_qsv.c AV_PIX_FMT_YUYV422, AV_PIX_FMT_RGB32, AV_PIX_FMT_QSV, -@@ -379,6 +378,7 @@ static int overlay_qsv_query_formats(AVF +@@ -381,6 +379,7 @@ static int overlay_qsv_query_formats(AVF }; static const enum AVPixelFormat out_pix_fmts[] = { AV_PIX_FMT_NV12, @@ -184,13 +168,13 @@ Index: FFmpeg/libavfilter/vf_vpp_qsv.c +static mfxStatus get_mfx_platform(const AVFilterContext *ctx, mfxPlatform *mfx_platform) +{ -+ const AVFilterLink *inlink = ctx->inputs[0]; ++ const FilterLink *l = ff_filter_link(ctx->inputs[0]); + AVBufferRef *device_ref; + AVHWDeviceContext *device_ctx; + AVQSVDeviceContext *device_hwctx; + -+ if (inlink->hw_frames_ctx) { -+ AVHWFramesContext *frames_ctx = (AVHWFramesContext *)inlink->hw_frames_ctx->data; ++ if (l->hw_frames_ctx) { ++ AVHWFramesContext *frames_ctx = (AVHWFramesContext *)l->hw_frames_ctx->data; + device_ref = frames_ctx->device_ref; + } else if (ctx->hw_device_ctx) { + device_ref = ctx->hw_device_ctx; @@ -249,7 +233,7 @@ Index: FFmpeg/libavfilter/vf_vpp_qsv.c outvsi_conf.ColourDescriptionPresent = 1; if (memcmp(&vpp->invsi_conf, &invsi_conf, sizeof(mfxExtVideoSignalInfo)) || -@@ -686,12 +715,24 @@ static int config_output(AVFilterLink *o +@@ -689,12 +718,23 @@ static int config_output(AVFilterLink *o if (inlink->w != outlink->w || inlink->h != outlink->h || in_format != vpp->out_format) { if (QSV_RUNTIME_VERSION_ATLEAST(mfx_version, 1, 19)) { @@ -267,7 +251,6 @@ Index: FFmpeg/libavfilter/vf_vpp_qsv.c + int code_name = mfx_platform.CodeName; + compute = code_name >= 45 && + code_name <= 54 && -+ code_name != 55 && + code_name != 50; + } + @@ -278,7 +261,7 @@ Index: FFmpeg/libavfilter/vf_vpp_qsv.c INIT_MFX_EXTBUF(scale_conf, MFX_EXTBUFF_VPP_SCALING); SET_MFX_PARAM_FIELD(scale_conf, ScalingMode, mode); -@@ -880,19 +921,13 @@ static const AVOption vpp_options[] = { +@@ -884,19 +924,13 @@ static const AVOption vpp_options[] = { { "height", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, { "format", "Output pixel format", OFFSET(output_format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = 4 }, 0, INT_MAX, .flags = FLAGS }, @@ -299,7 +282,7 @@ Index: FFmpeg/libavfilter/vf_vpp_qsv.c { "rate", "Generate output at frame rate or field rate, available only for deinterlace mode", OFFSET(field_rate), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, .unit = "rate" }, -@@ -923,8 +958,9 @@ static const AVOption vpp_options[] = { +@@ -927,8 +961,9 @@ static const AVOption vpp_options[] = { { "out_color_transfer", "Output color transfer characteristics", OFFSET(color_transfer_str), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, @@ -310,7 +293,7 @@ Index: FFmpeg/libavfilter/vf_vpp_qsv.c { NULL } }; -@@ -978,19 +1014,14 @@ static const AVOption qsvscale_options[] +@@ -982,19 +1017,14 @@ static const AVOption qsvscale_options[] { "h", "Output video height(0=input video height, -1=keep input video aspect)", OFFSET(oh), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS }, { "format", "Output pixel format", OFFSET(output_format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, @@ -332,7 +315,7 @@ Index: FFmpeg/libavfilter/vf_vpp_qsv.c { NULL }, }; -@@ -1015,6 +1046,7 @@ static const AVOption qsvdeint_options[] +@@ -1019,6 +1049,7 @@ static const AVOption qsvdeint_options[] { "bob", "bob algorithm", 0, AV_OPT_TYPE_CONST, {.i64 = MFX_DEINTERLACING_BOB}, MFX_DEINTERLACING_BOB, MFX_DEINTERLACING_ADVANCED, FLAGS, .unit = "mode"}, { "advanced", "Motion adaptive algorithm", 0, AV_OPT_TYPE_CONST, {.i64 = MFX_DEINTERLACING_ADVANCED}, MFX_DEINTERLACING_BOB, MFX_DEINTERLACING_ADVANCED, FLAGS, .unit = "mode"}, @@ -340,3 +323,89 @@ Index: FFmpeg/libavfilter/vf_vpp_qsv.c { NULL }, }; +Index: FFmpeg/libavutil/hwcontext_qsv.c +=================================================================== +--- FFmpeg.orig/libavutil/hwcontext_qsv.c ++++ FFmpeg/libavutil/hwcontext_qsv.c +@@ -1706,13 +1706,47 @@ static int qsv_transfer_data_child(AVHWF + dummy->width = src->width; + dummy->height = src->height; + dummy->buf[0] = download ? src->buf[0] : dst->buf[0]; +- dummy->data[3] = surf->Data.MemId; + dummy->hw_frames_ctx = s->child_frames_ref; + ++ switch (child_frames_ctx->device_ctx->type) { ++#if CONFIG_VAAPI ++ case AV_HWDEVICE_TYPE_VAAPI: ++ { ++ mfxHDLPair *pair = (mfxHDLPair *)surf->Data.MemId; ++ dummy->data[3] = (uint8_t *)(intptr_t)*(VASurfaceID *)pair->first; ++ break; ++ } ++#endif ++#if CONFIG_D3D11VA ++ case AV_HWDEVICE_TYPE_D3D11VA: ++ { ++ mfxHDLPair *pair = (mfxHDLPair *)surf->Data.MemId; ++ dummy->data[0] = (uint8_t *)pair->first; ++ dummy->data[1] = pair->second == (mfxMemId)MFX_INFINITE ? ++ (uint8_t *)0 : (uint8_t *)pair->second; ++ break; ++ } ++#endif ++#if CONFIG_DXVA2 ++ case AV_HWDEVICE_TYPE_DXVA2: ++ { ++ mfxHDLPair *pair = (mfxHDLPair *)surf->Data.MemId; ++ dummy->data[3] = (uint8_t *)pair->first; ++ break; ++ } ++#endif ++ default: ++ ret = AVERROR(ENOSYS); ++ goto exit; ++ } ++ + ret = download ? av_hwframe_transfer_data(dst, dummy, 0) : + av_hwframe_transfer_data(dummy, src, 0); + ++exit: + dummy->buf[0] = NULL; ++ dummy->data[0] = NULL; ++ dummy->data[1] = NULL; + dummy->data[3] = NULL; + dummy->hw_frames_ctx = NULL; + +@@ -1902,6 +1936,9 @@ static int qsv_transfer_data_from(AVHWFr + static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, + const AVFrame *src) + { ++#if CONFIG_D3D11VA ++ QSVDeviceContext *device_priv = ctx->device_ctx->hwctx; ++#endif + QSVFramesContext *s = ctx->hwctx; + mfxFrameSurface1 in = {{ 0 }}; + mfxFrameSurface1 *out = (mfxFrameSurface1*)dst->data[3]; +@@ -1954,9 +1991,20 @@ static int qsv_transfer_data_to(AVHWFram + + src_frame = realigned ? tmp_frame : src; + +- if (!s->session_upload) { +- if (s->child_frames_ref) ++ if (!s->session_upload ++#if CONFIG_D3D11VA /* Wa an out of sync issue in MSDK RT on Windows */ ++ || ((src_frame->format == AV_PIX_FMT_BGRA) && ++ !QSV_RUNTIME_VERSION_ATLEAST(device_priv->ver, 1, 255) && ++ (device_priv->handle_type == MFX_HANDLE_D3D11_DEVICE)) ++#endif ++ ) { ++ if (s->child_frames_ref) { ++ if (realigned) { ++ out->Info.CropW = tmp_info.CropW; ++ out->Info.CropH = tmp_info.CropH; ++ } + return qsv_transfer_data_child(ctx, dst, src_frame); ++ } + + av_log(ctx, AV_LOG_ERROR, "Surface upload not possible\n"); + return AVERROR(ENOSYS); diff --git a/debian/patches/0022-add-external-frame-support-for-qsv-enc.patch b/debian/patches/0021-add-external-frame-support-for-qsv-enc.patch similarity index 100% rename from debian/patches/0022-add-external-frame-support-for-qsv-enc.patch rename to debian/patches/0021-add-external-frame-support-for-qsv-enc.patch diff --git a/debian/patches/0023-suppress-overlay-warning-logs.patch b/debian/patches/0022-suppress-overlay-warning-logs.patch similarity index 94% rename from debian/patches/0023-suppress-overlay-warning-logs.patch rename to debian/patches/0022-suppress-overlay-warning-logs.patch index 86e41fa24..0703edf79 100644 --- a/debian/patches/0023-suppress-overlay-warning-logs.patch +++ b/debian/patches/0022-suppress-overlay-warning-logs.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavfilter/buffersrc.c =================================================================== --- FFmpeg.orig/libavfilter/buffersrc.c +++ FFmpeg/libavfilter/buffersrc.c -@@ -75,7 +75,7 @@ typedef struct BufferSourceContext { +@@ -74,7 +74,7 @@ typedef struct BufferSourceContext { c->prev_delta = c->prev_w != width || c->prev_h != height || c->prev_pix_fmt != format ||\ c->prev_color_space != csp || c->prev_color_range != range;\ if (c->link_delta) {\ diff --git a/debian/patches/0024-add-fixes-for-hevc-hdr-decoding-in-bsf.patch b/debian/patches/0023-add-fixes-for-hevc-hdr-decoding-in-bsf.patch similarity index 90% rename from debian/patches/0024-add-fixes-for-hevc-hdr-decoding-in-bsf.patch rename to debian/patches/0023-add-fixes-for-hevc-hdr-decoding-in-bsf.patch index ee6f95ec8..ab05e3ee5 100644 --- a/debian/patches/0024-add-fixes-for-hevc-hdr-decoding-in-bsf.patch +++ b/debian/patches/0023-add-fixes-for-hevc-hdr-decoding-in-bsf.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavcodec/bsf/hevc_mp4toannexb.c =================================================================== --- FFmpeg.orig/libavcodec/bsf/hevc_mp4toannexb.c +++ FFmpeg/libavcodec/bsf/hevc_mp4toannexb.c -@@ -126,6 +126,7 @@ static int hevc_mp4toannexb_filter(AVBSF +@@ -127,6 +127,7 @@ static int hevc_mp4toannexb_filter(AVBSF int got_irap = 0; int i, ret = 0; @@ -10,7 +10,7 @@ Index: FFmpeg/libavcodec/bsf/hevc_mp4toannexb.c ret = ff_bsf_get_packet(ctx, &in); if (ret < 0) -@@ -157,11 +158,14 @@ static int hevc_mp4toannexb_filter(AVBSF +@@ -158,11 +159,14 @@ static int hevc_mp4toannexb_filter(AVBSF } nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f; @@ -30,7 +30,7 @@ Index: FFmpeg/tests/fate/hevc.mak =================================================================== --- FFmpeg.orig/tests/fate/hevc.mak +++ FFmpeg/tests/fate/hevc.mak -@@ -222,7 +222,7 @@ FATE_HEVC-$(call ALLYES, HEVC_DEMUXER MO +@@ -233,7 +233,7 @@ FATE_HEVC-$(call ALLYES, HEVC_DEMUXER MO fate-hevc-bsf-mp4toannexb: tests/data/hevc-mp4.mov fate-hevc-bsf-mp4toannexb: CMD = md5 -i $(TARGET_PATH)/tests/data/hevc-mp4.mov -c:v copy -fflags +bitexact -f hevc fate-hevc-bsf-mp4toannexb: CMP = oneline diff --git a/debian/patches/0025-add-sub2video-option-to-subtitles-filter.patch b/debian/patches/0024-add-sub2video-option-to-subtitles-filter.patch similarity index 90% rename from debian/patches/0025-add-sub2video-option-to-subtitles-filter.patch rename to debian/patches/0024-add-sub2video-option-to-subtitles-filter.patch index 2fb3b01fd..2a02335ed 100644 --- a/debian/patches/0025-add-sub2video-option-to-subtitles-filter.patch +++ b/debian/patches/0024-add-sub2video-option-to-subtitles-filter.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavfilter/vf_subtitles.c =================================================================== --- FFmpeg.orig/libavfilter/vf_subtitles.c +++ FFmpeg/libavfilter/vf_subtitles.c -@@ -65,6 +65,9 @@ typedef struct AssContext { +@@ -64,6 +64,9 @@ typedef struct AssContext { int shaping; FFDrawContext draw; int wrap_unicode; @@ -12,7 +12,7 @@ Index: FFmpeg/libavfilter/vf_subtitles.c } AssContext; #define OFFSET(x) offsetof(AssContext, x) -@@ -75,7 +78,12 @@ typedef struct AssContext { +@@ -74,7 +77,12 @@ typedef struct AssContext { {"f", "set the filename of file to read", OFFSET(filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS }, \ {"original_size", "set the size of the original video (used to scale fonts)", OFFSET(original_w), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, FLAGS }, \ {"fontsdir", "set the directory containing the fonts to read", OFFSET(fontsdir), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS }, \ @@ -26,7 +26,7 @@ Index: FFmpeg/libavfilter/vf_subtitles.c /* libass supports a log level ranging from 0 to 7 */ static const int ass_libavfilter_log_level_map[] = { -@@ -162,6 +170,8 @@ static int config_input(AVFilterLink *in +@@ -161,6 +169,8 @@ static int config_input(AVFilterLink *in if (ass->shaping != -1) ass_set_shaper(ass->renderer, ass->shaping); @@ -35,8 +35,11 @@ Index: FFmpeg/libavfilter/vf_subtitles.c return 0; } -@@ -192,18 +202,41 @@ static int filter_frame(AVFilterLink *in +@@ -189,20 +199,44 @@ static int filter_frame(AVFilterLink *in + { + AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; ++ FilterLink *outl = ff_filter_link(outlink); AssContext *ass = ctx->priv; int detect_change = 0; - double time_ms = picref->pts * av_q2d(inlink->time_base) * 1000; @@ -45,7 +48,7 @@ Index: FFmpeg/libavfilter/vf_subtitles.c time_ms, &detect_change); + if (ass->sub2video) { -+ if (!image && !ass->last_image && picref->pts <= ass->max_pts && outlink->current_pts != AV_NOPTS_VALUE) { ++ if (!image && !ass->last_image && picref->pts <= ass->max_pts && outl->current_pts != AV_NOPTS_VALUE) { + av_log(ctx, AV_LOG_DEBUG, "sub2video skip pts:%"PRId64"\n", picref->pts); + av_frame_free(&picref); + return 0; @@ -79,7 +82,7 @@ Index: FFmpeg/libavfilter/vf_subtitles.c static const AVFilterPad ass_inputs[] = { { .name = "default", -@@ -218,10 +251,6 @@ static const AVFilterPad ass_inputs[] = +@@ -217,10 +251,6 @@ static const AVFilterPad ass_inputs[] = static const AVOption ass_options[] = { COMMON_OPTIONS @@ -90,7 +93,7 @@ Index: FFmpeg/libavfilter/vf_subtitles.c {NULL}, }; -@@ -245,6 +274,9 @@ static av_cold int init_ass(AVFilterCont +@@ -244,6 +274,9 @@ static av_cold int init_ass(AVFilterCont ass->filename); return AVERROR(EINVAL); } @@ -100,7 +103,7 @@ Index: FFmpeg/libavfilter/vf_subtitles.c return 0; } -@@ -266,8 +298,8 @@ const AVFilter ff_vf_ass = { +@@ -265,8 +298,8 @@ const AVFilter ff_vf_ass = { static const AVOption subtitles_options[] = { COMMON_OPTIONS {"charenc", "set input character encoding", OFFSET(charenc), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS}, @@ -111,7 +114,7 @@ Index: FFmpeg/libavfilter/vf_subtitles.c {"force_style", "force subtitle style", OFFSET(force_style), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS}, #if FF_ASS_FEATURE_WRAP_UNICODE {"wrap_unicode", "break lines according to the Unicode Line Breaking Algorithm", OFFSET(wrap_unicode), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, FLAGS }, -@@ -496,6 +528,8 @@ static av_cold int init_subtitles(AVFilt +@@ -495,6 +528,8 @@ static av_cold int init_subtitles(AVFilt avsubtitle_free(&sub); } diff --git a/debian/patches/0026-add-alphasrc-source-video-filter.patch b/debian/patches/0025-add-alphasrc-source-video-filter.patch similarity index 96% rename from debian/patches/0026-add-alphasrc-source-video-filter.patch rename to debian/patches/0025-add-alphasrc-source-video-filter.patch index 0cb378cb0..ce95651ce 100644 --- a/debian/patches/0026-add-alphasrc-source-video-filter.patch +++ b/debian/patches/0025-add-alphasrc-source-video-filter.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavfilter/Makefile =================================================================== --- FFmpeg.orig/libavfilter/Makefile +++ FFmpeg/libavfilter/Makefile -@@ -588,6 +588,7 @@ OBJS-$(CONFIG_XSTACK_QSV_FILTER) +@@ -593,6 +593,7 @@ OBJS-$(CONFIG_DRAWBOX_VAAPI_FILTER) OBJS-$(CONFIG_ALLRGB_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_ALLYUV_FILTER) += vsrc_testsrc.o @@ -14,7 +14,7 @@ Index: FFmpeg/libavfilter/allfilters.c =================================================================== --- FFmpeg.orig/libavfilter/allfilters.c +++ FFmpeg/libavfilter/allfilters.c -@@ -552,6 +552,7 @@ extern const AVFilter ff_vf_xstack_qsv; +@@ -556,6 +556,7 @@ extern const AVFilter ff_vf_drawbox_vaap extern const AVFilter ff_vsrc_allrgb; extern const AVFilter ff_vsrc_allyuv; @@ -26,7 +26,7 @@ Index: FFmpeg/libavfilter/vsrc_alphasrc.c =================================================================== --- /dev/null +++ FFmpeg/libavfilter/vsrc_alphasrc.c -@@ -0,0 +1,164 @@ +@@ -0,0 +1,165 @@ +/* + * Copyright (c) 2021 NyanMisaka + * @@ -54,11 +54,11 @@ Index: FFmpeg/libavfilter/vsrc_alphasrc.c + +#include "libavutil/avstring.h" +#include "libavutil/imgutils.h" ++#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" -+#include "filters.h" +#include "avfilter.h" -+#include "internal.h" ++#include "filters.h" +#include "formats.h" +#include "video.h" + @@ -99,6 +99,7 @@ Index: FFmpeg/libavfilter/vsrc_alphasrc.c + +static int alphasrc_config_output(AVFilterLink *outlink) +{ ++ FilterLink *outl = ff_filter_link(outlink); + AVFilterContext *ctx = outlink->src; + AlphaSrc *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); @@ -118,7 +119,7 @@ Index: FFmpeg/libavfilter/vsrc_alphasrc.c + + outlink->w = s->out_w; + outlink->h = s->out_h; -+ outlink->frame_rate = s->frame_rate; ++ outl->frame_rate = s->frame_rate; + outlink->time_base = s->time_base; + outlink->sample_aspect_ratio = (AVRational){1, 1}; + diff --git a/debian/patches/0026-increase-the-default-async-depth-for-vaapi-encode.patch b/debian/patches/0026-increase-the-default-async-depth-for-vaapi-encode.patch new file mode 100644 index 000000000..069608a80 --- /dev/null +++ b/debian/patches/0026-increase-the-default-async-depth-for-vaapi-encode.patch @@ -0,0 +1,12 @@ +Index: FFmpeg/libavcodec/hw_base_encode.h +=================================================================== +--- FFmpeg.orig/libavcodec/hw_base_encode.h ++++ FFmpeg/libavcodec/hw_base_encode.h +@@ -248,6 +248,6 @@ int ff_hw_base_encode_close(FFHWBaseEnco + { "async_depth", "Maximum processing parallelism. " \ + "Increase this to improve single channel performance.", \ + OFFSET(common.base.async_depth), AV_OPT_TYPE_INT, \ +- { .i64 = 2 }, 1, MAX_ASYNC_DEPTH, FLAGS } ++ { .i64 = 4 }, 1, MAX_ASYNC_DEPTH, FLAGS } + + #endif /* AVCODEC_HW_BASE_ENCODE_H */ diff --git a/debian/patches/0028-add-fixes-for-hevc-vaapi-encoding-on-tgl.patch b/debian/patches/0027-add-fixes-for-hevc-vaapi-encoding-on-tgl.patch similarity index 75% rename from debian/patches/0028-add-fixes-for-hevc-vaapi-encoding-on-tgl.patch rename to debian/patches/0027-add-fixes-for-hevc-vaapi-encoding-on-tgl.patch index b0fe14d2a..42098e615 100644 --- a/debian/patches/0028-add-fixes-for-hevc-vaapi-encoding-on-tgl.patch +++ b/debian/patches/0027-add-fixes-for-hevc-vaapi-encoding-on-tgl.patch @@ -1,8 +1,8 @@ -Index: FFmpeg/libavcodec/vaapi_encode_h265.c +Index: FFmpeg/libavcodec/hw_base_encode_h265.c =================================================================== ---- FFmpeg.orig/libavcodec/vaapi_encode_h265.c -+++ FFmpeg/libavcodec/vaapi_encode_h265.c -@@ -452,8 +452,9 @@ static int vaapi_encode_h265_init_sequen +--- FFmpeg.orig/libavcodec/hw_base_encode_h265.c ++++ FFmpeg/libavcodec/hw_base_encode_h265.c +@@ -216,8 +216,9 @@ int ff_hw_base_encode_init_params_h265(F sps->log2_min_luma_transform_block_size_minus2 = 0; sps->log2_diff_max_min_luma_transform_block_size = 3; // Full transform hierarchy allowed (2-5). diff --git a/debian/patches/0027-increase-the-default-async-depth-for-vaapi-encode.patch b/debian/patches/0027-increase-the-default-async-depth-for-vaapi-encode.patch deleted file mode 100644 index 3cda64250..000000000 --- a/debian/patches/0027-increase-the-default-async-depth-for-vaapi-encode.patch +++ /dev/null @@ -1,13 +0,0 @@ -Index: FFmpeg/libavcodec/vaapi_encode.h -=================================================================== ---- FFmpeg.orig/libavcodec/vaapi_encode.h -+++ FFmpeg/libavcodec/vaapi_encode.h -@@ -520,7 +520,7 @@ int ff_vaapi_encode_close(AVCodecContext - "Increase this to improve single channel performance. This option " \ - "doesn't work if driver doesn't implement vaSyncBuffer function.", \ - OFFSET(common.async_depth), AV_OPT_TYPE_INT, \ -- { .i64 = 2 }, 1, MAX_ASYNC_DEPTH, FLAGS }, \ -+ { .i64 = 4 }, 1, MAX_ASYNC_DEPTH, FLAGS }, \ - { "max_frame_size", \ - "Maximum frame size (in bytes)",\ - OFFSET(common.max_frame_size), AV_OPT_TYPE_INT, \ diff --git a/debian/patches/0029-add-multiple-values-tags-and-webp-support-for-id3v2.patch b/debian/patches/0028-add-multiple-values-tags-and-webp-support-for-id3v2.patch similarity index 96% rename from debian/patches/0029-add-multiple-values-tags-and-webp-support-for-id3v2.patch rename to debian/patches/0028-add-multiple-values-tags-and-webp-support-for-id3v2.patch index 9754bb099..715ddb0dd 100644 --- a/debian/patches/0029-add-multiple-values-tags-and-webp-support-for-id3v2.patch +++ b/debian/patches/0028-add-multiple-values-tags-and-webp-support-for-id3v2.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavformat/id3v2.c =================================================================== --- FFmpeg.orig/libavformat/id3v2.c +++ FFmpeg/libavformat/id3v2.c -@@ -136,6 +136,7 @@ const CodecMime ff_id3v2_mime_tags[] = { +@@ -137,6 +137,7 @@ const CodecMime ff_id3v2_mime_tags[] = { { "image/png", AV_CODEC_ID_PNG }, { "image/tiff", AV_CODEC_ID_TIFF }, { "image/bmp", AV_CODEC_ID_BMP }, @@ -10,7 +10,7 @@ Index: FFmpeg/libavformat/id3v2.c { "JPG", AV_CODEC_ID_MJPEG }, /* ID3v2.2 */ { "PNG", AV_CODEC_ID_PNG }, /* ID3v2.2 */ { "", AV_CODEC_ID_NONE }, -@@ -325,39 +326,54 @@ static void read_ttag(AVFormatContext *s +@@ -326,39 +327,54 @@ static void read_ttag(AVFormatContext *s AVDictionary **metadata, const char *key) { uint8_t *dst; diff --git a/debian/patches/0030-remove-fdk-aac-from-nonfree.patch b/debian/patches/0029-remove-fdk-aac-from-nonfree.patch similarity index 77% rename from debian/patches/0030-remove-fdk-aac-from-nonfree.patch rename to debian/patches/0029-remove-fdk-aac-from-nonfree.patch index 5f7965a6f..080840ec0 100644 --- a/debian/patches/0030-remove-fdk-aac-from-nonfree.patch +++ b/debian/patches/0029-remove-fdk-aac-from-nonfree.patch @@ -2,7 +2,7 @@ Index: FFmpeg/configure =================================================================== --- FFmpeg.orig/configure +++ FFmpeg/configure -@@ -1872,7 +1872,6 @@ EXTERNAL_LIBRARY_GPL_LIST=" +@@ -1876,7 +1876,6 @@ EXTERNAL_LIBRARY_GPL_LIST=" EXTERNAL_LIBRARY_NONFREE_LIST=" decklink @@ -10,7 +10,7 @@ Index: FFmpeg/configure libtls " -@@ -1912,6 +1911,7 @@ EXTERNAL_LIBRARY_LIST=" +@@ -1916,6 +1915,7 @@ EXTERNAL_LIBRARY_LIST=" libcodec2 libdav1d libdc1394 diff --git a/debian/patches/0031-pass-dovi-sidedata-to-hlsenc-and-mpegtsenc.patch b/debian/patches/0030-pass-dovi-sidedata-to-hlsenc-and-mpegtsenc.patch similarity index 79% rename from debian/patches/0031-pass-dovi-sidedata-to-hlsenc-and-mpegtsenc.patch rename to debian/patches/0030-pass-dovi-sidedata-to-hlsenc-and-mpegtsenc.patch index 6617cd190..6e686ab5c 100644 --- a/debian/patches/0031-pass-dovi-sidedata-to-hlsenc-and-mpegtsenc.patch +++ b/debian/patches/0030-pass-dovi-sidedata-to-hlsenc-and-mpegtsenc.patch @@ -1,168 +1,10 @@ -Index: FFmpeg/libavformat/hlsenc.c -=================================================================== ---- FFmpeg.orig/libavformat/hlsenc.c -+++ FFmpeg/libavformat/hlsenc.c -@@ -850,7 +850,7 @@ static int hls_mux_init(AVFormatContext - AVFormatContext *vtt_oc = NULL; - int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); - int remaining_options; -- int i, ret; -+ int i, j, ret; - - ret = avformat_alloc_output_context2(&vs->avf, vs->oformat, NULL, NULL); - if (ret < 0) -@@ -896,6 +896,20 @@ static int hls_mux_init(AVFormatContext - st->codecpar->codec_tag = 0; - } - -+ // copy side data -+ for (j = 0; j < vs->streams[i]->codecpar->nb_coded_side_data; j++) { -+ const AVPacketSideData *sd_src = &vs->streams[i]->codecpar->coded_side_data[j]; -+ AVPacketSideData *sd_dst; -+ -+ sd_dst = av_packet_side_data_new(&st->codecpar->coded_side_data, -+ &st->codecpar->nb_coded_side_data, -+ sd_src->type, sd_src->size, 0); -+ if (!sd_dst) -+ return AVERROR(ENOMEM); -+ -+ memcpy(sd_dst->data, sd_src->data, sd_src->size); -+ } -+ - st->sample_aspect_ratio = vs->streams[i]->sample_aspect_ratio; - st->time_base = vs->streams[i]->time_base; - av_dict_copy(&st->metadata, vs->streams[i]->metadata, 0); -Index: FFmpeg/libavformat/movenc.c -=================================================================== ---- FFmpeg.orig/libavformat/movenc.c -+++ FFmpeg/libavformat/movenc.c -@@ -2538,8 +2538,9 @@ static int mov_write_video_tag(AVFormatC - mov_write_st3d_tag(s, pb, (AVStereo3D*)stereo_3d->data); - if (spherical_mapping) - mov_write_sv3d_tag(mov->fc, pb, (AVSphericalMapping*)spherical_mapping->data); -- if (dovi) -+ if (dovi && !ff_isom_validate_dovi_config((AVDOVIDecoderConfigurationRecord *)dovi->data, track->par, track->tag)) { - mov_write_dvcc_dvvc_tag(s, pb, (AVDOVIDecoderConfigurationRecord *)dovi->data); -+ } - } - - if (track->par->sample_aspect_ratio.den && track->par->sample_aspect_ratio.num) { -@@ -8128,6 +8129,7 @@ static const AVCodecTag codec_mp4_tags[] - { AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') }, - { AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') }, - { AV_CODEC_ID_HEVC, MKTAG('d', 'v', 'h', '1') }, -+ { AV_CODEC_ID_HEVC, MKTAG('d', 'v', 'h', 'e') }, - { AV_CODEC_ID_VVC, MKTAG('v', 'v', 'c', '1') }, - { AV_CODEC_ID_VVC, MKTAG('v', 'v', 'i', '1') }, - { AV_CODEC_ID_EVC, MKTAG('e', 'v', 'c', '1') }, -@@ -8141,6 +8143,7 @@ static const AVCodecTag codec_mp4_tags[] - { AV_CODEC_ID_TSCC2, MKTAG('m', 'p', '4', 'v') }, - { AV_CODEC_ID_VP9, MKTAG('v', 'p', '0', '9') }, - { AV_CODEC_ID_AV1, MKTAG('a', 'v', '0', '1') }, -+ { AV_CODEC_ID_AV1, MKTAG('d', 'a', 'v', '1') }, - { AV_CODEC_ID_AAC, MKTAG('m', 'p', '4', 'a') }, - { AV_CODEC_ID_ALAC, MKTAG('a', 'l', 'a', 'c') }, - { AV_CODEC_ID_MP4ALS, MKTAG('m', 'p', '4', 'a') }, -Index: FFmpeg/libavformat/mpegtsenc.c -=================================================================== ---- FFmpeg.orig/libavformat/mpegtsenc.c -+++ FFmpeg/libavformat/mpegtsenc.c -@@ -23,6 +23,7 @@ - #include "libavutil/bswap.h" - #include "libavutil/crc.h" - #include "libavutil/dict.h" -+#include "libavutil/dovi_meta.h" - #include "libavutil/intreadwrite.h" - #include "libavutil/mathematics.h" - #include "libavutil/opt.h" -@@ -40,6 +41,7 @@ - #include "internal.h" - #include "mpegts.h" - #include "mux.h" -+#include "dovi_isom.h" - - #define PCR_TIME_BASE 27000000 - -@@ -350,6 +352,52 @@ static void put_registration_descriptor( - *q_ptr = q; - } - -+static int put_dovi_descriptor(AVFormatContext *s, uint8_t **q_ptr, -+ const AVDOVIDecoderConfigurationRecord *dovi) -+{ -+ uint16_t val16; -+ uint8_t *q = *q_ptr; -+ -+ if (!dovi) -+ return AVERROR(ENOMEM); -+ -+ if (!dovi->bl_present_flag) { -+ av_log(s, AV_LOG_ERROR, -+ "EL only DOVI stream is not supported!\n"); -+ return AVERROR_INVALIDDATA; -+ } -+ -+ put_registration_descriptor(&q, MKTAG('D', 'O', 'V', 'I')); // format_identifier -+ -+ /* DOVI Video Stream Descriptor Syntax */ -+ *q++ = 0xb0; // descriptor_tag -+ *q++ = 0x05; // descriptor_length -+ *q++ = dovi->dv_version_major; -+ *q++ = dovi->dv_version_minor; -+ -+ val16 = (dovi->dv_profile & 0x7f) << 9 | // 7 bits -+ (dovi->dv_level & 0x3f) << 3 | // 6 bits -+ (dovi->rpu_present_flag & 0x01) << 2 | // 1 bits -+ (dovi->el_present_flag & 0x01) << 1 | // 1 bits -+ (dovi->bl_present_flag & 0x01); // 1 bits -+ put16(&q, val16); -+ -+#if 0 -+ // TODO: support dependency_pid (EL only stream) -+ // descriptor_length: 0x05->0x07 -+ if (!bl_present_flag) { -+ val16 = (dependency_pid & 0x1fff) << 3; // 13+3 bits -+ put16(&q, val16); -+ } -+#endif -+ -+ *q++ = (dovi->dv_bl_signal_compatibility_id & 0x0f) << 4; // 4+4 bits -+ -+ *q_ptr = q; -+ -+ return 0; -+} -+ - static int get_dvb_stream_type(AVFormatContext *s, AVStream *st) - { - MpegTSWrite *ts = s->priv_data; -@@ -803,7 +851,18 @@ static int mpegts_write_pmt(AVFormatCont - } else if (stream_type == STREAM_TYPE_VIDEO_VC1) { - put_registration_descriptor(&q, MKTAG('V', 'C', '-', '1')); - } else if (stream_type == STREAM_TYPE_VIDEO_HEVC && s->strict_std_compliance <= FF_COMPLIANCE_NORMAL) { -- put_registration_descriptor(&q, MKTAG('H', 'E', 'V', 'C')); -+ const AVPacketSideData *sd = av_packet_side_data_get(st->codecpar->coded_side_data, -+ st->codecpar->nb_coded_side_data, AV_PKT_DATA_DOVI_CONF); -+ const AVDOVIDecoderConfigurationRecord *dovi = sd ? (const AVDOVIDecoderConfigurationRecord *)sd->data : NULL; -+ if (dovi && -+ dovi->bl_present_flag && -+ s->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL && -+ !ff_isom_validate_dovi_config(dovi, st->codecpar, MKTAG('d', 'v', 'h', '1'))) { // always assume tag is valid -+ if (put_dovi_descriptor(s, &q, dovi) < 0) -+ break; -+ } else { -+ put_registration_descriptor(&q, MKTAG('H', 'E', 'V', 'C')); -+ } - } else if (stream_type == STREAM_TYPE_VIDEO_CAVS || stream_type == STREAM_TYPE_VIDEO_AVS2 || - stream_type == STREAM_TYPE_VIDEO_AVS3) { - put_registration_descriptor(&q, MKTAG('A', 'V', 'S', 'V')); Index: FFmpeg/libavformat/dovi_isom.c =================================================================== --- FFmpeg.orig/libavformat/dovi_isom.c +++ FFmpeg/libavformat/dovi_isom.c -@@ -116,3 +116,74 @@ void ff_isom_put_dvcc_dvvc(void *logctx, - dovi->bl_present_flag, - dovi->dv_bl_signal_compatibility_id); +@@ -124,3 +124,74 @@ void ff_isom_put_dvcc_dvvc(void *logctx, + dovi->dv_bl_signal_compatibility_id, + dovi->dv_md_compression); } + +int ff_isom_validate_dovi_config(const AVDOVIDecoderConfigurationRecord *dovi, @@ -242,7 +84,7 @@ Index: FFmpeg/libavformat/dovi_isom.h @@ -33,4 +33,12 @@ int ff_isom_parse_dvcc_dvvc(void *logctx void ff_isom_put_dvcc_dvvc(void *logctx, uint8_t out[ISOM_DVCC_DVVC_SIZE], const AVDOVIDecoderConfigurationRecord *dovi); - + +/* + * Check if the AVDOVIDecoderConfigurationRecord is spec-compliant for current codec parameters + * Used by muxers to determine if the configuration record should be copied into the container @@ -252,13 +94,47 @@ Index: FFmpeg/libavformat/dovi_isom.h + const AVCodecParameters *codec_par, int codec_tag); + #endif /* AVFORMAT_DOVI_ISOM_H */ +Index: FFmpeg/libavformat/hlsenc.c +=================================================================== +--- FFmpeg.orig/libavformat/hlsenc.c ++++ FFmpeg/libavformat/hlsenc.c +@@ -850,7 +850,7 @@ static int hls_mux_init(AVFormatContext + AVFormatContext *vtt_oc = NULL; + int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); + int remaining_options; +- int i, ret; ++ int i, j, ret; + + ret = avformat_alloc_output_context2(&vs->avf, vs->oformat, NULL, NULL); + if (ret < 0) +@@ -898,6 +898,20 @@ static int hls_mux_init(AVFormatContext + st->codecpar->codec_tag = 0; + } + ++ // copy side data ++ for (j = 0; j < vs->streams[i]->codecpar->nb_coded_side_data; j++) { ++ const AVPacketSideData *sd_src = &vs->streams[i]->codecpar->coded_side_data[j]; ++ AVPacketSideData *sd_dst; ++ ++ sd_dst = av_packet_side_data_new(&st->codecpar->coded_side_data, ++ &st->codecpar->nb_coded_side_data, ++ sd_src->type, sd_src->size, 0); ++ if (!sd_dst) ++ return AVERROR(ENOMEM); ++ ++ memcpy(sd_dst->data, sd_src->data, sd_src->size); ++ } ++ + st->sample_aspect_ratio = vs->streams[i]->sample_aspect_ratio; + st->time_base = vs->streams[i]->time_base; + av_dict_copy(&st->metadata, vs->streams[i]->metadata, 0); Index: FFmpeg/libavformat/matroskaenc.c =================================================================== --- FFmpeg.orig/libavformat/matroskaenc.c +++ FFmpeg/libavformat/matroskaenc.c -@@ -1718,7 +1718,8 @@ static void mkv_write_blockadditionmappi +@@ -1724,7 +1724,8 @@ static void mkv_write_blockadditionmappi return; - + dovi = (const AVDOVIDecoderConfigurationRecord *)sd->data; - if (dovi->dv_profile <= 10) { + if (dovi->dv_profile <= 10 && @@ -266,3 +142,111 @@ Index: FFmpeg/libavformat/matroskaenc.c ebml_master mapping; uint8_t buf[ISOM_DVCC_DVVC_SIZE]; uint32_t type; +Index: FFmpeg/libavformat/movenc.c +=================================================================== +--- FFmpeg.orig/libavformat/movenc.c ++++ FFmpeg/libavformat/movenc.c +@@ -2809,7 +2809,9 @@ static int mov_write_video_tag(AVFormatC + track->st->codecpar->nb_coded_side_data, + AV_PKT_DATA_DOVI_CONF); + if (dovi && mov->fc->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) { +- mov_write_dvcc_dvvc_tag(s, pb, (AVDOVIDecoderConfigurationRecord *)dovi->data); ++ if (!ff_isom_validate_dovi_config((AVDOVIDecoderConfigurationRecord *)dovi->data, track->par, track->tag)) { ++ mov_write_dvcc_dvvc_tag(s, pb, (AVDOVIDecoderConfigurationRecord *)dovi->data); ++ } + } else if (dovi) { + av_log(mov->fc, AV_LOG_WARNING, "Not writing 'dvcC'/'dvvC' box. Requires -strict unofficial.\n"); + } +Index: FFmpeg/libavformat/mpegtsenc.c +=================================================================== +--- FFmpeg.orig/libavformat/mpegtsenc.c ++++ FFmpeg/libavformat/mpegtsenc.c +@@ -23,6 +23,7 @@ + #include "libavutil/bswap.h" + #include "libavutil/crc.h" + #include "libavutil/dict.h" ++#include "libavutil/dovi_meta.h" + #include "libavutil/intreadwrite.h" + #include "libavutil/mathematics.h" + #include "libavutil/mem.h" +@@ -38,6 +39,7 @@ + + #include "avformat.h" + #include "avio_internal.h" ++#include "dovi_isom.h" + #include "internal.h" + #include "mpegts.h" + #include "mux.h" +@@ -351,6 +353,52 @@ static void put_registration_descriptor( + *q_ptr = q; + } + ++static int put_dovi_descriptor(AVFormatContext *s, uint8_t **q_ptr, ++ const AVDOVIDecoderConfigurationRecord *dovi) ++{ ++ uint16_t val16; ++ uint8_t *q = *q_ptr; ++ ++ if (!dovi) ++ return AVERROR(ENOMEM); ++ ++ if (!dovi->bl_present_flag) { ++ av_log(s, AV_LOG_ERROR, ++ "EL only DOVI stream is not supported!\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ put_registration_descriptor(&q, MKTAG('D', 'O', 'V', 'I')); // format_identifier ++ ++ /* DOVI Video Stream Descriptor Syntax */ ++ *q++ = 0xb0; // descriptor_tag ++ *q++ = 0x05; // descriptor_length ++ *q++ = dovi->dv_version_major; ++ *q++ = dovi->dv_version_minor; ++ ++ val16 = (dovi->dv_profile & 0x7f) << 9 | // 7 bits ++ (dovi->dv_level & 0x3f) << 3 | // 6 bits ++ (dovi->rpu_present_flag & 0x01) << 2 | // 1 bit ++ (dovi->el_present_flag & 0x01) << 1 | // 1 bit ++ (dovi->bl_present_flag & 0x01); // 1 bit ++ put16(&q, val16); ++ ++#if 0 ++ // TODO: support dependency_pid (EL only stream) ++ // descriptor_length: 0x05->0x07 ++ if (!bl_present_flag) { ++ val16 = (dependency_pid & 0x1fff) << 3; // 13+3 bits ++ put16(&q, val16); ++ } ++#endif ++ ++ *q++ = (dovi->dv_bl_signal_compatibility_id & 0x0f) << 4; // 4+4 bits ++ ++ *q_ptr = q; ++ ++ return 0; ++} ++ + static int get_dvb_stream_type(AVFormatContext *s, AVStream *st) + { + MpegTSWrite *ts = s->priv_data; +@@ -804,7 +852,18 @@ static int mpegts_write_pmt(AVFormatCont + } else if (stream_type == STREAM_TYPE_VIDEO_VC1) { + put_registration_descriptor(&q, MKTAG('V', 'C', '-', '1')); + } else if (stream_type == STREAM_TYPE_VIDEO_HEVC && s->strict_std_compliance <= FF_COMPLIANCE_NORMAL) { +- put_registration_descriptor(&q, MKTAG('H', 'E', 'V', 'C')); ++ const AVPacketSideData *sd = av_packet_side_data_get(st->codecpar->coded_side_data, ++ st->codecpar->nb_coded_side_data, AV_PKT_DATA_DOVI_CONF); ++ const AVDOVIDecoderConfigurationRecord *dovi = sd ? (const AVDOVIDecoderConfigurationRecord *)sd->data : NULL; ++ if (dovi && ++ dovi->bl_present_flag && ++ s->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL && ++ !ff_isom_validate_dovi_config(dovi, st->codecpar, MKTAG('d', 'v', 'h', '1'))) { // always assume tag is valid ++ if (put_dovi_descriptor(s, &q, dovi) < 0) ++ break; ++ } else { ++ put_registration_descriptor(&q, MKTAG('H', 'E', 'V', 'C')); ++ } + } else if (stream_type == STREAM_TYPE_VIDEO_CAVS || stream_type == STREAM_TYPE_VIDEO_AVS2 || + stream_type == STREAM_TYPE_VIDEO_AVS3) { + put_registration_descriptor(&q, MKTAG('A', 'V', 'S', 'V')); diff --git a/debian/patches/0032-add-pause-support-for-ffmpeg-cli.patch b/debian/patches/0031-add-pause-support-for-ffmpeg-cli.patch similarity index 89% rename from debian/patches/0032-add-pause-support-for-ffmpeg-cli.patch rename to debian/patches/0031-add-pause-support-for-ffmpeg-cli.patch index 28fefb1f6..aa706a03d 100644 --- a/debian/patches/0032-add-pause-support-for-ffmpeg-cli.patch +++ b/debian/patches/0031-add-pause-support-for-ffmpeg-cli.patch @@ -2,7 +2,7 @@ Index: FFmpeg/fftools/ffmpeg.c =================================================================== --- FFmpeg.orig/fftools/ffmpeg.c +++ FFmpeg/fftools/ffmpeg.c -@@ -116,6 +116,9 @@ typedef struct BenchmarkTimeStamps { +@@ -95,6 +95,9 @@ typedef struct BenchmarkTimeStamps { static BenchmarkTimeStamps get_benchmark_time_stamps(void); static int64_t getmaxrss(void); @@ -12,7 +12,7 @@ Index: FFmpeg/fftools/ffmpeg.c atomic_uint nb_output_dumped = 0; -@@ -134,6 +137,9 @@ int nb_filtergraphs; +@@ -113,6 +116,9 @@ int nb_filtergraphs; Decoder **decoders; int nb_decoders; @@ -22,7 +22,7 @@ Index: FFmpeg/fftools/ffmpeg.c #if HAVE_TERMIOS_H /* init terminal so that we can grab keys */ -@@ -773,12 +779,28 @@ static void set_tty_echo(int on) +@@ -785,12 +791,28 @@ static void set_tty_echo(int on) #endif } @@ -52,7 +52,7 @@ Index: FFmpeg/fftools/ffmpeg.c /* read_key() returns 0 on EOF */ if (cur_time - last_time >= 100000) { key = read_key(); -@@ -791,6 +813,11 @@ static int check_keyboard_interaction(in +@@ -803,6 +825,11 @@ static int check_keyboard_interaction(in } if (key == '+') av_log_set_level(av_log_get_level()+10); if (key == '-') av_log_set_level(av_log_get_level()-10); @@ -64,7 +64,7 @@ Index: FFmpeg/fftools/ffmpeg.c if (key == 'c' || key == 'C'){ char buf[4096], target[64], command[256], arg[256] = {0}; double time; -@@ -825,7 +852,9 @@ static int check_keyboard_interaction(in +@@ -842,7 +869,9 @@ static int check_keyboard_interaction(in "c Send command to first matching filter supporting it\n" "C Send/Queue command to all matching filters\n" "h dump packets/hex press to cycle through the 3 states\n" @@ -74,7 +74,7 @@ Index: FFmpeg/fftools/ffmpeg.c "s Show QP histogram\n" ); } -@@ -855,12 +884,15 @@ static int transcode(Scheduler *sch) +@@ -872,12 +901,15 @@ static int transcode(Scheduler *sch) timer_start = av_gettime_relative(); while (!sch_wait(sch, stats_period, &transcode_ts)) { @@ -93,7 +93,7 @@ Index: FFmpeg/fftools/ffmpeg.c /* dump report by using the output first video and audio streams */ print_report(0, timer_start, cur_time, transcode_ts); -@@ -877,11 +909,17 @@ static int transcode(Scheduler *sch) +@@ -894,11 +926,17 @@ static int transcode(Scheduler *sch) term_exit(); /* dump report by using the first video and audio streams */ @@ -116,7 +116,7 @@ Index: FFmpeg/fftools/ffmpeg.h =================================================================== --- FFmpeg.orig/fftools/ffmpeg.h +++ FFmpeg/fftools/ffmpeg.h -@@ -667,6 +667,9 @@ extern int recast_media; +@@ -748,6 +748,9 @@ extern int recast_media; extern FILE *vstats_file; @@ -130,7 +130,7 @@ Index: FFmpeg/fftools/ffmpeg_demux.c =================================================================== --- FFmpeg.orig/fftools/ffmpeg_demux.c +++ FFmpeg/fftools/ffmpeg_demux.c -@@ -699,6 +699,11 @@ static int input_thread(void *arg) +@@ -703,6 +703,11 @@ static int input_thread(void *arg) DemuxStream *ds; unsigned send_flags = 0; diff --git a/debian/patches/0033-enable-gcc-vectorization-and-fix-cpuflags.patch b/debian/patches/0032-enable-gcc-vectorization-and-fix-cpuflags.patch similarity index 96% rename from debian/patches/0033-enable-gcc-vectorization-and-fix-cpuflags.patch rename to debian/patches/0032-enable-gcc-vectorization-and-fix-cpuflags.patch index 6b8c85eae..ebfb69765 100644 --- a/debian/patches/0033-enable-gcc-vectorization-and-fix-cpuflags.patch +++ b/debian/patches/0032-enable-gcc-vectorization-and-fix-cpuflags.patch @@ -2,7 +2,7 @@ Index: FFmpeg/configure =================================================================== --- FFmpeg.orig/configure +++ FFmpeg/configure -@@ -5558,7 +5558,7 @@ elif enabled x86; then +@@ -5601,7 +5601,7 @@ elif enabled x86; then ;; # everything else should support nopl and conditional mov (cmov) *) @@ -11,7 +11,7 @@ Index: FFmpeg/configure enable i686 enable fast_cmov ;; -@@ -7539,7 +7539,9 @@ if enabled icc; then +@@ -7592,7 +7592,9 @@ if enabled icc; then disable aligned_stack fi elif enabled gcc; then @@ -22,20 +22,6 @@ Index: FFmpeg/configure check_cflags -Werror=format-security check_cflags -Werror=implicit-function-declaration check_cflags -Werror=missing-prototypes -Index: FFmpeg/libavcodec/x86/cabac.h -=================================================================== ---- FFmpeg.orig/libavcodec/x86/cabac.h -+++ FFmpeg/libavcodec/x86/cabac.h -@@ -183,6 +183,9 @@ av_noinline - #else - av_always_inline - #endif -+#ifdef __GNUC__ -+__attribute__((optimize("-fno-tree-vectorize"))) -+#endif - int get_cabac_inline_x86(CABACContext *c, uint8_t *const state) - { - int bit, tmp; Index: FFmpeg/libavcodec/huffyuvdsp.c =================================================================== --- FFmpeg.orig/libavcodec/huffyuvdsp.c @@ -72,3 +58,17 @@ Index: FFmpeg/libavcodec/huffyuvenc.c #include "config_components.h" #include "avcodec.h" +Index: FFmpeg/libavcodec/x86/cabac.h +=================================================================== +--- FFmpeg.orig/libavcodec/x86/cabac.h ++++ FFmpeg/libavcodec/x86/cabac.h +@@ -183,6 +183,9 @@ av_noinline + #else + av_always_inline + #endif ++#ifdef __GNUC__ ++__attribute__((optimize("-fno-tree-vectorize"))) ++#endif + int get_cabac_inline_x86(CABACContext *c, uint8_t *const state) + { + int bit, tmp; diff --git a/debian/patches/0034-tune-dxva-align-for-intel-to-avoid-copy-on-qsv.patch b/debian/patches/0033-tune-dxva-align-for-intel-to-avoid-copy-on-qsv.patch similarity index 84% rename from debian/patches/0034-tune-dxva-align-for-intel-to-avoid-copy-on-qsv.patch rename to debian/patches/0033-tune-dxva-align-for-intel-to-avoid-copy-on-qsv.patch index 69101cacf..f23afdfc7 100644 --- a/debian/patches/0034-tune-dxva-align-for-intel-to-avoid-copy-on-qsv.patch +++ b/debian/patches/0033-tune-dxva-align-for-intel-to-avoid-copy-on-qsv.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavcodec/dxva2.c =================================================================== --- FFmpeg.orig/libavcodec/dxva2.c +++ FFmpeg/libavcodec/dxva2.c -@@ -615,6 +615,16 @@ int ff_dxva2_common_frame_params(AVCodec +@@ -616,6 +616,16 @@ int ff_dxva2_common_frame_params(AVCodec else surface_alignment = 16; @@ -19,11 +19,20 @@ Index: FFmpeg/libavcodec/dxva2.c /* 1 base work surface */ num_surfaces = 1; +@@ -625,7 +635,7 @@ int ff_dxva2_common_frame_params(AVCodec + else if (avctx->codec_id == AV_CODEC_ID_VP9 || avctx->codec_id == AV_CODEC_ID_AV1) + num_surfaces += 8; + else +- num_surfaces += 2; ++ num_surfaces += 2 + 4; /* 4 base work surface in vpp async */ + + frames_ctx->sw_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? + AV_PIX_FMT_P010 : AV_PIX_FMT_NV12; Index: FFmpeg/libavutil/hwcontext_d3d11va.c =================================================================== --- FFmpeg.orig/libavutil/hwcontext_d3d11va.c +++ FFmpeg/libavutil/hwcontext_d3d11va.c -@@ -609,6 +609,35 @@ static int d3d11va_device_find_adapter_b +@@ -611,6 +611,35 @@ static int d3d11va_device_find_adapter_b return -1; } @@ -59,7 +68,7 @@ Index: FFmpeg/libavutil/hwcontext_d3d11va.c static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags) { -@@ -686,6 +715,9 @@ static int d3d11va_device_create(AVHWDev +@@ -688,6 +717,9 @@ static int d3d11va_device_create(AVHWDev ID3D10Multithread_Release(pMultithread); } diff --git a/debian/patches/0035-add-10bit-support-for-cuda-overlay.patch b/debian/patches/0034-add-10bit-support-for-cuda-overlay.patch similarity index 89% rename from debian/patches/0035-add-10bit-support-for-cuda-overlay.patch rename to debian/patches/0034-add-10bit-support-for-cuda-overlay.patch index 906a7faaf..765f4e86e 100644 --- a/debian/patches/0035-add-10bit-support-for-cuda-overlay.patch +++ b/debian/patches/0034-add-10bit-support-for-cuda-overlay.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavfilter/vf_overlay_cuda.c =================================================================== --- FFmpeg.orig/libavfilter/vf_overlay_cuda.c +++ FFmpeg/libavfilter/vf_overlay_cuda.c -@@ -50,6 +50,8 @@ +@@ -49,6 +49,8 @@ static const enum AVPixelFormat supported_main_formats[] = { AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P, @@ -11,7 +11,7 @@ Index: FFmpeg/libavfilter/vf_overlay_cuda.c AV_PIX_FMT_NONE, }; -@@ -105,12 +107,15 @@ typedef struct OverlayCUDAContext { +@@ -104,12 +106,14 @@ typedef struct OverlayCUDAContext { enum AVPixelFormat in_format_overlay; enum AVPixelFormat in_format_main; @@ -20,7 +20,7 @@ Index: FFmpeg/libavfilter/vf_overlay_cuda.c AVBufferRef *hw_device_ctx; AVCUDADeviceContext *hwctx; - CUcontext cu_ctx; +- CUcontext cu_ctx; CUmodule cu_module; - CUfunction cu_func; + CUfunction cu_func_uchar; @@ -28,7 +28,7 @@ Index: FFmpeg/libavfilter/vf_overlay_cuda.c CUstream cu_stream; FFFrameSync fs; -@@ -185,7 +190,10 @@ static int set_expr(AVExpr **pexpr, cons +@@ -184,7 +188,10 @@ static int set_expr(AVExpr **pexpr, cons static int formats_match(const enum AVPixelFormat format_main, const enum AVPixelFormat format_overlay) { switch(format_main) { case AV_PIX_FMT_NV12: @@ -40,7 +40,7 @@ Index: FFmpeg/libavfilter/vf_overlay_cuda.c case AV_PIX_FMT_YUV420P: return format_overlay == AV_PIX_FMT_YUV420P || format_overlay == AV_PIX_FMT_YUVA420P; -@@ -200,11 +208,13 @@ static int formats_match(const enum AVPi +@@ -199,11 +206,13 @@ static int formats_match(const enum AVPi static int overlay_cuda_call_kernel( OverlayCUDAContext *ctx, int x_position, int y_position, @@ -57,7 +57,7 @@ Index: FFmpeg/libavfilter/vf_overlay_cuda.c int alpha_adj_x, int alpha_adj_y) { CudaFunctions *cu = ctx->hwctx->internal->cuda_dl; -@@ -212,14 +222,18 @@ static int overlay_cuda_call_kernel( +@@ -211,14 +220,18 @@ static int overlay_cuda_call_kernel( void* kernel_args[] = { &x_position, &y_position, &main_data, &main_linesize, @@ -77,7 +77,16 @@ Index: FFmpeg/libavfilter/vf_overlay_cuda.c DIV_UP(main_width, BLOCK_X), DIV_UP(main_height, BLOCK_Y), 1, BLOCK_X, BLOCK_Y, 1, 0, ctx->cu_stream, kernel_args, NULL)); -@@ -300,11 +314,13 @@ FF_ENABLE_DEPRECATION_WARNINGS +@@ -242,8 +255,6 @@ static int overlay_cuda_blend(FFFrameSyn + + AVFrame *input_main, *input_overlay; + +- ctx->cu_ctx = cuda_ctx; +- + // read main and overlay frames from inputs + ret = ff_framesync_dualinput_get(fs, &input_main, &input_overlay); + if (ret < 0) +@@ -300,11 +311,13 @@ FF_ENABLE_DEPRECATION_WARNINGS overlay_cuda_call_kernel(ctx, ctx->x_position, ctx->y_position, @@ -94,7 +103,7 @@ Index: FFmpeg/libavfilter/vf_overlay_cuda.c // overlay rest planes depending on pixel format -@@ -312,29 +328,42 @@ FF_ENABLE_DEPRECATION_WARNINGS +@@ -312,29 +325,42 @@ FF_ENABLE_DEPRECATION_WARNINGS case AV_PIX_FMT_NV12: overlay_cuda_call_kernel(ctx, ctx->x_position, ctx->y_position / 2, @@ -154,7 +163,16 @@ Index: FFmpeg/libavfilter/vf_overlay_cuda.c break; default: av_log(ctx, AV_LOG_ERROR, "Passed unsupported overlay pixel format\n"); -@@ -462,6 +491,8 @@ static int overlay_cuda_config_output(AV +@@ -406,7 +432,7 @@ static av_cold void overlay_cuda_uninit( + if (ctx->hwctx && ctx->cu_module) { + CUcontext dummy; + CudaFunctions *cu = ctx->hwctx->internal->cuda_dl; +- CHECK_CU(cu->cuCtxPushCurrent(ctx->cu_ctx)); ++ CHECK_CU(cu->cuCtxPushCurrent(ctx->hwctx->cuda_ctx)); + CHECK_CU(cu->cuModuleUnload(ctx->cu_module)); + CHECK_CU(cu->cuCtxPopCurrent(&dummy)); + } +@@ -465,6 +491,8 @@ static int overlay_cuda_config_output(AV return AVERROR(ENOSYS); } @@ -163,7 +181,7 @@ Index: FFmpeg/libavfilter/vf_overlay_cuda.c // check overlay input formats if (!frames_ctx_overlay) { -@@ -515,7 +546,13 @@ static int overlay_cuda_config_output(AV +@@ -518,7 +546,13 @@ static int overlay_cuda_config_output(AV return err; } diff --git a/debian/patches/0036-add-hdr-metadata-for-nvenc-hevc-encoder.patch b/debian/patches/0035-add-hdr-metadata-for-nvenc-hevc-encoder.patch similarity index 98% rename from debian/patches/0036-add-hdr-metadata-for-nvenc-hevc-encoder.patch rename to debian/patches/0035-add-hdr-metadata-for-nvenc-hevc-encoder.patch index 78671826d..00ff88946 100644 --- a/debian/patches/0036-add-hdr-metadata-for-nvenc-hevc-encoder.patch +++ b/debian/patches/0035-add-hdr-metadata-for-nvenc-hevc-encoder.patch @@ -5,7 +5,7 @@ Index: FFmpeg/libavcodec/nvenc.c @@ -24,6 +24,7 @@ #include "nvenc.h" - #include "hevc_sei.h" + #include "hevc/sei.h" +#include "put_bits.h" #if CONFIG_AV1_NVENC_ENCODER #include "av1.h" @@ -18,7 +18,7 @@ Index: FFmpeg/libavcodec/nvenc.c #include "libavutil/mem.h" #include "libavutil/pixdesc.h" #include "libavutil/mathematics.h" -@@ -2506,6 +2508,80 @@ static int prepare_sei_data_array(AVCode +@@ -2639,6 +2641,80 @@ static int prepare_sei_data_array(AVCode } } } diff --git a/debian/patches/0037-add-d3d11va-dxva2-hevc-422-444-decoding-on-intel.patch b/debian/patches/0036-add-d3d11va-dxva2-hevc-422-444-decoding-on-intel.patch similarity index 89% rename from debian/patches/0037-add-d3d11va-dxva2-hevc-422-444-decoding-on-intel.patch rename to debian/patches/0036-add-d3d11va-dxva2-hevc-422-444-decoding-on-intel.patch index 2199dfd96..1fb075a41 100644 --- a/debian/patches/0037-add-d3d11va-dxva2-hevc-422-444-decoding-on-intel.patch +++ b/debian/patches/0036-add-d3d11va-dxva2-hevc-422-444-decoding-on-intel.patch @@ -13,7 +13,7 @@ Index: FFmpeg/libavcodec/d3d12va_hevc.c DXVA_Slice_HEVC_Short slice_short[MAX_SLICES]; @@ -151,12 +151,12 @@ static int d3d12va_hevc_end_frame(AVCode HEVCContext *h = avctx->priv_data; - HEVCDecodePictureContext *ctx_pic = h->ref->hwaccel_picture_private; + HEVCDecodePictureContext *ctx_pic = h->cur_frame->hwaccel_picture_private; - int scale = ctx_pic->pp.dwCodingParamToolFlags & 1; + int scale = ctx_pic->pp.main.dwCodingParamToolFlags & 1; @@ -21,8 +21,8 @@ Index: FFmpeg/libavcodec/d3d12va_hevc.c if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0) return -1; -- return ff_d3d12va_common_end_frame(avctx, h->ref->frame, &ctx_pic->pp, sizeof(ctx_pic->pp), -+ return ff_d3d12va_common_end_frame(avctx, h->ref->frame, &ctx_pic->pp.main, sizeof(ctx_pic->pp.main), +- return ff_d3d12va_common_end_frame(avctx, h->cur_frame->f, &ctx_pic->pp, sizeof(ctx_pic->pp), ++ return ff_d3d12va_common_end_frame(avctx, h->cur_frame->f, &ctx_pic->pp.main, sizeof(ctx_pic->pp.main), scale ? &ctx_pic->qm : NULL, scale ? sizeof(ctx_pic->qm) : 0, update_input_arguments); } @@ -30,7 +30,7 @@ Index: FFmpeg/libavcodec/dxva2.c =================================================================== --- FFmpeg.orig/libavcodec/dxva2.c +++ FFmpeg/libavcodec/dxva2.c -@@ -43,6 +43,12 @@ DEFINE_GUID(ff_DXVA2_ModeVC1_D, +@@ -44,6 +44,12 @@ DEFINE_GUID(ff_DXVA2_ModeVC1_D, DEFINE_GUID(ff_DXVA2_ModeVC1_D2010, 0x1b81beA4, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main, 0x5b11d51b, 0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0); DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main10,0x107af0e0, 0xef1a,0x4d19,0xab,0xa8,0x67,0xa1,0x63,0x07,0x3d,0x13); @@ -43,7 +43,7 @@ Index: FFmpeg/libavcodec/dxva2.c DEFINE_GUID(ff_DXVA2_ModeVP9_VLD_Profile0,0x463707f8,0xa1d0,0x4585,0x87,0x6d,0x83,0xaa,0x6d,0x60,0xb8,0x9e); DEFINE_GUID(ff_DXVA2_ModeVP9_VLD_10bit_Profile2,0xa4c749ef,0x6ecf,0x48aa,0x84,0x48,0x50,0xa7,0xa1,0x16,0x5f,0xf7); DEFINE_GUID(ff_DXVA2_ModeAV1_VLD_Profile0,0xb8be4ccb,0xcf53,0x46ba,0x8d,0x59,0xd6,0xb8,0xa6,0xda,0x5d,0x2a); -@@ -69,6 +75,8 @@ static const int prof_hevc_main[] = { +@@ -70,6 +76,8 @@ static const int prof_hevc_main[] = { AV_PROFILE_UNKNOWN}; static const int prof_hevc_main10[] = {AV_PROFILE_HEVC_MAIN_10, AV_PROFILE_UNKNOWN}; @@ -52,7 +52,7 @@ Index: FFmpeg/libavcodec/dxva2.c static const int prof_vp9_profile0[] = {AV_PROFILE_VP9_0, AV_PROFILE_UNKNOWN}; static const int prof_vp9_profile2[] = {AV_PROFILE_VP9_2, -@@ -97,6 +105,14 @@ static const dxva_mode dxva_modes[] = { +@@ -98,6 +106,14 @@ static const dxva_mode dxva_modes[] = { { &ff_DXVA2_ModeHEVC_VLD_Main10, AV_CODEC_ID_HEVC, prof_hevc_main10 }, { &ff_DXVA2_ModeHEVC_VLD_Main, AV_CODEC_ID_HEVC, prof_hevc_main }, @@ -67,7 +67,7 @@ Index: FFmpeg/libavcodec/dxva2.c /* VP8/9 */ { &ff_DXVA2_ModeVP9_VLD_Profile0, AV_CODEC_ID_VP9, prof_vp9_profile0 }, { &ff_DXVA2_ModeVP9_VLD_10bit_Profile2, AV_CODEC_ID_VP9, prof_vp9_profile2 }, -@@ -107,6 +123,22 @@ static const dxva_mode dxva_modes[] = { +@@ -108,6 +124,22 @@ static const dxva_mode dxva_modes[] = { { NULL, 0 }, }; @@ -90,7 +90,7 @@ Index: FFmpeg/libavcodec/dxva2.c static int dxva_get_decoder_configuration(AVCodecContext *avctx, const void *cfg_list, unsigned cfg_count) -@@ -245,7 +277,14 @@ static void dxva_list_guids_debug(AVCode +@@ -246,7 +278,14 @@ static void dxva_list_guids_debug(AVCode #if CONFIG_DXVA2 if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { const D3DFORMAT formats[] = {MKTAG('N', 'V', '1', '2'), @@ -106,7 +106,7 @@ Index: FFmpeg/libavcodec/dxva2.c int i; for (i = 0; i < FF_ARRAY_ELEMS(formats); i++) { if (dxva2_validate_output(service, *guid, &formats[i])) -@@ -339,14 +378,28 @@ static int dxva2_get_decoder_configurati +@@ -340,14 +379,28 @@ static int dxva2_get_decoder_configurati return ret; } @@ -137,7 +137,7 @@ Index: FFmpeg/libavcodec/dxva2.c DXVA2_VideoDesc desc = { 0 }; DXVA2_ConfigPictureDecode config; HRESULT hr; -@@ -355,6 +408,7 @@ static int dxva2_create_decoder(AVCodecC +@@ -356,6 +409,7 @@ static int dxva2_create_decoder(AVCodecC AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx; AVDXVA2DeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; @@ -145,7 +145,7 @@ Index: FFmpeg/libavcodec/dxva2.c hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr, &device_handle); -@@ -455,10 +509,17 @@ static int d3d11va_get_decoder_configura +@@ -456,10 +510,17 @@ static int d3d11va_get_decoder_configura static DXGI_FORMAT d3d11va_map_sw_to_hw_format(enum AVPixelFormat pix_fmt) { switch (pix_fmt) { @@ -167,9 +167,9 @@ Index: FFmpeg/libavcodec/dxva2.c } } -@@ -636,8 +697,7 @@ int ff_dxva2_common_frame_params(AVCodec +@@ -627,8 +688,7 @@ int ff_dxva2_common_frame_params(AVCodec else - num_surfaces += 2; + num_surfaces += 2 + 4; /* 4 base work surface in vpp async */ - frames_ctx->sw_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? - AV_PIX_FMT_P010 : AV_PIX_FMT_NV12; @@ -190,7 +190,7 @@ Index: FFmpeg/libavcodec/dxva2_hevc.c DXVA_Qmatrix_HEVC qm; unsigned slice_count; DXVA_Slice_HEVC_Short slice_short[MAX_SLICES]; -@@ -58,19 +58,49 @@ static int get_refpic_index(const DXVA_P +@@ -58,7 +58,7 @@ static int get_refpic_index(const DXVA_P } void ff_dxva2_hevc_fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx, @@ -198,9 +198,10 @@ Index: FFmpeg/libavcodec/dxva2_hevc.c + ff_DXVA_PicParams_HEVC_Rext *ppext) { const HEVCContext *h = avctx->priv_data; - const HEVCFrame *current_picture = h->ref; - const HEVCSPS *sps = h->ps.sps; - const HEVCPPS *pps = h->ps.pps; + const HEVCLayerContext *l = &h->layers[h->cur_layer]; +@@ -66,12 +66,42 @@ void ff_dxva2_hevc_fill_picture_paramete + const HEVCPPS *pps = h->pps; + const HEVCSPS *sps = pps->sps; int i, j; + DXVA_PicParams_HEVC *pp = &ppext->main; @@ -210,16 +211,16 @@ Index: FFmpeg/libavcodec/dxva2_hevc.c pp->PicWidthInMinCbsY = sps->min_cb_width; pp->PicHeightInMinCbsY = sps->min_cb_height; -+ if (sps->sps_range_extension_flag) { -+ ppext->dwRangeExtensionFlags |= (sps->transform_skip_rotation_enabled_flag << 0) | -+ (sps->transform_skip_context_enabled_flag << 1) | -+ (sps->implicit_rdpcm_enabled_flag << 2) | -+ (sps->explicit_rdpcm_enabled_flag << 3) | -+ (sps->extended_precision_processing_flag << 4) | -+ (sps->intra_smoothing_disabled_flag << 5) | -+ (sps->high_precision_offsets_enabled_flag << 5) | -+ (sps->persistent_rice_adaptation_enabled_flag << 7) | -+ (sps->cabac_bypass_alignment_enabled_flag << 8); ++ if (sps->range_extension) { ++ ppext->dwRangeExtensionFlags |= (sps->transform_skip_rotation_enabled << 0) | ++ (sps->transform_skip_context_enabled << 1) | ++ (sps->implicit_rdpcm_enabled << 2) | ++ (sps->explicit_rdpcm_enabled << 3) | ++ (sps->extended_precision_processing << 4) | ++ (sps->intra_smoothing_disabled << 5) | ++ (sps->high_precision_offsets_enabled << 6) | ++ (sps->persistent_rice_adaptation_enabled << 7) | ++ (sps->cabac_bypass_alignment_enabled << 8); + } + if (pps->pps_range_extensions_flag) { + ppext->dwRangeExtensionFlags |= (pps->cross_component_prediction_enabled_flag << 9) | @@ -240,12 +241,12 @@ Index: FFmpeg/libavcodec/dxva2_hevc.c + } + pp->wFormatAndSequenceInfoFlags = (sps->chroma_format_idc << 0) | - (sps->separate_colour_plane_flag << 2) | + (sps->separate_colour_plane << 2) | ((sps->bit_depth - 8) << 3) | -@@ -409,14 +439,15 @@ static int dxva2_hevc_end_frame(AVCodecC +@@ -413,14 +443,15 @@ static int dxva2_hevc_end_frame(AVCodecC { HEVCContext *h = avctx->priv_data; - struct hevc_dxva2_picture_context *ctx_pic = h->ref->hwaccel_picture_private; + struct hevc_dxva2_picture_context *ctx_pic = h->cur_frame->hwaccel_picture_private; - int scale = ctx_pic->pp.dwCodingParamToolFlags & 1; + int scale = ctx_pic->pp.main.dwCodingParamToolFlags & 1; + int rext = avctx->profile == AV_PROFILE_HEVC_REXT; @@ -254,7 +255,7 @@ Index: FFmpeg/libavcodec/dxva2_hevc.c if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0) return -1; - ret = ff_dxva2_common_end_frame(avctx, h->ref->frame, + ret = ff_dxva2_common_end_frame(avctx, h->cur_frame->f, - &ctx_pic->pp, sizeof(ctx_pic->pp), + &ctx_pic->pp, rext ? sizeof(ctx_pic->pp) : sizeof(ctx_pic->pp.main), scale ? &ctx_pic->qm : NULL, scale ? sizeof(ctx_pic->qm) : 0, @@ -334,11 +335,11 @@ Index: FFmpeg/libavcodec/dxva2_internal.h void ff_dxva2_hevc_fill_scaling_lists(const AVCodecContext *avctx, AVDXVAContext *ctx, DXVA_Qmatrix_HEVC *qm); -Index: FFmpeg/libavcodec/hevcdec.c +Index: FFmpeg/libavcodec/hevc/hevcdec.c =================================================================== ---- FFmpeg.orig/libavcodec/hevcdec.c -+++ FFmpeg/libavcodec/hevcdec.c -@@ -465,6 +465,13 @@ static enum AVPixelFormat get_format(HEV +--- FFmpeg.orig/libavcodec/hevc/hevcdec.c ++++ FFmpeg/libavcodec/hevc/hevcdec.c +@@ -592,6 +592,13 @@ static enum AVPixelFormat get_format(HEV #endif break; case AV_PIX_FMT_YUV444P: @@ -352,7 +353,7 @@ Index: FFmpeg/libavcodec/hevcdec.c #if CONFIG_HEVC_VAAPI_HWACCEL *fmt++ = AV_PIX_FMT_VAAPI; #endif -@@ -483,6 +490,13 @@ static enum AVPixelFormat get_format(HEV +@@ -610,6 +617,13 @@ static enum AVPixelFormat get_format(HEV break; case AV_PIX_FMT_YUV422P: case AV_PIX_FMT_YUV422P10LE: @@ -366,7 +367,7 @@ Index: FFmpeg/libavcodec/hevcdec.c #if CONFIG_HEVC_VAAPI_HWACCEL *fmt++ = AV_PIX_FMT_VAAPI; #endif -@@ -500,6 +514,13 @@ static enum AVPixelFormat get_format(HEV +@@ -627,6 +641,13 @@ static enum AVPixelFormat get_format(HEV /* NOTE: fallthrough */ case AV_PIX_FMT_YUV420P12: case AV_PIX_FMT_YUV444P12: @@ -380,7 +381,7 @@ Index: FFmpeg/libavcodec/hevcdec.c #if CONFIG_HEVC_VAAPI_HWACCEL *fmt++ = AV_PIX_FMT_VAAPI; #endif -@@ -514,6 +535,13 @@ static enum AVPixelFormat get_format(HEV +@@ -641,6 +662,13 @@ static enum AVPixelFormat get_format(HEV #endif break; case AV_PIX_FMT_YUV422P12: diff --git a/debian/patches/0038-default-vaapi-scaler-algorithm-to-fast.patch b/debian/patches/0037-default-vaapi-scaler-algorithm-to-fast.patch similarity index 100% rename from debian/patches/0038-default-vaapi-scaler-algorithm-to-fast.patch rename to debian/patches/0037-default-vaapi-scaler-algorithm-to-fast.patch diff --git a/debian/patches/0039-dont-fail-on-vaapi-to-drm-export-vasync.patch b/debian/patches/0038-dont-fail-on-vaapi-to-drm-export-vasync.patch similarity index 100% rename from debian/patches/0039-dont-fail-on-vaapi-to-drm-export-vasync.patch rename to debian/patches/0038-dont-fail-on-vaapi-to-drm-export-vasync.patch diff --git a/debian/patches/0040-skip-loading-plugins-on-vpl-runtime.patch b/debian/patches/0039-skip-loading-plugins-on-vpl-runtime.patch similarity index 91% rename from debian/patches/0040-skip-loading-plugins-on-vpl-runtime.patch rename to debian/patches/0039-skip-loading-plugins-on-vpl-runtime.patch index 8477c9ffa..acaab4b74 100644 --- a/debian/patches/0040-skip-loading-plugins-on-vpl-runtime.patch +++ b/debian/patches/0039-skip-loading-plugins-on-vpl-runtime.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavcodec/qsv.c =================================================================== --- FFmpeg.orig/libavcodec/qsv.c +++ FFmpeg/libavcodec/qsv.c -@@ -406,9 +406,17 @@ static int qsv_load_plugins(mfxSession s +@@ -409,9 +409,17 @@ static int qsv_load_plugins(mfxSession s void *logctx) { #if QSV_HAVE_USER_PLUGIN diff --git a/debian/patches/0041-tune-the-default-bf-for-qsv-enc.patch b/debian/patches/0040-tune-the-default-bf-for-qsv-enc.patch similarity index 93% rename from debian/patches/0041-tune-the-default-bf-for-qsv-enc.patch rename to debian/patches/0040-tune-the-default-bf-for-qsv-enc.patch index b2093eeea..3a3dd2844 100644 --- a/debian/patches/0041-tune-the-default-bf-for-qsv-enc.patch +++ b/debian/patches/0040-tune-the-default-bf-for-qsv-enc.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavcodec/qsvenc_av1.c =================================================================== --- FFmpeg.orig/libavcodec/qsvenc_av1.c +++ FFmpeg/libavcodec/qsvenc_av1.c -@@ -203,8 +203,8 @@ static const AVClass class = { +@@ -201,8 +201,8 @@ static const AVClass class = { static const FFCodecDefault qsv_enc_defaults[] = { { "b", "0" }, @@ -32,7 +32,7 @@ Index: FFmpeg/libavcodec/qsvenc_hevc.c =================================================================== --- FFmpeg.orig/libavcodec/qsvenc_hevc.c +++ FFmpeg/libavcodec/qsvenc_hevc.c -@@ -379,8 +379,8 @@ static const AVClass class = { +@@ -381,8 +381,8 @@ static const AVClass class = { static const FFCodecDefault qsv_enc_defaults[] = { { "b", "0" }, { "refs", "0" }, diff --git a/debian/patches/0042-allow-vaapi-import-drm-prime2-planar-formats.patch b/debian/patches/0041-allow-vaapi-import-drm-prime2-planar-formats.patch similarity index 100% rename from debian/patches/0042-allow-vaapi-import-drm-prime2-planar-formats.patch rename to debian/patches/0041-allow-vaapi-import-drm-prime2-planar-formats.patch diff --git a/debian/patches/0043-add-vui-info-to-the-seq-header-of-hevc-vaapi-encoder.patch b/debian/patches/0042-add-vui-info-to-the-seq-header-of-hevc-vaapi-encoder.patch similarity index 73% rename from debian/patches/0043-add-vui-info-to-the-seq-header-of-hevc-vaapi-encoder.patch rename to debian/patches/0042-add-vui-info-to-the-seq-header-of-hevc-vaapi-encoder.patch index d4f83cb2f..fee818b5c 100644 --- a/debian/patches/0043-add-vui-info-to-the-seq-header-of-hevc-vaapi-encoder.patch +++ b/debian/patches/0042-add-vui-info-to-the-seq-header-of-hevc-vaapi-encoder.patch @@ -2,7 +2,15 @@ Index: FFmpeg/libavcodec/vaapi_encode_h265.c =================================================================== --- FFmpeg.orig/libavcodec/vaapi_encode_h265.c +++ FFmpeg/libavcodec/vaapi_encode_h265.c -@@ -691,7 +691,25 @@ static int vaapi_encode_h265_init_sequen +@@ -264,6 +264,7 @@ static int vaapi_encode_h265_init_sequen + H265RawVPS *vps = &priv->units.raw_vps; + H265RawSPS *sps = &priv->units.raw_sps; + H265RawPPS *pps = &priv->units.raw_pps; ++ H265RawVUI *vui = &sps->vui; + VAEncSequenceParameterBufferHEVC *vseq = ctx->codec_sequence_params; + VAEncPictureParameterBufferHEVC *vpic = ctx->codec_picture_params; + int i, err; +@@ -391,7 +392,25 @@ static int vaapi_encode_h265_init_sequen sps->log2_min_pcm_luma_coding_block_size_minus3 + sps->log2_diff_max_min_pcm_luma_coding_block_size, diff --git a/debian/patches/0044-sync-intel-d3d11va-textures-before-mapping-to-opencl.patch b/debian/patches/0043-sync-intel-d3d11va-textures-before-mapping-to-opencl.patch similarity index 98% rename from debian/patches/0044-sync-intel-d3d11va-textures-before-mapping-to-opencl.patch rename to debian/patches/0043-sync-intel-d3d11va-textures-before-mapping-to-opencl.patch index 323cecbb7..b341d1b24 100644 --- a/debian/patches/0044-sync-intel-d3d11va-textures-before-mapping-to-opencl.patch +++ b/debian/patches/0043-sync-intel-d3d11va-textures-before-mapping-to-opencl.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavcodec/dxva2.c =================================================================== --- FFmpeg.orig/libavcodec/dxva2.c +++ FFmpeg/libavcodec/dxva2.c -@@ -714,8 +714,10 @@ int ff_dxva2_common_frame_params(AVCodec +@@ -715,8 +715,10 @@ int ff_dxva2_common_frame_params(AVCodec #if CONFIG_D3D11VA if (frames_ctx->format == AV_PIX_FMT_D3D11) { AVD3D11VAFramesContext *frames_hwctx = frames_ctx->hwctx; @@ -17,7 +17,7 @@ Index: FFmpeg/libavfilter/qsvvpp.c =================================================================== --- FFmpeg.orig/libavfilter/qsvvpp.c +++ FFmpeg/libavfilter/qsvvpp.c -@@ -641,6 +641,9 @@ static int init_vpp_session(AVFilterCont +@@ -657,6 +657,9 @@ static int init_vpp_session(AVFilterCont out_frames_hwctx->frame_type = s->out_mem_mode; diff --git a/debian/patches/0045-add-icon-for-windows-version-ffmpeg.patch b/debian/patches/0044-add-icon-for-windows-version-ffmpeg.patch similarity index 100% rename from debian/patches/0045-add-icon-for-windows-version-ffmpeg.patch rename to debian/patches/0044-add-icon-for-windows-version-ffmpeg.patch diff --git a/debian/patches/0046-fix-libx265-encoded-fmp4-hls-playback-on-safari.patch b/debian/patches/0045-fix-libx265-encoded-fmp4-hls-playback-on-safari.patch similarity index 91% rename from debian/patches/0046-fix-libx265-encoded-fmp4-hls-playback-on-safari.patch rename to debian/patches/0045-fix-libx265-encoded-fmp4-hls-playback-on-safari.patch index 40d0364c0..b513949c7 100644 --- a/debian/patches/0046-fix-libx265-encoded-fmp4-hls-playback-on-safari.patch +++ b/debian/patches/0045-fix-libx265-encoded-fmp4-hls-playback-on-safari.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavformat/movenc.c =================================================================== --- FFmpeg.orig/libavformat/movenc.c +++ FFmpeg/libavformat/movenc.c -@@ -2908,7 +2908,7 @@ static int mov_write_stbl_tag(AVFormatCo +@@ -3202,7 +3202,7 @@ static int mov_write_stbl_tag(AVFormatCo track->par->codec_tag == MKTAG('r','t','p',' ')) && track->has_keyframes && track->has_keyframes < track->entry) mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE); diff --git a/debian/patches/0047-add-full-hwa-pipeline-for-rockchip-rk3588-platform.patch b/debian/patches/0046-add-full-hwa-pipeline-for-rockchip-rk3588-platform.patch similarity index 97% rename from debian/patches/0047-add-full-hwa-pipeline-for-rockchip-rk3588-platform.patch rename to debian/patches/0046-add-full-hwa-pipeline-for-rockchip-rk3588-platform.patch index 55e199aed..78163631b 100644 --- a/debian/patches/0047-add-full-hwa-pipeline-for-rockchip-rk3588-platform.patch +++ b/debian/patches/0046-add-full-hwa-pipeline-for-rockchip-rk3588-platform.patch @@ -2,7 +2,7 @@ Index: FFmpeg/configure =================================================================== --- FFmpeg.orig/configure +++ FFmpeg/configure -@@ -354,6 +354,7 @@ External library support: +@@ -358,6 +358,7 @@ External library support: --enable-omx enable OpenMAX IL code [no] --enable-omx-rpi enable OpenMAX IL code for Raspberry Pi [no] --enable-rkmpp enable Rockchip Media Process Platform code [no] @@ -10,7 +10,7 @@ Index: FFmpeg/configure --disable-v4l2-m2m disable V4L2 mem2mem code [autodetect] --disable-vaapi disable Video Acceleration API (mainly Unix/Intel) code [autodetect] --disable-vdpau disable Nvidia Video Decode and Presentation API for Unix code [autodetect] -@@ -1884,6 +1885,7 @@ EXTERNAL_LIBRARY_VERSION3_LIST=" +@@ -1888,6 +1889,7 @@ EXTERNAL_LIBRARY_VERSION3_LIST=" libvo_amrwbenc mbedtls rkmpp @@ -18,7 +18,7 @@ Index: FFmpeg/configure " EXTERNAL_LIBRARY_GPLV3_LIST=" -@@ -2018,6 +2020,7 @@ HWACCEL_LIBRARY_LIST=" +@@ -2025,6 +2027,7 @@ HWACCEL_LIBRARY_LIST=" mmal omx opencl @@ -26,10 +26,10 @@ Index: FFmpeg/configure " DOCUMENT_LIST=" -@@ -3312,8 +3315,10 @@ av1_mediacodec_decoder_deps="mediacodec" - av1_mediacodec_encoder_deps="mediacodec" - av1_nvenc_encoder_deps="nvenc NV_ENC_PIC_PARAMS_AV1" - av1_nvenc_encoder_select="atsc_a53" +@@ -3345,8 +3348,10 @@ av1_qsv_encoder_deps="libvpl" + av1_qsv_encoder_select="qsvenc" + av1_vaapi_encoder_deps="VAEncPictureParameterBufferAV1" + av1_vaapi_encoder_select="cbs_av1 vaapi_encode" +av1_rkmpp_decoder_deps="rkmpp" h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m" h263_v4l2m2m_encoder_deps="v4l2_m2m h263_v4l2_m2m" @@ -37,37 +37,37 @@ Index: FFmpeg/configure h264_amf_encoder_deps="amf" h264_cuvid_decoder_deps="cuvid" h264_cuvid_decoder_select="h264_mp4toannexb_bsf" -@@ -3330,6 +3335,7 @@ h264_qsv_decoder_select="h264_mp4toannex +@@ -3363,6 +3368,7 @@ h264_qsv_decoder_select="h264_mp4toannex h264_qsv_encoder_select="atsc_a53 qsvenc" h264_rkmpp_decoder_deps="rkmpp" h264_rkmpp_decoder_select="h264_mp4toannexb_bsf" +h264_rkmpp_encoder_deps="rkmpp" h264_vaapi_encoder_select="atsc_a53 cbs_h264 vaapi_encode" + h264_vulkan_encoder_select="cbs_h264 vulkan_encode" h264_v4l2m2m_decoder_deps="v4l2_m2m h264_v4l2_m2m" - h264_v4l2m2m_decoder_select="h264_mp4toannexb_bsf" -@@ -3348,6 +3354,7 @@ hevc_qsv_decoder_select="hevc_mp4toannex +@@ -3383,6 +3389,7 @@ hevc_qsv_decoder_select="hevc_mp4toannex hevc_qsv_encoder_select="hevcparse qsvenc" hevc_rkmpp_decoder_deps="rkmpp" hevc_rkmpp_decoder_select="hevc_mp4toannexb_bsf" +hevc_rkmpp_encoder_deps="rkmpp" hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC" hevc_vaapi_encoder_select="atsc_a53 cbs_h265 vaapi_encode" - hevc_v4l2m2m_decoder_deps="v4l2_m2m hevc_v4l2_m2m" -@@ -3357,11 +3364,13 @@ mjpeg_cuvid_decoder_deps="cuvid" - mjpeg_qsv_decoder_select="qsvdec" - mjpeg_qsv_encoder_deps="libmfx" + hevc_vulkan_encoder_select="atsc_a53 cbs_h265 vulkan_encode" +@@ -3395,11 +3402,13 @@ mjpeg_qsv_encoder_deps="libmfx" mjpeg_qsv_encoder_select="qsvenc" -+mjpeg_rkmpp_encoder_deps="rkmpp" mjpeg_vaapi_encoder_deps="VAEncPictureParameterBufferJPEG" mjpeg_vaapi_encoder_select="cbs_jpeg jpegtables vaapi_encode" ++mjpeg_rkmpp_encoder_deps="rkmpp" mp3_mf_encoder_deps="mediafoundation" + mp3_mediacodec_decoder_deps="mediacodec" + mp3_mediacodec_decoder_select="mpegaudioheader" mpeg1_cuvid_decoder_deps="cuvid" mpeg1_v4l2m2m_decoder_deps="v4l2_m2m mpeg1_v4l2_m2m" +mpeg1_rkmpp_decoder_deps="rkmpp" mpeg2_cuvid_decoder_deps="cuvid" mpeg2_mmal_decoder_deps="mmal" mpeg2_mediacodec_decoder_deps="mediacodec" -@@ -3369,6 +3378,7 @@ mpeg2_qsv_decoder_select="qsvdec" +@@ -3407,6 +3416,7 @@ mpeg2_qsv_decoder_select="qsvdec" mpeg2_qsv_encoder_select="qsvenc" mpeg2_vaapi_encoder_select="cbs_mpeg2 vaapi_encode" mpeg2_v4l2m2m_decoder_deps="v4l2_m2m mpeg2_v4l2_m2m" @@ -75,7 +75,7 @@ Index: FFmpeg/configure mpeg4_cuvid_decoder_deps="cuvid" mpeg4_mediacodec_decoder_deps="mediacodec" mpeg4_mediacodec_encoder_deps="mediacodec" -@@ -3376,6 +3386,8 @@ mpeg4_mmal_decoder_deps="mmal" +@@ -3415,6 +3425,8 @@ mpeg4_mmal_decoder_deps="mmal" mpeg4_omx_encoder_deps="omx" mpeg4_v4l2m2m_decoder_deps="v4l2_m2m mpeg4_v4l2_m2m" mpeg4_v4l2m2m_encoder_deps="v4l2_m2m mpeg4_v4l2_m2m" @@ -84,7 +84,7 @@ Index: FFmpeg/configure vc1_cuvid_decoder_deps="cuvid" vc1_mmal_decoder_deps="mmal" vc1_qsv_decoder_select="qsvdec" -@@ -3872,6 +3884,7 @@ overlay_qsv_filter_deps="libmfx" +@@ -3917,6 +3929,7 @@ overlay_qsv_filter_deps="libmfx" overlay_qsv_filter_select="qsvvpp" overlay_vaapi_filter_deps="vaapi VAProcPipelineCaps_blend_flags" overlay_vulkan_filter_deps="vulkan spirv_compiler" @@ -92,7 +92,7 @@ Index: FFmpeg/configure owdenoise_filter_deps="gpl" pad_opencl_filter_deps="opencl" pan_filter_deps="swresample" -@@ -3894,6 +3907,7 @@ scale_filter_deps="swscale" +@@ -3939,6 +3952,7 @@ scale_filter_deps="swscale" scale_opencl_filter_deps="opencl" scale_qsv_filter_deps="libmfx" scale_qsv_filter_select="qsvvpp" @@ -100,7 +100,7 @@ Index: FFmpeg/configure scdet_filter_select="scene_sad" select_filter_select="scene_sad" sharpness_vaapi_filter_deps="vaapi" -@@ -3937,6 +3951,7 @@ scale_vt_filter_deps="videotoolbox VTPix +@@ -3982,6 +3996,7 @@ scale_vt_filter_deps="videotoolbox VTPix scale_vulkan_filter_deps="vulkan spirv_compiler" vpp_qsv_filter_deps="libmfx" vpp_qsv_filter_select="qsvvpp" @@ -108,12 +108,12 @@ Index: FFmpeg/configure xfade_opencl_filter_deps="opencl" xfade_vulkan_filter_deps="vulkan spirv_compiler" yadif_cuda_filter_deps="ffnvcodec" -@@ -3984,14 +3999,14 @@ cws2fws_extralibs="zlib_extralibs" +@@ -4031,14 +4046,14 @@ cws2fws_extralibs="zlib_extralibs" # libraries, in any order avcodec_deps="avutil" --avcodec_suggest="libm stdatomic" -+avcodec_suggest="libm stdatomic rkrga" +-avcodec_suggest="libm stdatomic liblcevc_dec" ++avcodec_suggest="libm stdatomic liblcevc_dec rkrga" avdevice_deps="avformat avcodec avutil" avdevice_suggest="libm stdatomic" avfilter_deps="avutil" @@ -125,7 +125,7 @@ Index: FFmpeg/configure postproc_deps="avutil gpl" postproc_suggest="libm stdatomic" swresample_deps="avutil" -@@ -7068,11 +7083,16 @@ enabled openssl && { { check_p +@@ -7112,11 +7127,16 @@ enabled openssl && { { check_p check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 || die "ERROR: openssl not found"; } enabled pocketsphinx && require_pkg_config pocketsphinx pocketsphinx pocketsphinx/pocketsphinx.h ps_init @@ -141,10 +141,10 @@ Index: FFmpeg/configure + { enabled rkmpp || + die "ERROR: rkrga requires --enable-rkmpp"; } + } - enabled vapoursynth && require_pkg_config vapoursynth "vapoursynth-script >= 42" VSScript.h vsscript_init + enabled vapoursynth && require_headers "vapoursynth/VSScript4.h vapoursynth/VapourSynth4.h" -@@ -7272,7 +7292,7 @@ fi +@@ -7318,7 +7338,7 @@ fi if enabled_all opencl libdrm ; then check_type "CL/cl_intel.h" "clCreateImageFromFdINTEL_fn" && enable opencl_drm_beignet @@ -157,7 +157,7 @@ Index: FFmpeg/libavcodec/Makefile =================================================================== --- FFmpeg.orig/libavcodec/Makefile +++ FFmpeg/libavcodec/Makefile -@@ -259,6 +259,7 @@ OBJS-$(CONFIG_AV1_MEDIACODEC_ENCODER) + +@@ -268,6 +268,7 @@ OBJS-$(CONFIG_AV1_MEDIACODEC_ENCODER) + OBJS-$(CONFIG_AV1_NVENC_ENCODER) += nvenc_av1.o nvenc.o OBJS-$(CONFIG_AV1_QSV_ENCODER) += qsvenc_av1.o OBJS-$(CONFIG_AV1_VAAPI_ENCODER) += vaapi_encode_av1.o av1_levels.o @@ -165,7 +165,7 @@ Index: FFmpeg/libavcodec/Makefile OBJS-$(CONFIG_AVRN_DECODER) += avrndec.o OBJS-$(CONFIG_AVRP_DECODER) += r210dec.o OBJS-$(CONFIG_AVRP_ENCODER) += r210enc.o -@@ -402,6 +403,7 @@ OBJS-$(CONFIG_H263_ENCODER) + +@@ -409,6 +410,7 @@ OBJS-$(CONFIG_H263_ENCODER) + h263.o ituh263enc.o h263data.o OBJS-$(CONFIG_H263_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_H263_V4L2M2M_ENCODER) += v4l2_m2m_enc.o @@ -173,31 +173,31 @@ Index: FFmpeg/libavcodec/Makefile OBJS-$(CONFIG_H264_DECODER) += h264dec.o h264_cabac.o h264_cavlc.o \ h264_direct.o h264_loopfilter.o \ h264_mb.o h264_picture.o \ -@@ -418,6 +420,7 @@ OBJS-$(CONFIG_H264_OMX_ENCODER) + +@@ -425,6 +427,7 @@ OBJS-$(CONFIG_H264_OMX_ENCODER) + OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec.o OBJS-$(CONFIG_H264_QSV_ENCODER) += qsvenc_h264.o OBJS-$(CONFIG_H264_RKMPP_DECODER) += rkmppdec.o +OBJS-$(CONFIG_H264_RKMPP_ENCODER) += rkmppenc.o OBJS-$(CONFIG_H264_VAAPI_ENCODER) += vaapi_encode_h264.o h264_levels.o \ - h2645data.o - OBJS-$(CONFIG_H264_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o -@@ -443,6 +446,7 @@ OBJS-$(CONFIG_HEVC_QSV_DECODER) + - OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o \ - hevc_data.o + h2645data.o hw_base_encode_h264.o + OBJS-$(CONFIG_H264_VULKAN_ENCODER) += vulkan_encode.o vulkan_encode_h264.o \ +@@ -451,6 +454,7 @@ OBJS-$(CONFIG_HEVC_NVENC_ENCODER) + + OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec.o + OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc/ps_enc.o OBJS-$(CONFIG_HEVC_RKMPP_DECODER) += rkmppdec.o +OBJS-$(CONFIG_HEVC_RKMPP_ENCODER) += rkmppenc.o OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o h265_profile_level.o \ - h2645data.o - OBJS-$(CONFIG_HEVC_V4L2M2M_DECODER) += v4l2_m2m_dec.o -@@ -502,6 +506,7 @@ OBJS-$(CONFIG_MJPEG_ENCODER) + - OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o + h2645data.o hw_base_encode_h265.o + OBJS-$(CONFIG_HEVC_VULKAN_ENCODER) += vulkan_encode.o vulkan_encode_h265.o \ +@@ -514,6 +518,7 @@ OBJS-$(CONFIG_MJPEGB_DECODER) + OBJS-$(CONFIG_MJPEG_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_MJPEG_QSV_ENCODER) += qsvenc_jpeg.o -+OBJS-$(CONFIG_MJPEG_RKMPP_ENCODER) += rkmppenc.o OBJS-$(CONFIG_MJPEG_VAAPI_ENCODER) += vaapi_encode_mjpeg.o ++OBJS-$(CONFIG_MJPEG_RKMPP_ENCODER) += rkmppenc.o OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o OBJS-$(CONFIG_MLP_ENCODER) += mlpenc.o mlp.o -@@ -534,6 +539,7 @@ OBJS-$(CONFIG_MPEG1VIDEO_DECODER) + + OBJS-$(CONFIG_MMVIDEO_DECODER) += mmvideo.o +@@ -546,6 +551,7 @@ OBJS-$(CONFIG_MPEG1VIDEO_DECODER) + OBJS-$(CONFIG_MPEG1VIDEO_ENCODER) += mpeg12enc.o mpeg12.o OBJS-$(CONFIG_MPEG1_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_MPEG1_V4L2M2M_DECODER) += v4l2_m2m_dec.o @@ -205,7 +205,7 @@ Index: FFmpeg/libavcodec/Makefile OBJS-$(CONFIG_MPEG2_MMAL_DECODER) += mmaldec.o OBJS-$(CONFIG_MPEG2_QSV_DECODER) += qsvdec.o OBJS-$(CONFIG_MPEG2_QSV_ENCODER) += qsvenc_mpeg2.o -@@ -543,6 +549,7 @@ OBJS-$(CONFIG_MPEG2_CUVID_DECODER) + +@@ -555,6 +561,7 @@ OBJS-$(CONFIG_MPEG2_CUVID_DECODER) + OBJS-$(CONFIG_MPEG2_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_MPEG2_VAAPI_ENCODER) += vaapi_encode_mpeg2.o OBJS-$(CONFIG_MPEG2_V4L2M2M_DECODER) += v4l2_m2m_dec.o @@ -213,7 +213,7 @@ Index: FFmpeg/libavcodec/Makefile OBJS-$(CONFIG_MPEG4_DECODER) += mpeg4videodsp.o xvididct.o OBJS-$(CONFIG_MPEG4_ENCODER) += mpeg4videoenc.o OBJS-$(CONFIG_MPEG4_CUVID_DECODER) += cuviddec.o -@@ -551,6 +558,7 @@ OBJS-$(CONFIG_MPEG4_MEDIACODEC_ENCODER) +@@ -563,6 +570,7 @@ OBJS-$(CONFIG_MPEG4_MEDIACODEC_ENCODER) OBJS-$(CONFIG_MPEG4_OMX_ENCODER) += omx.o OBJS-$(CONFIG_MPEG4_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_MPEG4_V4L2M2M_ENCODER) += v4l2_m2m_enc.o @@ -225,7 +225,7 @@ Index: FFmpeg/libavcodec/allcodecs.c =================================================================== --- FFmpeg.orig/libavcodec/allcodecs.c +++ FFmpeg/libavcodec/allcodecs.c -@@ -147,6 +147,7 @@ extern const FFCodec ff_h263i_decoder; +@@ -146,6 +146,7 @@ extern const FFCodec ff_h263i_decoder; extern const FFCodec ff_h263p_encoder; extern const FFCodec ff_h263p_decoder; extern const FFCodec ff_h263_v4l2m2m_decoder; @@ -233,7 +233,7 @@ Index: FFmpeg/libavcodec/allcodecs.c extern const FFCodec ff_h264_decoder; extern const FFCodec ff_h264_v4l2m2m_decoder; extern const FFCodec ff_h264_mediacodec_decoder; -@@ -208,12 +209,15 @@ extern const FFCodec ff_mpeg4_encoder; +@@ -207,12 +208,15 @@ extern const FFCodec ff_mpeg4_encoder; extern const FFCodec ff_mpeg4_decoder; extern const FFCodec ff_mpeg4_v4l2m2m_decoder; extern const FFCodec ff_mpeg4_mmal_decoder; @@ -249,7 +249,7 @@ Index: FFmpeg/libavcodec/allcodecs.c extern const FFCodec ff_msa1_decoder; extern const FFCodec ff_mscc_decoder; extern const FFCodec ff_msmpeg4v1_decoder; -@@ -842,6 +846,7 @@ extern const FFCodec ff_av1_qsv_decoder; +@@ -839,6 +843,7 @@ extern const FFCodec ff_av1_qsv_decoder; extern const FFCodec ff_av1_qsv_encoder; extern const FFCodec ff_av1_amf_encoder; extern const FFCodec ff_av1_vaapi_encoder; @@ -257,25 +257,26 @@ Index: FFmpeg/libavcodec/allcodecs.c extern const FFCodec ff_libopenh264_encoder; extern const FFCodec ff_libopenh264_decoder; extern const FFCodec ff_h264_amf_encoder; -@@ -853,6 +858,7 @@ extern const FFCodec ff_h264_qsv_encoder - extern const FFCodec ff_h264_v4l2m2m_encoder; +@@ -851,6 +856,7 @@ extern const FFCodec ff_h264_v4l2m2m_enc extern const FFCodec ff_h264_vaapi_encoder; extern const FFCodec ff_h264_videotoolbox_encoder; + extern const FFCodec ff_h264_vulkan_encoder; +extern const FFCodec ff_h264_rkmpp_encoder; extern const FFCodec ff_hevc_amf_encoder; extern const FFCodec ff_hevc_cuvid_decoder; - extern const FFCodec ff_hevc_mediacodec_decoder; -@@ -863,10 +869,12 @@ extern const FFCodec ff_hevc_qsv_encoder - extern const FFCodec ff_hevc_v4l2m2m_encoder; + extern const FFCodec ff_hevc_d3d12va_encoder; +@@ -863,11 +869,13 @@ extern const FFCodec ff_hevc_v4l2m2m_enc extern const FFCodec ff_hevc_vaapi_encoder; extern const FFCodec ff_hevc_videotoolbox_encoder; + extern const FFCodec ff_hevc_vulkan_encoder; +extern const FFCodec ff_hevc_rkmpp_encoder; extern const FFCodec ff_libkvazaar_encoder; extern const FFCodec ff_mjpeg_cuvid_decoder; extern const FFCodec ff_mjpeg_qsv_encoder; extern const FFCodec ff_mjpeg_qsv_decoder; -+extern const FFCodec ff_mjpeg_rkmpp_encoder; extern const FFCodec ff_mjpeg_vaapi_encoder; ++extern const FFCodec ff_mjpeg_rkmpp_encoder; + extern const FFCodec ff_mp3_mediacodec_decoder; extern const FFCodec ff_mp3_mf_encoder; extern const FFCodec ff_mpeg1_cuvid_decoder; Index: FFmpeg/libavcodec/rkmppdec.c @@ -291,7 +292,7 @@ Index: FFmpeg/libavcodec/rkmppdec.c * * This file is part of FFmpeg. * -@@ -19,569 +20,1025 @@ +@@ -19,551 +20,1029 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -310,6 +311,7 @@ Index: FFmpeg/libavcodec/rkmppdec.c -#include "codec_internal.h" -#include "decode.h" -#include "hwconfig.h" +-#include "refstruct.h" -#include "libavutil/buffer.h" -#include "libavutil/common.h" -#include "libavutil/frame.h" @@ -317,6 +319,7 @@ Index: FFmpeg/libavcodec/rkmppdec.c -#include "libavutil/hwcontext_drm.h" -#include "libavutil/imgutils.h" -#include "libavutil/log.h" +-#include "libavutil/mem.h" - -#define RECEIVE_FRAME_TIMEOUT 100 -#define FRAMEGROUP_MAX_FRAMES 16 @@ -336,12 +339,12 @@ Index: FFmpeg/libavcodec/rkmppdec.c - -typedef struct { - AVClass *av_class; -- AVBufferRef *decoder_ref; +- RKMPPDecoder *decoder; ///< RefStruct reference -} RKMPPDecodeContext; - -typedef struct { - MppFrame frame; -- AVBufferRef *decoder_ref; +- const RKMPPDecoder *decoder_ref; ///< RefStruct reference -} RKMPPFrameContext; +#include "config.h" +#include "config_components.h" @@ -393,7 +396,7 @@ Index: FFmpeg/libavcodec/rkmppdec.c +static uint32_t rkmpp_get_drm_afbc_format(MppFrameFormat mpp_fmt) { - RKMPPDecodeContext *rk_context = avctx->priv_data; -- RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; +- RKMPPDecoder *decoder = rk_context->decoder; - int ret; - MppPacket packet; - @@ -448,7 +451,7 @@ Index: FFmpeg/libavcodec/rkmppdec.c + int *stride, int reverse) { - RKMPPDecodeContext *rk_context = avctx->priv_data; -- av_buffer_unref(&rk_context->decoder_ref); +- ff_refstruct_unref(&rk_context->decoder); - return 0; + if (!desc || !stride || *stride <= 0) + return AVERROR(EINVAL); @@ -471,10 +474,10 @@ Index: FFmpeg/libavcodec/rkmppdec.c + return (*stride > 0) ? 0 : AVERROR(EINVAL); } --static void rkmpp_release_decoder(void *opaque, uint8_t *data) +-static void rkmpp_release_decoder(FFRefStructOpaque unused, void *obj) +static void read_soc_name(AVCodecContext *avctx, char *name, int size) { -- RKMPPDecoder *decoder = (RKMPPDecoder *)data; +- RKMPPDecoder *decoder = obj; + const char *dt_path = "/proc/device-tree/compatible"; + int fd = open(dt_path, O_RDONLY); @@ -499,23 +502,32 @@ Index: FFmpeg/libavcodec/rkmppdec.c + break; + *ptr = ' '; + } -+ -+ av_log(avctx, AV_LOG_VERBOSE, "Found SoC name from device-tree: '%s'\n", name); -+ } - if (decoder->frame_group) { - mpp_buffer_group_put(decoder->frame_group); - decoder->frame_group = NULL; -+ close(fd); - } -+} -+ -+static av_cold int rkmpp_decode_close(AVCodecContext *avctx) -+{ -+ RKMPPDecContext *r = avctx->priv_data; +- } ++ av_log(avctx, AV_LOG_VERBOSE, "Found SoC name from device-tree: '%s'\n", name); ++ } - av_buffer_unref(&decoder->frames_ref); - av_buffer_unref(&decoder->device_ref); ++ close(fd); ++ } + } + +-static int rkmpp_init_decoder(AVCodecContext *avctx) ++static av_cold int rkmpp_decode_close(AVCodecContext *avctx) + { +- RKMPPDecodeContext *rk_context = avctx->priv_data; +- RKMPPDecoder *decoder = NULL; +- MppCodingType codectype = MPP_VIDEO_CodingUnused; +- int ret; +- RK_S64 paramS64; +- RK_S32 paramS32; ++ RKMPPDecContext *r = avctx->priv_data; + +- avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME; + r->eof = 0; + r->draining = 0; + r->info_change = 0; @@ -538,21 +550,17 @@ Index: FFmpeg/libavcodec/rkmppdec.c + if (r->hwdevice) + av_buffer_unref(&r->hwdevice); -- av_free(decoder); +- // create a decoder and a ref to it +- decoder = ff_refstruct_alloc_ext(sizeof(*decoder), 0, +- NULL, rkmpp_release_decoder); +- if (!decoder) { +- ret = AVERROR(ENOMEM); +- goto fail; + return 0; - } - --static int rkmpp_init_decoder(AVCodecContext *avctx) ++} ++ +static av_cold int rkmpp_decode_init(AVCodecContext *avctx) - { -- RKMPPDecodeContext *rk_context = avctx->priv_data; -- RKMPPDecoder *decoder = NULL; -- MppCodingType codectype = MPP_VIDEO_CodingUnused; -- int ret; -- RK_S64 paramS64; -- RK_S32 paramS32; -- -- avctx->pix_fmt = AV_PIX_FMT_DRM_PRIME; ++{ + RKMPPDecContext *r = avctx->priv_data; + MppCodingType coding_type = MPP_VIDEO_CodingUnused; + char soc_name[MAX_SOC_NAME_LENGTH]; @@ -607,32 +615,21 @@ Index: FFmpeg/libavcodec/rkmppdec.c + avcodec_get_name(avctx->codec_id), av_get_pix_fmt_name(avctx->pix_fmt)); + return AVERROR(ENOSYS); + } - -- // create a decoder and a ref to it -- decoder = av_mallocz(sizeof(RKMPPDecoder)); -- if (!decoder) { -- ret = AVERROR(ENOMEM); -- goto fail; ++ + if ((ret = ff_get_format(avctx, pix_fmts)) < 0) { + av_log(avctx, AV_LOG_ERROR, "ff_get_format failed: %d\n", ret); + return ret; + } + avctx->pix_fmt = ret; } +- rk_context->decoder = decoder; -- rk_context->decoder_ref = av_buffer_create((uint8_t *)decoder, sizeof(*decoder), rkmpp_release_decoder, -- NULL, AV_BUFFER_FLAG_READONLY); -- if (!rk_context->decoder_ref) { -- av_free(decoder); -- ret = AVERROR(ENOMEM); -- goto fail; +- av_log(avctx, AV_LOG_DEBUG, "Initializing RKMPP decoder.\n"); + if ((coding_type = rkmpp_get_coding_type(avctx)) == MPP_VIDEO_CodingUnused) { + av_log(avctx, AV_LOG_ERROR, "Unknown codec id: %d\n", avctx->codec_id); + return AVERROR(ENOSYS); - } ++ } -- av_log(avctx, AV_LOG_DEBUG, "Initializing RKMPP decoder.\n"); -- - codectype = rkmpp_get_codingtype(avctx); - if (codectype == MPP_VIDEO_CodingUnused) { - av_log(avctx, AV_LOG_ERROR, "Unknown codec type (%d).\n", avctx->codec_id); @@ -757,21 +754,21 @@ Index: FFmpeg/libavcodec/rkmppdec.c + if (r->hwdevice) + av_log(avctx, AV_LOG_VERBOSE, "Picked up an existing RKMPP hardware device\n"); + } -+ } + } + if (!r->hwdevice) { + if ((ret = av_hwdevice_ctx_create(&r->hwdevice, AV_HWDEVICE_TYPE_RKMPP, NULL, NULL, 0)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to create a RKMPP hardware device: %d\n", ret); + goto fail; + } + av_log(avctx, AV_LOG_VERBOSE, "Created a RKMPP hardware device\n"); - } ++ } ++ ++ return 0; - ret = decoder->mpi->control(decoder->ctx, MPP_DEC_SET_EXT_BUF_GROUP, decoder->frame_group); - if (ret) { - av_log(avctx, AV_LOG_ERROR, "Failed to assign buffer group (code = %d)\n", ret); - ret = AVERROR_UNKNOWN; -+ return 0; -+ +fail: + rkmpp_decode_close(avctx); + return ret; @@ -913,7 +910,7 @@ Index: FFmpeg/libavcodec/rkmppdec.c + MppFrameMasteringDisplayMetadata mpp_mastering) { - RKMPPDecodeContext *rk_context = avctx->priv_data; -- RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; +- RKMPPDecoder *decoder = rk_context->decoder; - int ret; + AVMasteringDisplayMetadata *mastering = NULL; + AVFrameSideData *sd = NULL; @@ -997,13 +994,11 @@ Index: FFmpeg/libavcodec/rkmppdec.c + MppFrameContentLightMetadata mpp_light) { - AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)data; -- AVBufferRef *framecontextref = (AVBufferRef *)opaque; -- RKMPPFrameContext *framecontext = (RKMPPFrameContext *)framecontextref->data; +- RKMPPFrameContext *framecontext = opaque; + AVContentLightMetadata *light = NULL; - mpp_frame_deinit(&framecontext->frame); -- av_buffer_unref(&framecontext->decoder_ref); -- av_buffer_unref(&framecontextref); +- ff_refstruct_unref(&framecontext->decoder_ref); + AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); + if (sd) + light = (AVContentLightMetadata *)sd->data; @@ -1011,11 +1006,11 @@ Index: FFmpeg/libavcodec/rkmppdec.c + light = av_content_light_metadata_create_side_data(frame); + if (!light) + return AVERROR(ENOMEM); -+ -+ light->MaxCLL = mpp_light.MaxCLL; -+ light->MaxFALL = mpp_light.MaxFALL; - av_free(desc); ++ light->MaxCLL = mpp_light.MaxCLL; ++ light->MaxFALL = mpp_light.MaxFALL; ++ + return 0; } @@ -1023,13 +1018,10 @@ Index: FFmpeg/libavcodec/rkmppdec.c +static void rkmpp_free_mpp_frame(void *opaque, uint8_t *data) { - RKMPPDecodeContext *rk_context = avctx->priv_data; -- RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; -- RKMPPFrameContext *framecontext = NULL; -- AVBufferRef *framecontextref = NULL; +- RKMPPDecoder *decoder = rk_context->decoder; - int ret; - MppFrame mppframe = NULL; - MppBuffer buffer = NULL; -- AVDRMFrameDescriptor *desc = NULL; + MppFrame mpp_frame = (MppFrame)opaque; + mpp_frame_deinit(&mpp_frame); +} @@ -1188,15 +1180,11 @@ Index: FFmpeg/libavcodec/rkmppdec.c + if (ret < 0) + return ret; + } -+ -+ return 0; -+} - mppformat = mpp_frame_get_fmt(mppframe); - drmformat = rkmpp_get_frameformat(mppformat); -+static void rkmpp_export_avctx_color_props(AVCodecContext *avctx, MppFrame mpp_frame) -+{ -+ int val; ++ return 0; ++} - hwframes = (AVHWFramesContext*)decoder->frames_ref->data; - hwframes->format = AV_PIX_FMT_DRM_PRIME; @@ -1206,8 +1194,9 @@ Index: FFmpeg/libavcodec/rkmppdec.c - ret = av_hwframe_ctx_init(decoder->frames_ref); - if (ret < 0) - goto fail; -+ if (!avctx || !mpp_frame) -+ return; ++static void rkmpp_export_avctx_color_props(AVCodecContext *avctx, MppFrame mpp_frame) ++{ ++ int val; - // here decoder is fully initialized, we need to feed it again with data - ret = AVERROR(EAGAIN); @@ -1215,6 +1204,9 @@ Index: FFmpeg/libavcodec/rkmppdec.c - } else if (mpp_frame_get_eos(mppframe)) { - av_log(avctx, AV_LOG_DEBUG, "Received a EOS frame.\n"); - decoder->eos_reached = 1; ++ if (!avctx || !mpp_frame) ++ return; ++ + if (avctx->color_primaries == AVCOL_PRI_RESERVED0) + avctx->color_primaries = AVCOL_PRI_UNSPECIFIED; + if ((val = mpp_frame_get_color_primaries(mpp_frame)) && @@ -1298,6 +1290,7 @@ Index: FFmpeg/libavcodec/rkmppdec.c + } + + if (r->info_change = mpp_frame_get_info_change(mpp_frame)) { ++ char *opts = NULL; + int fast_parse = r->fast_parse; + int mpp_frame_mode = mpp_frame_get_mode(mpp_frame); + const MppFrameFormat mpp_fmt = mpp_frame_get_fmt(mpp_frame); @@ -1338,11 +1331,21 @@ Index: FFmpeg/libavcodec/rkmppdec.c - // now setup the frame buffer info - buffer = mpp_frame_get_buffer(mppframe); - if (buffer) { -- desc = av_mallocz(sizeof(AVDRMFrameDescriptor)); -- if (!desc) { +- RKMPPFrameContext *framecontext; +- AVDRMFrameDescriptor *desc; +- // We allocate the descriptor in buf[0] jointly with a structure +- // that will allow to hold additional information +- // for properly releasing MPP frames and decoder. +- struct { +- AVDRMFrameDescriptor desc; +- RKMPPFrameContext framecontext; +- } *combined_desc = av_mallocz(sizeof(*combined_desc)); +- if (!combined_desc) { - ret = AVERROR(ENOMEM); - goto fail; - } +- desc = &combined_desc->desc; +- framecontext = &combined_desc->framecontext; + if (avctx->pix_fmt == AV_PIX_FMT_DRM_PRIME) + avctx->sw_pix_fmt = pix_fmts[1]; + else { @@ -1368,19 +1371,28 @@ Index: FFmpeg/libavcodec/rkmppdec.c - layer->planes[1].offset = layer->planes[0].pitch * mpp_frame_get_ver_stride(mppframe); - layer->planes[1].pitch = layer->planes[0].pitch; - -- // we also allocate a struct in buf[0] that will allow to hold additionnal information -- // for releasing properly MPP frames and decoder -- framecontextref = av_buffer_allocz(sizeof(*framecontext)); -- if (!framecontextref) { +- // MPP decoder needs to be closed only when all frames have been released. +- framecontext->frame = mppframe; +- +- frame->data[0] = (uint8_t *)desc; +- frame->buf[0] = av_buffer_create((uint8_t *)desc, sizeof(*desc), rkmpp_release_frame, +- framecontext, AV_BUFFER_FLAG_READONLY); +- +- if (!frame->buf[0]) { +- av_free(combined_desc); - ret = AVERROR(ENOMEM); - goto fail; - } +- framecontext->decoder_ref = ff_refstruct_ref(rk_context->decoder); + avctx->width = mpp_frame_get_width(mpp_frame); + avctx->height = mpp_frame_get_height(mpp_frame); + avctx->coded_width = FFALIGN(avctx->width, 64); + avctx->coded_height = FFALIGN(avctx->height, 64); + rkmpp_export_avctx_color_props(avctx, mpp_frame); + ++ if (av_opt_serialize(r, 0, 0, &opts, '=', ' ') >= 0) ++ av_log(avctx, AV_LOG_VERBOSE, "Decoder options: %s\n", opts); ++ + av_log(avctx, AV_LOG_VERBOSE, "Configured with size: %dx%d | pix_fmt: %s | sw_pix_fmt: %s\n", + avctx->width, avctx->height, + av_get_pix_fmt_name(avctx->pix_fmt), @@ -1401,23 +1413,21 @@ Index: FFmpeg/libavcodec/rkmppdec.c + goto exit; + } -- // MPP decoder needs to be closed only when all frames have been released. -- framecontext = (RKMPPFrameContext *)framecontextref->data; -- framecontext->decoder_ref = av_buffer_ref(rk_context->decoder_ref); -- framecontext->frame = mppframe; -- -- frame->data[0] = (uint8_t *)desc; -- frame->buf[0] = av_buffer_create((uint8_t *)desc, sizeof(*desc), rkmpp_release_frame, -- framecontextref, AV_BUFFER_FLAG_READONLY); +- frame->hw_frames_ctx = av_buffer_ref(decoder->frames_ref); +- if (!frame->hw_frames_ctx) { +- av_frame_unref(frame); +- return AVERROR(ENOMEM); +- } + if ((ret = r->mapi->control(r->mctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL)) != MPP_OK) { + av_log(avctx, AV_LOG_ERROR, "Failed to set info change ready: %d\n", ret); + ret = AVERROR_EXTERNAL; + goto exit; + } -- if (!frame->buf[0]) { -- ret = AVERROR(ENOMEM); -- goto fail; +- return 0; +- } else { +- av_log(avctx, AV_LOG_ERROR, "Failed to retrieve the frame buffer, frame is dropped (code = %d)\n", ret); +- mpp_frame_deinit(&mppframe); + /* no more new pkts after EOS, retry to get frame */ + if (r->draining) { + mpp_frame_deinit(&mpp_frame); @@ -1434,12 +1444,7 @@ Index: FFmpeg/libavcodec/rkmppdec.c + if ((ret = rkmpp_export_frame(avctx, frame, mpp_frame)) < 0) + goto exit; + return 0; - } -- -- frame->hw_frames_ctx = av_buffer_ref(decoder->frames_ref); -- if (!frame->hw_frames_ctx) { -- ret = AVERROR(ENOMEM); -- goto fail; ++ } + break; + case AV_PIX_FMT_NV12: + case AV_PIX_FMT_NV16: @@ -1472,12 +1477,7 @@ Index: FFmpeg/libavcodec/rkmppdec.c + } + av_frame_free(&tmp_frame); + return 0; - } -- -- return 0; -- } else { -- av_log(avctx, AV_LOG_ERROR, "Failed to retrieve the frame buffer, frame is dropped (code = %d)\n", ret); -- mpp_frame_deinit(&mppframe); ++ } + break; + default: + { @@ -1508,25 +1508,19 @@ Index: FFmpeg/libavcodec/rkmppdec.c + MppPacket mpp_pkt = NULL; + int ret; -- if (framecontext) -- av_buffer_unref(&framecontext->decoder_ref); +- return ret; + if ((ret = mpp_packet_init(&mpp_pkt, NULL, 0)) != MPP_OK) { + av_log(avctx, AV_LOG_ERROR, "Failed to init 'EOS' packet: %d\n", ret); + return AVERROR_EXTERNAL; + } + mpp_packet_set_eos(mpp_pkt); - -- if (framecontextref) -- av_buffer_unref(&framecontextref); ++ + do { + ret = r->mapi->decode_put_packet(r->mctx, mpp_pkt); + } while (ret != MPP_OK); - -- if (desc) -- av_free(desc); ++ + r->draining = 1; - -- return ret; ++ + mpp_packet_deinit(&mpp_pkt); + return 0; } @@ -1535,7 +1529,7 @@ Index: FFmpeg/libavcodec/rkmppdec.c +static int rkmpp_send_packet(AVCodecContext *avctx, AVPacket *pkt) { - RKMPPDecodeContext *rk_context = avctx->priv_data; -- RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; +- RKMPPDecoder *decoder = rk_context->decoder; - int ret = MPP_NOK; - AVPacket pkt = {0}; - RK_S32 usedslots, freeslots; @@ -1663,7 +1657,7 @@ Index: FFmpeg/libavcodec/rkmppdec.c +static void rkmpp_decode_flush(AVCodecContext *avctx) { - RKMPPDecodeContext *rk_context = avctx->priv_data; -- RKMPPDecoder *decoder = (RKMPPDecoder *)rk_context->decoder_ref->data; +- RKMPPDecoder *decoder = rk_context->decoder; - int ret = MPP_NOK; + RKMPPDecContext *r = avctx->priv_data; + int ret; @@ -1752,7 +1746,7 @@ Index: FFmpeg/libavcodec/rkmppdec.h =================================================================== --- /dev/null +++ FFmpeg/libavcodec/rkmppdec.h -@@ -0,0 +1,145 @@ +@@ -0,0 +1,146 @@ +/* + * Copyright (c) 2017 Lionel CHAZALLON + * Copyright (c) 2023 Huseyin BIYIK @@ -1793,6 +1787,7 @@ Index: FFmpeg/libavcodec/rkmppdec.h +#include "libavutil/avstring.h" +#include "libavutil/hwcontext_rkmpp.h" +#include "libavutil/mastering_display_metadata.h" ++#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + @@ -3041,7 +3036,7 @@ Index: FFmpeg/libavcodec/rkmppenc.h =================================================================== --- /dev/null +++ FFmpeg/libavcodec/rkmppenc.h -@@ -0,0 +1,280 @@ +@@ -0,0 +1,282 @@ +/* + * Copyright (c) 2023 Huseyin BIYIK + * Copyright (c) 2023 NyanMisaka @@ -3079,6 +3074,7 @@ Index: FFmpeg/libavcodec/rkmppenc.h +#include "internal.h" + +#include "libavutil/hwcontext_rkmpp.h" ++#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + @@ -3316,6 +3312,7 @@ Index: FFmpeg/libavcodec/rkmppenc.h + .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | \ + FF_CODEC_CAP_INIT_CLEANUP, \ + .p.pix_fmts = rkmpp_enc_pix_fmts_##xx, \ ++ .color_ranges = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG, \ + .hw_configs = rkmpp_enc_hw_configs, \ + .defaults = rkmpp_enc_defaults, \ + .p.wrapper_name = "rkmpp", \ @@ -3334,7 +3331,7 @@ Index: FFmpeg/libavfilter/Makefile OBJS-$(CONFIG_SCENE_SAD) += scene_sad.o OBJS-$(CONFIG_DNN) += dnn_filter_common.o include $(SRC_PATH)/libavfilter/dnn/Makefile -@@ -414,6 +415,7 @@ OBJS-$(CONFIG_OVERLAY_OPENCL_FILTER) +@@ -416,6 +417,7 @@ OBJS-$(CONFIG_OVERLAY_OPENCL_FILTER) OBJS-$(CONFIG_OVERLAY_QSV_FILTER) += vf_overlay_qsv.o framesync.o OBJS-$(CONFIG_OVERLAY_VAAPI_FILTER) += vf_overlay_vaapi.o framesync.o vaapi_vpp.o OBJS-$(CONFIG_OVERLAY_VULKAN_FILTER) += vf_overlay_vulkan.o vulkan.o vulkan_filter.o @@ -3342,15 +3339,15 @@ Index: FFmpeg/libavfilter/Makefile OBJS-$(CONFIG_OWDENOISE_FILTER) += vf_owdenoise.o OBJS-$(CONFIG_PAD_FILTER) += vf_pad.o OBJS-$(CONFIG_PAD_OPENCL_FILTER) += vf_pad_opencl.o opencl.o opencl/pad.o -@@ -465,6 +467,7 @@ OBJS-$(CONFIG_SCALE_QSV_FILTER) +@@ -467,6 +469,7 @@ OBJS-$(CONFIG_SCALE_QSV_FILTER) OBJS-$(CONFIG_SCALE_VAAPI_FILTER) += vf_scale_vaapi.o scale_eval.o vaapi_vpp.o OBJS-$(CONFIG_SCALE_VT_FILTER) += vf_scale_vt.o scale_eval.o OBJS-$(CONFIG_SCALE_VULKAN_FILTER) += vf_scale_vulkan.o vulkan.o vulkan_filter.o +OBJS-$(CONFIG_SCALE_RKRGA_FILTER) += vf_vpp_rkrga.o scale_eval.o - OBJS-$(CONFIG_SCALE2REF_FILTER) += vf_scale.o scale_eval.o + OBJS-$(CONFIG_SCALE2REF_FILTER) += vf_scale.o scale_eval.o framesync.o OBJS-$(CONFIG_SCALE2REF_NPP_FILTER) += vf_scale_npp.o scale_eval.o OBJS-$(CONFIG_SCDET_FILTER) += vf_scdet.o -@@ -557,6 +560,7 @@ OBJS-$(CONFIG_VIF_FILTER) +@@ -559,6 +562,7 @@ OBJS-$(CONFIG_VIF_FILTER) OBJS-$(CONFIG_VIGNETTE_FILTER) += vf_vignette.o OBJS-$(CONFIG_VMAFMOTION_FILTER) += vf_vmafmotion.o framesync.o OBJS-$(CONFIG_VPP_QSV_FILTER) += vf_vpp_qsv.o @@ -3358,7 +3355,7 @@ Index: FFmpeg/libavfilter/Makefile OBJS-$(CONFIG_VSTACK_FILTER) += vf_stack.o framesync.o OBJS-$(CONFIG_W3FDIF_FILTER) += vf_w3fdif.o OBJS-$(CONFIG_WAVEFORM_FILTER) += vf_waveform.o -@@ -658,6 +662,7 @@ SKIPHEADERS-$(CONFIG_LCMS2) +@@ -664,6 +668,7 @@ SKIPHEADERS-$(CONFIG_LCMS2) SKIPHEADERS-$(CONFIG_LIBVIDSTAB) += vidstabutils.h SKIPHEADERS-$(CONFIG_QSVVPP) += qsvvpp.h stack_internal.h @@ -3370,7 +3367,7 @@ Index: FFmpeg/libavfilter/allfilters.c =================================================================== --- FFmpeg.orig/libavfilter/allfilters.c +++ FFmpeg/libavfilter/allfilters.c -@@ -390,6 +390,7 @@ extern const AVFilter ff_vf_overlay_qsv; +@@ -391,6 +391,7 @@ extern const AVFilter ff_vf_overlay_qsv; extern const AVFilter ff_vf_overlay_vaapi; extern const AVFilter ff_vf_overlay_vulkan; extern const AVFilter ff_vf_overlay_cuda; @@ -3378,7 +3375,7 @@ Index: FFmpeg/libavfilter/allfilters.c extern const AVFilter ff_vf_owdenoise; extern const AVFilter ff_vf_pad; extern const AVFilter ff_vf_pad_opencl; -@@ -438,6 +439,7 @@ extern const AVFilter ff_vf_scale_qsv; +@@ -439,6 +440,7 @@ extern const AVFilter ff_vf_scale_qsv; extern const AVFilter ff_vf_scale_vaapi; extern const AVFilter ff_vf_scale_vt; extern const AVFilter ff_vf_scale_vulkan; @@ -3386,7 +3383,7 @@ Index: FFmpeg/libavfilter/allfilters.c extern const AVFilter ff_vf_scale2ref; extern const AVFilter ff_vf_scale2ref_npp; extern const AVFilter ff_vf_scdet; -@@ -525,6 +527,7 @@ extern const AVFilter ff_vf_vif; +@@ -526,6 +528,7 @@ extern const AVFilter ff_vf_vif; extern const AVFilter ff_vf_vignette; extern const AVFilter ff_vf_vmafmotion; extern const AVFilter ff_vf_vpp_qsv; @@ -3398,7 +3395,7 @@ Index: FFmpeg/libavfilter/rkrga_common.c =================================================================== --- /dev/null +++ FFmpeg/libavfilter/rkrga_common.c -@@ -0,0 +1,1357 @@ +@@ -0,0 +1,1364 @@ +/* + * Copyright (c) 2023 NyanMisaka + * @@ -3425,9 +3422,10 @@ Index: FFmpeg/libavfilter/rkrga_common.c + */ + +#include "libavutil/common.h" ++#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" + -+#include "internal.h" ++#include "filters.h" +#include "video.h" + +#include "rkrga_common.h" @@ -3935,6 +3933,7 @@ Index: FFmpeg/libavfilter/rkrga_common.c +static RGAFrame *query_frame(RKRGAContext *r, AVFilterLink *outlink, + const AVFrame *in, int pat_preproc) +{ ++ FilterLink *outl = ff_filter_link(outlink); + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = ctx->inputs[0]; + RGAFrame *out_frame; @@ -3942,7 +3941,7 @@ Index: FFmpeg/libavfilter/rkrga_common.c + RGAFrameInfo *in0_info = &r->in_rga_frame_infos[0]; + RGAFrameInfo *in1_info = ctx->nb_inputs > 1 ? &r->in_rga_frame_infos[1] : NULL; + RGAFrameInfo *out_info = pat_preproc ? in1_info : &r->out_rga_frame_info; -+ AVBufferRef *hw_frame_ctx = pat_preproc ? r->pat_preproc_hwframes_ctx : outlink->hw_frames_ctx; ++ AVBufferRef *hw_frame_ctx = pat_preproc ? r->pat_preproc_hwframes_ctx : outl->hw_frames_ctx; + int w_stride = 0, h_stride = 0; + AVDRMFrameDescriptor *desc; + AVDRMLayerDescriptor *layer; @@ -4091,6 +4090,8 @@ Index: FFmpeg/libavfilter/rkrga_common.c + RKRGAContext *r = avctx->priv; + AVFilterLink *inlink = avctx->inputs[0]; + AVFilterLink *outlink = avctx->outputs[0]; ++ FilterLink *inl = ff_filter_link(inlink); ++ FilterLink *outl = ff_filter_link(outlink); + AVHWFramesContext *hwfc_in; + AVHWFramesContext *hwfc_out; + AVBufferRef *hwfc_out_ref; @@ -4098,10 +4099,10 @@ Index: FFmpeg/libavfilter/rkrga_common.c + AVRKMPPFramesContext *rkmpp_fc; + int ret; + -+ if (!inlink->hw_frames_ctx) ++ if (!inl->hw_frames_ctx) + return AVERROR(EINVAL); + -+ hwfc_in = (AVHWFramesContext *)inlink->hw_frames_ctx->data; ++ hwfc_in = (AVHWFramesContext *)inl->hw_frames_ctx->data; + device_ctx = (AVHWDeviceContext *)hwfc_in->device_ref->data; + + if (!device_ctx || device_ctx->type != AV_HWDEVICE_TYPE_RKMPP) @@ -4127,28 +4128,30 @@ Index: FFmpeg/libavfilter/rkrga_common.c + return ret; + } + -+ av_buffer_unref(&outlink->hw_frames_ctx); -+ outlink->hw_frames_ctx = hwfc_out_ref; ++ av_buffer_unref(&outl->hw_frames_ctx); ++ outl->hw_frames_ctx = hwfc_out_ref; + + return 0; +} + +static av_cold int init_pat_preproc_hwframes_ctx(AVFilterContext *avctx) +{ -+ RKRGAContext *r = avctx->priv; ++ RKRGAContext *r = avctx->priv; + AVFilterLink *inlink0 = avctx->inputs[0]; + AVFilterLink *inlink1 = avctx->inputs[1]; ++ FilterLink *inl0 = ff_filter_link(inlink0); ++ FilterLink *inl1 = ff_filter_link(inlink1); + AVHWFramesContext *hwfc_in0, *hwfc_in1; + AVHWFramesContext *hwfc_pat; + AVBufferRef *hwfc_pat_ref; + AVHWDeviceContext *device_ctx0; + int ret; + -+ if (!inlink0->hw_frames_ctx || !inlink1->hw_frames_ctx) ++ if (!inl0->hw_frames_ctx || !inl1->hw_frames_ctx) + return AVERROR(EINVAL); + -+ hwfc_in0 = (AVHWFramesContext *)inlink0->hw_frames_ctx->data; -+ hwfc_in1 = (AVHWFramesContext *)inlink1->hw_frames_ctx->data; ++ hwfc_in0 = (AVHWFramesContext *)inl0->hw_frames_ctx->data; ++ hwfc_in1 = (AVHWFramesContext *)inl1->hw_frames_ctx->data; + device_ctx0 = (AVHWDeviceContext *)hwfc_in0->device_ref->data; + + if (!device_ctx0 || device_ctx0->type != AV_HWDEVICE_TYPE_RKMPP) @@ -4379,13 +4382,14 @@ Index: FFmpeg/libavfilter/rkrga_common.c + AVFilterLink *link, + int nb_link, int is_inlink) +{ ++ FilterLink *l = ff_filter_link(link); + AVHWFramesContext *hwfc; + RKRGAContext *r = avctx->priv; + -+ if (!link->hw_frames_ctx || link->format != AV_PIX_FMT_DRM_PRIME) ++ if (!l->hw_frames_ctx || link->format != AV_PIX_FMT_DRM_PRIME) + return AVERROR(EINVAL); + -+ hwfc = (AVHWFramesContext *)link->hw_frames_ctx->data; ++ hwfc = (AVHWFramesContext *)l->hw_frames_ctx->data; + + if (!map_av_to_rga_format(hwfc->sw_format, &info->rga_fmt, (is_inlink && nb_link > 0))) { + av_log(avctx, AV_LOG_ERROR, "Unsupported '%s' pad %d format: '%s'\n", @@ -4895,7 +4899,7 @@ Index: FFmpeg/libavfilter/vf_overlay_rkrga.c =================================================================== --- /dev/null +++ FFmpeg/libavfilter/vf_overlay_rkrga.c -@@ -0,0 +1,369 @@ +@@ -0,0 +1,371 @@ +/* + * Copyright (c) 2023 NyanMisaka + * @@ -5062,6 +5066,8 @@ Index: FFmpeg/libavfilter/vf_overlay_rkrga.c + RGAOverlayContext *r = ctx->priv; + AVFilterLink *inlink_main = ctx->inputs[0]; + AVFilterLink *inlink_overlay = ctx->inputs[1]; ++ FilterLink *inl_main = ff_filter_link(inlink_main); ++ FilterLink *inl_overlay = ff_filter_link(inlink_overlay); + AVHWFramesContext *frames_ctx_main; + AVHWFramesContext *frames_ctx_overlay; + enum AVPixelFormat in_format_main; @@ -5071,19 +5077,19 @@ Index: FFmpeg/libavfilter/vf_overlay_rkrga.c + + RKRGAParam param = { NULL }; + -+ if (!inlink_main->hw_frames_ctx) { ++ if (!inl_main->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "No hw context provided on main input\n"); + return AVERROR(EINVAL); + } -+ frames_ctx_main = (AVHWFramesContext *)inlink_main->hw_frames_ctx->data; ++ frames_ctx_main = (AVHWFramesContext *)inl_main->hw_frames_ctx->data; + in_format_main = frames_ctx_main->sw_format; + out_format = (r->format == AV_PIX_FMT_NONE) ? in_format_main : r->format; + -+ if (!inlink_overlay->hw_frames_ctx) { ++ if (!inl_overlay->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "No hw context provided on overlay input\n"); + return AVERROR(EINVAL); + } -+ frames_ctx_overlay = (AVHWFramesContext *)inlink_overlay->hw_frames_ctx->data; ++ frames_ctx_overlay = (AVHWFramesContext *)inl_overlay->hw_frames_ctx->data; + in_format_overlay = frames_ctx_overlay->sw_format; + + ret = set_size_info(ctx, inlink_main, inlink_overlay, outlink); @@ -5269,7 +5275,7 @@ Index: FFmpeg/libavfilter/vf_vpp_rkrga.c =================================================================== --- /dev/null +++ FFmpeg/libavfilter/vf_vpp_rkrga.c -@@ -0,0 +1,579 @@ +@@ -0,0 +1,580 @@ +/* + * Copyright (c) 2023 NyanMisaka + * @@ -5618,17 +5624,18 @@ Index: FFmpeg/libavfilter/vf_vpp_rkrga.c + AVFilterContext *ctx = outlink->src; + RGAVppContext *r = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; ++ FilterLink *inl = ff_filter_link(inlink); + AVHWFramesContext *in_frames_ctx; + enum AVPixelFormat in_format; + enum AVPixelFormat out_format; + RKRGAParam param = { NULL }; + int ret; + -+ if (!inlink->hw_frames_ctx) { ++ if (!inl->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n"); + return AVERROR(EINVAL); + } -+ in_frames_ctx = (AVHWFramesContext *)inlink->hw_frames_ctx->data; ++ in_frames_ctx = (AVHWFramesContext *)inl->hw_frames_ctx->data; + in_format = in_frames_ctx->sw_format; + out_format = (r->format == AV_PIX_FMT_NONE) ? in_format : r->format; + @@ -5976,8 +5983,8 @@ Index: FFmpeg/libavutil/hwcontext_opencl.c AVHWFramesContext *src_fc = (AVHWFramesContext*)src->hw_frames_ctx->data; - AVOpenCLDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; -+ OpenCLDeviceContext *device_priv = dst_fc->device_ctx->hwctx; -+ AVOpenCLDeviceContext *dst_dev = &device_priv->p; ++ OpenCLDeviceContext *device_priv = dst_fc->device_ctx->hwctx; ++ AVOpenCLDeviceContext *dst_dev = &device_priv->p; const AVDRMFrameDescriptor *desc; DRMARMtoOpenCLMapping *mapping = NULL; cl_mem_flags cl_flags; @@ -6005,7 +6012,7 @@ Index: FFmpeg/libavutil/hwcontext_rkmpp.c =================================================================== --- /dev/null +++ FFmpeg/libavutil/hwcontext_rkmpp.c -@@ -0,0 +1,603 @@ +@@ -0,0 +1,604 @@ +/* + * This file is part of FFmpeg. + * @@ -6044,6 +6051,7 @@ Index: FFmpeg/libavutil/hwcontext_rkmpp.c +#include "hwcontext_rkmpp.h" +#include "hwcontext_internal.h" +#include "imgutils.h" ++#include "mem.h" + +static const struct { + enum AVPixelFormat pixfmt; @@ -6905,7 +6913,7 @@ Index: FFmpeg/libswscale/swscale_unscaled.c =================================================================== --- FFmpeg.orig/libswscale/swscale_unscaled.c +++ FFmpeg/libswscale/swscale_unscaled.c -@@ -221,6 +221,61 @@ static int nv24ToPlanarWrapper(SwsContex +@@ -265,6 +265,61 @@ static int nv24ToYuv420Wrapper(SwsContex return srcSliceH; } @@ -6967,7 +6975,7 @@ Index: FFmpeg/libswscale/swscale_unscaled.c static int planarToP01xWrapper(SwsContext *c, const uint8_t *src8[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dstParam8[], -@@ -2004,6 +2059,19 @@ void ff_get_unscaled_swscale(SwsContext +@@ -2048,6 +2103,19 @@ void ff_get_unscaled_swscale(SwsContext (srcFormat == AV_PIX_FMT_NV24 || srcFormat == AV_PIX_FMT_NV42)) { c->convert_unscaled = nv24ToPlanarWrapper; } @@ -6991,7 +6999,7 @@ Index: FFmpeg/libswscale/utils.c =================================================================== --- FFmpeg.orig/libswscale/utils.c +++ FFmpeg/libswscale/utils.c -@@ -230,6 +230,8 @@ static const FormatEntry format_entries[ +@@ -231,6 +231,8 @@ static const FormatEntry format_entries[ [AV_PIX_FMT_XYZ12BE] = { 1, 1, 1 }, [AV_PIX_FMT_XYZ12LE] = { 1, 1, 1 }, [AV_PIX_FMT_AYUV64LE] = { 1, 1}, diff --git a/debian/patches/0048-add-format-option-to-vt-scale-filter.patch b/debian/patches/0047-add-format-option-to-vt-scale-filter.patch similarity index 76% rename from debian/patches/0048-add-format-option-to-vt-scale-filter.patch rename to debian/patches/0047-add-format-option-to-vt-scale-filter.patch index 20feee2a4..5f1bd99e6 100644 --- a/debian/patches/0048-add-format-option-to-vt-scale-filter.patch +++ b/debian/patches/0047-add-format-option-to-vt-scale-filter.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavfilter/vf_scale_vt.c =================================================================== --- FFmpeg.orig/libavfilter/vf_scale_vt.c +++ FFmpeg/libavfilter/vf_scale_vt.c -@@ -40,11 +40,26 @@ typedef struct ScaleVtContext { +@@ -41,11 +41,26 @@ typedef struct ScaleVtContext { enum AVColorPrimaries colour_primaries; enum AVColorTransferCharacteristic colour_transfer; enum AVColorSpace colour_matrix; @@ -29,17 +29,17 @@ Index: FFmpeg/libavfilter/vf_scale_vt.c static av_cold int scale_vt_init(AVFilterContext *avctx) { ScaleVtContext *s = avctx->priv; -@@ -179,6 +194,7 @@ static int scale_vt_config_output(AVFilt - AVFilterLink *inlink = outlink->src->inputs[0]; +@@ -182,6 +197,7 @@ static int scale_vt_config_output(AVFilt + FilterLink *inl = ff_filter_link(inlink); AVHWFramesContext *hw_frame_ctx_in; AVHWFramesContext *hw_frame_ctx_out; + enum AVPixelFormat out_format; err = ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink, &s->output_width, -@@ -198,13 +214,21 @@ static int scale_vt_config_output(AVFilt +@@ -201,11 +217,18 @@ static int scale_vt_config_output(AVFilt - hw_frame_ctx_in = (AVHWFramesContext *)inlink->hw_frames_ctx->data; + hw_frame_ctx_in = (AVHWFramesContext *)inl->hw_frames_ctx->data; + out_format = (s->format == AV_PIX_FMT_NONE) ? hw_frame_ctx_in->sw_format : s->format; + if (!format_is_supported(s->format)) { @@ -48,19 +48,16 @@ Index: FFmpeg/libavfilter/vf_scale_vt.c + return AVERROR(ENOSYS); + } + - av_buffer_unref(&outlink->hw_frames_ctx); - outlink->hw_frames_ctx = av_hwframe_ctx_alloc(hw_frame_ctx_in->device_ref); - hw_frame_ctx_out = (AVHWFramesContext *)outlink->hw_frames_ctx->data; + av_buffer_unref(&outl->hw_frames_ctx); + outl->hw_frames_ctx = av_hwframe_ctx_alloc(hw_frame_ctx_in->device_ref); + hw_frame_ctx_out = (AVHWFramesContext *)outl->hw_frames_ctx->data; hw_frame_ctx_out->format = AV_PIX_FMT_VIDEOTOOLBOX; - hw_frame_ctx_out->sw_format = hw_frame_ctx_in->sw_format; + hw_frame_ctx_out->sw_format = out_format; hw_frame_ctx_out->width = outlink->w; hw_frame_ctx_out->height = outlink->h; -+ ((AVVTFramesContext *)hw_frame_ctx_out->hwctx)->color_range = ((AVVTFramesContext *)hw_frame_ctx_in->hwctx)->color_range; - - err = ff_filter_init_hw_frames(avctx, outlink, 1); - if (err < 0) -@@ -234,6 +258,8 @@ static const AVOption scale_vt_options[] + ((AVVTFramesContext *)hw_frame_ctx_out->hwctx)->color_range = ((AVVTFramesContext *)hw_frame_ctx_in->hwctx)->color_range; +@@ -238,6 +261,8 @@ static const AVOption scale_vt_options[] OFFSET(colour_primaries_string), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, { "color_transfer", "Output colour transfer characteristics", OFFSET(colour_transfer_string), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, diff --git a/debian/patches/0050-add-vf-overlay-videotoolbox-filter.patch b/debian/patches/0048-add-vf-overlay-videotoolbox-filter.patch similarity index 96% rename from debian/patches/0050-add-vf-overlay-videotoolbox-filter.patch rename to debian/patches/0048-add-vf-overlay-videotoolbox-filter.patch index 6b545170f..f83ac472b 100644 --- a/debian/patches/0050-add-vf-overlay-videotoolbox-filter.patch +++ b/debian/patches/0048-add-vf-overlay-videotoolbox-filter.patch @@ -2,7 +2,7 @@ Index: FFmpeg/configure =================================================================== --- FFmpeg.orig/configure +++ FFmpeg/configure -@@ -3883,6 +3883,7 @@ overlay_opencl_filter_deps="opencl" +@@ -3928,6 +3928,7 @@ overlay_opencl_filter_deps="opencl" overlay_qsv_filter_deps="libmfx" overlay_qsv_filter_select="qsvvpp" overlay_vaapi_filter_deps="vaapi VAProcPipelineCaps_blend_flags" @@ -14,7 +14,7 @@ Index: FFmpeg/doc/filters.texi =================================================================== --- FFmpeg.orig/doc/filters.texi +++ FFmpeg/doc/filters.texi -@@ -19047,6 +19047,58 @@ See @ref{framesync}. +@@ -19050,6 +19050,58 @@ See @ref{framesync}. This filter also supports the @ref{framesync} options. @@ -77,7 +77,7 @@ Index: FFmpeg/libavfilter/Makefile =================================================================== --- FFmpeg.orig/libavfilter/Makefile +++ FFmpeg/libavfilter/Makefile -@@ -414,6 +414,9 @@ OBJS-$(CONFIG_OVERLAY_OPENCL_FILTER) +@@ -416,6 +416,9 @@ OBJS-$(CONFIG_OVERLAY_OPENCL_FILTER) opencl/overlay.o framesync.o OBJS-$(CONFIG_OVERLAY_QSV_FILTER) += vf_overlay_qsv.o framesync.o OBJS-$(CONFIG_OVERLAY_VAAPI_FILTER) += vf_overlay_vaapi.o framesync.o vaapi_vpp.o @@ -91,7 +91,7 @@ Index: FFmpeg/libavfilter/allfilters.c =================================================================== --- FFmpeg.orig/libavfilter/allfilters.c +++ FFmpeg/libavfilter/allfilters.c -@@ -388,6 +388,7 @@ extern const AVFilter ff_vf_overlay; +@@ -389,6 +389,7 @@ extern const AVFilter ff_vf_overlay; extern const AVFilter ff_vf_overlay_opencl; extern const AVFilter ff_vf_overlay_qsv; extern const AVFilter ff_vf_overlay_vaapi; @@ -232,7 +232,7 @@ Index: FFmpeg/libavfilter/vf_overlay_videotoolbox.m =================================================================== --- /dev/null +++ FFmpeg/libavfilter/vf_overlay_videotoolbox.m -@@ -0,0 +1,751 @@ +@@ -0,0 +1,758 @@ +/* + * Copyright (C) 2024 Gnattu OC + * @@ -255,7 +255,7 @@ Index: FFmpeg/libavfilter/vf_overlay_videotoolbox.m + +#include +#include -+#include "internal.h" ++#include "filters.h" +#include "metal/utils.h" +#include "framesync.h" +#include "libavutil/hwcontext.h" @@ -430,10 +430,12 @@ Index: FFmpeg/libavfilter/vf_overlay_videotoolbox.m + AVFilterLink *outlink = avctx->outputs[0]; + AVFilterLink *inlink_main = avctx->inputs[0]; + AVFilterLink *inlink_overlay = avctx->inputs[1]; ++ FilterLink *inl_main = ff_filter_link(inlink_main); ++ FilterLink *inl_overlay = ff_filter_link(inlink_overlay); + AVFrame *input_main, *input_overlay; + AVFrame *output; -+ AVHWFramesContext *frames_ctx = (AVHWFramesContext*)inlink_main->hw_frames_ctx->data; -+ AVHWFramesContext *frames_ctx_overlay = (AVHWFramesContext*)inlink_overlay->hw_frames_ctx->data; ++ AVHWFramesContext *frames_ctx = (AVHWFramesContext*)inl_main->hw_frames_ctx->data; ++ AVHWFramesContext *frames_ctx_overlay = (AVHWFramesContext*)inl_overlay->hw_frames_ctx->data; + const AVPixFmtDescriptor *in_overlay_desc; + + CVMetalTextureRef main, dst, overlay; @@ -571,10 +573,12 @@ Index: FFmpeg/libavfilter/vf_overlay_videotoolbox.m + AVFilterLink *outlink = avctx->outputs[0]; + AVFilterLink *inlink_main = avctx->inputs[0]; + AVFilterLink *inlink_overlay = avctx->inputs[1]; ++ FilterLink *inl_main = ff_filter_link(inlink_main); ++ FilterLink *inl_overlay = ff_filter_link(inlink_overlay); + AVFrame *input_main, *input_overlay; + AVFrame *output; -+ AVHWFramesContext *frames_ctx = (AVHWFramesContext*)inlink_main->hw_frames_ctx->data; -+ AVHWFramesContext *frames_ctx_overlay = (AVHWFramesContext*)inlink_overlay->hw_frames_ctx->data; ++ AVHWFramesContext *frames_ctx = (AVHWFramesContext*)inl_main->hw_frames_ctx->data; ++ AVHWFramesContext *frames_ctx_overlay = (AVHWFramesContext*)inl_overlay->hw_frames_ctx->data; + const AVPixFmtDescriptor *in_main_desc; + + CVMetalTextureRef main_y, main_uv, dst_y, dst_uv, overlay; @@ -802,23 +806,26 @@ Index: FFmpeg/libavfilter/vf_overlay_videotoolbox.m + +static int do_config_output(AVFilterLink *link) API_AVAILABLE(macos(10.11), ios(9.0)) +{ ++ FilterLink *outl = ff_filter_link(link); + AVFilterContext *avctx = link->src; + AVFilterLink *inlink_main = avctx->inputs[0]; + AVFilterLink *inlink_overlay = avctx->inputs[1]; ++ FilterLink *inl_main = ff_filter_link(inlink_main); ++ FilterLink *inl_overlay = ff_filter_link(inlink_overlay); + OverlayVideoToolboxContext *ctx = avctx->priv; + AVHWFramesContext *main_frames, *output_frames, *overlay_frames; + AVBufferRef *input_ref, *overlay_ref; + int ret = 0; + -+ if (!inlink_main->hw_frames_ctx || -+ !inlink_overlay->hw_frames_ctx) { ++ if (!inl_main->hw_frames_ctx || ++ !inl_overlay->hw_frames_ctx) { + av_log(avctx, AV_LOG_ERROR, "An input HW frames reference is " + "required to associate the processing device.\n"); + return AVERROR(EINVAL); + } + -+ input_ref = inlink_main->hw_frames_ctx; -+ overlay_ref = inlink_overlay->hw_frames_ctx; ++ input_ref = inl_main->hw_frames_ctx; ++ overlay_ref = inl_overlay->hw_frames_ctx; + main_frames = (AVHWFramesContext*)input_ref->data; + overlay_frames = (AVHWFramesContext*)overlay_ref->data; + av_assert0(main_frames); @@ -874,8 +881,8 @@ Index: FFmpeg/libavfilter/vf_overlay_videotoolbox.m + return AVERROR(ENOMEM); + } + -+ link->hw_frames_ctx = av_hwframe_ctx_alloc(ctx->device_ref); -+ if (!link->hw_frames_ctx) { ++ outl->hw_frames_ctx = av_hwframe_ctx_alloc(ctx->device_ref); ++ if (!outl->hw_frames_ctx) { + av_log(avctx, AV_LOG_ERROR, "Failed to create HW frame context " + "for output.\n"); + ret = AVERROR(ENOMEM); @@ -883,7 +890,7 @@ Index: FFmpeg/libavfilter/vf_overlay_videotoolbox.m + } + ctx->hwframe_ctx_allocated = 1; + -+ output_frames = (AVHWFramesContext*)link->hw_frames_ctx->data; ++ output_frames = (AVHWFramesContext*)outl->hw_frames_ctx->data; + + output_frames->format = AV_PIX_FMT_VIDEOTOOLBOX; + output_frames->sw_format = main_frames->sw_format; @@ -895,7 +902,7 @@ Index: FFmpeg/libavfilter/vf_overlay_videotoolbox.m + if (ret < 0) + return ret; + -+ ret = av_hwframe_ctx_init(link->hw_frames_ctx); ++ ret = av_hwframe_ctx_init(outl->hw_frames_ctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to initialise VideoToolbox frame " + "context for output: %d\n", ret); diff --git a/debian/patches/0051-add-coreimage-based-vf-transpose-vt-filter.patch b/debian/patches/0049-add-coreimage-based-vf-transpose-vt-filter.patch similarity index 94% rename from debian/patches/0051-add-coreimage-based-vf-transpose-vt-filter.patch rename to debian/patches/0049-add-coreimage-based-vf-transpose-vt-filter.patch index feecae90c..2ebee93a7 100644 --- a/debian/patches/0051-add-coreimage-based-vf-transpose-vt-filter.patch +++ b/debian/patches/0049-add-coreimage-based-vf-transpose-vt-filter.patch @@ -2,7 +2,7 @@ Index: FFmpeg/configure =================================================================== --- FFmpeg.orig/configure +++ FFmpeg/configure -@@ -3934,7 +3934,7 @@ tonemap_vaapi_filter_deps="vaapi VAProcF +@@ -3979,7 +3979,7 @@ tonemap_vaapi_filter_deps="vaapi VAProcF tonemap_opencl_filter_deps="opencl const_nan" transpose_opencl_filter_deps="opencl" transpose_vaapi_filter_deps="vaapi VAProcPipelineCaps_rotation_flags" @@ -15,7 +15,7 @@ Index: FFmpeg/libavfilter/vf_transpose_vt.c =================================================================== --- FFmpeg.orig/libavfilter/vf_transpose_vt.c +++ /dev/null -@@ -1,285 +0,0 @@ +@@ -1,291 +0,0 @@ -/* - * Copyright (c) 2023 Zhao Zhili - * @@ -42,7 +42,8 @@ Index: FFmpeg/libavfilter/vf_transpose_vt.c -#include "libavutil/hwcontext_videotoolbox.h" -#include "libavutil/opt.h" -#include "libavutil/pixdesc.h" --#include "internal.h" +- +-#include "filters.h" -#include "transpose.h" -#include "video.h" - @@ -123,27 +124,30 @@ Index: FFmpeg/libavfilter/vf_transpose_vt.c - -static int transpose_vt_recreate_hw_ctx(AVFilterLink *outlink) -{ +- FilterLink *outl = ff_filter_link(outlink); - AVFilterContext *avctx = outlink->src; - AVFilterLink *inlink = outlink->src->inputs[0]; +- FilterLink *inl = ff_filter_link(inlink); - AVHWFramesContext *hw_frame_ctx_in; - AVHWFramesContext *hw_frame_ctx_out; - int err; - -- av_buffer_unref(&outlink->hw_frames_ctx); +- av_buffer_unref(&outl->hw_frames_ctx); - -- hw_frame_ctx_in = (AVHWFramesContext *)inlink->hw_frames_ctx->data; -- outlink->hw_frames_ctx = av_hwframe_ctx_alloc(hw_frame_ctx_in->device_ref); -- hw_frame_ctx_out = (AVHWFramesContext *)outlink->hw_frames_ctx->data; +- hw_frame_ctx_in = (AVHWFramesContext *)inl->hw_frames_ctx->data; +- outl->hw_frames_ctx = av_hwframe_ctx_alloc(hw_frame_ctx_in->device_ref); +- hw_frame_ctx_out = (AVHWFramesContext *)outl->hw_frames_ctx->data; - hw_frame_ctx_out->format = AV_PIX_FMT_VIDEOTOOLBOX; - hw_frame_ctx_out->sw_format = hw_frame_ctx_in->sw_format; - hw_frame_ctx_out->width = outlink->w; - hw_frame_ctx_out->height = outlink->h; +- ((AVVTFramesContext *)hw_frame_ctx_out->hwctx)->color_range = ((AVVTFramesContext *)hw_frame_ctx_in->hwctx)->color_range; - - err = ff_filter_init_hw_frames(avctx, outlink, 1); - if (err < 0) - return err; - -- err = av_hwframe_ctx_init(outlink->hw_frames_ctx); +- err = av_hwframe_ctx_init(outl->hw_frames_ctx); - if (err < 0) { - av_log(avctx, AV_LOG_ERROR, - "Failed to init videotoolbox frame context, %s\n", @@ -157,16 +161,18 @@ Index: FFmpeg/libavfilter/vf_transpose_vt.c -static int transpose_vt_config_output(AVFilterLink *outlink) -{ - int err; +- FilterLink *outl = ff_filter_link(outlink); - AVFilterContext *avctx = outlink->src; - TransposeVtContext *s = avctx->priv; - AVFilterLink *inlink = outlink->src->inputs[0]; +- FilterLink *inl = ff_filter_link(inlink); - CFStringRef rotation = kVTRotation_0; - CFBooleanRef vflip = kCFBooleanFalse; - CFBooleanRef hflip = kCFBooleanFalse; - int swap_w_h = 0; - -- av_buffer_unref(&outlink->hw_frames_ctx); -- outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx); +- av_buffer_unref(&outl->hw_frames_ctx); +- outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx); - - if ((inlink->w >= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_LANDSCAPE) || - (inlink->w <= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_PORTRAIT)) { @@ -305,7 +311,7 @@ Index: FFmpeg/libavfilter/vf_transpose_vt.m =================================================================== --- /dev/null +++ FFmpeg/libavfilter/vf_transpose_vt.m -@@ -0,0 +1,379 @@ +@@ -0,0 +1,383 @@ +/* + * Copyright (c) 2023 Zhao Zhili + * Copyright (c) 2024 Gnattu OC @@ -334,7 +340,7 @@ Index: FFmpeg/libavfilter/vf_transpose_vt.m +#include "libavutil/hwcontext_videotoolbox.h" +#include "libavutil/opt.h" +#include "libavutil/objc.h" -+#include "internal.h" ++#include "filters.h" +#include "transpose.h" +#include "video.h" + @@ -468,17 +474,19 @@ Index: FFmpeg/libavfilter/vf_transpose_vt.m + +static int transpose_vt_recreate_hw_ctx(AVFilterLink *outlink) +{ ++ FilterLink *outl = ff_filter_link(outlink); + AVFilterContext *avctx = outlink->src; + AVFilterLink *inlink = outlink->src->inputs[0]; ++ FilterLink *inl = ff_filter_link(inlink); + AVHWFramesContext *hw_frame_ctx_in; + AVHWFramesContext *hw_frame_ctx_out; + int err; + -+ av_buffer_unref(&outlink->hw_frames_ctx); ++ av_buffer_unref(&outl->hw_frames_ctx); + -+ hw_frame_ctx_in = (AVHWFramesContext *)inlink->hw_frames_ctx->data; -+ outlink->hw_frames_ctx = av_hwframe_ctx_alloc(hw_frame_ctx_in->device_ref); -+ hw_frame_ctx_out = (AVHWFramesContext *)outlink->hw_frames_ctx->data; ++ hw_frame_ctx_in = (AVHWFramesContext *)inl->hw_frames_ctx->data; ++ outl->hw_frames_ctx = av_hwframe_ctx_alloc(hw_frame_ctx_in->device_ref); ++ hw_frame_ctx_out = (AVHWFramesContext *)outl->hw_frames_ctx->data; + hw_frame_ctx_out->format = AV_PIX_FMT_VIDEOTOOLBOX; + hw_frame_ctx_out->sw_format = hw_frame_ctx_in->sw_format; + hw_frame_ctx_out->width = outlink->w; @@ -489,7 +497,7 @@ Index: FFmpeg/libavfilter/vf_transpose_vt.m + if (err < 0) + return err; + -+ err = av_hwframe_ctx_init(outlink->hw_frames_ctx); ++ err = av_hwframe_ctx_init(outl->hw_frames_ctx); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, + "Failed to init videotoolbox frame context, %s\n", @@ -503,13 +511,15 @@ Index: FFmpeg/libavfilter/vf_transpose_vt.m +static int transpose_vt_config_output(AVFilterLink *outlink) +{ + int err; ++ FilterLink *outl = ff_filter_link(outlink); + AVFilterContext *avctx = outlink->src; + TransposeVtContext *s = avctx->priv; + AVFilterLink *inlink = outlink->src->inputs[0]; ++ FilterLink *inl = ff_filter_link(inlink); + int swap_w_h = 0; + -+ av_buffer_unref(&outlink->hw_frames_ctx); -+ outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx); ++ av_buffer_unref(&outl->hw_frames_ctx); ++ outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx); + + if ((inlink->w >= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_LANDSCAPE) || + (inlink->w <= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_PORTRAIT)) { diff --git a/debian/patches/0049-backport-fixes-for-videotoolbox-from-upstream.patch b/debian/patches/0049-backport-fixes-for-videotoolbox-from-upstream.patch deleted file mode 100644 index 6ea670e7c..000000000 --- a/debian/patches/0049-backport-fixes-for-videotoolbox-from-upstream.patch +++ /dev/null @@ -1,568 +0,0 @@ -Index: FFmpeg/libavcodec/videotoolboxenc.c -=================================================================== ---- FFmpeg.orig/libavcodec/videotoolboxenc.c -+++ FFmpeg/libavcodec/videotoolboxenc.c -@@ -226,9 +226,9 @@ typedef struct ExtraSEI { - - typedef struct BufNode { - CMSampleBufferRef cm_buffer; -- ExtraSEI *sei; -+ ExtraSEI sei; -+ AVBufferRef *frame_buf; - struct BufNode* next; -- int error; - } BufNode; - - typedef struct VTEncContext { -@@ -261,7 +261,7 @@ typedef struct VTEncContext { - int realtime; - int frames_before; - int frames_after; -- bool constant_bit_rate; -+ int constant_bit_rate; - - int allow_sw; - int require_sw; -@@ -280,6 +280,18 @@ typedef struct VTEncContext { - int max_ref_frames; - } VTEncContext; - -+static void vtenc_free_buf_node(BufNode *info) -+{ -+ if (!info) -+ return; -+ -+ av_free(info->sei.data); -+ if (info->cm_buffer) -+ CFRelease(info->cm_buffer); -+ av_buffer_unref(&info->frame_buf); -+ av_free(info); -+} -+ - static int vt_dump_encoder(AVCodecContext *avctx) - { - VTEncContext *vtctx = avctx->priv_data; -@@ -347,8 +359,7 @@ static void set_async_error(VTEncContext - - while (info) { - BufNode *next = info->next; -- CFRelease(info->cm_buffer); -- av_free(info); -+ vtenc_free_buf_node(info); - info = next; - } - -@@ -388,7 +399,7 @@ static void vtenc_reset(VTEncContext *vt - } - } - --static int vtenc_q_pop(VTEncContext *vtctx, bool wait, CMSampleBufferRef *buf, ExtraSEI **sei) -+static int vtenc_q_pop(VTEncContext *vtctx, bool wait, CMSampleBufferRef *buf, ExtraSEI *sei) - { - BufNode *info; - -@@ -426,31 +437,18 @@ static int vtenc_q_pop(VTEncContext *vtc - pthread_mutex_unlock(&vtctx->lock); - - *buf = info->cm_buffer; -+ info->cm_buffer = NULL; - if (sei && *buf) { - *sei = info->sei; -- } else if (info->sei) { -- if (info->sei->data) av_free(info->sei->data); -- av_free(info->sei); -+ info->sei = (ExtraSEI) {0}; - } -- av_free(info); -- -+ vtenc_free_buf_node(info); - - return 0; - } - --static void vtenc_q_push(VTEncContext *vtctx, CMSampleBufferRef buffer, ExtraSEI *sei) -+static void vtenc_q_push(VTEncContext *vtctx, BufNode *info) - { -- BufNode *info = av_malloc(sizeof(BufNode)); -- if (!info) { -- set_async_error(vtctx, AVERROR(ENOMEM)); -- return; -- } -- -- CFRetain(buffer); -- info->cm_buffer = buffer; -- info->sei = sei; -- info->next = NULL; -- - pthread_mutex_lock(&vtctx->lock); - - if (!vtctx->q_head) { -@@ -735,13 +733,16 @@ static void vtenc_output_callback( - { - AVCodecContext *avctx = ctx; - VTEncContext *vtctx = avctx->priv_data; -- ExtraSEI *sei = sourceFrameCtx; -+ BufNode *info = sourceFrameCtx; - -+ av_buffer_unref(&info->frame_buf); - if (vtctx->async_error) { -+ vtenc_free_buf_node(info); - return; - } - - if (status) { -+ vtenc_free_buf_node(info); - av_log(avctx, AV_LOG_ERROR, "Error encoding frame: %d\n", (int)status); - set_async_error(vtctx, AVERROR_EXTERNAL); - return; -@@ -751,15 +752,19 @@ static void vtenc_output_callback( - return; - } - -+ CFRetain(sample_buffer); -+ info->cm_buffer = sample_buffer; -+ - if (!avctx->extradata && (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) { - int set_status = set_extradata(avctx, sample_buffer); - if (set_status) { -+ vtenc_free_buf_node(info); - set_async_error(vtctx, set_status); - return; - } - } - -- vtenc_q_push(vtctx, sample_buffer, sei); -+ vtenc_q_push(vtctx, info); - } - - static int get_length_code_size( -@@ -2449,7 +2454,8 @@ static int copy_avframe_to_pixel_buffer( - - static int create_cv_pixel_buffer(AVCodecContext *avctx, - const AVFrame *frame, -- CVPixelBufferRef *cv_img) -+ CVPixelBufferRef *cv_img, -+ BufNode *node) - { - int plane_count; - int color; -@@ -2468,6 +2474,12 @@ static int create_cv_pixel_buffer(AVCode - av_assert0(*cv_img); - - CFRetain(*cv_img); -+ if (frame->buf[0]) { -+ node->frame_buf = av_buffer_ref(frame->buf[0]); -+ if (!node->frame_buf) -+ return AVERROR(ENOMEM); -+ } -+ - return 0; - } - -@@ -2565,33 +2577,29 @@ static int vtenc_send_frame(AVCodecConte - const AVFrame *frame) - { - CMTime time; -- CFDictionaryRef frame_dict; -+ CFDictionaryRef frame_dict = NULL; - CVPixelBufferRef cv_img = NULL; - AVFrameSideData *side_data = NULL; -- ExtraSEI *sei = NULL; -- int status = create_cv_pixel_buffer(avctx, frame, &cv_img); -+ BufNode *node = av_mallocz(sizeof(*node)); -+ int status; - -- if (status) return status; -+ if (!node) -+ return AVERROR(ENOMEM); -+ -+ status = create_cv_pixel_buffer(avctx, frame, &cv_img, node); -+ if (status) -+ goto out; - - status = create_encoder_dict_h264(frame, &frame_dict); -- if (status) { -- CFRelease(cv_img); -- return status; -- } -+ if (status) -+ goto out; - - #if CONFIG_ATSC_A53 - side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC); - if (vtctx->a53_cc && side_data && side_data->size) { -- sei = av_mallocz(sizeof(*sei)); -- if (!sei) { -- av_log(avctx, AV_LOG_ERROR, "Not enough memory for closed captions, skipping\n"); -- } else { -- int ret = ff_alloc_a53_sei(frame, 0, &sei->data, &sei->size); -- if (ret < 0) { -- av_log(avctx, AV_LOG_ERROR, "Not enough memory for closed captions, skipping\n"); -- av_free(sei); -- sei = NULL; -- } -+ status = ff_alloc_a53_sei(frame, 0, &node->sei.data, &node->sei.size); -+ if (status < 0) { -+ goto out; - } - } - #endif -@@ -2603,19 +2611,26 @@ static int vtenc_send_frame(AVCodecConte - time, - kCMTimeInvalid, - frame_dict, -- sei, -+ node, - NULL - ); - -- if (frame_dict) CFRelease(frame_dict); -- CFRelease(cv_img); -- - if (status) { - av_log(avctx, AV_LOG_ERROR, "Error: cannot encode frame: %d\n", status); -- return AVERROR_EXTERNAL; -+ status = AVERROR_EXTERNAL; -+ // Not necessary, just in case new code put after here -+ goto out; - } - -- return 0; -+out: -+ if (frame_dict) -+ CFRelease(frame_dict); -+ if (cv_img) -+ CFRelease(cv_img); -+ if (status) -+ vtenc_free_buf_node(node); -+ -+ return status; - } - - static av_cold int vtenc_frame( -@@ -2628,7 +2643,7 @@ static av_cold int vtenc_frame( - bool get_frame; - int status; - CMSampleBufferRef buf = NULL; -- ExtraSEI *sei = NULL; -+ ExtraSEI sei = {0}; - - if (frame) { - status = vtenc_send_frame(avctx, vtctx, frame); -@@ -2669,11 +2684,8 @@ static av_cold int vtenc_frame( - if (status) goto end_nopkt; - if (!buf) goto end_nopkt; - -- status = vtenc_cm_to_avpacket(avctx, buf, pkt, sei); -- if (sei) { -- if (sei->data) av_free(sei->data); -- av_free(sei); -- } -+ status = vtenc_cm_to_avpacket(avctx, buf, pkt, sei.data ? &sei : NULL); -+ av_free(sei.data); - CFRelease(buf); - if (status) goto end_nopkt; - -@@ -2698,6 +2710,10 @@ static int vtenc_populate_extradata(AVCo - CVPixelBufferRef pix_buf = NULL; - CMTime time; - CMSampleBufferRef buf = NULL; -+ BufNode *node = av_mallocz(sizeof(*node)); -+ -+ if (!node) -+ return AVERROR(ENOMEM); - - status = vtenc_create_encoder(avctx, - codec_type, -@@ -2733,7 +2749,7 @@ static int vtenc_populate_extradata(AVCo - time, - kCMTimeInvalid, - NULL, -- NULL, -+ node, - NULL); - - if (status) { -@@ -2744,6 +2760,7 @@ static int vtenc_populate_extradata(AVCo - status = AVERROR_EXTERNAL; - goto pe_cleanup; - } -+ node = NULL; - - //Populates extradata - output frames are flushed and param sets are available. - status = VTCompressionSessionCompleteFrames(vtctx->session, -@@ -2766,10 +2783,26 @@ static int vtenc_populate_extradata(AVCo - - pe_cleanup: - CVPixelBufferRelease(pix_buf); -- vtenc_reset(vtctx); -+ -+ if (status) { -+ vtenc_reset(vtctx); -+ } else { -+ if (vtctx->session) { -+ CFRelease(vtctx->session); -+ vtctx->session = NULL; -+ } -+ -+ if (vtctx->supported_props) { -+ CFRelease(vtctx->supported_props); -+ vtctx->supported_props = NULL; -+ } -+ } -+ - vtctx->frame_ct_out = 0; - - av_assert0(status != 0 || (avctx->extradata && avctx->extradata_size > 0)); -+ if (!status) -+ vtenc_free_buf_node(node); - - return status; - } -Index: FFmpeg/libavutil/hwcontext_videotoolbox.c -=================================================================== ---- FFmpeg.orig/libavutil/hwcontext_videotoolbox.c -+++ FFmpeg/libavutil/hwcontext_videotoolbox.c -@@ -342,8 +342,10 @@ static int vt_pixbuf_set_par(void *log_c - CFNumberRef num = NULL, den = NULL; - AVRational avpar = src->sample_aspect_ratio; - -- if (avpar.num == 0) -+ if (avpar.num == 0) { -+ CVBufferRemoveAttachment(pixbuf, kCVImageBufferPixelAspectRatioKey); - return 0; -+ } - - av_reduce(&avpar.num, &avpar.den, - avpar.num, avpar.den, -@@ -423,7 +425,10 @@ static int vt_pixbuf_set_chromaloc(void - kCVImageBufferChromaLocationTopFieldKey, - loc, - kCVAttachmentMode_ShouldPropagate); -- } -+ } else -+ CVBufferRemoveAttachment( -+ pixbuf, -+ kCVImageBufferChromaLocationTopFieldKey); - - return 0; - } -@@ -527,59 +532,116 @@ CFStringRef av_map_videotoolbox_color_tr - } - } - -+/** -+ * Copy all attachments for the specified mode from the given buffer. -+ */ -+static CFDictionaryRef vt_cv_buffer_copy_attachments(CVBufferRef buffer, -+ CVAttachmentMode attachment_mode) -+{ -+ CFDictionaryRef dict; -+ -+ // Check that our SDK is at least macOS 12 / iOS 15 / tvOS 15 -+ #if (TARGET_OS_OSX && defined(__MAC_12_0) && __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_12_0) || \ -+ (TARGET_OS_IOS && defined(__IPHONE_15_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_15_0) || \ -+ (TARGET_OS_TV && defined(__TVOS_15_0) && __TV_OS_VERSION_MAX_ALLOWED >= __TVOS_15_0) -+ // On recent enough versions, just use the respective API -+ if (__builtin_available(macOS 12.0, iOS 15.0, tvOS 15.0, *)) -+ return CVBufferCopyAttachments(buffer, attachment_mode); -+ #endif -+ -+ // Check that the target is lower than macOS 12 / iOS 15 / tvOS 15 -+ // else this would generate a deprecation warning and anyway never run because -+ // the runtime availability check above would be always true. -+ #if (TARGET_OS_OSX && (!defined(__MAC_12_0) || __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_12_0)) || \ -+ (TARGET_OS_IOS && (!defined(__IPHONE_15_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_15_0)) || \ -+ (TARGET_OS_TV && (!defined(__TVOS_15_0) || __TV_OS_VERSION_MIN_REQUIRED < __TVOS_15_0)) -+ // Fallback on SDKs or runtime versions < macOS 12 / iOS 15 / tvOS 15 -+ dict = CVBufferGetAttachments(buffer, attachment_mode); -+ return (dict) ? CFDictionaryCreateCopy(NULL, dict) : NULL; -+ #else -+ return NULL; // Impossible, just make the compiler happy -+ #endif -+} -+ - static int vt_pixbuf_set_colorspace(void *log_ctx, - CVPixelBufferRef pixbuf, const AVFrame *src) - { -+ CGColorSpaceRef colorspace = NULL; - CFStringRef colormatrix = NULL, colorpri = NULL, colortrc = NULL; - Float32 gamma = 0; - - colormatrix = av_map_videotoolbox_color_matrix_from_av(src->colorspace); -- if (!colormatrix && src->colorspace != AVCOL_SPC_UNSPECIFIED) -- av_log(log_ctx, AV_LOG_WARNING, "Color space %s is not supported.\n", av_color_space_name(src->colorspace)); -+ if (colormatrix) -+ CVBufferSetAttachment(pixbuf, kCVImageBufferYCbCrMatrixKey, -+ colormatrix, kCVAttachmentMode_ShouldPropagate); -+ else { -+ CVBufferRemoveAttachment(pixbuf, kCVImageBufferYCbCrMatrixKey); -+ if (src->colorspace != AVCOL_SPC_UNSPECIFIED && src->colorspace != AVCOL_SPC_RGB) -+ av_log(log_ctx, AV_LOG_WARNING, -+ "Color space %s is not supported.\n", -+ av_color_space_name(src->colorspace)); -+ } - - colorpri = av_map_videotoolbox_color_primaries_from_av(src->color_primaries); -- if (!colorpri && src->color_primaries != AVCOL_PRI_UNSPECIFIED) -- av_log(log_ctx, AV_LOG_WARNING, "Color primaries %s is not supported.\n", av_color_primaries_name(src->color_primaries)); -+ if (colorpri) -+ CVBufferSetAttachment(pixbuf, kCVImageBufferColorPrimariesKey, -+ colorpri, kCVAttachmentMode_ShouldPropagate); -+ else { -+ CVBufferRemoveAttachment(pixbuf, kCVImageBufferColorPrimariesKey); -+ if (src->color_primaries != AVCOL_SPC_UNSPECIFIED) -+ av_log(log_ctx, AV_LOG_WARNING, -+ "Color primaries %s is not supported.\n", -+ av_color_primaries_name(src->color_primaries)); -+ } - - colortrc = av_map_videotoolbox_color_trc_from_av(src->color_trc); -- if (!colortrc && src->color_trc != AVCOL_TRC_UNSPECIFIED) -- av_log(log_ctx, AV_LOG_WARNING, "Color transfer function %s is not supported.\n", av_color_transfer_name(src->color_trc)); -+ if (colortrc) -+ CVBufferSetAttachment(pixbuf, kCVImageBufferTransferFunctionKey, -+ colortrc, kCVAttachmentMode_ShouldPropagate); -+ else { -+ CVBufferRemoveAttachment(pixbuf, kCVImageBufferTransferFunctionKey); -+ if (src->color_trc != AVCOL_TRC_UNSPECIFIED) -+ av_log(log_ctx, AV_LOG_WARNING, -+ "Color transfer function %s is not supported.\n", -+ av_color_transfer_name(src->color_trc)); -+ } - - if (src->color_trc == AVCOL_TRC_GAMMA22) - gamma = 2.2; - else if (src->color_trc == AVCOL_TRC_GAMMA28) - gamma = 2.8; - -- if (colormatrix) { -- CVBufferSetAttachment( -- pixbuf, -- kCVImageBufferYCbCrMatrixKey, -- colormatrix, -- kCVAttachmentMode_ShouldPropagate); -- } -- if (colorpri) { -- CVBufferSetAttachment( -- pixbuf, -- kCVImageBufferColorPrimariesKey, -- colorpri, -- kCVAttachmentMode_ShouldPropagate); -- } -- if (colortrc) { -- CVBufferSetAttachment( -- pixbuf, -- kCVImageBufferTransferFunctionKey, -- colortrc, -- kCVAttachmentMode_ShouldPropagate); -- } - if (gamma != 0) { - CFNumberRef gamma_level = CFNumberCreate(NULL, kCFNumberFloat32Type, &gamma); -- CVBufferSetAttachment( -- pixbuf, -- kCVImageBufferGammaLevelKey, -- gamma_level, -- kCVAttachmentMode_ShouldPropagate); -+ CVBufferSetAttachment(pixbuf, kCVImageBufferGammaLevelKey, -+ gamma_level, kCVAttachmentMode_ShouldPropagate); - CFRelease(gamma_level); -+ } else -+ CVBufferRemoveAttachment(pixbuf, kCVImageBufferGammaLevelKey); -+ -+#if (TARGET_OS_OSX && __MAC_OS_X_VERSION_MAX_ALLOWED >= 100800) || \ -+ (TARGET_OS_IOS && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000) -+ if (__builtin_available(macOS 10.8, iOS 10, *)) { -+ CFDictionaryRef attachments = -+ vt_cv_buffer_copy_attachments(pixbuf, kCVAttachmentMode_ShouldPropagate); -+ -+ if (attachments) { -+ colorspace = -+ CVImageBufferCreateColorSpaceFromAttachments(attachments); -+ CFRelease(attachments); -+ } - } -+#endif -+ -+ // Done outside the above preprocessor code and if's so that -+ // in any case a wrong kCVImageBufferCGColorSpaceKey is removed -+ // if the above code is not used or fails. -+ if (colorspace) { -+ CVBufferSetAttachment(pixbuf, kCVImageBufferCGColorSpaceKey, -+ colorspace, kCVAttachmentMode_ShouldPropagate); -+ CFRelease(colorspace); -+ } else -+ CVBufferRemoveAttachment(pixbuf, kCVImageBufferCGColorSpaceKey); - - return 0; - } -Index: FFmpeg/libavutil/hwcontext_videotoolbox.h -=================================================================== ---- FFmpeg.orig/libavutil/hwcontext_videotoolbox.h -+++ FFmpeg/libavutil/hwcontext_videotoolbox.h -@@ -90,8 +90,15 @@ CFStringRef av_map_videotoolbox_color_pr - CFStringRef av_map_videotoolbox_color_trc_from_av(enum AVColorTransferCharacteristic trc); - - /** -- * Update a CVPixelBufferRef's metadata to based on an AVFrame. -- * Returns 0 if no known equivalent was found. -+ * Set CVPixelBufferRef's metadata based on an AVFrame. -+ * -+ * Sets/unsets the CVPixelBuffer attachments to match as closely as possible the -+ * AVFrame metadata. To prevent inconsistent attachments, the attachments for properties -+ * that could not be matched or are unspecified in the given AVFrame are unset. So if -+ * any attachments already covered by AVFrame metadata need to be set to a specific -+ * value, this should happen after calling this function. -+ * -+ * Returns < 0 in case of an error. - */ - int av_vt_pixbuf_set_attachments(void *log_ctx, - CVPixelBufferRef pixbuf, const struct AVFrame *src); -Index: FFmpeg/libavfilter/vf_yadif_videotoolbox.m -=================================================================== ---- FFmpeg.orig/libavfilter/vf_yadif_videotoolbox.m -+++ FFmpeg/libavfilter/vf_yadif_videotoolbox.m -@@ -24,6 +24,7 @@ - #include "yadif.h" - #include "libavutil/avassert.h" - #include "libavutil/hwcontext.h" -+#include "libavutil/hwcontext_videotoolbox.h" - #include "libavutil/objc.h" - - #include -@@ -94,9 +95,6 @@ static void call_kernel(AVFilterContext - - [buffer commit]; - [buffer waitUntilCompleted]; -- -- ff_objc_release(&encoder); -- ff_objc_release(&buffer); - } - - static void filter(AVFilterContext *ctx, AVFrame *dst, -@@ -321,8 +319,9 @@ static int config_input(AVFilterLink *in - - static int do_config_output(AVFilterLink *link) API_AVAILABLE(macos(10.11), ios(8.0)) - { -- AVHWFramesContext *output_frames; -+ AVHWFramesContext *output_frames, *input_frames; - AVFilterContext *ctx = link->src; -+ AVFilterLink *inlink = link->src->inputs[0]; - YADIFVTContext *s = ctx->priv; - YADIFContext *y = &s->yadif; - int ret = 0; -@@ -343,12 +342,14 @@ static int do_config_output(AVFilterLink - goto exit; - } - -+ input_frames = (AVHWFramesContext*)inlink->hw_frames_ctx->data; - 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; -+ ((AVVTFramesContext *)output_frames->hwctx)->color_range = ((AVVTFramesContext *)input_frames->hwctx)->color_range; - - ret = ff_filter_init_hw_frames(ctx, link, 10); - if (ret < 0) diff --git a/debian/patches/0052-add-vf-tonemap-videotoolbox-filter.patch b/debian/patches/0050-add-vf-tonemap-videotoolbox-filter.patch similarity index 97% rename from debian/patches/0052-add-vf-tonemap-videotoolbox-filter.patch rename to debian/patches/0050-add-vf-tonemap-videotoolbox-filter.patch index 34aaf48e6..cd445b51a 100644 --- a/debian/patches/0052-add-vf-tonemap-videotoolbox-filter.patch +++ b/debian/patches/0050-add-vf-tonemap-videotoolbox-filter.patch @@ -2,7 +2,7 @@ Index: FFmpeg/configure =================================================================== --- FFmpeg.orig/configure +++ FFmpeg/configure -@@ -3931,6 +3931,7 @@ tinterlace_merge_test_deps="tinterlace_f +@@ -3976,6 +3976,7 @@ tinterlace_merge_test_deps="tinterlace_f tinterlace_pad_test_deps="tinterlace_filter" tonemap_filter_deps="const_nan" tonemap_vaapi_filter_deps="vaapi VAProcFilterParameterBufferHDRToneMapping" @@ -14,7 +14,7 @@ Index: FFmpeg/libavfilter/Makefile =================================================================== --- FFmpeg.orig/libavfilter/Makefile +++ FFmpeg/libavfilter/Makefile -@@ -535,6 +535,9 @@ OBJS-$(CONFIG_TONEMAP_CUDA_FILTER) +@@ -537,6 +537,9 @@ OBJS-$(CONFIG_TONEMAP_CUDA_FILTER) OBJS-$(CONFIG_TONEMAP_OPENCL_FILTER) += vf_tonemap_opencl.o opencl.o \ opencl/tonemap.o opencl/colorspace_common.o OBJS-$(CONFIG_TONEMAP_VAAPI_FILTER) += vf_tonemap_vaapi.o vaapi_vpp.o @@ -28,7 +28,7 @@ Index: FFmpeg/libavfilter/allfilters.c =================================================================== --- FFmpeg.orig/libavfilter/allfilters.c +++ FFmpeg/libavfilter/allfilters.c -@@ -501,6 +501,7 @@ extern const AVFilter ff_vf_tonemap; +@@ -502,6 +502,7 @@ extern const AVFilter ff_vf_tonemap; extern const AVFilter ff_vf_tonemap_cuda; extern const AVFilter ff_vf_tonemap_opencl; extern const AVFilter ff_vf_tonemap_vaapi; @@ -966,7 +966,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_videotoolbox.m =================================================================== --- /dev/null +++ FFmpeg/libavfilter/vf_tonemap_videotoolbox.m -@@ -0,0 +1,1159 @@ +@@ -0,0 +1,1209 @@ +/* + * Copyright (c) 2024 Gnattu OC + * @@ -990,14 +990,15 @@ Index: FFmpeg/libavfilter/vf_tonemap_videotoolbox.m +#include + +#include "libavutil/avassert.h" -+#include "libavutil/common.h" +#include "libavutil/imgutils.h" ++#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/objc.h" +#include "libavutil/hwcontext.h" + +#include "avfilter.h" -+#include "internal.h" ++#include "filters.h" ++#include "formats.h" +#include "video.h" +#include "colorspace.h" +#include "dither_matrix.h" @@ -1021,6 +1022,13 @@ Index: FFmpeg/libavfilter/vf_tonemap_videotoolbox.m + AV_PIX_FMT_P010, +}; + ++static const int colorspaces_out[] = { ++ AVCOL_SPC_UNSPECIFIED, ++ AVCOL_SPC_BT709, ++ AVCOL_SPC_BT2020_NCL, ++ -1 ++}; ++ +enum TonemapAlgorithm { + TONEMAP_NONE, + TONEMAP_LINEAR, @@ -1693,8 +1701,10 @@ Index: FFmpeg/libavfilter/vf_tonemap_videotoolbox.m + +static int tonemap_videotoolbox_config_output(AVFilterLink *outlink) +{ ++ FilterLink *outl = ff_filter_link(outlink); + AVFilterContext *avctx = outlink->src; + AVFilterLink *inlink = avctx->inputs[0]; ++ FilterLink *inl = ff_filter_link(inlink); + TonemapVideoToolboxContext *ctx = avctx->priv; + AVHWFramesContext *in_frames_ctx, *out_frames_ctx; + enum AVPixelFormat in_format; @@ -1703,9 +1713,9 @@ Index: FFmpeg/libavfilter/vf_tonemap_videotoolbox.m + const AVPixFmtDescriptor *out_desc; + int ret; + -+ if (!inlink->hw_frames_ctx) ++ if (!inl->hw_frames_ctx) + return AVERROR(EINVAL); -+ in_frames_ctx = (AVHWFramesContext*)inlink->hw_frames_ctx->data; ++ in_frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data; + in_format = in_frames_ctx->sw_format; + out_format = (ctx->format == AV_PIX_FMT_NONE) ? in_format : ctx->format; + in_desc = av_pix_fmt_desc_get(in_format); @@ -1734,11 +1744,11 @@ Index: FFmpeg/libavfilter/vf_tonemap_videotoolbox.m + ctx->in_planes = av_pix_fmt_count_planes(in_format); + ctx->out_planes = av_pix_fmt_count_planes(out_format); + -+ av_buffer_unref(&outlink->hw_frames_ctx); -+ outlink->hw_frames_ctx = av_hwframe_ctx_alloc(in_frames_ctx->device_ref); ++ av_buffer_unref(&outl->hw_frames_ctx); ++ outl->hw_frames_ctx = av_hwframe_ctx_alloc(in_frames_ctx->device_ref); + outlink->w = inlink->w; + outlink->h = inlink->h; -+ out_frames_ctx = (AVHWFramesContext *)outlink->hw_frames_ctx->data; ++ out_frames_ctx = (AVHWFramesContext *)outl->hw_frames_ctx->data; + out_frames_ctx->format = AV_PIX_FMT_VIDEOTOOLBOX; + out_frames_ctx->sw_format = out_format; + out_frames_ctx->width = outlink->w; @@ -1754,7 +1764,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_videotoolbox.m + if (ret < 0) + return ret; + -+ ret = av_hwframe_ctx_init(outlink->hw_frames_ctx); ++ ret = av_hwframe_ctx_init(outl->hw_frames_ctx); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, + "Failed to init videotoolbox frame context, %s\n", @@ -1881,7 +1891,7 @@ Index: FFmpeg/libavfilter/vf_tonemap_videotoolbox.m + output->colorspace = input->colorspace = AVCOL_SPC_BT2020_NCL; + output->color_primaries = input->color_primaries = AVCOL_PRI_BT2020; + if (rpu->bl_video_full_range_flag) -+ output->color_range = input->color_range = AVCOL_RANGE_JPEG; ++ input->color_range = AVCOL_RANGE_JPEG; + } + } + @@ -1889,10 +1899,9 @@ Index: FFmpeg/libavfilter/vf_tonemap_videotoolbox.m + output->color_trc = ctx->trc; + if (ctx->primaries != -1) + output->color_primaries = ctx->primaries; -+ if (ctx->colorspace != -1) -+ output->colorspace = ctx->colorspace; -+ if (ctx->range != -1) -+ output->color_range = ctx->range; ++ ++ output->colorspace = outlink->colorspace; ++ output->color_range = outlink->color_range; + + ctx->trc_in = input->color_trc; + ctx->trc_out = output->color_trc; @@ -2050,6 +2059,47 @@ Index: FFmpeg/libavfilter/vf_tonemap_videotoolbox.m + return err; +} + ++static int tonemap_videotoolbox_query_formats(AVFilterContext *avctx) ++{ ++ TonemapVideoToolboxContext *ctx = avctx->priv; ++ AVFilterFormats *formats; ++ int ret; ++ const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_VIDEOTOOLBOX, AV_PIX_FMT_NONE }; ++ ++ // single format ++ formats = ff_make_format_list(pix_fmts); ++ ret = ff_formats_ref(formats, &avctx->inputs[0]->outcfg.formats); ++ if (ret < 0) ++ return ret; ++ ++ ret = ff_formats_ref(formats, &avctx->outputs[0]->incfg.formats); ++ if (ret < 0) ++ return ret; ++ ++ // colorspaces and ranges ++ if ((ret = ff_formats_ref(ff_all_color_spaces(), ++ &avctx->inputs[0]->outcfg.color_spaces)) < 0) ++ return ret; ++ ++ if ((ret = ff_formats_ref(ff_all_color_ranges(), ++ &avctx->inputs[0]->outcfg.color_ranges)) < 0) ++ return ret; ++ ++ formats = ctx->colorspace != -1 ++ ? ff_make_formats_list_singleton(ctx->colorspace) ++ : ff_make_format_list(colorspaces_out); ++ if ((ret = ff_formats_ref(formats, &avctx->outputs[0]->incfg.color_spaces)) < 0) ++ return ret; ++ ++ formats = ctx->range != -1 ++ ? ff_make_formats_list_singleton(ctx->range) ++ : ff_all_color_ranges(); ++ if ((ret = ff_formats_ref(formats, &avctx->outputs[0]->incfg.color_ranges)) < 0) ++ return ret; ++ ++ return 0; ++} ++ +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +#define OFFSET(x) offsetof(TonemapVideoToolboxContext, x) + @@ -2123,6 +2173,6 @@ Index: FFmpeg/libavfilter/vf_tonemap_videotoolbox.m + .uninit = tonemap_videotoolbox_uninit, + FILTER_INPUTS(tonemap_videotoolbox_inputs), + FILTER_OUTPUTS(tonemap_videotoolbox_outputs), -+ FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VIDEOTOOLBOX), ++ FILTER_QUERY_FUNC(tonemap_videotoolbox_query_formats), + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff --git a/debian/patches/0053-add-mjpeg-videotoolbox-encoder.patch b/debian/patches/0051-add-mjpeg-videotoolbox-encoder.patch similarity index 86% rename from debian/patches/0053-add-mjpeg-videotoolbox-encoder.patch rename to debian/patches/0051-add-mjpeg-videotoolbox-encoder.patch index bc3869137..17f90ecb7 100644 --- a/debian/patches/0053-add-mjpeg-videotoolbox-encoder.patch +++ b/debian/patches/0051-add-mjpeg-videotoolbox-encoder.patch @@ -2,7 +2,7 @@ Index: FFmpeg/configure =================================================================== --- FFmpeg.orig/configure +++ FFmpeg/configure -@@ -3488,6 +3488,8 @@ h264_videotoolbox_encoder_deps="pthreads +@@ -3524,6 +3524,8 @@ h264_videotoolbox_encoder_deps="pthreads h264_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder" hevc_videotoolbox_encoder_deps="pthreads" hevc_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder" @@ -15,31 +15,31 @@ Index: FFmpeg/libavcodec/Makefile =================================================================== --- FFmpeg.orig/libavcodec/Makefile +++ FFmpeg/libavcodec/Makefile -@@ -508,6 +508,7 @@ OBJS-$(CONFIG_MJPEG_CUVID_DECODER) + +@@ -518,6 +518,7 @@ OBJS-$(CONFIG_MJPEGB_DECODER) + + OBJS-$(CONFIG_MJPEG_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_MJPEG_QSV_ENCODER) += qsvenc_jpeg.o - OBJS-$(CONFIG_MJPEG_RKMPP_ENCODER) += rkmppenc.o OBJS-$(CONFIG_MJPEG_VAAPI_ENCODER) += vaapi_encode_mjpeg.o +OBJS-$(CONFIG_MJPEG_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o + OBJS-$(CONFIG_MJPEG_RKMPP_ENCODER) += rkmppenc.o OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o OBJS-$(CONFIG_MLP_ENCODER) += mlpenc.o mlp.o - OBJS-$(CONFIG_MMVIDEO_DECODER) += mmvideo.o Index: FFmpeg/libavcodec/allcodecs.c =================================================================== --- FFmpeg.orig/libavcodec/allcodecs.c +++ FFmpeg/libavcodec/allcodecs.c -@@ -876,6 +876,7 @@ extern const FFCodec ff_mjpeg_qsv_encode +@@ -875,6 +875,7 @@ extern const FFCodec ff_mjpeg_cuvid_deco + extern const FFCodec ff_mjpeg_qsv_encoder; extern const FFCodec ff_mjpeg_qsv_decoder; - extern const FFCodec ff_mjpeg_rkmpp_encoder; extern const FFCodec ff_mjpeg_vaapi_encoder; +extern const FFCodec ff_mjpeg_videotoolbox_encoder; + extern const FFCodec ff_mjpeg_rkmpp_encoder; + extern const FFCodec ff_mp3_mediacodec_decoder; extern const FFCodec ff_mp3_mf_encoder; - extern const FFCodec ff_mpeg1_cuvid_decoder; - extern const FFCodec ff_mpeg2_cuvid_decoder; Index: FFmpeg/libavcodec/videotoolboxenc.c =================================================================== --- FFmpeg.orig/libavcodec/videotoolboxenc.c +++ FFmpeg/libavcodec/videotoolboxenc.c -@@ -545,6 +545,7 @@ static CMVideoCodecType get_cm_codec_typ +@@ -546,6 +546,7 @@ static CMVideoCodecType get_cm_codec_typ else return MKBETAG('a','p','c','n'); // kCMVideoCodecType_AppleProRes422 } @@ -47,7 +47,7 @@ Index: FFmpeg/libavcodec/videotoolboxenc.c default: return 0; } } -@@ -1238,7 +1239,7 @@ static int vtenc_create_encoder(AVCodecC +@@ -1243,7 +1244,7 @@ static int vtenc_create_encoder(AVCodecC kVTCompressionPropertyKey_Quality, quality_num); CFRelease(quality_num); @@ -56,7 +56,7 @@ Index: FFmpeg/libavcodec/videotoolboxenc.c bit_rate_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &bit_rate); -@@ -1352,7 +1353,7 @@ static int vtenc_create_encoder(AVCodecC +@@ -1357,7 +1358,7 @@ static int vtenc_create_encoder(AVCodecC } } @@ -65,7 +65,7 @@ Index: FFmpeg/libavcodec/videotoolboxenc.c CFNumberRef interval = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &avctx->gop_size); -@@ -1501,7 +1502,7 @@ static int vtenc_create_encoder(AVCodecC +@@ -1506,7 +1507,7 @@ static int vtenc_create_encoder(AVCodecC } } @@ -74,7 +74,7 @@ Index: FFmpeg/libavcodec/videotoolboxenc.c status = VTSessionSetProperty(vtctx->session, kVTCompressionPropertyKey_AllowFrameReordering, kCFBooleanFalse); -@@ -2870,6 +2871,13 @@ static const enum AVPixelFormat prores_p +@@ -2875,6 +2876,13 @@ static const enum AVPixelFormat prores_p AV_PIX_FMT_NONE }; @@ -88,7 +88,7 @@ Index: FFmpeg/libavcodec/videotoolboxenc.c #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM #define COMMON_OPTIONS \ { "allow_sw", "Allow software encoding", OFFSET(allow_sw), AV_OPT_TYPE_BOOL, \ -@@ -3039,4 +3047,35 @@ const FFCodec ff_prores_videotoolbox_enc +@@ -3046,4 +3054,36 @@ const FFCodec ff_prores_videotoolbox_enc .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .p.wrapper_name = "videotoolbox", .hw_configs = vt_encode_hw_configs, @@ -116,6 +116,7 @@ Index: FFmpeg/libavcodec/videotoolboxenc.c + .priv_data_size = sizeof(VTEncContext), + .p.pix_fmts = mjpeg_pix_fmts, + .defaults = vt_defaults, ++ .color_ranges = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG, + .init = vtenc_init, + FF_CODEC_ENCODE_CB(vtenc_frame), + .close = vtenc_close, diff --git a/debian/patches/0054-add-vt-low-priority-keyframe-decoding.patch b/debian/patches/0052-add-vt-low-priority-keyframe-decoding.patch similarity index 94% rename from debian/patches/0054-add-vt-low-priority-keyframe-decoding.patch rename to debian/patches/0052-add-vt-low-priority-keyframe-decoding.patch index 7b6377a6a..267892780 100644 --- a/debian/patches/0054-add-vt-low-priority-keyframe-decoding.patch +++ b/debian/patches/0052-add-vt-low-priority-keyframe-decoding.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavcodec/avcodec.h =================================================================== --- FFmpeg.orig/libavcodec/avcodec.h +++ FFmpeg/libavcodec/avcodec.h -@@ -2174,6 +2174,13 @@ typedef struct AVHWAccel { +@@ -2185,6 +2185,13 @@ typedef struct AVHWAccel { #define AV_HWACCEL_FLAG_UNSAFE_OUTPUT (1 << 3) /** @@ -20,7 +20,7 @@ Index: FFmpeg/libavcodec/options_table.h =================================================================== --- FFmpeg.orig/libavcodec/options_table.h +++ FFmpeg/libavcodec/options_table.h -@@ -407,6 +407,7 @@ static const AVOption avcodec_options[] +@@ -412,6 +412,7 @@ static const AVOption avcodec_options[] {"mastering_display_metadata", .default_val.i64 = AV_PKT_DATA_MASTERING_DISPLAY_METADATA, .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" }, {"content_light_level", .default_val.i64 = AV_PKT_DATA_CONTENT_LIGHT_LEVEL, .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" }, {"icc_profile", .default_val.i64 = AV_PKT_DATA_ICC_PROFILE, .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = "side_data_pkt" }, @@ -32,7 +32,7 @@ Index: FFmpeg/libavcodec/videotoolbox.c =================================================================== --- FFmpeg.orig/libavcodec/videotoolbox.c +++ FFmpeg/libavcodec/videotoolbox.c -@@ -984,6 +984,23 @@ static int videotoolbox_start(AVCodecCon +@@ -985,6 +985,23 @@ static int videotoolbox_start(AVCodecCon av_log(avctx, AV_LOG_VERBOSE, "VideoToolbox reported invalid data.\n"); return AVERROR_INVALIDDATA; case 0: diff --git a/debian/patches/0055-add-dummy-device-derive-to-videotoolbox-hwcontext.patch b/debian/patches/0053-add-dummy-device-derive-to-videotoolbox-hwcontext.patch similarity index 100% rename from debian/patches/0055-add-dummy-device-derive-to-videotoolbox-hwcontext.patch rename to debian/patches/0053-add-dummy-device-derive-to-videotoolbox-hwcontext.patch diff --git a/debian/patches/0056-add-cuda-transpose-filter-impl.patch b/debian/patches/0054-add-cuda-transpose-filter-impl.patch similarity index 95% rename from debian/patches/0056-add-cuda-transpose-filter-impl.patch rename to debian/patches/0054-add-cuda-transpose-filter-impl.patch index a6975b749..aa236e2a5 100644 --- a/debian/patches/0056-add-cuda-transpose-filter-impl.patch +++ b/debian/patches/0054-add-cuda-transpose-filter-impl.patch @@ -2,7 +2,7 @@ Index: FFmpeg/configure =================================================================== --- FFmpeg.orig/configure +++ FFmpeg/configure -@@ -3297,6 +3297,8 @@ thumbnail_cuda_filter_deps="ffnvcodec" +@@ -3317,6 +3317,8 @@ thumbnail_cuda_filter_deps="ffnvcodec" thumbnail_cuda_filter_deps_any="cuda_nvcc cuda_llvm" tonemap_cuda_filter_deps="ffnvcodec const_nan" tonemap_cuda_filter_deps_any="cuda_nvcc cuda_llvm" @@ -15,7 +15,7 @@ Index: FFmpeg/libavfilter/Makefile =================================================================== --- FFmpeg.orig/libavfilter/Makefile +++ FFmpeg/libavfilter/Makefile -@@ -540,6 +540,8 @@ OBJS-$(CONFIG_TONEMAP_VIDEOTOOLBOX_FILTE +@@ -542,6 +542,8 @@ OBJS-$(CONFIG_TONEMAP_VIDEOTOOLBOX_FILTE metal/utils.o OBJS-$(CONFIG_TPAD_FILTER) += vf_tpad.o OBJS-$(CONFIG_TRANSPOSE_FILTER) += vf_transpose.o @@ -28,7 +28,7 @@ Index: FFmpeg/libavfilter/allfilters.c =================================================================== --- FFmpeg.orig/libavfilter/allfilters.c +++ FFmpeg/libavfilter/allfilters.c -@@ -504,6 +504,7 @@ extern const AVFilter ff_vf_tonemap_vaap +@@ -505,6 +505,7 @@ extern const AVFilter ff_vf_tonemap_vaap extern const AVFilter ff_vf_tonemap_videotoolbox; extern const AVFilter ff_vf_tpad; extern const AVFilter ff_vf_transpose; @@ -40,7 +40,7 @@ Index: FFmpeg/libavfilter/vf_transpose_cuda.c =================================================================== --- /dev/null +++ FFmpeg/libavfilter/vf_transpose_cuda.c -@@ -0,0 +1,477 @@ +@@ -0,0 +1,481 @@ +/* + * Copyright (C) 2024 NyanMisaka + * @@ -70,9 +70,9 @@ Index: FFmpeg/libavfilter/vf_transpose_cuda.c +#include "libavutil/pixdesc.h" + +#include "avfilter.h" -+#include "internal.h" -+#include "video.h" ++#include "filters.h" +#include "transpose.h" ++#include "video.h" + +#include "cuda/load_helper.h" + @@ -201,18 +201,20 @@ Index: FFmpeg/libavfilter/vf_transpose_cuda.c +static int init_processing_chain(AVFilterContext *ctx, + int out_width, int out_height) +{ ++ FilterLink *inl = ff_filter_link(ctx->inputs[0]); ++ FilterLink *outl = ff_filter_link(ctx->outputs[0]); + TransposeCUDAContext *s = ctx->priv; + AVHWFramesContext *in_frames_ctx; + enum AVPixelFormat format; + int ret; + + /* check that we have a hw context */ -+ if (!ctx->inputs[0]->hw_frames_ctx) { ++ if (!inl->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n"); + return AVERROR(EINVAL); + } + -+ in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data; ++ in_frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data; + format = in_frames_ctx->sw_format; + s->pix_desc = av_pix_fmt_desc_get(format); + @@ -230,8 +232,8 @@ Index: FFmpeg/libavfilter/vf_transpose_cuda.c + s->hwctx = in_frames_ctx->device_ctx->hwctx; + s->cu_stream = s->hwctx->stream; + -+ ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->frames_ctx); -+ if (!ctx->outputs[0]->hw_frames_ctx) ++ outl->hw_frames_ctx = av_buffer_ref(s->frames_ctx); ++ if (!outl->hw_frames_ctx) + return AVERROR(ENOMEM); + + return 0; @@ -241,8 +243,10 @@ Index: FFmpeg/libavfilter/vf_transpose_cuda.c +{ + extern const unsigned char ff_vf_transpose_cuda_ptx_data[]; + extern const unsigned int ff_vf_transpose_cuda_ptx_len; -+ AVFilterContext *ctx = outlink->src; -+ AVFilterLink *inlink = ctx->inputs[0]; ++ FilterLink *outl = ff_filter_link(outlink); ++ AVFilterContext *ctx = outlink->src; ++ AVFilterLink *inlink = ctx->inputs[0]; ++ FilterLink *inl = ff_filter_link(inlink); + TransposeCUDAContext *s = ctx->priv; + CUcontext dummy, cuda_ctx; + CudaFunctions *cu; @@ -250,9 +254,9 @@ Index: FFmpeg/libavfilter/vf_transpose_cuda.c + + if ((inlink->w >= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_LANDSCAPE) || + (inlink->w <= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_PORTRAIT)) { -+ if (inlink->hw_frames_ctx) { -+ outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx); -+ if (!outlink->hw_frames_ctx) ++ if (inl->hw_frames_ctx) { ++ outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx); ++ if (!outl->hw_frames_ctx) + return AVERROR(ENOMEM); + } + @@ -390,7 +394,7 @@ Index: FFmpeg/libavfilter/vf_transpose_cuda.c + AVFrame *out, AVFrame *in) +{ + TransposeCUDAContext *s = ctx->priv; -+ AVFilterLink *outlink = ctx->outputs[0]; ++ AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *src = in; + int ret; + diff --git a/debian/patches/0057-add-flip-feat-to-opencl-transpose-filter.patch b/debian/patches/0055-add-flip-feat-to-opencl-transpose-filter.patch similarity index 95% rename from debian/patches/0057-add-flip-feat-to-opencl-transpose-filter.patch rename to debian/patches/0055-add-flip-feat-to-opencl-transpose-filter.patch index df0842784..96c4ab733 100644 --- a/debian/patches/0057-add-flip-feat-to-opencl-transpose-filter.patch +++ b/debian/patches/0055-add-flip-feat-to-opencl-transpose-filter.patch @@ -19,7 +19,7 @@ Index: FFmpeg/libavfilter/vf_transpose_opencl.c =================================================================== --- FFmpeg.orig/libavfilter/vf_transpose_opencl.c +++ FFmpeg/libavfilter/vf_transpose_opencl.c -@@ -101,8 +101,20 @@ static int transpose_opencl_config_outpu +@@ -103,8 +103,20 @@ static int transpose_opencl_config_outpu return AVERROR(EINVAL); } @@ -42,7 +42,7 @@ Index: FFmpeg/libavfilter/vf_transpose_opencl.c ret = ff_opencl_filter_config_output(outlink); if (ret < 0) return ret; -@@ -114,10 +126,8 @@ static int transpose_opencl_config_outpu +@@ -116,10 +128,8 @@ static int transpose_opencl_config_outpu outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; av_log(avctx, AV_LOG_VERBOSE, @@ -55,7 +55,7 @@ Index: FFmpeg/libavfilter/vf_transpose_opencl.c return 0; } -@@ -235,11 +245,14 @@ static av_cold void transpose_opencl_uni +@@ -237,11 +247,14 @@ static av_cold void transpose_opencl_uni #define OFFSET(x) offsetof(TransposeOpenCLContext, x) #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) static const AVOption transpose_opencl_options[] = { diff --git a/debian/patches/0059-opus-allow-5point1-side-inputs.patch b/debian/patches/0056-opus-allow-5point1-side-inputs.patch similarity index 92% rename from debian/patches/0059-opus-allow-5point1-side-inputs.patch rename to debian/patches/0056-opus-allow-5point1-side-inputs.patch index aba6298b4..fa083e9bd 100644 --- a/debian/patches/0059-opus-allow-5point1-side-inputs.patch +++ b/debian/patches/0056-opus-allow-5point1-side-inputs.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavcodec/libopusenc.c =================================================================== --- FFmpeg.orig/libavcodec/libopusenc.c +++ FFmpeg/libavcodec/libopusenc.c -@@ -196,6 +196,10 @@ static int libopus_check_vorbis_layout(A +@@ -197,6 +197,10 @@ static int libopus_check_vorbis_layout(A av_log(avctx, AV_LOG_WARNING, "No channel layout specified. Opus encoder will use Vorbis " "channel layout for %d channels.\n", avctx->ch_layout.nb_channels); diff --git a/debian/patches/0060-add-simd-optimized-tonemapx-filter.patch b/debian/patches/0057-add-simd-optimized-tonemapx-filter.patch similarity index 99% rename from debian/patches/0060-add-simd-optimized-tonemapx-filter.patch rename to debian/patches/0057-add-simd-optimized-tonemapx-filter.patch index 7fb24da65..a0c7d03c0 100644 --- a/debian/patches/0060-add-simd-optimized-tonemapx-filter.patch +++ b/debian/patches/0057-add-simd-optimized-tonemapx-filter.patch @@ -2,28 +2,27 @@ Index: FFmpeg/configure =================================================================== --- FFmpeg.orig/configure +++ FFmpeg/configure -@@ -2314,6 +2314,9 @@ HEADERS_LIST=" - +@@ -2316,6 +2316,9 @@ HEADERS_LIST=" INTRINSICS_LIST=" intrinsics_neon + intrinsics_sse2 + intrinsics_sse42 + intrinsics_fma3 + intrinsics_avx2 " MATH_FUNCS=" -@@ -2797,6 +2800,10 @@ avx2_deps="avx" - avx512_deps="avx2" - avx512icl_deps="avx512" - +@@ -2750,6 +2753,9 @@ armv8_deps="aarch64" + neon_deps_any="aarch64 arm" + intrinsics_neon_deps="neon" + intrinsics_sse2_deps="sse2" +intrinsics_sse42_deps="sse42" +intrinsics_fma3_deps="fma3" +intrinsics_avx2_deps="avx2" -+ - mmx_external_deps="x86asm" - mmx_inline_deps="inline_asm x86" - mmx_suggest="mmx_external mmx_inline" -@@ -3934,6 +3941,7 @@ tinterlace_filter_deps="gpl" + vfp_deps="arm" + vfpv3_deps="vfp" + setend_deps="arm" +@@ -3979,6 +3985,7 @@ tinterlace_filter_deps="gpl" tinterlace_merge_test_deps="tinterlace_filter" tinterlace_pad_test_deps="tinterlace_filter" tonemap_filter_deps="const_nan" @@ -31,9 +30,9 @@ Index: FFmpeg/configure tonemap_vaapi_filter_deps="vaapi VAProcFilterParameterBufferHDRToneMapping" tonemap_videotoolbox_filter_deps="metal corevideo videotoolbox const_nan" tonemap_opencl_filter_deps="opencl const_nan" -@@ -6464,6 +6472,19 @@ fi - +@@ -6510,6 +6517,19 @@ fi check_cc intrinsics_neon arm_neon.h "int16x8_t test = vdupq_n_s16(0)" + check_cc intrinsics_sse2 emmintrin.h "__m128i test = _mm_setzero_si128()" +disable intrinsics_sse42 && test_cc -msse4.2 < @@ -51,7 +50,7 @@ Index: FFmpeg/configure check_ldflags -Wl,--as-needed check_ldflags -Wl,-z,noexecstack -@@ -7586,6 +7607,16 @@ elif enabled gcc; then +@@ -7639,6 +7659,16 @@ elif enabled gcc; then check_cflags -mpreferred-stack-boundary=4 ;; esac @@ -72,13 +71,13 @@ Index: FFmpeg/libavfilter/Makefile =================================================================== --- FFmpeg.orig/libavfilter/Makefile +++ FFmpeg/libavfilter/Makefile -@@ -530,6 +530,7 @@ OBJS-$(CONFIG_TMEDIAN_FILTER) +@@ -532,6 +532,7 @@ OBJS-$(CONFIG_TMEDIAN_FILTER) OBJS-$(CONFIG_TMIDEQUALIZER_FILTER) += vf_tmidequalizer.o OBJS-$(CONFIG_TMIX_FILTER) += vf_mix.o framesync.o OBJS-$(CONFIG_TONEMAP_FILTER) += vf_tonemap.o +OBJS-$(CONFIG_TONEMAPX_FILTER) += vf_tonemapx.o OBJS-$(CONFIG_TONEMAP_CUDA_FILTER) += vf_tonemap_cuda.o cuda/tonemap.ptx.o \ - cuda/host_util.o + cuda/host_util.o cuda/load_helper.o OBJS-$(CONFIG_TONEMAP_OPENCL_FILTER) += vf_tonemap_opencl.o opencl.o \ Index: FFmpeg/libavfilter/aarch64/Makefile =================================================================== @@ -2546,7 +2545,7 @@ Index: FFmpeg/libavfilter/allfilters.c =================================================================== --- FFmpeg.orig/libavfilter/allfilters.c +++ FFmpeg/libavfilter/allfilters.c -@@ -498,6 +498,7 @@ extern const AVFilter ff_vf_tmedian; +@@ -499,6 +499,7 @@ extern const AVFilter ff_vf_tmedian; extern const AVFilter ff_vf_tmidequalizer; extern const AVFilter ff_vf_tmix; extern const AVFilter ff_vf_tonemap; @@ -2635,7 +2634,7 @@ Index: FFmpeg/libavfilter/vf_tonemapx.c =================================================================== --- /dev/null +++ FFmpeg/libavfilter/vf_tonemapx.c -@@ -0,0 +1,1886 @@ +@@ -0,0 +1,1918 @@ +/* + * This file is part of FFmpeg. + * @@ -2665,6 +2664,7 @@ Index: FFmpeg/libavfilter/vf_tonemapx.c +#include "libavutil/avassert.h" +#include "libavutil/imgutils.h" +#include "libavutil/internal.h" ++#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" +#include "libavutil/opt.h" +#include "libavutil/cpu.h" @@ -2690,8 +2690,8 @@ Index: FFmpeg/libavfilter/vf_tonemapx.c +#endif // CC_SUPPORTS_TONEMAPX_INTRINSICS + +#include "avfilter.h" ++#include "filters.h" +#include "formats.h" -+#include "internal.h" +#include "video.h" + +#define MIX(x, y, a) ((x) + ((y) - (x)) * (a)) @@ -2806,6 +2806,13 @@ Index: FFmpeg/libavfilter/vf_tonemapx.c + AV_PIX_FMT_P010, +}; + ++static const int colorspaces_out[] = { ++ AVCOL_SPC_UNSPECIFIED, ++ AVCOL_SPC_BT709, ++ AVCOL_SPC_BT2020_NCL, ++ -1 ++}; ++ +const double dovi_lms2rgb_matrix[3][3] = +{ + { 3.06441879, -2.16597676, 0.10155818}, @@ -4164,9 +4171,9 @@ Index: FFmpeg/libavfilter/vf_tonemapx.c + } + + out->color_trc = s->trc == -1 ? AVCOL_TRC_UNSPECIFIED : s->trc; -+ out->colorspace = s->spc == -1 ? AVCOL_SPC_UNSPECIFIED : s->spc; ++ out->colorspace = outlink->colorspace; + out->color_primaries = s->pri == -1 ? AVCOL_PRI_UNSPECIFIED : s->pri; -+ out->color_range = s->range == -1 ? in->color_range : s->range; ++ out->color_range = outlink->color_range; + + if (in->color_trc == AVCOL_TRC_UNSPECIFIED) + in->color_trc = AVCOL_TRC_SMPTE2084; @@ -4254,9 +4261,9 @@ Index: FFmpeg/libavfilter/vf_tonemapx.c + AVFilterFormats *formats; + const AVPixFmtDescriptor *desc; + TonemapxContext *s = ctx->priv; ++ int res; + + if (!strcmp(s->format_str, "same")) { -+ int res; + formats = ff_make_format_list(in_pix_fmts); + res = ff_formats_ref(formats, &ctx->inputs[0]->outcfg.formats); + if (res < 0) @@ -4264,7 +4271,6 @@ Index: FFmpeg/libavfilter/vf_tonemapx.c + s->format = AV_PIX_FMT_NONE; + } else { + int i, j = 0; -+ int res; + formats = ff_make_format_list(in_pix_fmts); + res = ff_formats_ref(formats, &ctx->inputs[0]->outcfg.formats); + if (res < 0) @@ -4306,7 +4312,32 @@ Index: FFmpeg/libavfilter/vf_tonemapx.c + } + } + -+ return ff_formats_ref(formats, &ctx->outputs[0]->incfg.formats); ++ res = ff_formats_ref(formats, &ctx->outputs[0]->incfg.formats); ++ if (res < 0) ++ return res; ++ ++ // colorspaces and ranges ++ if ((res = ff_formats_ref(ff_all_color_spaces(), ++ &ctx->inputs[0]->outcfg.color_spaces)) < 0) ++ return res; ++ ++ if ((res = ff_formats_ref(ff_all_color_ranges(), ++ &ctx->inputs[0]->outcfg.color_ranges)) < 0) ++ return res; ++ ++ formats = s->spc != -1 ++ ? ff_make_formats_list_singleton(s->spc) ++ : ff_make_format_list(colorspaces_out); ++ if ((res = ff_formats_ref(formats, &ctx->outputs[0]->incfg.color_spaces)) < 0) ++ return res; ++ ++ formats = s->range != -1 ++ ? ff_make_formats_list_singleton(s->range) ++ : ff_all_color_ranges(); ++ if ((res = ff_formats_ref(formats, &ctx->outputs[0]->incfg.color_ranges)) < 0) ++ return res; ++ ++ return 0; +} + +static av_cold int init(AVFilterContext *ctx) @@ -4675,7 +4706,7 @@ Index: FFmpeg/libavfilter/x86/Makefile =================================================================== --- FFmpeg.orig/libavfilter/x86/Makefile +++ FFmpeg/libavfilter/x86/Makefile -@@ -34,6 +34,8 @@ OBJS-$(CONFIG_STEREO3D_FILTER) +@@ -36,6 +36,8 @@ OBJS-$(CONFIG_STEREO3D_FILTER) OBJS-$(CONFIG_TBLEND_FILTER) += x86/vf_blend_init.o OBJS-$(CONFIG_THRESHOLD_FILTER) += x86/vf_threshold_init.o OBJS-$(CONFIG_TINTERLACE_FILTER) += x86/vf_tinterlace_init.o diff --git a/debian/patches/0061-add-ac4-decoder-for-atsc-3-0.patch b/debian/patches/0058-add-ac4-decoder-for-atsc-3-0.patch similarity index 99% rename from debian/patches/0061-add-ac4-decoder-for-atsc-3-0.patch rename to debian/patches/0058-add-ac4-decoder-for-atsc-3-0.patch index d5dd109d3..40eecc1d2 100644 --- a/debian/patches/0061-add-ac4-decoder-for-atsc-3-0.patch +++ b/debian/patches/0058-add-ac4-decoder-for-atsc-3-0.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavcodec/Makefile =================================================================== --- FFmpeg.orig/libavcodec/Makefile +++ FFmpeg/libavcodec/Makefile -@@ -203,6 +203,7 @@ OBJS-$(CONFIG_AC3_ENCODER) + +@@ -210,6 +210,7 @@ OBJS-$(CONFIG_AC3_ENCODER) + ac3.o kbdwin.o OBJS-$(CONFIG_AC3_FIXED_ENCODER) += ac3enc_fixed.o ac3enc.o ac3tab.o ac3.o kbdwin.o OBJS-$(CONFIG_AC3_MF_ENCODER) += mfenc.o mf_utils.o @@ -14,7 +14,7 @@ Index: FFmpeg/libavcodec/ac4dec.c =================================================================== --- /dev/null +++ FFmpeg/libavcodec/ac4dec.c -@@ -0,0 +1,5924 @@ +@@ -0,0 +1,5925 @@ +/* + * AC-4 Audio Decoder + * @@ -43,6 +43,7 @@ Index: FFmpeg/libavcodec/ac4dec.c +#include "libavutil/tx.h" +#include "libavutil/channel_layout.h" +#include "libavutil/float_dsp.h" ++#include "libavutil/mem.h" +#include "libavutil/mem_internal.h" +#include "libavutil/qsort.h" +#include "libavutil/opt.h" @@ -7612,7 +7613,7 @@ Index: FFmpeg/libavcodec/allcodecs.c =================================================================== --- FFmpeg.orig/libavcodec/allcodecs.c +++ FFmpeg/libavcodec/allcodecs.c -@@ -431,6 +431,7 @@ extern const FFCodec ff_ac3_encoder; +@@ -430,6 +430,7 @@ extern const FFCodec ff_ac3_encoder; extern const FFCodec ff_ac3_decoder; extern const FFCodec ff_ac3_fixed_encoder; extern const FFCodec ff_ac3_fixed_decoder; @@ -7637,7 +7638,7 @@ Index: FFmpeg/libavcodec/utils.c =================================================================== --- FFmpeg.orig/libavcodec/utils.c +++ FFmpeg/libavcodec/utils.c -@@ -598,7 +598,8 @@ static int get_audio_frame_duration(enum +@@ -601,7 +601,8 @@ static int get_audio_frame_duration(enum case AV_CODEC_ID_ATRAC3P: return 2048; case AV_CODEC_ID_MP2: case AV_CODEC_ID_MUSEPACK7: return 1152; @@ -7651,7 +7652,7 @@ Index: FFmpeg/libavformat/isom_tags.c =================================================================== --- FFmpeg.orig/libavformat/isom_tags.c +++ FFmpeg/libavformat/isom_tags.c -@@ -308,6 +308,7 @@ const AVCodecTag ff_codec_movaudio_tags[ +@@ -310,6 +310,7 @@ const AVCodecTag ff_codec_movaudio_tags[ { AV_CODEC_ID_DTS, MKTAG('d', 't', 's', 'e') }, /* DTS Express */ { AV_CODEC_ID_DTS, MKTAG('D', 'T', 'S', ' ') }, /* non-standard */ { AV_CODEC_ID_EAC3, MKTAG('e', 'c', '-', '3') }, /* ETSI TS 102 366 Annex F (only valid in ISOBMFF) */ diff --git a/debian/patches/0058-add-customized-surf-align-for-vaapi-encoder.patch b/debian/patches/0058-add-customized-surf-align-for-vaapi-encoder.patch deleted file mode 100644 index 0f9e4bdaa..000000000 --- a/debian/patches/0058-add-customized-surf-align-for-vaapi-encoder.patch +++ /dev/null @@ -1,59 +0,0 @@ -Index: FFmpeg/libavcodec/vaapi_encode.c -=================================================================== ---- FFmpeg.orig/libavcodec/vaapi_encode.c -+++ FFmpeg/libavcodec/vaapi_encode.c -@@ -2728,6 +2728,17 @@ static av_cold int vaapi_encode_create_r - av_log(avctx, AV_LOG_DEBUG, "Using %s as format of " - "reconstructed frames.\n", av_get_pix_fmt_name(recon_format)); - -+ if (constraints->width_align || constraints->height_align) { -+ if (constraints->width_align) { -+ ctx->surface_width = FFALIGN(avctx->width, constraints->width_align); -+ } -+ if (constraints->height_align) { -+ ctx->surface_height = FFALIGN(avctx->height, constraints->height_align); -+ } -+ av_log(avctx, AV_LOG_VERBOSE, "Using customized alignment size " -+ "[%dx%d].\n", constraints->width_align, constraints->height_align); -+ } -+ - if (ctx->surface_width < constraints->min_width || - ctx->surface_height < constraints->min_height || - ctx->surface_width > constraints->max_width || -Index: FFmpeg/libavutil/hwcontext.h -=================================================================== ---- FFmpeg.orig/libavutil/hwcontext.h -+++ FFmpeg/libavutil/hwcontext.h -@@ -467,6 +467,13 @@ typedef struct AVHWFramesConstraints { - */ - int max_width; - int max_height; -+ -+ /** -+ * The frame width/height alignment when available -+ * (Zero is not applied, use the default value.) -+ */ -+ int width_align; -+ int height_align; - } AVHWFramesConstraints; - - /** -Index: FFmpeg/libavutil/hwcontext_vaapi.c -=================================================================== ---- FFmpeg.orig/libavutil/hwcontext_vaapi.c -+++ FFmpeg/libavutil/hwcontext_vaapi.c -@@ -297,6 +297,14 @@ static int vaapi_frames_get_constraints( - case VASurfaceAttribMaxHeight: - constraints->max_height = attr_list[i].value.value.i; - break; -+#if VA_CHECK_VERSION(1, 21, 0) -+ case VASurfaceAttribAlignmentSize: -+ if (attr_list[i].value.value.i) { -+ constraints->width_align = 1 << (attr_list[i].value.value.i & 0xf); -+ constraints->height_align = 1 << ((attr_list[i].value.value.i & 0xf0) >> 4); -+ } -+ break; -+#endif - } - } - if (pix_fmt_count == 0) { diff --git a/debian/patches/0062-tune-the-default-inter-thread-queue-sizes.patch b/debian/patches/0059-tune-the-default-inter-thread-queue-sizes.patch similarity index 94% rename from debian/patches/0062-tune-the-default-inter-thread-queue-sizes.patch rename to debian/patches/0059-tune-the-default-inter-thread-queue-sizes.patch index dfd752fbb..d0f438bd9 100644 --- a/debian/patches/0062-tune-the-default-inter-thread-queue-sizes.patch +++ b/debian/patches/0059-tune-the-default-inter-thread-queue-sizes.patch @@ -2,7 +2,7 @@ Index: FFmpeg/fftools/ffmpeg_sched.h =================================================================== --- FFmpeg.orig/fftools/ffmpeg_sched.h +++ FFmpeg/fftools/ffmpeg_sched.h -@@ -243,7 +243,10 @@ int sch_add_mux(Scheduler *sch, SchThrea +@@ -257,7 +257,10 @@ int sch_add_mux(Scheduler *sch, SchThrea /** * Default size of a frame thread queue. */ diff --git a/debian/patches/0060-backport-fixes-for-vulkan-from-upstream.patch b/debian/patches/0060-backport-fixes-for-vulkan-from-upstream.patch new file mode 100644 index 000000000..dca09bba9 --- /dev/null +++ b/debian/patches/0060-backport-fixes-for-vulkan-from-upstream.patch @@ -0,0 +1,185 @@ +Index: FFmpeg/libavutil/hwcontext_vulkan.c +=================================================================== +--- FFmpeg.orig/libavutil/hwcontext_vulkan.c ++++ FFmpeg/libavutil/hwcontext_vulkan.c +@@ -90,6 +90,9 @@ typedef struct VulkanDevicePriv { + VkPhysicalDeviceMemoryProperties mprops; + VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops; + ++ /* Opaque FD external semaphore properties */ ++ VkExternalSemaphoreProperties ext_sem_props_opaque; ++ + /* Features */ + VkPhysicalDeviceVulkan11Features device_features_1_1; + VkPhysicalDeviceVulkan12Features device_features_1_2; +@@ -1212,7 +1215,7 @@ static int setup_queue_families(AVHWDevi + }; + qf[i] = (VkQueueFamilyProperties2) { + .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2, +- .pNext = &qf_vid[i], ++ .pNext = p->vkctx.extensions & FF_VK_EXT_VIDEO_QUEUE ? &qf_vid[i] : NULL, + }; + } + +@@ -1642,6 +1645,7 @@ static int vulkan_device_init(AVHWDevice + FFVulkanFunctions *vk = &p->vkctx.vkfn; + VkQueueFamilyProperties2 *qf; + VkQueueFamilyVideoPropertiesKHR *qf_vid; ++ VkPhysicalDeviceExternalSemaphoreInfo ext_sem_props_info; + int graph_index, comp_index, tx_index, enc_index, dec_index; + + /* Set device extension flags */ +@@ -1687,6 +1691,24 @@ static int vulkan_device_init(AVHWDevice + return AVERROR_EXTERNAL; + } + ++ ext_sem_props_info = (VkPhysicalDeviceExternalSemaphoreInfo) { ++ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, ++ }; ++ ++ /* Opaque FD semaphore properties */ ++ ext_sem_props_info.handleType = ++#ifdef _WIN32 ++ IsWindows8OrGreater() ++ ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT ++ : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; ++#else ++ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; ++#endif ++ p->ext_sem_props_opaque.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES; ++ vk->GetPhysicalDeviceExternalSemaphoreProperties(hwctx->phys_dev, ++ &ext_sem_props_info, ++ &p->ext_sem_props_opaque); ++ + qf = av_malloc_array(qf_num, sizeof(VkQueueFamilyProperties2)); + if (!qf) + return AVERROR(ENOMEM); +@@ -1703,7 +1725,7 @@ static int vulkan_device_init(AVHWDevice + }; + qf[i] = (VkQueueFamilyProperties2) { + .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2, +- .pNext = &qf_vid[i], ++ .pNext = p->vkctx.extensions & FF_VK_EXT_VIDEO_QUEUE ? &qf_vid[i] : NULL, + }; + } + +@@ -1980,7 +2002,7 @@ static int vulkan_frames_get_constraints + count += vkfmt_from_pixfmt2(ctx, vk_formats_list[i].pixfmt, + p->use_linear_images ? VK_IMAGE_TILING_LINEAR : + VK_IMAGE_TILING_OPTIMAL, +- NULL, NULL, NULL, NULL, 0, 0) >= 0; ++ NULL, NULL, NULL, NULL, p->disable_multiplane, 1) >= 0; + } + + constraints->valid_sw_formats = av_malloc_array(count + 1, +@@ -1993,7 +2015,7 @@ static int vulkan_frames_get_constraints + if (vkfmt_from_pixfmt2(ctx, vk_formats_list[i].pixfmt, + p->use_linear_images ? VK_IMAGE_TILING_LINEAR : + VK_IMAGE_TILING_OPTIMAL, +- NULL, NULL, NULL, NULL, 0, 0) >= 0) { ++ NULL, NULL, NULL, NULL, p->disable_multiplane, 1) >= 0) { + constraints->valid_sw_formats[count++] = vk_formats_list[i].pixfmt; + } + } +@@ -2346,8 +2368,19 @@ static int create_frame(AVHWFramesContex + VulkanDevicePriv *p = ctx->hwctx; + AVVulkanDeviceContext *hwctx = &p->p; + FFVulkanFunctions *vk = &p->vkctx.vkfn; ++ AVVkFrame *f; + +- VkExportSemaphoreCreateInfo ext_sem_info = { ++ VkSemaphoreTypeCreateInfo sem_type_info = { ++ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, ++ .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, ++ .initialValue = 0, ++ }; ++ VkSemaphoreCreateInfo sem_spawn = { ++ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, ++ .pNext = &sem_type_info, ++ }; ++ ++ VkExportSemaphoreCreateInfo ext_sem_info_opaque = { + .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, + #ifdef _WIN32 + .handleTypes = IsWindows8OrGreater() +@@ -2358,23 +2391,13 @@ static int create_frame(AVHWFramesContex + #endif + }; + +- VkSemaphoreTypeCreateInfo sem_type_info = { +- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, +-#ifdef _WIN32 +- .pNext = p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM ? &ext_sem_info : NULL, +-#else +- .pNext = p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_SEM ? &ext_sem_info : NULL, +-#endif +- .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, +- .initialValue = 0, +- }; +- +- VkSemaphoreCreateInfo sem_spawn = { +- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, +- .pNext = &sem_type_info, +- }; ++ /* Check if exporting is supported before chaining any structs */ ++ if (p->ext_sem_props_opaque.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) { ++ if (p->vkctx.extensions & (FF_VK_EXT_EXTERNAL_WIN32_SEM | FF_VK_EXT_EXTERNAL_FD_SEM)) ++ ff_vk_link_struct(&sem_type_info, &ext_sem_info_opaque); ++ } + +- AVVkFrame *f = av_vk_frame_alloc(); ++ f = av_vk_frame_alloc(); + if (!f) { + av_log(ctx, AV_LOG_ERROR, "Unable to allocate memory for AVVkFrame!\n"); + return AVERROR(ENOMEM); +@@ -2689,11 +2712,11 @@ static int vulkan_frames_init(AVHWFrames + !(hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR))); + int sampleable = hwctx->usage & (VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_STORAGE_BIT); ++ hwctx->img_flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + if (sampleable && !is_lone_dpb) { +- hwctx->img_flags = VK_IMAGE_CREATE_ALIAS_BIT; ++ hwctx->img_flags |= VK_IMAGE_CREATE_ALIAS_BIT; + if ((fmt->vk_planes > 1) && (hwctx->format[0] == fmt->vkf)) +- hwctx->img_flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | +- VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; ++ hwctx->img_flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; + } + } + +Index: FFmpeg/libavutil/vulkan.c +=================================================================== +--- FFmpeg.orig/libavutil/vulkan.c ++++ FFmpeg/libavutil/vulkan.c +@@ -185,7 +185,7 @@ int ff_vk_load_props(FFVulkanContext *s) + }; + s->qf_props[i] = (VkQueueFamilyProperties2) { + .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2, +- .pNext = &s->video_props[i], ++ .pNext = s->extensions & FF_VK_EXT_VIDEO_QUEUE ? &s->video_props[i] : NULL, + }; + } + +Index: FFmpeg/libavutil/vulkan_functions.h +=================================================================== +--- FFmpeg.orig/libavutil/vulkan_functions.h ++++ FFmpeg/libavutil/vulkan_functions.h +@@ -33,10 +33,8 @@ typedef enum FFVulkanExtensions { + FF_VK_EXT_EXTERNAL_FD_SEM = 1ULL << 3, /* VK_KHR_external_semaphore_fd */ + FF_VK_EXT_EXTERNAL_HOST_MEMORY = 1ULL << 4, /* VK_EXT_external_memory_host */ + FF_VK_EXT_DEBUG_UTILS = 1ULL << 5, /* VK_EXT_debug_utils */ +-#ifdef _WIN32 + FF_VK_EXT_EXTERNAL_WIN32_MEMORY = 1ULL << 6, /* VK_KHR_external_memory_win32 */ + FF_VK_EXT_EXTERNAL_WIN32_SEM = 1ULL << 7, /* VK_KHR_external_semaphore_win32 */ +-#endif + FF_VK_EXT_DESCRIPTOR_BUFFER = 1ULL << 8, /* VK_EXT_descriptor_buffer */ + FF_VK_EXT_DEVICE_DRM = 1ULL << 9, /* VK_EXT_physical_device_drm */ + FF_VK_EXT_VIDEO_QUEUE = 1ULL << 10, /* VK_KHR_video_queue */ +@@ -75,6 +73,7 @@ typedef enum FFVulkanExtensions { + MACRO(1, 0, FF_VK_EXT_NO_FLAG, CreateDevice) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceFeatures2) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceProperties) \ ++ MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceExternalSemaphoreProperties) \ + MACRO(1, 0, FF_VK_EXT_VIDEO_QUEUE, GetPhysicalDeviceVideoCapabilitiesKHR) \ + MACRO(1, 0, FF_VK_EXT_VIDEO_QUEUE, GetPhysicalDeviceVideoFormatPropertiesKHR) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, DeviceWaitIdle) \ diff --git a/debian/patches/0065-revert-the-broken-vulkan-hwupload-rewrite.patch b/debian/patches/0061-revert-the-broken-vulkan-hwupload-rewrite.patch similarity index 98% rename from debian/patches/0065-revert-the-broken-vulkan-hwupload-rewrite.patch rename to debian/patches/0061-revert-the-broken-vulkan-hwupload-rewrite.patch index 5d6caff19..db47056af 100644 --- a/debian/patches/0065-revert-the-broken-vulkan-hwupload-rewrite.patch +++ b/debian/patches/0061-revert-the-broken-vulkan-hwupload-rewrite.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c =================================================================== --- FFmpeg.orig/libavutil/hwcontext_vulkan.c +++ FFmpeg/libavutil/hwcontext_vulkan.c -@@ -131,9 +131,6 @@ typedef struct VulkanFramesPriv { +@@ -139,9 +139,6 @@ typedef struct VulkanFramesPriv { FFVkExecPool upload_exec; FFVkExecPool download_exec; @@ -12,7 +12,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c /* Modifier info list to free at uninit */ VkImageDrmFormatModifierListCreateInfoEXT *modifier_info; } VulkanFramesPriv; -@@ -2561,8 +2558,6 @@ static void vulkan_frames_uninit(AVHWFra +@@ -2622,8 +2619,6 @@ static void vulkan_frames_uninit(AVHWFra ff_vk_exec_pool_free(&p->vkctx, &fp->compute_exec); ff_vk_exec_pool_free(&p->vkctx, &fp->upload_exec); ff_vk_exec_pool_free(&p->vkctx, &fp->download_exec); @@ -21,7 +21,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c } static int vulkan_frames_init(AVHWFramesContext *hwfc) -@@ -3611,290 +3606,128 @@ static int vulkan_map_from(AVHWFramesCon +@@ -3809,290 +3804,128 @@ static int vulkan_map_from(AVHWFramesCon return AVERROR(ENOSYS); } @@ -234,6 +234,10 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c - } - - get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i); +- +- /* Get the previous point at which mapping was possible and use it */ +- offs = (uintptr_t)swf->data[i] % p->hprops.minImportedHostPointerAlignment; +- import_desc.pHostPointer = swf->data[i] - offs; + ff_vk_frame_barrier(&p->vkctx, exec, f, img_bar, &nb_img_bar, + VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, @@ -243,10 +247,6 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED); -- /* Get the previous point at which mapping was possible and use it */ -- offs = (uintptr_t)swf->data[i] % p->hprops.minImportedHostPointerAlignment; -- import_desc.pHostPointer = swf->data[i] - offs; -- - props = (VkMemoryHostPointerPropertiesEXT) { - VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT, - }; @@ -383,10 +383,10 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c - VK_IMAGE_ASPECT_PLANE_0_BIT, - VK_IMAGE_ASPECT_PLANE_1_BIT, - VK_IMAGE_ASPECT_PLANE_2_BIT, }; -- + - VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS]; - int nb_img_bar = 0; - +- - AVBufferRef *bufs[AV_NUM_DATA_POINTERS]; - int nb_bufs = 0; + int host_mapped[AV_NUM_DATA_POINTERS] = { 0 }; @@ -399,7 +399,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c if ((swf->format != AV_PIX_FMT_NONE && !av_vkfmt_from_pixfmt(swf->format))) { av_log(hwfc, AV_LOG_ERROR, "Unsupported software frame pixel format!\n"); return AVERROR(EINVAL); -@@ -3903,97 +3736,115 @@ static int vulkan_transfer_frame(AVHWFra +@@ -4101,97 +3934,115 @@ static int vulkan_transfer_frame(AVHWFra if (swf->width > hwfc->width || swf->height > hwfc->height) return AVERROR(EINVAL); @@ -412,9 +412,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c + /* Create buffers */ + for (int i = 0; i < planes; i++) { + size_t req_size; - -- if (!host_mapped) { -- err = get_plane_buf(hwfc, &bufs[0], swf, region, upload); ++ + VkExternalMemoryBufferCreateInfo create_desc = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, + .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, @@ -430,7 +428,9 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c + }; + + get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i); -+ + +- if (!host_mapped) { +- err = get_plane_buf(hwfc, &bufs[0], swf, region, upload); + tmp.linesize[i] = FFABS(swf->linesize[i]); + + /* Do not map images with a negative stride */ @@ -587,7 +587,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c av_buffer_unref(&bufs[i]); return err; -@@ -4020,7 +3871,7 @@ static int vulkan_transfer_data_to(AVHWF +@@ -4218,7 +4069,7 @@ static int vulkan_transfer_data_to(AVHWF if (src->hw_frames_ctx) return AVERROR(ENOSYS); else @@ -596,7 +596,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c } } -@@ -4137,7 +3988,7 @@ static int vulkan_transfer_data_from(AVH +@@ -4335,7 +4186,7 @@ static int vulkan_transfer_data_from(AVH if (dst->hw_frames_ctx) return AVERROR(ENOSYS); else @@ -609,7 +609,7 @@ Index: FFmpeg/libavutil/vulkan.c =================================================================== --- FFmpeg.orig/libavutil/vulkan.c +++ FFmpeg/libavutil/vulkan.c -@@ -819,8 +819,11 @@ int ff_vk_alloc_mem(FFVulkanContext *s, +@@ -887,8 +887,11 @@ int ff_vk_alloc_mem(FFVulkanContext *s, ret = vk->AllocateMemory(s->hwctx->act_dev, &alloc_info, s->hwctx->alloc, mem); diff --git a/debian/patches/0066-use-linear-contiguous-vulkan-images-for-amd-encoder.patch b/debian/patches/0062-use-linear-contiguous-vulkan-images-for-amd-encoder.patch similarity index 73% rename from debian/patches/0066-use-linear-contiguous-vulkan-images-for-amd-encoder.patch rename to debian/patches/0062-use-linear-contiguous-vulkan-images-for-amd-encoder.patch index 63bfb35db..4fd0af5ee 100644 --- a/debian/patches/0066-use-linear-contiguous-vulkan-images-for-amd-encoder.patch +++ b/debian/patches/0062-use-linear-contiguous-vulkan-images-for-amd-encoder.patch @@ -2,7 +2,21 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c =================================================================== --- FFmpeg.orig/libavutil/hwcontext_vulkan.c +++ FFmpeg/libavutil/hwcontext_vulkan.c -@@ -1382,6 +1382,7 @@ static void vulkan_device_uninit(AVHWDev +@@ -64,6 +64,13 @@ + #if HAVE_LINUX_DMA_BUF_H + #include + #include ++#if 0 // ndef DMA_BUF_IOCTL_EXPORT_SYNC_FILE ++#define DMA_BUF_IOCTL_EXPORT_SYNC_FILE _IOWR(DMA_BUF_BASE, 2, struct dma_buf_export_sync_file) ++struct dma_buf_export_sync_file { ++ uint32_t flags; ++ int32_t fd; ++}; ++#endif + #endif + + #if CONFIG_CUDA +@@ -1400,6 +1407,7 @@ static void vulkan_device_uninit(AVHWDev static int vulkan_device_create_internal(AVHWDeviceContext *ctx, VulkanDeviceSelection *dev_select, @@ -10,7 +24,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c int disable_multiplane, AVDictionary *opts, int flags) { -@@ -1580,10 +1581,14 @@ static int vulkan_device_create_internal +@@ -1599,10 +1607,14 @@ static int vulkan_device_create_internal goto end; } @@ -29,7 +43,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c /* * The disable_multiplane argument takes precedent over the option. -@@ -1829,7 +1834,7 @@ static int vulkan_device_create(AVHWDevi +@@ -1882,7 +1894,7 @@ static int vulkan_device_create(AVHWDevi } } @@ -38,7 +52,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c } static int vulkan_device_derive(AVHWDeviceContext *ctx, -@@ -1853,6 +1858,7 @@ static int vulkan_device_derive(AVHWDevi +@@ -1906,6 +1918,7 @@ static int vulkan_device_derive(AVHWDevi }; #endif const char *vendor; @@ -46,7 +60,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c #if VA_CHECK_VERSION(1, 15, 0) vas = vaGetDisplayAttributes(dpy, &attr, 1); -@@ -1867,11 +1873,14 @@ static int vulkan_device_derive(AVHWDevi +@@ -1920,11 +1933,14 @@ static int vulkan_device_derive(AVHWDevi return AVERROR_EXTERNAL; } @@ -63,7 +77,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c } #endif #if CONFIG_LIBDRM -@@ -1880,6 +1889,7 @@ static int vulkan_device_derive(AVHWDevi +@@ -1933,6 +1949,7 @@ static int vulkan_device_derive(AVHWDevi struct stat drm_node_info; drmDevice *drm_dev_info; AVDRMDeviceContext *src_hwctx = src_ctx->hwctx; @@ -71,7 +85,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c err = fstat(src_hwctx->fd, &drm_node_info); if (err) { -@@ -1899,12 +1909,15 @@ static int vulkan_device_derive(AVHWDevi +@@ -1952,12 +1969,15 @@ static int vulkan_device_derive(AVHWDevi return AVERROR_EXTERNAL; } @@ -89,7 +103,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c } #endif #if CONFIG_CUDA -@@ -1927,7 +1940,7 @@ static int vulkan_device_derive(AVHWDevi +@@ -1980,7 +2000,7 @@ static int vulkan_device_derive(AVHWDevi * CUDA is not able to import multiplane images, so always derive a * Vulkan device with multiplane disabled. */ @@ -98,18 +112,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c } #endif default: -@@ -2774,6 +2787,10 @@ static const struct { - { DRM_FORMAT_XRGB8888, VK_FORMAT_B8G8R8A8_UNORM }, - { DRM_FORMAT_ABGR8888, VK_FORMAT_R8G8B8A8_UNORM }, - { DRM_FORMAT_XBGR8888, VK_FORMAT_R8G8B8A8_UNORM }, -+ { DRM_FORMAT_ARGB2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 }, -+ { DRM_FORMAT_XRGB2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 }, -+ { DRM_FORMAT_ABGR2101010, VK_FORMAT_A2B10G10R10_UNORM_PACK32 }, -+ { DRM_FORMAT_XBGR2101010, VK_FORMAT_A2B10G10R10_UNORM_PACK32 }, - - // All these DRM_FORMATs were added in the same libdrm commit. - #ifdef DRM_FORMAT_XYUV8888 -@@ -2808,6 +2825,7 @@ static int vulkan_map_from_drm_frame_des +@@ -2876,6 +2896,7 @@ static int vulkan_map_from_drm_frame_des const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->data[0]; VkBindImageMemoryInfo bind_info[AV_DRM_MAX_PLANES]; VkBindImagePlaneMemoryInfo plane_info[AV_DRM_MAX_PLANES]; @@ -117,7 +120,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c for (int i = 0; i < desc->nb_layers; i++) { if (drm_to_vulkan_fmt(desc->layers[i].format) == VK_FORMAT_UNDEFINED) { -@@ -2817,13 +2835,21 @@ static int vulkan_map_from_drm_frame_des +@@ -2885,13 +2906,21 @@ static int vulkan_map_from_drm_frame_des } } @@ -140,25 +143,63 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c for (int i = 0; i < desc->nb_layers; i++) { const int planes = desc->layers[i].nb_planes; -@@ -2861,7 +2887,7 @@ static int vulkan_map_from_drm_frame_des +@@ -2929,7 +2958,7 @@ static int vulkan_map_from_drm_frame_des .mipLevels = 1, .arrayLayers = 1, .flags = 0x0, - .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, + .tiling = f->tiling, .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, /* specs say so */ - .usage = VK_IMAGE_USAGE_SAMPLED_BIT | - VK_IMAGE_USAGE_TRANSFER_SRC_BIT, -@@ -2894,7 +2920,7 @@ static int vulkan_map_from_drm_frame_des - }; - VkPhysicalDeviceImageFormatInfo2 fmt_props = { + .usage = 0x0, /* filled in below */ + .samples = VK_SAMPLE_COUNT_1_BIT, +@@ -2970,7 +2999,7 @@ static int vulkan_map_from_drm_frame_des + + fmt_props = (VkPhysicalDeviceImageFormatInfo2) { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, - .pNext = &props_ext, + .pNext = has_modifiers ? &props_ext : NULL, .format = create_info.format, .type = create_info.imageType, .tiling = create_info.tiling, -@@ -3396,22 +3422,14 @@ fail: +@@ -3145,7 +3174,7 @@ static int vulkan_map_from_drm_frame_syn + + const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->data[0]; + +-#ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE ++#if 0 // def DMA_BUF_IOCTL_EXPORT_SYNC_FILE + if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_SEM) { + VkCommandBuffer cmd_buf; + FFVkExecContext *exec; +@@ -3171,8 +3200,10 @@ static int vulkan_map_from_drm_frame_syn + if (ioctl(desc->objects[i].fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE, + &implicit_fd_info)) { + err = AVERROR(errno); +- av_log(hwctx, AV_LOG_ERROR, "Failed to retrieve implicit DRM sync file: %s\n", ++ av_log(hwctx, i ? AV_LOG_ERROR : AV_LOG_DEBUG, "Failed to retrieve implicit DRM sync file: %s\n", + av_err2str(err)); ++ if (i == 0) /* Bail out from the plane0 if ioctl failed */ ++ goto fallback; + for (; i >= 0; i--) + vk->DestroySemaphore(hwctx->act_dev, drm_sync_sem[i], hwctx->alloc); + return err; +@@ -3248,10 +3279,12 @@ static int vulkan_map_from_drm_frame_syn + } else + #endif + { +- AVVkFrame *f = (AVVkFrame *)dst->data[0]; +- av_log(hwctx, AV_LOG_WARNING, "No support for synchronization when importing DMA-BUFs, " +- "image may be corrupted.\n"); +- err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_EXTERNAL_IMPORT); ++#if 0 // def DMA_BUF_IOCTL_EXPORT_SYNC_FILE ++fallback: ++#endif ++ av_log(hwctx, AV_LOG_DEBUG, "No support for synchronization when importing DMA-BUFs, " ++ "image may be corrupted.\n"); ++ err = prepare_frame(hwfc, &fp->compute_exec, (AVVkFrame *)dst->data[0], PREP_MODE_EXTERNAL_IMPORT); + if (err) + return err; + } +@@ -3594,22 +3627,14 @@ fail: static int vulkan_map_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { @@ -183,7 +224,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c #endif default: return AVERROR(ENOSYS); -@@ -3454,13 +3472,14 @@ static int vulkan_map_to_drm(AVHWFramesC +@@ -3652,13 +3677,14 @@ static int vulkan_map_to_drm(AVHWFramesC VulkanFramesPriv *fp = hwfc->hwctx; AVVulkanFramesContext *hwfctx = &fp->p; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); @@ -199,7 +240,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c }; AVDRMFrameDescriptor *drm_desc = av_mallocz(sizeof(*drm_desc)); -@@ -3481,10 +3500,16 @@ static int vulkan_map_to_drm(AVHWFramesC +@@ -3679,10 +3705,16 @@ static int vulkan_map_to_drm(AVHWFramesC if (err < 0) goto end; @@ -220,7 +261,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c err = AVERROR_EXTERNAL; goto end; } -@@ -3506,7 +3531,7 @@ static int vulkan_map_to_drm(AVHWFramesC +@@ -3704,7 +3736,7 @@ static int vulkan_map_to_drm(AVHWFramesC drm_desc->nb_objects++; drm_desc->objects[i].size = f->size[i]; @@ -229,7 +270,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c } drm_desc->nb_layers = planes; -@@ -3517,6 +3542,14 @@ static int vulkan_map_to_drm(AVHWFramesC +@@ -3715,6 +3747,14 @@ static int vulkan_map_to_drm(AVHWFramesC }; VkFormat plane_vkfmt = av_vkfmt_from_pixfmt(hwfc->sw_format)[i]; @@ -244,7 +285,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c drm_desc->layers[i].format = vulkan_fmt_to_drm(plane_vkfmt); drm_desc->layers[i].nb_planes = 1; -@@ -3531,7 +3564,7 @@ static int vulkan_map_to_drm(AVHWFramesC +@@ -3729,7 +3769,7 @@ static int vulkan_map_to_drm(AVHWFramesC if (f->tiling == VK_IMAGE_TILING_OPTIMAL) continue; @@ -253,7 +294,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c drm_desc->layers[i].planes[0].offset = layout.offset; drm_desc->layers[i].planes[0].pitch = layout.rowPitch; -@@ -3583,21 +3616,13 @@ fail: +@@ -3781,21 +3821,13 @@ fail: static int vulkan_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { diff --git a/debian/patches/0063-add-vendor-id-option-to-vaapi-hwcontext.patch b/debian/patches/0063-add-vendor-id-option-to-vaapi-hwcontext.patch deleted file mode 100644 index 874eafce4..000000000 --- a/debian/patches/0063-add-vendor-id-option-to-vaapi-hwcontext.patch +++ /dev/null @@ -1,78 +0,0 @@ -Index: FFmpeg/libavcodec/qsv.c -=================================================================== ---- FFmpeg.orig/libavcodec/qsv.c -+++ FFmpeg/libavcodec/qsv.c -@@ -473,8 +473,8 @@ static int ff_qsv_set_display_handle(AVC - AVVAAPIDeviceContext *hwctx; - int ret; - -- av_dict_set(&child_device_opts, "kernel_driver", "i915", 0); -- av_dict_set(&child_device_opts, "driver", "iHD", 0); -+ av_dict_set(&child_device_opts, "vendor_id", "0x8086", 0); -+ av_dict_set(&child_device_opts, "driver", "iHD", 0); - - ret = av_hwdevice_ctx_create(&qs->va_device_ref, AV_HWDEVICE_TYPE_VAAPI, NULL, child_device_opts, 0); - av_dict_free(&child_device_opts); -Index: FFmpeg/libavutil/hwcontext_qsv.c -=================================================================== ---- FFmpeg.orig/libavutil/hwcontext_qsv.c -+++ FFmpeg/libavutil/hwcontext_qsv.c -@@ -2644,8 +2644,8 @@ static int qsv_device_create(AVHWDeviceC - // used on recent Intel hardware. Set options to the VAAPI device - // creation so that we should pick a usable setup by default if - // possible, even when multiple devices and drivers are available. -- av_dict_set(&child_device_opts, "kernel_driver", "i915", 0); -- av_dict_set(&child_device_opts, "driver", "iHD", 0); -+ av_dict_set(&child_device_opts, "vendor_id", "0x8086", 0); -+ av_dict_set(&child_device_opts, "driver", "iHD", 0); - } - break; - #endif -Index: FFmpeg/libavutil/hwcontext_vaapi.c -=================================================================== ---- FFmpeg.orig/libavutil/hwcontext_vaapi.c -+++ FFmpeg/libavutil/hwcontext_vaapi.c -@@ -1763,7 +1763,9 @@ static int vaapi_device_create(AVHWDevic - #if CONFIG_LIBDRM - drmVersion *info; - const AVDictionaryEntry *kernel_driver; -+ const AVDictionaryEntry *vendor_id; - kernel_driver = av_dict_get(opts, "kernel_driver", NULL, 0); -+ vendor_id = av_dict_get(opts, "vendor_id", NULL, 0); - #endif - for (n = 0; n < max_devices; n++) { - snprintf(path, sizeof(path), -@@ -1818,6 +1820,33 @@ static int vaapi_device_create(AVHWDevic - close(priv->drm_fd); - priv->drm_fd = -1; - continue; -+ } else if (vendor_id) { -+ drmDevicePtr device; -+ char drm_vendor[8]; -+ if (drmGetDevice(priv->drm_fd, &device)) { -+ av_log(ctx, AV_LOG_VERBOSE, -+ "Failed to get DRM device info for device %d.\n", n); -+ close(priv->drm_fd); -+ priv->drm_fd = -1; -+ continue; -+ } -+ -+ snprintf(drm_vendor, sizeof(drm_vendor), "0x%x", device->deviceinfo.pci->vendor_id); -+ if (strcmp(vendor_id->value, drm_vendor)) { -+ av_log(ctx, AV_LOG_VERBOSE, "Ignoring device %d " -+ "with non-matching vendor id (%s).\n", -+ n, vendor_id->value); -+ drmFreeDevice(&device); -+ close(priv->drm_fd); -+ priv->drm_fd = -1; -+ continue; -+ } -+ av_log(ctx, AV_LOG_VERBOSE, "Trying to use " -+ "DRM render node for device %d, " -+ "with matching vendor id (%s).\n", -+ n, vendor_id->value); -+ drmFreeDevice(&device); -+ break; - } - drmFreeVersion(info); - #endif diff --git a/debian/patches/0067-prefer-vulkan-device-with-higher-api-version.patch b/debian/patches/0063-prefer-vulkan-device-with-higher-api-version.patch similarity index 97% rename from debian/patches/0067-prefer-vulkan-device-with-higher-api-version.patch rename to debian/patches/0063-prefer-vulkan-device-with-higher-api-version.patch index 99169e99d..256327f51 100644 --- a/debian/patches/0067-prefer-vulkan-device-with-higher-api-version.patch +++ b/debian/patches/0063-prefer-vulkan-device-with-higher-api-version.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c =================================================================== --- FFmpeg.orig/libavutil/hwcontext_vulkan.c +++ FFmpeg/libavutil/hwcontext_vulkan.c -@@ -950,7 +950,7 @@ static const char *vk_dev_type(enum VkPh +@@ -968,7 +968,7 @@ static const char *vk_dev_type(enum VkPh static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select) { int err = 0, choice = -1; @@ -11,7 +11,7 @@ Index: FFmpeg/libavutil/hwcontext_vulkan.c VkResult ret; VulkanDevicePriv *p = ctx->hwctx; AVVulkanDeviceContext *hwctx = &p->p; -@@ -1017,63 +1017,78 @@ static int find_device(AVHWDeviceContext +@@ -1035,63 +1035,78 @@ static int find_device(AVHWDeviceContext if (select->has_uuid) { for (int i = 0; i < num; i++) { diff --git a/debian/patches/0068-add-pgs-support-to-vulkan-overlay.patch b/debian/patches/0064-add-pgs-support-to-vulkan-overlay.patch similarity index 94% rename from debian/patches/0068-add-pgs-support-to-vulkan-overlay.patch rename to debian/patches/0064-add-pgs-support-to-vulkan-overlay.patch index bdafe2a19..210063dd5 100644 --- a/debian/patches/0068-add-pgs-support-to-vulkan-overlay.patch +++ b/debian/patches/0064-add-pgs-support-to-vulkan-overlay.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavfilter/vf_overlay_vulkan.c =================================================================== --- FFmpeg.orig/libavfilter/vf_overlay_vulkan.c +++ FFmpeg/libavfilter/vf_overlay_vulkan.c -@@ -32,9 +32,11 @@ typedef struct OverlayVulkanContext { +@@ -33,9 +33,11 @@ typedef struct OverlayVulkanContext { int initialized; FFVulkanPipeline pl; @@ -14,7 +14,7 @@ Index: FFmpeg/libavfilter/vf_overlay_vulkan.c VkSampler sampler; /* Push constants / options */ -@@ -47,6 +49,10 @@ typedef struct OverlayVulkanContext { +@@ -48,6 +50,10 @@ typedef struct OverlayVulkanContext { int overlay_y; int overlay_w; int overlay_h; @@ -25,7 +25,7 @@ Index: FFmpeg/libavfilter/vf_overlay_vulkan.c } OverlayVulkanContext; static const char overlay_noalpha[] = { -@@ -83,15 +89,16 @@ static const char overlay_alpha[] = { +@@ -84,15 +90,16 @@ static const char overlay_alpha[] = { static av_cold int init_filter(AVFilterContext *ctx) { int err; @@ -44,7 +44,7 @@ Index: FFmpeg/libavfilter/vf_overlay_vulkan.c FFVkSPIRVCompiler *spv; FFVulkanDescriptorSetBinding *desc; -@@ -104,90 +111,143 @@ static av_cold int init_filter(AVFilterC +@@ -105,90 +112,143 @@ static av_cold int init_filter(AVFilterC ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT); RET(ff_vk_exec_pool_init(vkctx, &s->qf, &s->e, s->qf.nb_queues*4, 0, 0, 0, NULL)); RET(ff_vk_init_sampler(vkctx, &s->sampler, 1, VK_FILTER_NEAREST)); @@ -262,7 +262,7 @@ Index: FFmpeg/libavfilter/vf_overlay_vulkan.c if (spv) spv->uninit(&spv); -@@ -209,22 +269,11 @@ static int overlay_vulkan_blend(FFFrameS +@@ -210,22 +270,11 @@ static int overlay_vulkan_blend(FFFrameS if (err < 0) goto fail; @@ -288,7 +288,7 @@ Index: FFmpeg/libavfilter/vf_overlay_vulkan.c out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { -@@ -232,9 +281,13 @@ static int overlay_vulkan_blend(FFFrameS +@@ -233,9 +282,13 @@ static int overlay_vulkan_blend(FFFrameS goto fail; } @@ -305,14 +305,16 @@ Index: FFmpeg/libavfilter/vf_overlay_vulkan.c err = av_frame_copy_props(out, input_main); if (err < 0) -@@ -252,6 +305,18 @@ static int overlay_vulkan_config_output( +@@ -253,6 +306,20 @@ static int overlay_vulkan_config_output( int err; AVFilterContext *avctx = outlink->src; OverlayVulkanContext *s = avctx->priv; + AVFilterLink *inlink = avctx->inputs[0]; + AVFilterLink *inlink_overlay = avctx->inputs[1]; -+ AVHWFramesContext *main_fc = (AVHWFramesContext*)inlink->hw_frames_ctx->data; -+ AVHWFramesContext *overlay_fc = (AVHWFramesContext*)inlink_overlay->hw_frames_ctx->data; ++ FilterLink *inl = ff_filter_link(inlink); ++ FilterLink *inl_overlay = ff_filter_link(inlink_overlay); ++ AVHWFramesContext *main_fc = (AVHWFramesContext*)inl->hw_frames_ctx->data; ++ AVHWFramesContext *overlay_fc = (AVHWFramesContext*)inl_overlay->hw_frames_ctx->data; + + if (main_fc->sw_format != overlay_fc->sw_format) { + av_log(avctx, AV_LOG_ERROR, "Mismatching sw formats!\n"); @@ -324,7 +326,7 @@ Index: FFmpeg/libavfilter/vf_overlay_vulkan.c err = ff_vk_filter_config_output(outlink); if (err < 0) -@@ -261,6 +326,11 @@ static int overlay_vulkan_config_output( +@@ -262,6 +329,11 @@ static int overlay_vulkan_config_output( if (err < 0) return err; @@ -336,7 +338,7 @@ Index: FFmpeg/libavfilter/vf_overlay_vulkan.c return ff_framesync_configure(&s->fs); } -@@ -288,7 +358,9 @@ static void overlay_vulkan_uninit(AVFilt +@@ -289,7 +361,9 @@ static void overlay_vulkan_uninit(AVFilt ff_vk_exec_pool_free(vkctx, &s->e); ff_vk_pipeline_free(vkctx, &s->pl); @@ -346,7 +348,7 @@ Index: FFmpeg/libavfilter/vf_overlay_vulkan.c if (s->sampler) vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler, -@@ -305,6 +377,14 @@ static void overlay_vulkan_uninit(AVFilt +@@ -306,6 +380,14 @@ static void overlay_vulkan_uninit(AVFilt static const AVOption overlay_vulkan_options[] = { { "x", "Set horizontal offset", OFFSET(overlay_x), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, .flags = FLAGS }, { "y", "Set vertical offset", OFFSET(overlay_y), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, .flags = FLAGS }, diff --git a/debian/patches/0064-backport-fixes-for-vulkan-from-upstream.patch b/debian/patches/0064-backport-fixes-for-vulkan-from-upstream.patch deleted file mode 100644 index afec8f0b3..000000000 --- a/debian/patches/0064-backport-fixes-for-vulkan-from-upstream.patch +++ /dev/null @@ -1,2615 +0,0 @@ -Index: FFmpeg/libavcodec/vulkan_decode.c -=================================================================== ---- FFmpeg.orig/libavcodec/vulkan_decode.c -+++ FFmpeg/libavcodec/vulkan_decode.c -@@ -87,7 +87,7 @@ int ff_vk_update_thread_context(AVCodecC - - const VkVideoProfileInfoKHR *profile = get_video_profile(ctx, dst->codec_id); - if (!profile) { -- av_log(dst, AV_LOG_ERROR, "Video profile missing from frames context!"); -+ av_log(dst, AV_LOG_ERROR, "Video profile missing from frames context!\n"); - return AVERROR(EINVAL); - } - -@@ -259,7 +259,7 @@ int ff_vk_decode_add_slice(AVCodecContex - const int nb = *nb_slices; - uint8_t *slices; - uint32_t *slice_off; -- FFVkVideoBuffer *vkbuf; -+ FFVkBuffer *vkbuf; - - size_t new_size = vp->slices_size + startcode_len + size + - ctx->caps.minBitstreamBufferSizeAlignment; -@@ -273,29 +273,38 @@ int ff_vk_decode_add_slice(AVCodecContex - *offsets = dec->slice_off = slice_off; - slice_off[nb] = vp->slices_size; - -- vkbuf = vp->slices_buf ? (FFVkVideoBuffer *)vp->slices_buf->data : NULL; -- if (!vkbuf || vkbuf->buf.size < new_size) { -+ vkbuf = vp->slices_buf ? (FFVkBuffer *)vp->slices_buf->data : NULL; -+ if (!vkbuf || vkbuf->size < new_size) { - int err; - AVBufferRef *new_ref; -- FFVkVideoBuffer *new_buf; -- err = ff_vk_video_get_buffer(&ctx->s, &ctx->common, &new_ref, -- VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR, -- ctx->s.hwfc->create_pnext, new_size); -+ FFVkBuffer *new_buf; -+ -+ /* No point in requesting anything smaller. */ -+ size_t buf_size = FFMAX(new_size, 1024*1024); -+ -+ /* Align buffer to nearest power of two. Makes fragmentation management -+ * easier, and gives us ample headroom. */ -+ buf_size = 2 << av_log2(buf_size); -+ -+ err = ff_vk_get_pooled_buffer(&ctx->s, &ctx->buf_pool, &new_ref, -+ VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR, -+ ctx->s.hwfc->create_pnext, buf_size, -+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - if (err < 0) - return err; - -- new_buf = (FFVkVideoBuffer *)new_ref->data; -+ new_buf = (FFVkBuffer *)new_ref->data; - - /* Copy data from the old buffer */ - if (vkbuf) { -- memcpy(new_buf->mem, vkbuf->mem, vp->slices_size); -+ memcpy(new_buf->mapped_mem, vkbuf->mapped_mem, vp->slices_size); - av_buffer_unref(&vp->slices_buf); - } - - vp->slices_buf = new_ref; - vkbuf = new_buf; - } -- slices = vkbuf->mem; -+ slices = vkbuf->mapped_mem; - - /* Startcode */ - memcpy(slices + vp->slices_size, startcode_prefix, startcode_len); -@@ -346,7 +355,7 @@ int ff_vk_decode_frame(AVCodecContext *a - int err; - VkResult ret; - VkCommandBuffer cmd_buf; -- FFVkVideoBuffer *sd_buf; -+ FFVkBuffer *sd_buf; - - FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; - FFVulkanDecodeShared *ctx = dec->shared_ctx; -@@ -399,13 +408,13 @@ int ff_vk_decode_frame(AVCodecContext *a - "Result of previous frame decoding: %"PRId64"\n", prev_sub_res); - } - -- sd_buf = (FFVkVideoBuffer *)vp->slices_buf->data; -+ sd_buf = (FFVkBuffer *)vp->slices_buf->data; - - /* Flush if needed */ -- if (!(sd_buf->buf.flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { -+ if (!(sd_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { - VkMappedMemoryRange flush_buf = { - .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, -- .memory = sd_buf->buf.mem, -+ .memory = sd_buf->mem, - .offset = 0, - .size = FFALIGN(vp->slices_size, - ctx->s.props.properties.limits.nonCoherentAtomSize), -@@ -419,7 +428,7 @@ int ff_vk_decode_frame(AVCodecContext *a - } - } - -- vp->decode_info.srcBuffer = sd_buf->buf.buf; -+ vp->decode_info.srcBuffer = sd_buf->buf; - vp->decode_info.srcBufferOffset = 0; - vp->decode_info.srcBufferRange = data_size; - -@@ -620,6 +629,8 @@ static void free_common(FFRefStructOpaqu - ctx->empty_session_params, - s->hwctx->alloc); - -+ av_buffer_pool_uninit(&ctx->buf_pool); -+ - ff_vk_video_common_uninit(s, &ctx->common); - - if (ctx->yuv_sampler) -@@ -911,9 +922,9 @@ static int vulkan_decode_get_profile(AVC - return AVERROR_EXTERNAL; - } - -- /* TODO: make dedicated_dpb tunable */ - dec->dedicated_dpb = !(dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR); -- dec->layered_dpb = !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR); -+ dec->layered_dpb = !dec->dedicated_dpb ? 0 : -+ !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR); - - if (dec->dedicated_dpb) { - fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; -@@ -922,6 +933,10 @@ static int vulkan_decode_get_profile(AVC - VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT; -+ -+ if (ctx->s.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE | -+ FF_VK_EXT_VIDEO_MAINTENANCE_1)) -+ fmt_info.imageUsage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; - } - - /* Get the format of the images necessary */ -@@ -1011,6 +1026,7 @@ int ff_vk_frame_params(AVCodecContext *a - AVVulkanFramesContext *hwfc = frames_ctx->hwctx; - FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; - FFVulkanDecodeProfileData *prof; -+ FFVulkanDecodeShared *ctx; - - frames_ctx->sw_format = AV_PIX_FMT_NONE; - -@@ -1047,6 +1063,11 @@ int ff_vk_frame_params(AVCodecContext *a - if (!dec->dedicated_dpb) - hwfc->usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; - -+ ctx = dec->shared_ctx; -+ if (ctx->s.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE | -+ FF_VK_EXT_VIDEO_MAINTENANCE_1)) -+ hwfc->usage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; -+ - return err; - } - -@@ -1106,7 +1127,7 @@ int ff_vk_decode_uninit(AVCodecContext * - - int ff_vk_decode_init(AVCodecContext *avctx) - { -- int err, qf, cxpos = 0, cypos = 0, nb_q = 0; -+ int err, cxpos = 0, cypos = 0, nb_q = 0; - VkResult ret; - FFVulkanDecodeContext *dec = avctx->internal->hwaccel_priv_data; - FFVulkanDecodeShared *ctx; -@@ -1171,22 +1192,22 @@ int ff_vk_decode_init(AVCodecContext *av - goto fail; - - /* Create queue context */ -- qf = ff_vk_qf_init(s, &ctx->qf, VK_QUEUE_VIDEO_DECODE_BIT_KHR); -- - vk_desc = get_codecdesc(avctx->codec_id); -- /* Check for support */ -- if (!(s->video_props[qf].videoCodecOperations & vk_desc->decode_op)) { -- av_log(avctx, AV_LOG_ERROR, "Decoding %s not supported on the given " -- "queue family %i!\n", avcodec_get_name(avctx->codec_id), qf); -- return AVERROR(EINVAL); -+ err = ff_vk_video_qf_init(s, &ctx->qf, -+ VK_QUEUE_VIDEO_DECODE_BIT_KHR, -+ vk_desc->decode_op); -+ if (err < 0) { -+ av_log(avctx, AV_LOG_ERROR, "Decoding of %s is not supported by this device\n", -+ avcodec_get_name(avctx->codec_id)); -+ return err; - } - - /* Enable queries if supported */ -- if (s->query_props[qf].queryResultStatusSupport) -+ if (s->query_props[ctx->qf.queue_family].queryResultStatusSupport) - nb_q = 1; - - session_create.flags = 0x0; -- session_create.queueFamilyIndex = s->hwctx->queue_family_decode_index; -+ session_create.queueFamilyIndex = ctx->qf.queue_family; - session_create.maxCodedExtent = ctx->caps.maxCodedExtent; - session_create.maxDpbSlots = ctx->caps.maxDpbSlots; - session_create.maxActiveReferencePictures = ctx->caps.maxActiveReferencePictures; -Index: FFmpeg/libavcodec/vulkan_decode.h -=================================================================== ---- FFmpeg.orig/libavcodec/vulkan_decode.h -+++ FFmpeg/libavcodec/vulkan_decode.h -@@ -48,6 +48,8 @@ typedef struct FFVulkanDecodeShared { - FFVkVideoCommon common; - FFVkQueueFamilyCtx qf; - -+ AVBufferPool *buf_pool; -+ - VkVideoCapabilitiesKHR caps; - VkVideoDecodeCapabilitiesKHR dec_caps; - -Index: FFmpeg/libavcodec/vulkan_video.c -=================================================================== ---- FFmpeg.orig/libavcodec/vulkan_video.c -+++ FFmpeg/libavcodec/vulkan_video.c -@@ -176,84 +176,18 @@ int ff_vk_h265_level_to_av(StdVideoH265L - } - } - --static void free_data_buf(void *opaque, uint8_t *data) -+int ff_vk_video_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, -+ VkQueueFlagBits family, VkVideoCodecOperationFlagBitsKHR caps) - { -- FFVulkanContext *ctx = opaque; -- FFVkVideoBuffer *buf = (FFVkVideoBuffer *)data; -- ff_vk_unmap_buffer(ctx, &buf->buf, 0); -- ff_vk_free_buf(ctx, &buf->buf); -- av_free(data); --} -- --static AVBufferRef *alloc_data_buf(void *opaque, size_t size) --{ -- AVBufferRef *ref; -- uint8_t *buf = av_mallocz(size); -- if (!buf) -- return NULL; -- -- ref = av_buffer_create(buf, size, free_data_buf, opaque, 0); -- if (!ref) -- av_free(buf); -- return ref; --} -- --int ff_vk_video_get_buffer(FFVulkanContext *ctx, FFVkVideoCommon *s, -- AVBufferRef **buf, VkBufferUsageFlags usage, -- void *create_pNext, size_t size) --{ -- int err; -- AVBufferRef *ref; -- FFVkVideoBuffer *data; -- -- if (!s->buf_pool) { -- s->buf_pool = av_buffer_pool_init2(sizeof(FFVkVideoBuffer), ctx, -- alloc_data_buf, NULL); -- if (!s->buf_pool) -- return AVERROR(ENOMEM); -+ for (int i = 0; i < s->hwctx->nb_qf; i++) { -+ if ((s->hwctx->qf[i].flags & family) && -+ (s->hwctx->qf[i].video_caps & caps)) { -+ qf->queue_family = s->hwctx->qf[i].idx; -+ qf->nb_queues = s->hwctx->qf[i].num; -+ return 0; -+ } - } -- -- *buf = ref = av_buffer_pool_get(s->buf_pool); -- if (!ref) -- return AVERROR(ENOMEM); -- -- data = (FFVkVideoBuffer *)ref->data; -- -- if (data->buf.size >= size) -- return 0; -- -- /* No point in requesting anything smaller. */ -- size = FFMAX(size, 1024*1024); -- -- /* Align buffer to nearest power of two. Makes fragmentation management -- * easier, and gives us ample headroom. */ -- size--; -- size |= size >> 1; -- size |= size >> 2; -- size |= size >> 4; -- size |= size >> 8; -- size |= size >> 16; -- size++; -- -- ff_vk_free_buf(ctx, &data->buf); -- memset(data, 0, sizeof(FFVkVideoBuffer)); -- -- err = ff_vk_create_buf(ctx, &data->buf, size, -- create_pNext, NULL, usage, -- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); -- if (err < 0) { -- av_buffer_unref(&ref); -- return err; -- } -- -- /* Map the buffer */ -- err = ff_vk_map_buffer(ctx, &data->buf, &data->mem, 0); -- if (err < 0) { -- av_buffer_unref(&ref); -- return err; -- } -- -- return 0; -+ return AVERROR(ENOTSUP); - } - - av_cold void ff_vk_video_common_uninit(FFVulkanContext *s, -@@ -272,8 +206,6 @@ av_cold void ff_vk_video_common_uninit(F - vk->FreeMemory(s->hwctx->act_dev, common->mem[i], s->hwctx->alloc); - - av_freep(&common->mem); -- -- av_buffer_pool_uninit(&common->buf_pool); - } - - av_cold int ff_vk_video_common_init(void *log, FFVulkanContext *s, -Index: FFmpeg/libavcodec/vulkan_video.h -=================================================================== ---- FFmpeg.orig/libavcodec/vulkan_video.h -+++ FFmpeg/libavcodec/vulkan_video.h -@@ -32,8 +32,6 @@ typedef struct FFVkVideoSession { - VkVideoSessionKHR session; - VkDeviceMemory *mem; - uint32_t nb_mem; -- -- AVBufferPool *buf_pool; - } FFVkVideoCommon; - - /** -@@ -56,6 +54,11 @@ VkVideoChromaSubsamplingFlagBitsKHR ff_v - */ - VkVideoComponentBitDepthFlagBitsKHR ff_vk_depth_from_av_depth(int depth); - -+/** -+ * Chooses a QF and loads it into a context. -+ */ -+int ff_vk_video_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, -+ VkQueueFlagBits family, VkVideoCodecOperationFlagBitsKHR caps); - - /** - * Convert level from Vulkan to AV. -@@ -63,19 +66,6 @@ VkVideoComponentBitDepthFlagBitsKHR ff_v - int ff_vk_h264_level_to_av(StdVideoH264LevelIdc level); - int ff_vk_h265_level_to_av(StdVideoH265LevelIdc level); - --typedef struct FFVkVideoBuffer { -- FFVkBuffer buf; -- uint8_t *mem; --} FFVkVideoBuffer; -- --/** -- * Get a mapped FFVkPooledBuffer with a specific guaranteed minimum size -- * from a pool. -- */ --int ff_vk_video_get_buffer(FFVulkanContext *ctx, FFVkVideoCommon *s, -- AVBufferRef **buf, VkBufferUsageFlags usage, -- void *create_pNext, size_t size); -- - /** - * Initialize video session, allocating and binding necessary memory. - */ -Index: FFmpeg/libavfilter/vulkan_filter.c -=================================================================== ---- FFmpeg.orig/libavfilter/vulkan_filter.c -+++ FFmpeg/libavfilter/vulkan_filter.c -@@ -36,6 +36,7 @@ int ff_vk_filter_init_context(AVFilterCo - if (frames_ref) { - int no_storage = 0; - FFVulkanFunctions *vk; -+ VkImageUsageFlagBits usage_req; - const VkFormat *sub = av_vkfmt_from_pixfmt(sw_format); - - frames_ctx = (AVHWFramesContext *)frames_ref->data; -@@ -52,22 +53,44 @@ int ff_vk_filter_init_context(AVFilterCo - if (sw_format != frames_ctx->sw_format) - goto skip; - -- /* Unusual tiling mismatch. Don't let linear through either. */ -- if (vk_frames->tiling != VK_IMAGE_TILING_OPTIMAL) -- goto skip; -- -- /* Usage mismatch */ -- if ((vk_frames->usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT)) != -- (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT)) -+ /* Don't let linear through. */ -+ if (vk_frames->tiling == VK_IMAGE_TILING_LINEAR) - goto skip; - - s->extensions = ff_vk_extensions_to_mask(vk_dev->enabled_dev_extensions, - vk_dev->nb_enabled_dev_extensions); -+ -+ /* More advanced format checks */ - err = ff_vk_load_functions(device_ctx, &s->vkfn, s->extensions, 1, 1); - if (err < 0) - return err; - vk = &s->vkfn; - -+ /* Usage mismatch */ -+ usage_req = VK_IMAGE_USAGE_SAMPLED_BIT; -+ -+ /* If format supports hardware encoding, make sure -+ * the context includes it. */ -+ if (vk_frames->format[1] == VK_FORMAT_UNDEFINED && -+ (s->extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE | -+ FF_VK_EXT_VIDEO_MAINTENANCE_1))) { -+ VkFormatProperties3 fprops = { -+ .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3, -+ }; -+ VkFormatProperties2 prop = { -+ .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, -+ .pNext = &fprops, -+ }; -+ vk->GetPhysicalDeviceFormatProperties2(vk_dev->phys_dev, -+ vk_frames->format[0], -+ &prop); -+ if (fprops.optimalTilingFeatures & VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR) -+ usage_req |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; -+ } -+ -+ if ((vk_frames->usage & usage_req) != usage_req) -+ goto skip; -+ - /* Check if the subformats can do storage */ - for (int i = 0; sub[i] != VK_FORMAT_UNDEFINED; i++) { - VkFormatProperties2 prop = { -@@ -75,14 +98,8 @@ int ff_vk_filter_init_context(AVFilterCo - }; - vk->GetPhysicalDeviceFormatProperties2(vk_dev->phys_dev, sub[i], - &prop); -- -- if (vk_frames->tiling == VK_IMAGE_TILING_LINEAR) { -- no_storage |= !(prop.formatProperties.linearTilingFeatures & -- VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT); -- } else { -- no_storage |= !(prop.formatProperties.optimalTilingFeatures & -- VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT); -- } -+ no_storage |= !(prop.formatProperties.optimalTilingFeatures & -+ VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT); - } - - /* Check if it's usable */ -@@ -112,13 +129,6 @@ skip: - frames_ctx->width = width; - frames_ctx->height = height; - -- vk_frames = frames_ctx->hwctx; -- vk_frames->tiling = VK_IMAGE_TILING_OPTIMAL; -- vk_frames->usage = VK_IMAGE_USAGE_SAMPLED_BIT | -- VK_IMAGE_USAGE_STORAGE_BIT | -- VK_IMAGE_USAGE_TRANSFER_SRC_BIT | -- VK_IMAGE_USAGE_TRANSFER_DST_BIT; -- - err = av_hwframe_ctx_init(frames_ref); - if (err < 0) { - av_buffer_unref(&frames_ref); -Index: FFmpeg/libavfilter/vulkan_shaderc.c -=================================================================== ---- FFmpeg.orig/libavfilter/vulkan_shaderc.c -+++ FFmpeg/libavfilter/vulkan_shaderc.c -@@ -51,6 +51,7 @@ static int shdc_shader_compile(FFVkSPIRV - shaderc_compile_options_set_target_env(opts, shaderc_target_env_vulkan, - shaderc_env_version_vulkan_1_2); - shaderc_compile_options_set_target_spirv(opts, shaderc_spirv_version_1_5); -+ shaderc_compile_options_set_generate_debug_info(opts); - shaderc_compile_options_set_optimization_level(opts, - shaderc_optimization_level_performance); - -@@ -65,6 +66,9 @@ static int shdc_shader_compile(FFVkSPIRV - warn = shaderc_result_get_num_warnings(res); - message = shaderc_result_get_error_message(res); - -+ if (ret != shaderc_compilation_status_success && !err) -+ err = 1; -+ - loglevel = err ? AV_LOG_ERROR : warn ? AV_LOG_WARNING : AV_LOG_VERBOSE; - - ff_vk_shader_print(avctx, shd, loglevel); -Index: FFmpeg/libavutil/hwcontext_vulkan.c -=================================================================== ---- FFmpeg.orig/libavutil/hwcontext_vulkan.c -+++ FFmpeg/libavutil/hwcontext_vulkan.c -@@ -67,19 +67,6 @@ - #define CHECK_CU(x) FF_CUDA_CHECK_DL(cuda_cu, cu, x) - #endif - --typedef struct VulkanQueueCtx { -- VkFence fence; -- VkQueue queue; -- int was_synchronous; -- int qf; -- int qidx; -- -- /* Buffer dependencies */ -- AVBufferRef **buf_deps; -- int nb_buf_deps; -- unsigned int buf_deps_alloc_size; --} VulkanQueueCtx; -- - typedef struct VulkanDevicePriv { - /** - * The public AVVulkanDeviceContext. See hwcontext_vulkan.h for it. -@@ -105,6 +92,9 @@ typedef struct VulkanDevicePriv { - VkPhysicalDeviceDescriptorBufferFeaturesEXT desc_buf_features; - VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float_features; - VkPhysicalDeviceCooperativeMatrixFeaturesKHR coop_matrix_features; -+ VkPhysicalDeviceOpticalFlowFeaturesNV optical_flow_features; -+ VkPhysicalDeviceShaderObjectFeaturesEXT shader_object_features; -+ VkPhysicalDeviceVideoMaintenance1FeaturesKHR video_maint_1_features; - - /* Queues */ - pthread_mutex_t **qf_mutex; -@@ -141,6 +131,9 @@ typedef struct VulkanFramesPriv { - FFVkExecPool upload_exec; - FFVkExecPool download_exec; - -+ /* Temporary buffer pools */ -+ AVBufferPool *tmp; -+ - /* Modifier info list to free at uninit */ - VkImageDrmFormatModifierListCreateInfoEXT *modifier_info; - } VulkanFramesPriv; -@@ -424,11 +417,13 @@ static const VulkanOptExtension optional - /* Misc or required by other extensions */ - { VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, - { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, -- { VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, - { VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME, FF_VK_EXT_DESCRIPTOR_BUFFER, }, - { VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME, FF_VK_EXT_DEVICE_DRM }, - { VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME, FF_VK_EXT_ATOMIC_FLOAT }, - { VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME, FF_VK_EXT_COOP_MATRIX }, -+ { VK_NV_OPTICAL_FLOW_EXTENSION_NAME, FF_VK_EXT_OPTICAL_FLOW }, -+ { VK_EXT_SHADER_OBJECT_EXTENSION_NAME, FF_VK_EXT_SHADER_OBJECT }, -+ { VK_KHR_VIDEO_MAINTENANCE_1_EXTENSION_NAME, FF_VK_EXT_VIDEO_MAINTENANCE_1 }, - - /* Imports/exports */ - { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_MEMORY }, -@@ -443,8 +438,11 @@ static const VulkanOptExtension optional - - /* Video encoding/decoding */ - { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_QUEUE }, -+ { VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_ENCODE_QUEUE }, - { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_QUEUE }, -+ { VK_KHR_VIDEO_ENCODE_H264_EXTENSION_NAME, FF_VK_EXT_VIDEO_ENCODE_H264 }, - { VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H264 }, -+ { VK_KHR_VIDEO_ENCODE_H265_EXTENSION_NAME, FF_VK_EXT_VIDEO_ENCODE_H265 }, - { VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H265 }, - { VK_KHR_VIDEO_DECODE_AV1_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_AV1 }, - }; -@@ -457,6 +455,14 @@ static VkBool32 VKAPI_CALL vk_dbg_callba - int l; - AVHWDeviceContext *ctx = priv; - -+ /* Ignore false positives */ -+ switch (data->messageIdNumber) { -+ case 0x30f4ac70: /* VUID-VkImageCreateInfo-pNext-06811 */ -+ return VK_FALSE; -+ default: -+ break; -+ } -+ - switch (severity) { - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: l = AV_LOG_VERBOSE; break; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: l = AV_LOG_INFO; break; -@@ -469,7 +475,7 @@ static VkBool32 VKAPI_CALL vk_dbg_callba - for (int i = 0; i < data->cmdBufLabelCount; i++) - av_log(ctx, l, "\t%i: %s\n", i, data->pCmdBufLabels[i].pLabelName); - -- return 0; -+ return VK_FALSE; - } - - #define ADD_VAL_TO_LIST(list, count, val) \ -@@ -493,8 +499,19 @@ static VkBool32 VKAPI_CALL vk_dbg_callba - av_free((void *)props); \ - } - -+enum FFVulkanDebugMode { -+ FF_VULKAN_DEBUG_NONE = 0, -+ /* Standard GPU-assisted validation */ -+ FF_VULKAN_DEBUG_VALIDATE = 1, -+ /* Passes printfs in shaders to the debug callback */ -+ FF_VULKAN_DEBUG_PRINTF = 2, -+ /* Enables extra printouts */ -+ FF_VULKAN_DEBUG_PRACTICES = 3, -+}; -+ - static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, -- const char * const **dst, uint32_t *num, int debug) -+ const char * const **dst, uint32_t *num, -+ enum FFVulkanDebugMode debug_mode) - { - const char *tstr; - const char **extension_names = NULL; -@@ -566,7 +583,10 @@ static int check_extensions(AVHWDeviceCo - ADD_VAL_TO_LIST(extension_names, extensions_found, tstr); - } - -- if (debug && !dev) { -+ if (!dev && -+ ((debug_mode == FF_VULKAN_DEBUG_VALIDATE) || -+ (debug_mode == FF_VULKAN_DEBUG_PRINTF) || -+ (debug_mode == FF_VULKAN_DEBUG_PRACTICES))) { - tstr = VK_EXT_DEBUG_UTILS_EXTENSION_NAME; - found = 0; - for (int j = 0; j < sup_ext_count; j++) { -@@ -622,20 +642,21 @@ fail: - return err; - } - --static int check_validation_layers(AVHWDeviceContext *ctx, AVDictionary *opts, -- const char * const **dst, uint32_t *num, -- int *debug_mode) -+static int check_layers(AVHWDeviceContext *ctx, AVDictionary *opts, -+ const char * const **dst, uint32_t *num, -+ enum FFVulkanDebugMode *debug_mode) - { -- static const char default_layer[] = { "VK_LAYER_KHRONOS_validation" }; -- -- int found = 0, err = 0; -+ int err = 0; - VulkanDevicePriv *priv = ctx->hwctx; - FFVulkanFunctions *vk = &priv->vkctx.vkfn; - -+ static const char layer_standard_validation[] = { "VK_LAYER_KHRONOS_validation" }; -+ int layer_standard_validation_found = 0; -+ - uint32_t sup_layer_count; - VkLayerProperties *sup_layers; - -- AVDictionaryEntry *user_layers; -+ AVDictionaryEntry *user_layers = av_dict_get(opts, "layers", NULL, 0); - char *user_layers_str = NULL; - char *save, *token; - -@@ -643,99 +664,136 @@ static int check_validation_layers(AVHWD - uint32_t enabled_layers_count = 0; - - AVDictionaryEntry *debug_opt = av_dict_get(opts, "debug", NULL, 0); -- int debug = debug_opt && strtol(debug_opt->value, NULL, 10); -+ enum FFVulkanDebugMode mode; - -- /* If `debug=0`, enable no layers at all. */ -- if (debug_opt && !debug) -- return 0; -+ *debug_mode = mode = FF_VULKAN_DEBUG_NONE; - -+ /* Get a list of all layers */ - vk->EnumerateInstanceLayerProperties(&sup_layer_count, NULL); - sup_layers = av_malloc_array(sup_layer_count, sizeof(VkLayerProperties)); - if (!sup_layers) - return AVERROR(ENOMEM); - vk->EnumerateInstanceLayerProperties(&sup_layer_count, sup_layers); - -- av_log(ctx, AV_LOG_VERBOSE, "Supported validation layers:\n"); -+ av_log(ctx, AV_LOG_VERBOSE, "Supported layers:\n"); - for (int i = 0; i < sup_layer_count; i++) - av_log(ctx, AV_LOG_VERBOSE, "\t%s\n", sup_layers[i].layerName); - -- /* If `debug=1` is specified, enable the standard validation layer extension */ -- if (debug) { -- *debug_mode = debug; -+ /* If no user layers or debug layers are given, return */ -+ if (!debug_opt && !user_layers) -+ goto end; -+ -+ /* Check for any properly supported validation layer */ -+ if (debug_opt) { -+ if (!strcmp(debug_opt->value, "printf")) { -+ mode = FF_VULKAN_DEBUG_PRINTF; -+ } else if (!strcmp(debug_opt->value, "validate")) { -+ mode = FF_VULKAN_DEBUG_VALIDATE; -+ } else if (!strcmp(debug_opt->value, "practices")) { -+ mode = FF_VULKAN_DEBUG_PRACTICES; -+ } else { -+ char *end_ptr = NULL; -+ int idx = strtol(debug_opt->value, &end_ptr, 10); -+ if (end_ptr == debug_opt->value || end_ptr[0] != '\0' || -+ idx < 0 || idx > FF_VULKAN_DEBUG_PRACTICES) { -+ av_log(ctx, AV_LOG_ERROR, "Invalid debugging mode \"%s\"\n", -+ debug_opt->value); -+ err = AVERROR(EINVAL); -+ goto end; -+ } -+ mode = idx; -+ } -+ } -+ -+ /* If mode is VALIDATE or PRINTF, try to find the standard validation layer extension */ -+ if ((mode == FF_VULKAN_DEBUG_VALIDATE) || -+ (mode == FF_VULKAN_DEBUG_PRINTF) || -+ (mode == FF_VULKAN_DEBUG_PRACTICES)) { - for (int i = 0; i < sup_layer_count; i++) { -- if (!strcmp(default_layer, sup_layers[i].layerName)) { -- found = 1; -- av_log(ctx, AV_LOG_VERBOSE, "Default validation layer %s is enabled\n", -- default_layer); -- ADD_VAL_TO_LIST(enabled_layers, enabled_layers_count, default_layer); -+ if (!strcmp(layer_standard_validation, sup_layers[i].layerName)) { -+ av_log(ctx, AV_LOG_VERBOSE, "Standard validation layer %s is enabled\n", -+ layer_standard_validation); -+ ADD_VAL_TO_LIST(enabled_layers, enabled_layers_count, layer_standard_validation); -+ *debug_mode = mode; -+ layer_standard_validation_found = 1; - break; - } - } -+ if (!layer_standard_validation_found) { -+ av_log(ctx, AV_LOG_ERROR, -+ "Validation Layer \"%s\" not supported\n", layer_standard_validation); -+ err = AVERROR(ENOTSUP); -+ goto end; -+ } - } - -- user_layers = av_dict_get(opts, "validation_layers", NULL, 0); -- if (!user_layers) -- goto end; -+ /* Process any custom layers enabled */ -+ if (user_layers) { -+ int found; - -- user_layers_str = av_strdup(user_layers->value); -- if (!user_layers_str) { -- err = AVERROR(ENOMEM); -- goto fail; -- } -+ user_layers_str = av_strdup(user_layers->value); -+ if (!user_layers_str) { -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } - -- token = av_strtok(user_layers_str, "+", &save); -- while (token) { -- found = 0; -- if (!strcmp(default_layer, token)) { -- if (debug) { -- /* if the `debug=1`, default_layer is enabled, skip here */ -+ token = av_strtok(user_layers_str, "+", &save); -+ while (token) { -+ found = 0; -+ -+ /* If debug=1/2 was specified as an option, skip this layer */ -+ if (!strcmp(layer_standard_validation, token) && layer_standard_validation_found) { - token = av_strtok(NULL, "+", &save); -- continue; -- } else { -- /* if the `debug=0`, enable debug mode to load its callback properly */ -- *debug_mode = debug; -- } -- } -- for (int j = 0; j < sup_layer_count; j++) { -- if (!strcmp(token, sup_layers[j].layerName)) { -- found = 1; - break; - } -- } -- if (found) { -- av_log(ctx, AV_LOG_VERBOSE, "Requested Validation Layer: %s\n", token); -- ADD_VAL_TO_LIST(enabled_layers, enabled_layers_count, token); -- } else { -- av_log(ctx, AV_LOG_ERROR, -- "Validation Layer \"%s\" not support.\n", token); -- err = AVERROR(EINVAL); -- goto fail; -- } -- token = av_strtok(NULL, "+", &save); -- } - -- av_free(user_layers_str); -+ /* Try to find the layer in the list of supported layers */ -+ for (int j = 0; j < sup_layer_count; j++) { -+ if (!strcmp(token, sup_layers[j].layerName)) { -+ found = 1; -+ break; -+ } -+ } - --end: -- av_free(sup_layers); -+ if (found) { -+ av_log(ctx, AV_LOG_VERBOSE, "Using layer: %s\n", token); -+ ADD_VAL_TO_LIST(enabled_layers, enabled_layers_count, token); - -- *dst = enabled_layers; -- *num = enabled_layers_count; -+ /* If debug was not set as an option, force it */ -+ if (!strcmp(layer_standard_validation, token)) -+ *debug_mode = FF_VULKAN_DEBUG_VALIDATE; -+ } else { -+ av_log(ctx, AV_LOG_ERROR, -+ "Layer \"%s\" not supported\n", token); -+ err = AVERROR(EINVAL); -+ goto end; -+ } - -- return 0; -+ token = av_strtok(NULL, "+", &save); -+ } -+ } - - fail: -- RELEASE_PROPS(enabled_layers, enabled_layers_count); -+end: - av_free(sup_layers); - av_free(user_layers_str); -+ -+ if (err < 0) { -+ RELEASE_PROPS(enabled_layers, enabled_layers_count); -+ } else { -+ *dst = enabled_layers; -+ *num = enabled_layers_count; -+ } -+ - return err; - } - - /* Creates a VkInstance */ - static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) - { -- int err = 0, debug_mode = 0; -+ int err = 0; - VkResult ret; -+ enum FFVulkanDebugMode debug_mode; - VulkanDevicePriv *p = ctx->hwctx; - AVVulkanDeviceContext *hwctx = &p->p; - FFVulkanFunctions *vk = &p->vkctx.vkfn; -@@ -771,8 +829,8 @@ static int create_instance(AVHWDeviceCon - return err; - } - -- err = check_validation_layers(ctx, opts, &inst_props.ppEnabledLayerNames, -- &inst_props.enabledLayerCount, &debug_mode); -+ err = check_layers(ctx, opts, &inst_props.ppEnabledLayerNames, -+ &inst_props.enabledLayerCount, &debug_mode); - if (err) - goto fail; - -@@ -784,14 +842,32 @@ static int create_instance(AVHWDeviceCon - if (err < 0) - goto fail; - -- if (debug_mode) { -- VkValidationFeatureEnableEXT feat_list[] = { -+ /* Enable debug features if needed */ -+ if (debug_mode == FF_VULKAN_DEBUG_VALIDATE) { -+ static const VkValidationFeatureEnableEXT feat_list_validate[] = { -+ VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT, -+ VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT, - VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT, -+ }; -+ validation_features.pEnabledValidationFeatures = feat_list_validate; -+ validation_features.enabledValidationFeatureCount = FF_ARRAY_ELEMS(feat_list_validate); -+ inst_props.pNext = &validation_features; -+ } else if (debug_mode == FF_VULKAN_DEBUG_PRINTF) { -+ static const VkValidationFeatureEnableEXT feat_list_debug[] = { -+ VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT, - VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT, -+ VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT, -+ }; -+ validation_features.pEnabledValidationFeatures = feat_list_debug; -+ validation_features.enabledValidationFeatureCount = FF_ARRAY_ELEMS(feat_list_debug); -+ inst_props.pNext = &validation_features; -+ } else if (debug_mode == FF_VULKAN_DEBUG_PRACTICES) { -+ static const VkValidationFeatureEnableEXT feat_list_practices[] = { - VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT, -+ VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT, - }; -- validation_features.pEnabledValidationFeatures = feat_list; -- validation_features.enabledValidationFeatureCount = FF_ARRAY_ELEMS(feat_list); -+ validation_features.pEnabledValidationFeatures = feat_list_practices; -+ validation_features.enabledValidationFeatureCount = FF_ARRAY_ELEMS(feat_list_practices); - inst_props.pNext = &validation_features; - } - -@@ -822,7 +898,10 @@ static int create_instance(AVHWDeviceCon - goto fail; - } - -- if (debug_mode) { -+ /* Setup debugging callback if needed */ -+ if ((debug_mode == FF_VULKAN_DEBUG_VALIDATE) || -+ (debug_mode == FF_VULKAN_DEBUG_PRINTF) || -+ (debug_mode == FF_VULKAN_DEBUG_PRACTICES)) { - VkDebugUtilsMessengerCreateInfoEXT dbg = { - .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, - .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | -@@ -1028,16 +1107,51 @@ end: - } - - /* Picks the least used qf with the fewest unneeded flags, or -1 if none found */ --static inline int pick_queue_family(VkQueueFamilyProperties *qf, uint32_t num_qf, -+static inline int pick_queue_family(VkQueueFamilyProperties2 *qf, uint32_t num_qf, - VkQueueFlagBits flags) - { - int index = -1; - uint32_t min_score = UINT32_MAX; - - for (int i = 0; i < num_qf; i++) { -- const VkQueueFlagBits qflags = qf[i].queueFlags; -+ VkQueueFlagBits qflags = qf[i].queueFamilyProperties.queueFlags; -+ -+ /* Per the spec, reporting transfer caps is optional for these 2 types */ -+ if ((flags & VK_QUEUE_TRANSFER_BIT) && -+ (qflags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT))) -+ qflags |= VK_QUEUE_TRANSFER_BIT; -+ - if (qflags & flags) { -- uint32_t score = av_popcount(qflags) + qf[i].timestampValidBits; -+ uint32_t score = av_popcount(qflags) + qf[i].queueFamilyProperties.timestampValidBits; -+ if (score < min_score) { -+ index = i; -+ min_score = score; -+ } -+ } -+ } -+ -+ if (index > -1) -+ qf[index].queueFamilyProperties.timestampValidBits++; -+ -+ return index; -+} -+ -+static inline int pick_video_queue_family(VkQueueFamilyProperties2 *qf, -+ VkQueueFamilyVideoPropertiesKHR *qf_vid, uint32_t num_qf, -+ VkVideoCodecOperationFlagBitsKHR flags) -+{ -+ int index = -1; -+ uint32_t min_score = UINT32_MAX; -+ -+ for (int i = 0; i < num_qf; i++) { -+ const VkQueueFlagBits qflags = qf[i].queueFamilyProperties.queueFlags; -+ const VkQueueFlagBits vflags = qf_vid[i].videoCodecOperations; -+ -+ if (!(qflags & (VK_QUEUE_VIDEO_ENCODE_BIT_KHR | VK_QUEUE_VIDEO_DECODE_BIT_KHR))) -+ continue; -+ -+ if (vflags & flags) { -+ uint32_t score = av_popcount(vflags) + qf[i].queueFamilyProperties.timestampValidBits; - if (score < min_score) { - index = i; - min_score = score; -@@ -1046,7 +1160,7 @@ static inline int pick_queue_family(VkQu - } - - if (index > -1) -- qf[index].timestampValidBits++; -+ qf[index].queueFamilyProperties.timestampValidBits++; - - return index; - } -@@ -1054,12 +1168,12 @@ static inline int pick_queue_family(VkQu - static int setup_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd) - { - uint32_t num; -- float *weights; -- VkQueueFamilyProperties *qf = NULL; - VulkanDevicePriv *p = ctx->hwctx; - AVVulkanDeviceContext *hwctx = &p->p; - FFVulkanFunctions *vk = &p->vkctx.vkfn; -- int graph_index, comp_index, tx_index, enc_index, dec_index; -+ -+ VkQueueFamilyProperties2 *qf = NULL; -+ VkQueueFamilyVideoPropertiesKHR *qf_vid = NULL; - - /* First get the number of queue families */ - vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &num, NULL); -@@ -1069,118 +1183,161 @@ static int setup_queue_families(AVHWDevi - } - - /* Then allocate memory */ -- qf = av_malloc_array(num, sizeof(VkQueueFamilyProperties)); -+ qf = av_malloc_array(num, sizeof(VkQueueFamilyProperties2)); - if (!qf) - return AVERROR(ENOMEM); - -+ qf_vid = av_malloc_array(num, sizeof(VkQueueFamilyVideoPropertiesKHR)); -+ if (!qf_vid) -+ return AVERROR(ENOMEM); -+ -+ for (uint32_t i = 0; i < num; i++) { -+ qf_vid[i] = (VkQueueFamilyVideoPropertiesKHR) { -+ .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR, -+ }; -+ qf[i] = (VkQueueFamilyProperties2) { -+ .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2, -+ .pNext = &qf_vid[i], -+ }; -+ } -+ - /* Finally retrieve the queue families */ -- vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &num, qf); -+ vk->GetPhysicalDeviceQueueFamilyProperties2(hwctx->phys_dev, &num, qf); - - av_log(ctx, AV_LOG_VERBOSE, "Queue families:\n"); - for (int i = 0; i < num; i++) { -- av_log(ctx, AV_LOG_VERBOSE, " %i:%s%s%s%s%s%s%s (queues: %i)\n", i, -- ((qf[i].queueFlags) & VK_QUEUE_GRAPHICS_BIT) ? " graphics" : "", -- ((qf[i].queueFlags) & VK_QUEUE_COMPUTE_BIT) ? " compute" : "", -- ((qf[i].queueFlags) & VK_QUEUE_TRANSFER_BIT) ? " transfer" : "", -- ((qf[i].queueFlags) & VK_QUEUE_VIDEO_ENCODE_BIT_KHR) ? " encode" : "", -- ((qf[i].queueFlags) & VK_QUEUE_VIDEO_DECODE_BIT_KHR) ? " decode" : "", -- ((qf[i].queueFlags) & VK_QUEUE_SPARSE_BINDING_BIT) ? " sparse" : "", -- ((qf[i].queueFlags) & VK_QUEUE_PROTECTED_BIT) ? " protected" : "", -- qf[i].queueCount); -+ av_log(ctx, AV_LOG_VERBOSE, " %i:%s%s%s%s%s%s%s%s (queues: %i)\n", i, -+ ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_GRAPHICS_BIT) ? " graphics" : "", -+ ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_COMPUTE_BIT) ? " compute" : "", -+ ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_TRANSFER_BIT) ? " transfer" : "", -+ ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_VIDEO_ENCODE_BIT_KHR) ? " encode" : "", -+ ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_VIDEO_DECODE_BIT_KHR) ? " decode" : "", -+ ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_SPARSE_BINDING_BIT) ? " sparse" : "", -+ ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_OPTICAL_FLOW_BIT_NV) ? " optical_flow" : "", -+ ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_PROTECTED_BIT) ? " protected" : "", -+ qf[i].queueFamilyProperties.queueCount); - - /* We use this field to keep a score of how many times we've used that - * queue family in order to make better choices. */ -- qf[i].timestampValidBits = 0; -+ qf[i].queueFamilyProperties.timestampValidBits = 0; - } - -+ hwctx->nb_qf = 0; -+ - /* Pick each queue family to use */ -- graph_index = pick_queue_family(qf, num, VK_QUEUE_GRAPHICS_BIT); -- comp_index = pick_queue_family(qf, num, VK_QUEUE_COMPUTE_BIT); -- tx_index = pick_queue_family(qf, num, VK_QUEUE_TRANSFER_BIT); -- enc_index = pick_queue_family(qf, num, VK_QUEUE_VIDEO_ENCODE_BIT_KHR); -- dec_index = pick_queue_family(qf, num, VK_QUEUE_VIDEO_DECODE_BIT_KHR); -- -- /* Signalling the transfer capabilities on a queue family is optional */ -- if (tx_index < 0) { -- tx_index = pick_queue_family(qf, num, VK_QUEUE_COMPUTE_BIT); -- if (tx_index < 0) -- tx_index = pick_queue_family(qf, num, VK_QUEUE_GRAPHICS_BIT); -+#define PICK_QF(type, vid_op) \ -+ do { \ -+ uint32_t i; \ -+ uint32_t idx; \ -+ \ -+ if (vid_op) \ -+ idx = pick_video_queue_family(qf, qf_vid, num, vid_op); \ -+ else \ -+ idx = pick_queue_family(qf, num, type); \ -+ \ -+ if (idx == -1) \ -+ continue; \ -+ \ -+ for (i = 0; i < hwctx->nb_qf; i++) { \ -+ if (hwctx->qf[i].idx == idx) { \ -+ hwctx->qf[i].flags |= type; \ -+ hwctx->qf[i].video_caps |= vid_op; \ -+ break; \ -+ } \ -+ } \ -+ if (i == hwctx->nb_qf) { \ -+ hwctx->qf[i].idx = idx; \ -+ hwctx->qf[i].num = qf[idx].queueFamilyProperties.queueCount; \ -+ hwctx->qf[i].flags = type; \ -+ hwctx->qf[i].video_caps = vid_op; \ -+ hwctx->nb_qf++; \ -+ } \ -+ } while (0) -+ -+ PICK_QF(VK_QUEUE_GRAPHICS_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR); -+ PICK_QF(VK_QUEUE_COMPUTE_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR); -+ PICK_QF(VK_QUEUE_TRANSFER_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR); -+ PICK_QF(VK_QUEUE_OPTICAL_FLOW_BIT_NV, VK_VIDEO_CODEC_OPERATION_NONE_KHR); -+ -+ PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR); -+ PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR); -+ -+ PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR); -+ PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR); -+ -+ PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR); -+ -+ av_free(qf); -+ av_free(qf_vid); -+ -+#undef PICK_QF -+ -+ cd->pQueueCreateInfos = av_malloc_array(hwctx->nb_qf, -+ sizeof(VkDeviceQueueCreateInfo)); -+ if (!cd->pQueueCreateInfos) -+ return AVERROR(ENOMEM); -+ -+ for (uint32_t i = 0; i < hwctx->nb_qf; i++) { -+ int dup = 0; -+ float *weights = NULL; -+ VkDeviceQueueCreateInfo *pc; -+ for (uint32_t j = 0; j < cd->queueCreateInfoCount; j++) { -+ if (hwctx->qf[i].idx == cd->pQueueCreateInfos[j].queueFamilyIndex) { -+ dup = 1; -+ break; -+ } -+ } -+ if (dup) -+ continue; -+ -+ weights = av_malloc_array(hwctx->qf[i].num, sizeof(float)); -+ if (!weights) { -+ for (uint32_t j = 0; j < cd->queueCreateInfoCount; j++) -+ av_free((void *)cd->pQueueCreateInfos[i].pQueuePriorities); -+ av_free((void *)cd->pQueueCreateInfos); -+ return AVERROR(ENOMEM); -+ } -+ -+ for (uint32_t j = 0; j < hwctx->qf[i].num; j++) -+ weights[j] = 1.0; -+ -+ pc = (VkDeviceQueueCreateInfo *)cd->pQueueCreateInfos; -+ pc[cd->queueCreateInfoCount++] = (VkDeviceQueueCreateInfo) { -+ .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, -+ .queueFamilyIndex = hwctx->qf[i].idx, -+ .queueCount = hwctx->qf[i].num, -+ .pQueuePriorities = weights, -+ }; - } - -+#if FF_API_VULKAN_FIXED_QUEUES -+FF_DISABLE_DEPRECATION_WARNINGS -+ /* Setup deprecated fields */ - hwctx->queue_family_index = -1; - hwctx->queue_family_comp_index = -1; - hwctx->queue_family_tx_index = -1; - hwctx->queue_family_encode_index = -1; - hwctx->queue_family_decode_index = -1; - --#define SETUP_QUEUE(qf_idx) \ -- if (qf_idx > -1) { \ -- int fidx = qf_idx; \ -- int qc = qf[fidx].queueCount; \ -- VkDeviceQueueCreateInfo *pc; \ -- \ -- if (fidx == graph_index) { \ -- hwctx->queue_family_index = fidx; \ -- hwctx->nb_graphics_queues = qc; \ -- graph_index = -1; \ -- } \ -- if (fidx == comp_index) { \ -- hwctx->queue_family_comp_index = fidx; \ -- hwctx->nb_comp_queues = qc; \ -- comp_index = -1; \ -- } \ -- if (fidx == tx_index) { \ -- hwctx->queue_family_tx_index = fidx; \ -- hwctx->nb_tx_queues = qc; \ -- tx_index = -1; \ -- } \ -- if (fidx == enc_index) { \ -- hwctx->queue_family_encode_index = fidx; \ -- hwctx->nb_encode_queues = qc; \ -- enc_index = -1; \ -- } \ -- if (fidx == dec_index) { \ -- hwctx->queue_family_decode_index = fidx; \ -- hwctx->nb_decode_queues = qc; \ -- dec_index = -1; \ -- } \ -- \ -- pc = av_realloc((void *)cd->pQueueCreateInfos, \ -- sizeof(*pc) * (cd->queueCreateInfoCount + 1)); \ -- if (!pc) { \ -- av_free(qf); \ -- return AVERROR(ENOMEM); \ -- } \ -- cd->pQueueCreateInfos = pc; \ -- pc = &pc[cd->queueCreateInfoCount]; \ -- \ -- weights = av_malloc(qc * sizeof(float)); \ -- if (!weights) { \ -- av_free(qf); \ -- return AVERROR(ENOMEM); \ -- } \ -- \ -- memset(pc, 0, sizeof(*pc)); \ -- pc->sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; \ -- pc->queueFamilyIndex = fidx; \ -- pc->queueCount = qc; \ -- pc->pQueuePriorities = weights; \ -- \ -- for (int i = 0; i < qc; i++) \ -- weights[i] = 1.0f / qc; \ -- \ -- cd->queueCreateInfoCount++; \ -- } -- -- SETUP_QUEUE(graph_index) -- SETUP_QUEUE(comp_index) -- SETUP_QUEUE(tx_index) -- SETUP_QUEUE(enc_index) -- SETUP_QUEUE(dec_index) -+#define SET_OLD_QF(field, nb_field, type) \ -+ do { \ -+ if (field < 0 && hwctx->qf[i].flags & type) { \ -+ field = hwctx->qf[i].idx; \ -+ nb_field = hwctx->qf[i].num; \ -+ } \ -+ } while (0) - --#undef SETUP_QUEUE -+ for (uint32_t i = 0; i < hwctx->nb_qf; i++) { -+ SET_OLD_QF(hwctx->queue_family_index, hwctx->nb_graphics_queues, VK_QUEUE_GRAPHICS_BIT); -+ SET_OLD_QF(hwctx->queue_family_comp_index, hwctx->nb_comp_queues, VK_QUEUE_COMPUTE_BIT); -+ SET_OLD_QF(hwctx->queue_family_tx_index, hwctx->nb_tx_queues, VK_QUEUE_TRANSFER_BIT); -+ SET_OLD_QF(hwctx->queue_family_encode_index, hwctx->nb_encode_queues, VK_QUEUE_VIDEO_ENCODE_BIT_KHR); -+ SET_OLD_QF(hwctx->queue_family_decode_index, hwctx->nb_decode_queues, VK_QUEUE_VIDEO_DECODE_BIT_KHR); -+ } - -- av_free(qf); -+#undef SET_OLD_QF -+FF_ENABLE_DEPRECATION_WARNINGS -+#endif - - return 0; - } -@@ -1246,9 +1403,21 @@ static int vulkan_device_create_internal - VkPhysicalDeviceTimelineSemaphoreFeatures timeline_features = { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, - }; -+ VkPhysicalDeviceVideoMaintenance1FeaturesKHR video_maint_1_features = { -+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR, -+ .pNext = &timeline_features, -+ }; -+ VkPhysicalDeviceShaderObjectFeaturesEXT shader_object_features = { -+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT, -+ .pNext = &video_maint_1_features, -+ }; -+ VkPhysicalDeviceOpticalFlowFeaturesNV optical_flow_features = { -+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_FEATURES_NV, -+ .pNext = &shader_object_features, -+ }; - VkPhysicalDeviceCooperativeMatrixFeaturesKHR coop_matrix_features = { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR, -- .pNext = &timeline_features, -+ .pNext = &optical_flow_features, - }; - VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float_features = { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT, -@@ -1279,21 +1448,6 @@ static int vulkan_device_create_internal - .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - }; - -- hwctx->device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; -- hwctx->device_features.pNext = &p->device_features_1_1; -- p->device_features_1_1.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; -- p->device_features_1_1.pNext = &p->device_features_1_2; -- p->device_features_1_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; -- p->device_features_1_2.pNext = &p->device_features_1_3; -- p->device_features_1_3.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; -- p->device_features_1_3.pNext = &p->desc_buf_features; -- p->desc_buf_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT; -- p->desc_buf_features.pNext = &p->atomic_float_features; -- p->atomic_float_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT; -- p->atomic_float_features.pNext = &p->coop_matrix_features; -- p->coop_matrix_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR; -- p->coop_matrix_features.pNext = NULL; -- - ctx->free = vulkan_device_free; - - /* Create an instance if not given one */ -@@ -1327,6 +1481,8 @@ static int vulkan_device_create_internal - - p->device_features_1_1.samplerYcbcrConversion = dev_features_1_1.samplerYcbcrConversion; - p->device_features_1_1.storagePushConstant16 = dev_features_1_1.storagePushConstant16; -+ p->device_features_1_1.storageBuffer16BitAccess = dev_features_1_1.storageBuffer16BitAccess; -+ p->device_features_1_1.uniformAndStorageBuffer16BitAccess = dev_features_1_1.uniformAndStorageBuffer16BitAccess; - - p->device_features_1_2.timelineSemaphore = 1; - p->device_features_1_2.bufferDeviceAddress = dev_features_1_2.bufferDeviceAddress; -@@ -1348,6 +1504,8 @@ static int vulkan_device_create_internal - p->device_features_1_3.shaderZeroInitializeWorkgroupMemory = dev_features_1_3.shaderZeroInitializeWorkgroupMemory; - p->device_features_1_3.dynamicRendering = dev_features_1_3.dynamicRendering; - -+ p->video_maint_1_features.videoMaintenance1 = video_maint_1_features.videoMaintenance1; -+ - p->desc_buf_features.descriptorBuffer = desc_buf_features.descriptorBuffer; - p->desc_buf_features.descriptorBufferPushDescriptors = desc_buf_features.descriptorBufferPushDescriptors; - -@@ -1356,12 +1514,11 @@ static int vulkan_device_create_internal - - p->coop_matrix_features.cooperativeMatrix = coop_matrix_features.cooperativeMatrix; - -- dev_info.pNext = &hwctx->device_features; -+ p->optical_flow_features.opticalFlow = optical_flow_features.opticalFlow; - -- /* Setup queue family */ -- if ((err = setup_queue_families(ctx, &dev_info))) -- goto end; -+ p->shader_object_features.shaderObject = shader_object_features.shaderObject; - -+ /* Find and enable extensions */ - if ((err = check_extensions(ctx, 1, opts, &dev_info.ppEnabledExtensionNames, - &dev_info.enabledExtensionCount, 0))) { - for (int i = 0; i < dev_info.queueCreateInfoCount; i++) -@@ -1370,6 +1527,45 @@ static int vulkan_device_create_internal - goto end; - } - -+ /* Setup enabled device features */ -+ hwctx->device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; -+ hwctx->device_features.pNext = &p->device_features_1_1; -+ p->device_features_1_1.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; -+ p->device_features_1_1.pNext = &p->device_features_1_2; -+ p->device_features_1_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; -+ p->device_features_1_2.pNext = &p->device_features_1_3; -+ p->device_features_1_3.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; -+ p->device_features_1_3.pNext = NULL; -+ -+#define OPT_CHAIN(EXT_FLAG, STRUCT_P, TYPE) \ -+ do { \ -+ if (p->vkctx.extensions & EXT_FLAG) { \ -+ (STRUCT_P)->sType = TYPE; \ -+ ff_vk_link_struct(hwctx->device_features.pNext, STRUCT_P); \ -+ } \ -+ } while (0) -+ -+ OPT_CHAIN(FF_VK_EXT_DESCRIPTOR_BUFFER, &p->desc_buf_features, -+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT); -+ OPT_CHAIN(FF_VK_EXT_ATOMIC_FLOAT, &p->atomic_float_features, -+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT); -+ OPT_CHAIN(FF_VK_EXT_COOP_MATRIX, &p->coop_matrix_features, -+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR); -+ OPT_CHAIN(FF_VK_EXT_SHADER_OBJECT, &p->shader_object_features, -+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT); -+ OPT_CHAIN(FF_VK_EXT_OPTICAL_FLOW, &p->optical_flow_features, -+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_FEATURES_NV); -+ OPT_CHAIN(FF_VK_EXT_VIDEO_MAINTENANCE_1, &p->video_maint_1_features, -+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR); -+#undef OPT_CHAIN -+ -+ /* Add the enabled features into the pnext chain of device creation */ -+ dev_info.pNext = &hwctx->device_features; -+ -+ /* Setup enabled queue families */ -+ if ((err = setup_queue_families(ctx, &dev_info))) -+ goto end; -+ - ret = vk->CreateDevice(hwctx->phys_dev, &dev_info, hwctx->alloc, - &hwctx->act_dev); - -@@ -1423,12 +1619,13 @@ static void unlock_queue(AVHWDeviceConte - - static int vulkan_device_init(AVHWDeviceContext *ctx) - { -- int err; -+ int err = 0; - uint32_t qf_num; - VulkanDevicePriv *p = ctx->hwctx; - AVVulkanDeviceContext *hwctx = &p->p; - FFVulkanFunctions *vk = &p->vkctx.vkfn; -- VkQueueFamilyProperties *qf; -+ VkQueueFamilyProperties2 *qf; -+ VkQueueFamilyVideoPropertiesKHR *qf_vid; - int graph_index, comp_index, tx_index, enc_index, dec_index; - - /* Set device extension flags */ -@@ -1474,38 +1671,55 @@ static int vulkan_device_init(AVHWDevice - return AVERROR_EXTERNAL; - } - -- qf = av_malloc_array(qf_num, sizeof(VkQueueFamilyProperties)); -+ qf = av_malloc_array(qf_num, sizeof(VkQueueFamilyProperties2)); - if (!qf) - return AVERROR(ENOMEM); - -- vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &qf_num, qf); -+ qf_vid = av_malloc_array(qf_num, sizeof(VkQueueFamilyVideoPropertiesKHR)); -+ if (!qf_vid) { -+ av_free(qf); -+ return AVERROR(ENOMEM); -+ } -+ -+ for (uint32_t i = 0; i < qf_num; i++) { -+ qf_vid[i] = (VkQueueFamilyVideoPropertiesKHR) { -+ .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR, -+ }; -+ qf[i] = (VkQueueFamilyProperties2) { -+ .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2, -+ .pNext = &qf_vid[i], -+ }; -+ } -+ -+ vk->GetPhysicalDeviceQueueFamilyProperties2(hwctx->phys_dev, &qf_num, qf); - - p->qf_mutex = av_calloc(qf_num, sizeof(*p->qf_mutex)); - if (!p->qf_mutex) { -- av_free(qf); -- return AVERROR(ENOMEM); -+ err = AVERROR(ENOMEM); -+ goto end; - } - p->nb_tot_qfs = qf_num; - - for (uint32_t i = 0; i < qf_num; i++) { -- p->qf_mutex[i] = av_calloc(qf[i].queueCount, sizeof(**p->qf_mutex)); -+ p->qf_mutex[i] = av_calloc(qf[i].queueFamilyProperties.queueCount, -+ sizeof(**p->qf_mutex)); - if (!p->qf_mutex[i]) { -- av_free(qf); -- return AVERROR(ENOMEM); -+ err = AVERROR(ENOMEM); -+ goto end; - } -- for (uint32_t j = 0; j < qf[i].queueCount; j++) { -+ for (uint32_t j = 0; j < qf[i].queueFamilyProperties.queueCount; j++) { - err = pthread_mutex_init(&p->qf_mutex[i][j], NULL); - if (err != 0) { - av_log(ctx, AV_LOG_ERROR, "pthread_mutex_init failed : %s\n", - av_err2str(err)); -- av_free(qf); -- return AVERROR(err); -+ err = AVERROR(err); -+ goto end; - } - } - } - -- av_free(qf); -- -+#if FF_API_VULKAN_FIXED_QUEUES -+FF_DISABLE_DEPRECATION_WARNINGS - graph_index = hwctx->nb_graphics_queues ? hwctx->queue_family_index : -1; - comp_index = hwctx->nb_comp_queues ? hwctx->queue_family_comp_index : -1; - tx_index = hwctx->nb_tx_queues ? hwctx->queue_family_tx_index : -1; -@@ -1517,13 +1731,15 @@ static int vulkan_device_init(AVHWDevice - if (ctx_qf < 0 && required) { \ - av_log(ctx, AV_LOG_ERROR, "%s queue family is required, but marked as missing" \ - " in the context!\n", type); \ -- return AVERROR(EINVAL); \ -+ err = AVERROR(EINVAL); \ -+ goto end; \ - } else if (fidx < 0 || ctx_qf < 0) { \ - break; \ - } else if (ctx_qf >= qf_num) { \ - av_log(ctx, AV_LOG_ERROR, "Invalid %s family index %i (device has %i families)!\n", \ - type, ctx_qf, qf_num); \ -- return AVERROR(EINVAL); \ -+ err = AVERROR(EINVAL); \ -+ goto end; \ - } \ - \ - av_log(ctx, AV_LOG_VERBOSE, "Using queue family %i (queues: %i)" \ -@@ -1550,6 +1766,38 @@ static int vulkan_device_init(AVHWDevice - - #undef CHECK_QUEUE - -+ /* Update the new queue family fields. If non-zero already, -+ * it means API users have set it. */ -+ if (!hwctx->nb_qf) { -+#define ADD_QUEUE(ctx_qf, qc, flag) \ -+ do { \ -+ if (ctx_qf != -1) { \ -+ hwctx->qf[hwctx->nb_qf++] = (AVVulkanDeviceQueueFamily) { \ -+ .idx = ctx_qf, \ -+ .num = qc, \ -+ .flags = flag, \ -+ }; \ -+ } \ -+ } while (0) -+ -+ ADD_QUEUE(hwctx->queue_family_index, hwctx->nb_graphics_queues, VK_QUEUE_GRAPHICS_BIT); -+ ADD_QUEUE(hwctx->queue_family_comp_index, hwctx->nb_comp_queues, VK_QUEUE_COMPUTE_BIT); -+ ADD_QUEUE(hwctx->queue_family_tx_index, hwctx->nb_tx_queues, VK_QUEUE_TRANSFER_BIT); -+ ADD_QUEUE(hwctx->queue_family_decode_index, hwctx->nb_decode_queues, VK_QUEUE_VIDEO_DECODE_BIT_KHR); -+ ADD_QUEUE(hwctx->queue_family_encode_index, hwctx->nb_encode_queues, VK_QUEUE_VIDEO_ENCODE_BIT_KHR); -+#undef ADD_QUEUE -+ } -+FF_ENABLE_DEPRECATION_WARNINGS -+#endif -+ -+ for (int i = 0; i < hwctx->nb_qf; i++) { -+ if (!hwctx->qf[i].video_caps && -+ hwctx->qf[i].flags & (VK_QUEUE_VIDEO_DECODE_BIT_KHR | -+ VK_QUEUE_VIDEO_ENCODE_BIT_KHR)) { -+ hwctx->qf[i].video_caps = qf_vid[hwctx->qf[i].idx].videoCodecOperations; -+ } -+ } -+ - if (!hwctx->lock_queue) - hwctx->lock_queue = lock_queue; - if (!hwctx->unlock_queue) -@@ -1565,7 +1813,10 @@ static int vulkan_device_init(AVHWDevice - ff_vk_qf_init(&p->vkctx, &p->compute_qf, VK_QUEUE_COMPUTE_BIT); - ff_vk_qf_init(&p->vkctx, &p->transfer_qf, VK_QUEUE_TRANSFER_BIT); - -- return 0; -+end: -+ av_free(qf_vid); -+ av_free(qf); -+ return err; - } - - static int vulkan_device_create(AVHWDeviceContext *ctx, const char *device, -@@ -1941,6 +2192,7 @@ enum PrepMode { - PREP_MODE_EXTERNAL_IMPORT, - PREP_MODE_DECODING_DST, - PREP_MODE_DECODING_DPB, -+ PREP_MODE_ENCODING_DPB, - }; - - static int prepare_frame(AVHWFramesContext *hwfc, FFVkExecPool *ectx, -@@ -2002,6 +2254,10 @@ static int prepare_frame(AVHWFramesConte - new_layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR; - new_access = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; - break; -+ case PREP_MODE_ENCODING_DPB: -+ new_layout = VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR; -+ new_access = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; -+ break; - } - - ff_vk_frame_barrier(&p->vkctx, exec, &tmp_frame, img_bar, &nb_img_bar, -@@ -2262,6 +2518,8 @@ static AVBufferRef *vulkan_pool_alloc(vo - err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_DECODING_DPB); - else if (hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR) - err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_DECODING_DST); -+ else if (hwctx->usage & VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR) -+ err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_ENCODING_DPB); - else - err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_WRITE); - if (err) -@@ -2303,6 +2561,8 @@ static void vulkan_frames_uninit(AVHWFra - ff_vk_exec_pool_free(&p->vkctx, &fp->compute_exec); - ff_vk_exec_pool_free(&p->vkctx, &fp->upload_exec); - ff_vk_exec_pool_free(&p->vkctx, &fp->download_exec); -+ -+ av_buffer_pool_uninit(&fp->tmp); - } - - static int vulkan_frames_init(AVHWFramesContext *hwfc) -@@ -2372,6 +2632,12 @@ static int vulkan_frames_init(AVHWFrames - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | - VK_IMAGE_USAGE_STORAGE_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT); -+ -+ /* Enables encoding of images, if supported by format and extensions */ -+ if ((supported_usage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) && -+ (p->vkctx.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE | -+ FF_VK_EXT_VIDEO_MAINTENANCE_1))) -+ hwctx->usage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; - } - - /* Image creation flags. -@@ -2390,6 +2656,28 @@ static int vulkan_frames_init(AVHWFrames - } - } - -+ /* If the image has an ENCODE_SRC usage, and the maintenance1 -+ * extension is supported, check if it has a profile list. -+ * If there's no profile list, or it has no encode operations, -+ * then allow creating the image with no specific profile. */ -+ if ((hwctx->usage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) && -+ p->video_maint_1_features.videoMaintenance1) { -+ const VkVideoProfileListInfoKHR *pl; -+ pl = ff_vk_find_struct(hwctx->create_pnext, VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR); -+ if (!pl) { -+ hwctx->img_flags |= VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR; -+ } else { -+ uint32_t i; -+ for (i = 0; i < pl->profileCount; i++) { -+ /* Video ops start at exactly 0x00010000 */ -+ if (pl->pProfiles[i].videoCodecOperation & 0xFFFF0000) -+ break; -+ } -+ if (i == pl->profileCount) -+ hwctx->img_flags |= VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR; -+ } -+ } -+ - if (!hwctx->lock_frame) - hwctx->lock_frame = lock_frame; - -@@ -3323,128 +3611,290 @@ static int vulkan_map_from(AVHWFramesCon - return AVERROR(ENOSYS); - } - --static size_t get_req_buffer_size(VulkanDevicePriv *p, int *stride, int height) -+static int copy_buffer_data(AVHWFramesContext *hwfc, AVBufferRef *buf, -+ AVFrame *swf, VkBufferImageCopy *region, -+ int planes, int upload) - { -- size_t size; -- *stride = FFALIGN(*stride, p->props.properties.limits.optimalBufferCopyRowPitchAlignment); -- size = height*(*stride); -- size = FFALIGN(size, p->props.properties.limits.minMemoryMapAlignment); -- return size; -+ VkResult ret; -+ VulkanDevicePriv *p = hwfc->device_ctx->hwctx; -+ FFVulkanFunctions *vk = &p->vkctx.vkfn; -+ AVVulkanDeviceContext *hwctx = &p->p; -+ -+ FFVkBuffer *vkbuf = (FFVkBuffer *)buf->data; -+ -+ const VkMappedMemoryRange flush_info = { -+ .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, -+ .memory = vkbuf->mem, -+ .size = VK_WHOLE_SIZE, -+ }; -+ -+ if (!(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) && !upload) { -+ ret = vk->InvalidateMappedMemoryRanges(hwctx->act_dev, 1, -+ &flush_info); -+ if (ret != VK_SUCCESS) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to invalidate buffer data: %s\n", -+ ff_vk_ret2str(ret)); -+ return AVERROR_EXTERNAL; -+ } -+ } -+ -+ for (int i = 0; i < planes; i++) -+ av_image_copy_plane(vkbuf->mapped_mem + region[i].bufferOffset, -+ region[i].bufferRowLength, -+ swf->data[i], -+ swf->linesize[i], -+ swf->linesize[i], -+ region[i].imageExtent.height); -+ -+ if (!(vkbuf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) && upload) { -+ ret = vk->FlushMappedMemoryRanges(hwctx->act_dev, 1, -+ &flush_info); -+ if (ret != VK_SUCCESS) { -+ av_log(hwfc, AV_LOG_ERROR, "Failed to flush buffer data: %s\n", -+ ff_vk_ret2str(ret)); -+ return AVERROR_EXTERNAL; -+ } -+ } -+ -+ return 0; - } - --static int transfer_image_buf(AVHWFramesContext *hwfc, AVFrame *f, -- AVBufferRef **bufs, size_t *buf_offsets, -- const int *buf_stride, int w, -- int h, enum AVPixelFormat pix_fmt, int to_buf) -+static int get_plane_buf(AVHWFramesContext *hwfc, AVBufferRef **dst, -+ AVFrame *swf, VkBufferImageCopy *region, int upload) - { - int err; -- AVVkFrame *frame = (AVVkFrame *)f->data[0]; - VulkanFramesPriv *fp = hwfc->hwctx; - VulkanDevicePriv *p = hwfc->device_ctx->hwctx; -- FFVulkanFunctions *vk = &p->vkctx.vkfn; -- VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS]; -- int nb_img_bar = 0; -+ const int planes = av_pix_fmt_count_planes(swf->format); - -- const int nb_images = ff_vk_count_images(frame); -- int pixfmt_planes = av_pix_fmt_count_planes(pix_fmt); -- const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); -+ size_t buf_offset = 0; -+ for (int i = 0; i < planes; i++) { -+ size_t size; -+ ptrdiff_t linesize = swf->linesize[i]; - -- VkCommandBuffer cmd_buf; -- FFVkExecContext *exec = ff_vk_exec_get(to_buf ? &fp->download_exec : -- &fp->upload_exec); -- cmd_buf = exec->buf; -- ff_vk_exec_start(&p->vkctx, exec); -+ uint32_t p_w, p_h; -+ get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i); -+ -+ linesize = FFALIGN(linesize, -+ p->props.properties.limits.optimalBufferCopyRowPitchAlignment); -+ size = p_h*linesize; -+ -+ region[i] = (VkBufferImageCopy) { -+ .bufferOffset = buf_offset, -+ .bufferRowLength = linesize, -+ .bufferImageHeight = p_h, -+ .imageSubresource.layerCount = 1, -+ .imageExtent = (VkExtent3D){ p_w, p_h, 1 }, -+ /* Rest of the fields adjusted/filled in later */ -+ }; -+ -+ buf_offset = FFALIGN(buf_offset + size, -+ p->props.properties.limits.optimalBufferCopyOffsetAlignment); -+ } - -- err = ff_vk_exec_add_dep_buf(&p->vkctx, exec, bufs, pixfmt_planes, 1); -+ err = ff_vk_get_pooled_buffer(&p->vkctx, &fp->tmp, dst, -+ VK_BUFFER_USAGE_TRANSFER_SRC_BIT | -+ VK_BUFFER_USAGE_TRANSFER_DST_BIT, -+ NULL, buf_offset, -+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | -+ VK_MEMORY_PROPERTY_HOST_CACHED_BIT); - if (err < 0) - return err; - -- err = ff_vk_exec_add_dep_frame(&p->vkctx, exec, f, -- VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, -- VK_PIPELINE_STAGE_2_TRANSFER_BIT); -+ return 0; -+} -+ -+static int create_mapped_buffer(AVHWFramesContext *hwfc, -+ FFVkBuffer *vkb, VkBufferUsageFlags usage, -+ size_t size, -+ VkExternalMemoryBufferCreateInfo *create_desc, -+ VkImportMemoryHostPointerInfoEXT *import_desc, -+ VkMemoryHostPointerPropertiesEXT props) -+{ -+ int err; -+ VkResult ret; -+ VulkanDevicePriv *p = hwfc->device_ctx->hwctx; -+ FFVulkanFunctions *vk = &p->vkctx.vkfn; -+ AVVulkanDeviceContext *hwctx = &p->p; -+ -+ VkBufferCreateInfo buf_spawn = { -+ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, -+ .pNext = create_desc, -+ .usage = usage, -+ .sharingMode = VK_SHARING_MODE_EXCLUSIVE, -+ .size = size, -+ }; -+ VkMemoryRequirements req = { -+ .size = size, -+ .alignment = p->hprops.minImportedHostPointerAlignment, -+ .memoryTypeBits = props.memoryTypeBits, -+ }; -+ -+ err = ff_vk_alloc_mem(&p->vkctx, &req, -+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, -+ import_desc, &vkb->flags, &vkb->mem); - if (err < 0) - return err; - -- ff_vk_frame_barrier(&p->vkctx, exec, f, img_bar, &nb_img_bar, -- VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, -- VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, -- to_buf ? VK_ACCESS_TRANSFER_READ_BIT : -- VK_ACCESS_TRANSFER_WRITE_BIT, -- to_buf ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL : -- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, -- VK_QUEUE_FAMILY_IGNORED); -+ ret = vk->CreateBuffer(hwctx->act_dev, &buf_spawn, hwctx->alloc, &vkb->buf); -+ if (ret != VK_SUCCESS) { -+ vk->FreeMemory(hwctx->act_dev, vkb->mem, hwctx->alloc); -+ return AVERROR_EXTERNAL; -+ } - -- vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) { -- .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, -- .pImageMemoryBarriers = img_bar, -- .imageMemoryBarrierCount = nb_img_bar, -- }); -+ ret = vk->BindBufferMemory(hwctx->act_dev, vkb->buf, vkb->mem, 0); -+ if (ret != VK_SUCCESS) { -+ vk->FreeMemory(hwctx->act_dev, vkb->mem, hwctx->alloc); -+ vk->DestroyBuffer(hwctx->act_dev, vkb->buf, hwctx->alloc); -+ return AVERROR_EXTERNAL; -+ } - -- /* Schedule a copy for each plane */ -- for (int i = 0; i < pixfmt_planes; i++) { -- int idx = FFMIN(i, nb_images - 1); -- VkImageAspectFlags plane_aspect[] = { VK_IMAGE_ASPECT_COLOR_BIT, -- VK_IMAGE_ASPECT_PLANE_0_BIT, -- VK_IMAGE_ASPECT_PLANE_1_BIT, -- VK_IMAGE_ASPECT_PLANE_2_BIT, }; -- -- FFVkBuffer *vkbuf = (FFVkBuffer *)bufs[i]->data; -- VkBufferImageCopy buf_reg = { -- .bufferOffset = buf_offsets[i], -- .bufferRowLength = buf_stride[i] / desc->comp[i].step, -- .imageSubresource.layerCount = 1, -- .imageSubresource.aspectMask = plane_aspect[(pixfmt_planes != nb_images) + -- i*(pixfmt_planes != nb_images)], -- .imageOffset = { 0, 0, 0, }, -- }; -+ return 0; -+} -+ -+static void destroy_avvkbuf(void *opaque, uint8_t *data) -+{ -+ FFVulkanContext *s = opaque; -+ FFVkBuffer *buf = (FFVkBuffer *)data; -+ ff_vk_free_buf(s, buf); -+ av_free(buf); -+} -+ -+static int host_map_frame(AVHWFramesContext *hwfc, AVBufferRef **dst, int *nb_bufs, -+ AVFrame *swf, VkBufferImageCopy *region, int upload) -+{ -+ int err; -+ VkResult ret; -+ VulkanDevicePriv *p = hwfc->device_ctx->hwctx; -+ FFVulkanFunctions *vk = &p->vkctx.vkfn; -+ AVVulkanDeviceContext *hwctx = &p->p; -+ -+ const int planes = av_pix_fmt_count_planes(swf->format); - -+ VkExternalMemoryBufferCreateInfo create_desc = { -+ .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, -+ .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, -+ }; -+ VkImportMemoryHostPointerInfoEXT import_desc = { -+ .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT, -+ .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, -+ }; -+ VkMemoryHostPointerPropertiesEXT props; -+ -+ for (int i = 0; i < planes; i++) { -+ FFVkBuffer *vkb; - uint32_t p_w, p_h; -- get_plane_wh(&p_w, &p_h, pix_fmt, w, h, i); -+ size_t offs; -+ size_t buffer_size; - -- buf_reg.bufferImageHeight = p_h; -- buf_reg.imageExtent = (VkExtent3D){ p_w, p_h, 1, }; -+ /* We can't host map images with negative strides */ -+ if (swf->linesize[i] < 0) { -+ err = AVERROR(EINVAL); -+ goto fail; -+ } - -- if (to_buf) -- vk->CmdCopyImageToBuffer(cmd_buf, frame->img[idx], -- img_bar[0].newLayout, -- vkbuf->buf, -- 1, &buf_reg); -- else -- vk->CmdCopyBufferToImage(cmd_buf, vkbuf->buf, frame->img[idx], -- img_bar[0].newLayout, -- 1, &buf_reg); -- } -+ get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i); - -- err = ff_vk_exec_submit(&p->vkctx, exec); -- if (err < 0) -- return err; -+ /* Get the previous point at which mapping was possible and use it */ -+ offs = (uintptr_t)swf->data[i] % p->hprops.minImportedHostPointerAlignment; -+ import_desc.pHostPointer = swf->data[i] - offs; -+ -+ props = (VkMemoryHostPointerPropertiesEXT) { -+ VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT, -+ }; -+ ret = vk->GetMemoryHostPointerPropertiesEXT(hwctx->act_dev, -+ import_desc.handleType, -+ import_desc.pHostPointer, -+ &props); -+ if (!(ret == VK_SUCCESS && props.memoryTypeBits)) { -+ err = AVERROR(EINVAL); -+ goto fail; -+ } -+ -+ /* Buffer region for this plane */ -+ region[i] = (VkBufferImageCopy) { -+ .bufferOffset = offs, -+ .bufferRowLength = swf->linesize[i], -+ .bufferImageHeight = p_h, -+ .imageSubresource.layerCount = 1, -+ .imageExtent = (VkExtent3D){ p_w, p_h, 1 }, -+ /* Rest of the fields adjusted/filled in later */ -+ }; -+ -+ /* Add the offset at the start, which gets ignored */ -+ buffer_size = offs + swf->linesize[i]*p_h; -+ buffer_size = FFALIGN(buffer_size, p->props.properties.limits.minMemoryMapAlignment); -+ buffer_size = FFALIGN(buffer_size, p->hprops.minImportedHostPointerAlignment); -+ -+ /* Create a buffer */ -+ vkb = av_mallocz(sizeof(*vkb)); -+ if (!vkb) { -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ -+ err = create_mapped_buffer(hwfc, vkb, -+ upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : -+ VK_BUFFER_USAGE_TRANSFER_DST_BIT, -+ buffer_size, &create_desc, &import_desc, -+ props); -+ if (err < 0) { -+ av_free(vkb); -+ goto fail; -+ } - -- ff_vk_exec_wait(&p->vkctx, exec); -+ /* Create a ref */ -+ dst[*nb_bufs] = av_buffer_create((uint8_t *)vkb, sizeof(*vkb), -+ destroy_avvkbuf, &p->vkctx, 0); -+ if (!dst[*nb_bufs]) { -+ destroy_avvkbuf(&p->vkctx, (uint8_t *)vkb); -+ err = AVERROR(ENOMEM); -+ goto fail; -+ } -+ -+ (*nb_bufs)++; -+ } - - return 0; -+ -+fail: -+ for (int i = 0; i < (*nb_bufs); i++) -+ av_buffer_unref(&dst[i]); -+ return err; - } - --static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, -- const AVFrame *swf, int from) -+static int vulkan_transfer_frame(AVHWFramesContext *hwfc, -+ AVFrame *swf, AVFrame *hwf, -+ int upload) - { -- int err = 0; -- VkResult ret; -- AVHWDeviceContext *dev_ctx = hwfc->device_ctx; -- VulkanDevicePriv *p = dev_ctx->hwctx; -- AVVulkanDeviceContext *hwctx = &p->p; -+ int err; -+ VulkanFramesPriv *fp = hwfc->hwctx; -+ VulkanDevicePriv *p = hwfc->device_ctx->hwctx; - FFVulkanFunctions *vk = &p->vkctx.vkfn; - -- AVFrame tmp; -- FFVkBuffer *vkbufs[AV_NUM_DATA_POINTERS]; -- AVBufferRef *bufs[AV_NUM_DATA_POINTERS] = { 0 }; -- size_t buf_offsets[AV_NUM_DATA_POINTERS] = { 0 }; -+ int host_mapped = 0; -+ -+ AVVkFrame *hwf_vk = (AVVkFrame *)hwf->data[0]; -+ VkBufferImageCopy region[AV_NUM_DATA_POINTERS]; // always one per plane - -- uint32_t p_w, p_h; - const int planes = av_pix_fmt_count_planes(swf->format); -+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(swf->format); -+ const int nb_images = ff_vk_count_images(hwf_vk); -+ static const VkImageAspectFlags plane_aspect[] = { VK_IMAGE_ASPECT_COLOR_BIT, -+ VK_IMAGE_ASPECT_PLANE_0_BIT, -+ VK_IMAGE_ASPECT_PLANE_1_BIT, -+ VK_IMAGE_ASPECT_PLANE_2_BIT, }; -+ -+ VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS]; -+ int nb_img_bar = 0; - -- int host_mapped[AV_NUM_DATA_POINTERS] = { 0 }; -- const int map_host = !!(p->vkctx.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY); -+ AVBufferRef *bufs[AV_NUM_DATA_POINTERS]; -+ int nb_bufs = 0; - -+ VkCommandBuffer cmd_buf; -+ FFVkExecContext *exec; -+ -+ /* Sanity checking */ - if ((swf->format != AV_PIX_FMT_NONE && !av_vkfmt_from_pixfmt(swf->format))) { - av_log(hwfc, AV_LOG_ERROR, "Unsupported software frame pixel format!\n"); - return AVERROR(EINVAL); -@@ -3453,115 +3903,97 @@ static int vulkan_transfer_data(AVHWFram - if (swf->width > hwfc->width || swf->height > hwfc->height) - return AVERROR(EINVAL); - -- /* Create buffers */ -- for (int i = 0; i < planes; i++) { -- size_t req_size; -- -- VkExternalMemoryBufferCreateInfo create_desc = { -- .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, -- .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, -- }; -- -- VkImportMemoryHostPointerInfoEXT import_desc = { -- .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT, -- .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, -- }; -- -- VkMemoryHostPointerPropertiesEXT p_props = { -- .sType = VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT, -- }; -- -- get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i); -- -- tmp.linesize[i] = FFABS(swf->linesize[i]); -- -- /* Do not map images with a negative stride */ -- if (map_host && swf->linesize[i] > 0) { -- size_t offs; -- offs = (uintptr_t)swf->data[i] % p->hprops.minImportedHostPointerAlignment; -- import_desc.pHostPointer = swf->data[i] - offs; -- -- /* We have to compensate for the few extra bytes of padding we -- * completely ignore at the start */ -- req_size = FFALIGN(offs + tmp.linesize[i] * p_h, -- p->hprops.minImportedHostPointerAlignment); -- -- ret = vk->GetMemoryHostPointerPropertiesEXT(hwctx->act_dev, -- import_desc.handleType, -- import_desc.pHostPointer, -- &p_props); -- if (ret == VK_SUCCESS && p_props.memoryTypeBits) { -- host_mapped[i] = 1; -- buf_offsets[i] = offs; -- } -- } -+ /* Setup buffers first */ -+ if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) { -+ err = host_map_frame(hwfc, bufs, &nb_bufs, swf, region, upload); -+ if (err >= 0) -+ host_mapped = 1; -+ } - -- if (!host_mapped[i]) -- req_size = get_req_buffer_size(p, &tmp.linesize[i], p_h); -- -- err = ff_vk_create_avbuf(&p->vkctx, &bufs[i], req_size, -- host_mapped[i] ? &create_desc : NULL, -- host_mapped[i] ? &import_desc : NULL, -- from ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : -- VK_BUFFER_USAGE_TRANSFER_SRC_BIT, -- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | -- (host_mapped[i] ? -- VK_MEMORY_PROPERTY_HOST_COHERENT_BIT : 0x0)); -+ if (!host_mapped) { -+ err = get_plane_buf(hwfc, &bufs[0], swf, region, upload); - if (err < 0) - goto end; -+ nb_bufs = 1; - -- vkbufs[i] = (FFVkBuffer *)bufs[i]->data; -+ if (upload) { -+ err = copy_buffer_data(hwfc, bufs[0], swf, region, planes, 1); -+ if (err < 0) -+ goto end; -+ } - } - -- if (!from) { -- /* Map, copy image TO buffer (which then goes to the VkImage), unmap */ -- if ((err = ff_vk_map_buffers(&p->vkctx, vkbufs, tmp.data, planes, 0))) -- goto end; -- -- for (int i = 0; i < planes; i++) { -- if (host_mapped[i]) -- continue; -+ exec = ff_vk_exec_get(&fp->upload_exec); -+ cmd_buf = exec->buf; - -- get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i); -+ ff_vk_exec_start(&p->vkctx, exec); - -- av_image_copy_plane(tmp.data[i], tmp.linesize[i], -- (const uint8_t *)swf->data[i], swf->linesize[i], -- FFMIN(tmp.linesize[i], FFABS(swf->linesize[i])), -- p_h); -- } -+ /* Prep destination Vulkan frame */ -+ err = ff_vk_exec_add_dep_frame(&p->vkctx, exec, hwf, -+ VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, -+ VK_PIPELINE_STAGE_2_TRANSFER_BIT); -+ if (err < 0) -+ goto end; - -- if ((err = ff_vk_unmap_buffers(&p->vkctx, vkbufs, planes, 1))) -+ /* No need to declare buf deps for synchronous transfers */ -+ if (upload) { -+ err = ff_vk_exec_add_dep_buf(&p->vkctx, exec, bufs, nb_bufs, 1); -+ if (err < 0) { -+ ff_vk_exec_discard_deps(&p->vkctx, exec); - goto end; -+ } - } - -- /* Copy buffers into/from image */ -- err = transfer_image_buf(hwfc, (AVFrame *)vkf, bufs, buf_offsets, -- tmp.linesize, swf->width, swf->height, swf->format, -- from); -- -- if (from) { -- /* Map, copy buffer (which came FROM the VkImage) to the frame, unmap */ -- if ((err = ff_vk_map_buffers(&p->vkctx, vkbufs, tmp.data, planes, 0))) -- goto end; -+ ff_vk_frame_barrier(&p->vkctx, exec, hwf, img_bar, &nb_img_bar, -+ VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, -+ VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR, -+ upload ? VK_ACCESS_TRANSFER_WRITE_BIT : -+ VK_ACCESS_TRANSFER_READ_BIT, -+ upload ? VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL : -+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, -+ VK_QUEUE_FAMILY_IGNORED); - -- for (int i = 0; i < planes; i++) { -- if (host_mapped[i]) -- continue; -+ vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) { -+ .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, -+ .pImageMemoryBarriers = img_bar, -+ .imageMemoryBarrierCount = nb_img_bar, -+ }); - -- get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i); -+ for (int i = 0; i < planes; i++) { -+ int buf_idx = FFMIN(i, (nb_bufs - 1)); -+ int img_idx = FFMIN(i, (nb_images - 1)); -+ FFVkBuffer *vkbuf = (FFVkBuffer *)bufs[buf_idx]->data; -+ -+ uint32_t orig_stride = region[i].bufferRowLength; -+ region[i].bufferRowLength /= desc->comp[i].step; -+ region[i].imageSubresource.aspectMask = plane_aspect[(planes != nb_images) + -+ i*(planes != nb_images)]; -+ -+ if (upload) -+ vk->CmdCopyBufferToImage(cmd_buf, vkbuf->buf, -+ hwf_vk->img[img_idx], -+ img_bar[img_idx].newLayout, -+ 1, ®ion[i]); -+ else -+ vk->CmdCopyImageToBuffer(cmd_buf, hwf_vk->img[img_idx], -+ img_bar[img_idx].newLayout, -+ vkbuf->buf, -+ 1, ®ion[i]); - -- av_image_copy_plane_uc_from(swf->data[i], swf->linesize[i], -- (const uint8_t *)tmp.data[i], tmp.linesize[i], -- FFMIN(tmp.linesize[i], FFABS(swf->linesize[i])), -- p_h); -- } -+ region[i].bufferRowLength = orig_stride; -+ } - -- if ((err = ff_vk_unmap_buffers(&p->vkctx, vkbufs, planes, 1))) -- goto end; -+ err = ff_vk_exec_submit(&p->vkctx, exec); -+ if (err < 0) { -+ ff_vk_exec_discard_deps(&p->vkctx, exec); -+ } else if (!upload) { -+ ff_vk_exec_wait(&p->vkctx, exec); -+ if (!host_mapped) -+ err = copy_buffer_data(hwfc, bufs[0], swf, region, planes, 0); - } - - end: -- for (int i = 0; i < planes; i++) -+ for (int i = 0; i < nb_bufs; i++) - av_buffer_unref(&bufs[i]); - - return err; -@@ -3588,7 +4020,7 @@ static int vulkan_transfer_data_to(AVHWF - if (src->hw_frames_ctx) - return AVERROR(ENOSYS); - else -- return vulkan_transfer_data(hwfc, dst, src, 0); -+ return vulkan_transfer_frame(hwfc, (AVFrame *)src, dst, 1); - } - } - -@@ -3705,7 +4137,7 @@ static int vulkan_transfer_data_from(AVH - if (dst->hw_frames_ctx) - return AVERROR(ENOSYS); - else -- return vulkan_transfer_data(hwfc, src, dst, 1); -+ return vulkan_transfer_frame(hwfc, dst, (AVFrame *)src, 0); - } - } - -Index: FFmpeg/libavutil/hwcontext_vulkan.h -=================================================================== ---- FFmpeg.orig/libavutil/hwcontext_vulkan.h -+++ FFmpeg/libavutil/hwcontext_vulkan.h -@@ -29,6 +29,20 @@ - - typedef struct AVVkFrame AVVkFrame; - -+typedef struct AVVulkanDeviceQueueFamily { -+ /* Queue family index */ -+ int idx; -+ /* Number of queues in the queue family in use */ -+ int num; -+ /* Queue family capabilities. Must be non-zero. -+ * Flags may be removed to indicate the queue family may not be used -+ * for a given purpose. */ -+ VkQueueFlagBits flags; -+ /* Vulkan implementations are allowed to list multiple video queues -+ * which differ in what they can encode or decode. */ -+ VkVideoCodecOperationFlagBitsKHR video_caps; -+} AVVulkanDeviceQueueFamily; -+ - /** - * @file - * API-specific header for AV_HWDEVICE_TYPE_VULKAN. -@@ -48,9 +62,8 @@ typedef struct AVVulkanDeviceContext { - const VkAllocationCallbacks *alloc; - - /** -- * Pointer to the instance-provided vkGetInstanceProcAddr loading function. -- * If NULL, will pick either libvulkan or libvolk, depending on libavutil's -- * compilation settings, and set this field. -+ * Pointer to a vkGetInstanceProcAddr loading function. -+ * If unset, will dynamically load and use libvulkan. - */ - PFN_vkGetInstanceProcAddr get_proc_addr; - -@@ -98,6 +111,7 @@ typedef struct AVVulkanDeviceContext { - const char * const *enabled_dev_extensions; - int nb_enabled_dev_extensions; - -+#if FF_API_VULKAN_FIXED_QUEUES - /** - * Queue family index for graphics operations, and the number of queues - * enabled for it. If unavaiable, will be set to -1. Not required. -@@ -105,21 +119,27 @@ typedef struct AVVulkanDeviceContext { - * queue family, or pick the one with the least unrelated flags set. - * Queue indices here may overlap if a queue has to share capabilities. - */ -+ attribute_deprecated - int queue_family_index; -+ attribute_deprecated - int nb_graphics_queues; - - /** - * Queue family index for transfer operations and the number of queues - * enabled. Required. - */ -+ attribute_deprecated - int queue_family_tx_index; -+ attribute_deprecated - int nb_tx_queues; - - /** - * Queue family index for compute operations and the number of queues - * enabled. Required. - */ -+ attribute_deprecated - int queue_family_comp_index; -+ attribute_deprecated - int nb_comp_queues; - - /** -@@ -127,7 +147,9 @@ typedef struct AVVulkanDeviceContext { - * If the device doesn't support such, queue_family_encode_index will be -1. - * Not required. - */ -+ attribute_deprecated - int queue_family_encode_index; -+ attribute_deprecated - int nb_encode_queues; - - /** -@@ -135,8 +157,11 @@ typedef struct AVVulkanDeviceContext { - * If the device doesn't support such, queue_family_decode_index will be -1. - * Not required. - */ -+ attribute_deprecated - int queue_family_decode_index; -+ attribute_deprecated - int nb_decode_queues; -+#endif - - /** - * Locks a queue, preventing other threads from submitting any command -@@ -150,6 +175,17 @@ typedef struct AVVulkanDeviceContext { - * Similar to lock_queue(), unlocks a queue. Must only be called after locking. - */ - void (*unlock_queue)(struct AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index); -+ -+ /** -+ * Queue families used. Must be preferentially ordered. List may contain -+ * duplicates. -+ * -+ * For compatibility reasons, all the enabled queue families listed above -+ * (queue_family_(tx/comp/encode/decode)_index) must also be included in -+ * this list until they're removed after deprecation. -+ */ -+ AVVulkanDeviceQueueFamily qf[64]; -+ int nb_qf; - } AVVulkanDeviceContext; - - /** -Index: FFmpeg/libavutil/version.h -=================================================================== ---- FFmpeg.orig/libavutil/version.h -+++ FFmpeg/libavutil/version.h -@@ -112,6 +112,7 @@ - #define FF_API_PALETTE_HAS_CHANGED (LIBAVUTIL_VERSION_MAJOR < 60) - #define FF_API_VULKAN_CONTIGUOUS_MEMORY (LIBAVUTIL_VERSION_MAJOR < 60) - #define FF_API_H274_FILM_GRAIN_VCS (LIBAVUTIL_VERSION_MAJOR < 60) -+#define FF_API_VULKAN_FIXED_QUEUES (LIBAVUTIL_VERSION_MAJOR < 60) - - /** - * @} -Index: FFmpeg/libavutil/vulkan.c -=================================================================== ---- FFmpeg.orig/libavutil/vulkan.c -+++ FFmpeg/libavutil/vulkan.c -@@ -82,6 +82,25 @@ const char *ff_vk_ret2str(VkResult res) - #undef CASE - } - -+static void load_enabled_qfs(FFVulkanContext *s) -+{ -+ s->nb_qfs = 0; -+ for (int i = 0; i < s->hwctx->nb_qf; i++) { -+ /* Skip duplicates */ -+ int skip = 0; -+ for (int j = 0; j < s->nb_qfs; j++) { -+ if (s->qfs[j] == s->hwctx->qf[i].idx) { -+ skip = 1; -+ break; -+ } -+ } -+ if (skip) -+ continue; -+ -+ s->qfs[s->nb_qfs++] = s->hwctx->qf[i].idx; -+ } -+} -+ - int ff_vk_load_props(FFVulkanContext *s) - { - FFVulkanFunctions *vk = &s->vkfn; -@@ -89,9 +108,13 @@ int ff_vk_load_props(FFVulkanContext *s) - s->hprops = (VkPhysicalDeviceExternalMemoryHostPropertiesEXT) { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT, - }; -+ s->optical_flow_props = (VkPhysicalDeviceOpticalFlowPropertiesNV) { -+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV, -+ .pNext = &s->hprops, -+ }; - s->coop_matrix_props = (VkPhysicalDeviceCooperativeMatrixPropertiesKHR) { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR, -- .pNext = &s->hprops, -+ .pNext = &s->optical_flow_props, - }; - s->subgroup_props = (VkPhysicalDeviceSubgroupSizeControlProperties) { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES, -@@ -126,6 +149,8 @@ int ff_vk_load_props(FFVulkanContext *s) - vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops); - vk->GetPhysicalDeviceFeatures2(s->hwctx->phys_dev, &s->feats); - -+ load_enabled_qfs(s); -+ - if (s->qf_props) - return 0; - -@@ -188,66 +213,22 @@ int ff_vk_load_props(FFVulkanContext *s) - - static int vk_qf_get_index(FFVulkanContext *s, VkQueueFlagBits dev_family, int *nb) - { -- int ret, num; -- -- switch (dev_family) { -- case VK_QUEUE_GRAPHICS_BIT: -- ret = s->hwctx->queue_family_index; -- num = s->hwctx->nb_graphics_queues; -- break; -- case VK_QUEUE_COMPUTE_BIT: -- ret = s->hwctx->queue_family_comp_index; -- num = s->hwctx->nb_comp_queues; -- break; -- case VK_QUEUE_TRANSFER_BIT: -- ret = s->hwctx->queue_family_tx_index; -- num = s->hwctx->nb_tx_queues; -- break; -- case VK_QUEUE_VIDEO_ENCODE_BIT_KHR: -- ret = s->hwctx->queue_family_encode_index; -- num = s->hwctx->nb_encode_queues; -- break; -- case VK_QUEUE_VIDEO_DECODE_BIT_KHR: -- ret = s->hwctx->queue_family_decode_index; -- num = s->hwctx->nb_decode_queues; -- break; -- default: -- av_assert0(0); /* Should never happen */ -+ for (int i = 0; i < s->hwctx->nb_qf; i++) { -+ if (s->hwctx->qf[i].flags & dev_family) { -+ *nb = s->hwctx->qf[i].num; -+ return s->hwctx->qf[i].idx; -+ } - } - -- if (nb) -- *nb = num; -- -- return ret; -+ av_assert0(0); /* Should never happen */ - } - - int ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, - VkQueueFlagBits dev_family) - { - /* Fill in queue families from context if not done yet */ -- if (!s->nb_qfs) { -- s->nb_qfs = 0; -- -- /* Simply fills in all unique queues into s->qfs */ -- if (s->hwctx->queue_family_index >= 0) -- s->qfs[s->nb_qfs++] = s->hwctx->queue_family_index; -- if (!s->nb_qfs || s->qfs[0] != s->hwctx->queue_family_tx_index) -- s->qfs[s->nb_qfs++] = s->hwctx->queue_family_tx_index; -- if (!s->nb_qfs || (s->qfs[0] != s->hwctx->queue_family_comp_index && -- s->qfs[1] != s->hwctx->queue_family_comp_index)) -- s->qfs[s->nb_qfs++] = s->hwctx->queue_family_comp_index; -- if (s->hwctx->queue_family_decode_index >= 0 && -- (s->qfs[0] != s->hwctx->queue_family_decode_index && -- s->qfs[1] != s->hwctx->queue_family_decode_index && -- s->qfs[2] != s->hwctx->queue_family_decode_index)) -- s->qfs[s->nb_qfs++] = s->hwctx->queue_family_decode_index; -- if (s->hwctx->queue_family_encode_index >= 0 && -- (s->qfs[0] != s->hwctx->queue_family_encode_index && -- s->qfs[1] != s->hwctx->queue_family_encode_index && -- s->qfs[2] != s->hwctx->queue_family_encode_index && -- s->qfs[3] != s->hwctx->queue_family_encode_index)) -- s->qfs[s->nb_qfs++] = s->hwctx->queue_family_encode_index; -- } -+ if (!s->nb_qfs) -+ load_enabled_qfs(s); - - return (qf->queue_family = vk_qf_get_index(s, dev_family, &qf->nb_queues)); - } -@@ -304,6 +285,15 @@ int ff_vk_exec_pool_init(FFVulkanContext - VkCommandPoolCreateInfo cqueue_create; - VkCommandBufferAllocateInfo cbuf_create; - -+ const VkQueryPoolVideoEncodeFeedbackCreateInfoKHR *ef = NULL; -+ -+ if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) { -+ ef = ff_vk_find_struct(query_create_pnext, -+ VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR); -+ if (!ef) -+ return AVERROR(EINVAL); -+ } -+ - /* Create command pool */ - cqueue_create = (VkCommandPoolCreateInfo) { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, -@@ -361,21 +351,18 @@ int ff_vk_exec_pool_init(FFVulkanContext - } - - pool->nb_queries = nb_queries; -- pool->query_status_stride = 2; -+ pool->query_status_stride = 1 + 1; /* One result, one status by default */ - pool->query_results = nb_queries; -- pool->query_statuses = 0; /* if radv supports it, nb_queries; */ -+ pool->query_statuses = nb_queries; - --#if 0 /* CONFIG_VULKAN_ENCODE */ - /* Video encode quieries produce two results per query */ - if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) { -- pool->query_status_stride = 3; /* skip,skip,result,skip,skip,result */ -- pool->query_results *= 2; -- } else --#endif -- if (query_type == VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR) { -+ int nb_results = av_popcount(ef->encodeFeedbackFlags); -+ pool->query_status_stride = nb_results + 1; -+ pool->query_results *= nb_results; -+ } else if (query_type == VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR) { - pool->query_status_stride = 1; - pool->query_results = 0; -- pool->query_statuses = nb_queries; - } - - pool->qd_size = (pool->query_results + pool->query_statuses)*(query_64bit ? 8 : 4); -@@ -467,7 +454,7 @@ VkResult ff_vk_exec_get_query(FFVulkanCo - e->query_idx, - pool->nb_queries, - pool->qd_size, e->query_data, -- pool->query_64bit ? 8 : 4, qf); -+ pool->qd_size, qf); - if (ret != VK_SUCCESS) - return ret; - -@@ -832,11 +819,8 @@ int ff_vk_alloc_mem(FFVulkanContext *s, - - ret = vk->AllocateMemory(s->hwctx->act_dev, &alloc_info, - s->hwctx->alloc, mem); -- if (ret != VK_SUCCESS) { -- av_log(s, AV_LOG_ERROR, "Failed to allocate memory: %s\n", -- ff_vk_ret2str(ret)); -+ if (ret != VK_SUCCESS) - return AVERROR(ENOMEM); -- } - - if (mem_flags) - *mem_flags |= s->mprops.memoryTypes[index].propertyFlags; -@@ -881,7 +865,7 @@ int ff_vk_create_buf(FFVulkanContext *s, - .pNext = &ded_req, - }; - -- ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, NULL, &buf->buf); -+ ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, s->hwctx->alloc, &buf->buf); - if (ret != VK_SUCCESS) { - av_log(s, AV_LOG_ERROR, "Failed to create buffer: %s\n", - ff_vk_ret2str(ret)); -@@ -1595,6 +1579,7 @@ int ff_vk_exec_pipeline_register(FFVulka - - err = ff_vk_create_buf(s, &set->buf, set->aligned_size*nb, - NULL, NULL, set->usage, -+ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - if (err < 0) -Index: FFmpeg/libavutil/vulkan.h -=================================================================== ---- FFmpeg.orig/libavutil/vulkan.h -+++ FFmpeg/libavutil/vulkan.h -@@ -237,6 +237,7 @@ typedef struct FFVulkanContext { - VkPhysicalDeviceDescriptorBufferPropertiesEXT desc_buf_props; - VkPhysicalDeviceSubgroupSizeControlProperties subgroup_props; - VkPhysicalDeviceCooperativeMatrixPropertiesKHR coop_matrix_props; -+ VkPhysicalDeviceOpticalFlowPropertiesNV optical_flow_props; - VkQueueFamilyQueryResultStatusPropertiesKHR *query_props; - VkQueueFamilyVideoPropertiesKHR *video_props; - VkQueueFamilyProperties2 *qf_props; -@@ -257,7 +258,7 @@ typedef struct FFVulkanContext { - AVHWFramesContext *frames; - AVVulkanFramesContext *hwfc; - -- uint32_t qfs[5]; -+ uint32_t qfs[64]; - int nb_qfs; - - /* Properties */ -@@ -289,6 +290,15 @@ static inline const void *ff_vk_find_str - return NULL; - } - -+static inline void ff_vk_link_struct(void *chain, const void *in) -+{ -+ VkBaseOutStructure *out = chain; -+ while (out->pNext) -+ out = out->pNext; -+ -+ out->pNext = (void *)in; -+} -+ - /* Identity mapping - r = r, b = b, g = g, a = a */ - extern const VkComponentMapping ff_comp_identity_map; - -Index: FFmpeg/libavutil/vulkan_functions.h -=================================================================== ---- FFmpeg.orig/libavutil/vulkan_functions.h -+++ FFmpeg/libavutil/vulkan_functions.h -@@ -46,6 +46,13 @@ typedef enum FFVulkanExtensions { - FF_VK_EXT_VIDEO_DECODE_AV1 = 1ULL << 14, /* VK_KHR_video_decode_av1 */ - FF_VK_EXT_ATOMIC_FLOAT = 1ULL << 15, /* VK_EXT_shader_atomic_float */ - FF_VK_EXT_COOP_MATRIX = 1ULL << 16, /* VK_KHR_cooperative_matrix */ -+ FF_VK_EXT_OPTICAL_FLOW = 1ULL << 17, /* VK_NV_optical_flow */ -+ FF_VK_EXT_SHADER_OBJECT = 1ULL << 18, /* VK_EXT_shader_object */ -+ -+ FF_VK_EXT_VIDEO_MAINTENANCE_1 = 1ULL << 27, /* VK_KHR_video_maintenance1 */ -+ FF_VK_EXT_VIDEO_ENCODE_QUEUE = 1ULL << 28, /* VK_KHR_video_encode_queue */ -+ FF_VK_EXT_VIDEO_ENCODE_H264 = 1ULL << 29, /* VK_KHR_video_encode_h264 */ -+ FF_VK_EXT_VIDEO_ENCODE_H265 = 1ULL << 30, /* VK_KHR_video_encode_h265 */ - - FF_VK_EXT_NO_FLAG = 1ULL << 31, - } FFVulkanExtensions; -@@ -194,6 +201,11 @@ typedef enum FFVulkanExtensions { - \ - /* Video decoding */ \ - MACRO(1, 1, FF_VK_EXT_VIDEO_DECODE_QUEUE, CmdDecodeVideoKHR) \ -+ \ -+ /* Video encoding */ \ -+ MACRO(1, 1, FF_VK_EXT_VIDEO_ENCODE_QUEUE, CmdEncodeVideoKHR) \ -+ MACRO(1, 1, FF_VK_EXT_VIDEO_ENCODE_QUEUE, GetEncodedVideoSessionParametersKHR) \ -+ MACRO(1, 0, FF_VK_EXT_VIDEO_ENCODE_QUEUE, GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR) \ - \ - /* Pipeline */ \ - MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreatePipelineLayout) \ -@@ -208,10 +220,21 @@ typedef enum FFVulkanExtensions { - MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroySamplerYcbcrConversion) \ - MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateSampler) \ - MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroySampler) \ -+ \ -+ /* Optical flow */ \ -+ MACRO(1, 1, FF_VK_EXT_OPTICAL_FLOW, BindOpticalFlowSessionImageNV) \ -+ MACRO(1, 1, FF_VK_EXT_OPTICAL_FLOW, CmdOpticalFlowExecuteNV) \ -+ MACRO(1, 1, FF_VK_EXT_OPTICAL_FLOW, CreateOpticalFlowSessionNV) \ -+ MACRO(1, 1, FF_VK_EXT_OPTICAL_FLOW, DestroyOpticalFlowSessionNV) \ -+ MACRO(1, 0, FF_VK_EXT_OPTICAL_FLOW, GetPhysicalDeviceOpticalFlowImageFormatsNV)\ - \ - /* Shaders */ \ - MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateShaderModule) \ -- MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyShaderModule) -+ MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyShaderModule) \ -+ MACRO(1, 1, FF_VK_EXT_SHADER_OBJECT, CmdBindShadersEXT) \ -+ MACRO(1, 1, FF_VK_EXT_SHADER_OBJECT, CreateShadersEXT) \ -+ MACRO(1, 1, FF_VK_EXT_SHADER_OBJECT, DestroyShaderEXT) \ -+ MACRO(1, 1, FF_VK_EXT_SHADER_OBJECT, GetShaderBinaryDataEXT) - - /* Macro containing every win32 specific function that we utilize in our codebase */ - #define FN_LIST_WIN32(MACRO) \ -Index: FFmpeg/libavutil/vulkan_loader.h -=================================================================== ---- FFmpeg.orig/libavutil/vulkan_loader.h -+++ FFmpeg/libavutil/vulkan_loader.h -@@ -49,14 +49,20 @@ static inline uint64_t ff_vk_extensions_ - { VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME, FF_VK_EXT_DEVICE_DRM }, - { VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME, FF_VK_EXT_ATOMIC_FLOAT }, - { VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME, FF_VK_EXT_COOP_MATRIX }, -+ { VK_NV_OPTICAL_FLOW_EXTENSION_NAME, FF_VK_EXT_OPTICAL_FLOW }, -+ { VK_EXT_SHADER_OBJECT_EXTENSION_NAME, FF_VK_EXT_SHADER_OBJECT }, -+ { VK_KHR_VIDEO_MAINTENANCE_1_EXTENSION_NAME, FF_VK_EXT_VIDEO_MAINTENANCE_1 }, - #ifdef _WIN32 - { VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_MEMORY }, - { VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_SEM }, - #endif - { VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME, FF_VK_EXT_DESCRIPTOR_BUFFER, }, - { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_QUEUE }, -+ { VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_ENCODE_QUEUE }, - { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_QUEUE }, -+ { VK_KHR_VIDEO_ENCODE_H264_EXTENSION_NAME, FF_VK_EXT_VIDEO_ENCODE_H264 }, - { VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H264 }, -+ { VK_KHR_VIDEO_ENCODE_H265_EXTENSION_NAME, FF_VK_EXT_VIDEO_ENCODE_H265 }, - { VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H265 }, - { VK_KHR_VIDEO_DECODE_AV1_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_AV1 }, - }; diff --git a/debian/patches/0070-fix-yuv420p-to-p01x-unscaled-conversion.patch b/debian/patches/0065-fix-yuv420p-to-p01x-unscaled-conversion.patch similarity index 98% rename from debian/patches/0070-fix-yuv420p-to-p01x-unscaled-conversion.patch rename to debian/patches/0065-fix-yuv420p-to-p01x-unscaled-conversion.patch index 0ae88c653..1c0bb0f32 100644 --- a/debian/patches/0070-fix-yuv420p-to-p01x-unscaled-conversion.patch +++ b/debian/patches/0065-fix-yuv420p-to-p01x-unscaled-conversion.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libswscale/swscale_unscaled.c =================================================================== --- FFmpeg.orig/libswscale/swscale_unscaled.c +++ FFmpeg/libswscale/swscale_unscaled.c -@@ -352,7 +352,7 @@ static int planar8ToP01xleWrapper(SwsCon +@@ -396,7 +396,7 @@ static int planar8ToP01xleWrapper(SwsCon const uint8_t *tsrc0 = src[0]; for (x = c->srcW; x > 0; x--) { t = *tsrc0++; @@ -11,7 +11,7 @@ Index: FFmpeg/libswscale/swscale_unscaled.c } src[0] += srcStride[0]; dstY += dstStride[0] / 2; -@@ -363,9 +363,9 @@ static int planar8ToP01xleWrapper(SwsCon +@@ -407,9 +407,9 @@ static int planar8ToP01xleWrapper(SwsCon const uint8_t *tsrc2 = src[2]; for (x = c->srcW / 2; x > 0; x--) { t = *tsrc1++; diff --git a/debian/patches/0071-allow-vt-sw-decoder-for-every-codec.patch b/debian/patches/0066-allow-vt-sw-decoder-for-every-codec.patch similarity index 92% rename from debian/patches/0071-allow-vt-sw-decoder-for-every-codec.patch rename to debian/patches/0066-allow-vt-sw-decoder-for-every-codec.patch index eda581789..ada8f0c48 100644 --- a/debian/patches/0071-allow-vt-sw-decoder-for-every-codec.patch +++ b/debian/patches/0066-allow-vt-sw-decoder-for-every-codec.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavcodec/videotoolbox.c =================================================================== --- FFmpeg.orig/libavcodec/videotoolbox.c +++ FFmpeg/libavcodec/videotoolbox.c -@@ -812,9 +812,7 @@ static CFDictionaryRef videotoolbox_deco +@@ -813,9 +813,7 @@ static CFDictionaryRef videotoolbox_deco &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(config_info, diff --git a/debian/patches/0072-add-bwdif-videotoolbox-filter.patch b/debian/patches/0067-add-bwdif-videotoolbox-filter.patch similarity index 97% rename from debian/patches/0072-add-bwdif-videotoolbox-filter.patch rename to debian/patches/0067-add-bwdif-videotoolbox-filter.patch index cdeae3f03..43fc781e7 100644 --- a/debian/patches/0072-add-bwdif-videotoolbox-filter.patch +++ b/debian/patches/0067-add-bwdif-videotoolbox-filter.patch @@ -2,7 +2,7 @@ Index: FFmpeg/configure =================================================================== --- FFmpeg.orig/configure +++ FFmpeg/configure -@@ -3821,6 +3821,7 @@ boxblur_opencl_filter_deps="opencl gpl" +@@ -3863,6 +3863,7 @@ boxblur_opencl_filter_deps="opencl gpl" bs2b_filter_deps="libbs2b" bwdif_cuda_filter_deps="ffnvcodec" bwdif_cuda_filter_deps_any="cuda_nvcc cuda_llvm" @@ -14,7 +14,7 @@ Index: FFmpeg/libavfilter/Makefile =================================================================== --- FFmpeg.orig/libavfilter/Makefile +++ FFmpeg/libavfilter/Makefile -@@ -218,6 +218,10 @@ OBJS-$(CONFIG_BOXBLUR_OPENCL_FILTER) +@@ -219,6 +219,10 @@ OBJS-$(CONFIG_BOXBLUR_OPENCL_FILTER) OBJS-$(CONFIG_BWDIF_FILTER) += vf_bwdif.o bwdifdsp.o yadif_common.o OBJS-$(CONFIG_BWDIF_CUDA_FILTER) += vf_bwdif_cuda.o vf_bwdif_cuda.ptx.o \ yadif_common.o @@ -317,7 +317,7 @@ Index: FFmpeg/libavfilter/vf_bwdif_videotoolbox.m =================================================================== --- /dev/null +++ FFmpeg/libavfilter/vf_bwdif_videotoolbox.m -@@ -0,0 +1,445 @@ +@@ -0,0 +1,448 @@ +/* + * Copyright (C) 2018 Philip Langdale + * 2020 Aman Karmani @@ -340,7 +340,7 @@ Index: FFmpeg/libavfilter/vf_bwdif_videotoolbox.m + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + -+#include "internal.h" ++#include "filters.h" +#include "metal/utils.h" +#include "yadif.h" +#include "libavutil/avassert.h" @@ -610,16 +610,17 @@ Index: FFmpeg/libavfilter/vf_bwdif_videotoolbox.m + +static int do_config_input(AVFilterLink *inlink) API_AVAILABLE(macos(10.11), ios(8.0)) +{ ++ FilterLink *inl = ff_filter_link(inlink); + AVFilterContext *ctx = inlink->dst; + BWDIFVTContext *s = ctx->priv; + -+ if (!inlink->hw_frames_ctx) { ++ if (!inl->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); ++ s->input_frames_ref = av_buffer_ref(inl->hw_frames_ctx); + if (!s->input_frames_ref) { + av_log(ctx, AV_LOG_ERROR, "A input frames reference create " + "failed.\n"); @@ -643,9 +644,11 @@ Index: FFmpeg/libavfilter/vf_bwdif_videotoolbox.m + +static int do_config_output(AVFilterLink *link) API_AVAILABLE(macos(10.11), ios(8.0)) +{ ++ FilterLink *outl = ff_filter_link(link); + AVHWFramesContext *output_frames, *input_frames; + AVFilterContext *ctx = link->src; + AVFilterLink *inlink = link->src->inputs[0]; ++ FilterLink *inl = ff_filter_link(inlink); + BWDIFVTContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + int ret = 0; @@ -658,16 +661,16 @@ Index: FFmpeg/libavfilter/vf_bwdif_videotoolbox.m + return AVERROR(ENOMEM); + } + -+ link->hw_frames_ctx = av_hwframe_ctx_alloc(s->device_ref); -+ if (!link->hw_frames_ctx) { ++ outl->hw_frames_ctx = av_hwframe_ctx_alloc(s->device_ref); ++ if (!outl->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "Failed to create HW frame context " + "for output.\n"); + ret = AVERROR(ENOMEM); + goto exit; + } + -+ input_frames = (AVHWFramesContext*)inlink->hw_frames_ctx->data; -+ output_frames = (AVHWFramesContext*)link->hw_frames_ctx->data; ++ input_frames = (AVHWFramesContext*)inl->hw_frames_ctx->data; ++ output_frames = (AVHWFramesContext*)outl->hw_frames_ctx->data; + + output_frames->format = AV_PIX_FMT_VIDEOTOOLBOX; + output_frames->sw_format = s->input_frames->sw_format; @@ -679,7 +682,7 @@ Index: FFmpeg/libavfilter/vf_bwdif_videotoolbox.m + if (ret < 0) + goto exit; + -+ ret = av_hwframe_ctx_init(link->hw_frames_ctx); ++ ret = av_hwframe_ctx_init(outl->hw_frames_ctx); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to initialise VideoToolbox frame " + "context for output: %d\n", ret); diff --git a/debian/patches/0073-add-12bit-decoding-on-videotoolbox.patch b/debian/patches/0068-add-12bit-decoding-on-videotoolbox.patch similarity index 67% rename from debian/patches/0073-add-12bit-decoding-on-videotoolbox.patch rename to debian/patches/0068-add-12bit-decoding-on-videotoolbox.patch index 0236a92c7..c77f36529 100644 --- a/debian/patches/0073-add-12bit-decoding-on-videotoolbox.patch +++ b/debian/patches/0068-add-12bit-decoding-on-videotoolbox.patch @@ -1,8 +1,8 @@ -Index: FFmpeg/libavcodec/hevcdec.c +Index: FFmpeg/libavcodec/hevc/hevcdec.c =================================================================== ---- FFmpeg.orig/libavcodec/hevcdec.c -+++ FFmpeg/libavcodec/hevcdec.c -@@ -533,6 +533,9 @@ static enum AVPixelFormat get_format(HEV +--- FFmpeg.orig/libavcodec/hevc/hevcdec.c ++++ FFmpeg/libavcodec/hevc/hevcdec.c +@@ -660,6 +660,9 @@ static enum AVPixelFormat get_format(HEV #if CONFIG_HEVC_NVDEC_HWACCEL *fmt++ = AV_PIX_FMT_CUDA; #endif @@ -12,7 +12,7 @@ Index: FFmpeg/libavcodec/hevcdec.c break; case AV_PIX_FMT_YUV422P12: #if CONFIG_HEVC_DXVA2_HWACCEL -@@ -548,6 +551,9 @@ static enum AVPixelFormat get_format(HEV +@@ -675,6 +678,9 @@ static enum AVPixelFormat get_format(HEV #if CONFIG_HEVC_VULKAN_HWACCEL *fmt++ = AV_PIX_FMT_VULKAN; #endif diff --git a/debian/patches/0069-add-fixes-x265-build-from-upstream.patch b/debian/patches/0069-add-fixes-x265-build-from-upstream.patch deleted file mode 100644 index 711b3c3b3..000000000 --- a/debian/patches/0069-add-fixes-x265-build-from-upstream.patch +++ /dev/null @@ -1,79 +0,0 @@ -Index: FFmpeg/libavcodec/libx265.c -=================================================================== ---- FFmpeg.orig/libavcodec/libx265.c -+++ FFmpeg/libavcodec/libx265.c -@@ -646,7 +646,13 @@ static int libx265_encode_frame(AVCodecC - { - libx265Context *ctx = avctx->priv_data; - x265_picture x265pic; -- x265_picture x265pic_out = { 0 }; -+#if (X265_BUILD >= 210) && (X265_BUILD < 213) -+ x265_picture x265pic_layers_out[MAX_SCALABLE_LAYERS]; -+ x265_picture* x265pic_lyrptr_out[MAX_SCALABLE_LAYERS]; -+#else -+ x265_picture x265pic_solo_out = { 0 }; -+#endif -+ x265_picture* x265pic_out; - x265_nal *nal; - x265_sei *sei; - uint8_t *dst; -@@ -764,8 +770,16 @@ static int libx265_encode_frame(AVCodecC - } - } - -+#if (X265_BUILD >= 210) && (X265_BUILD < 213) -+ for (i = 0; i < MAX_SCALABLE_LAYERS; i++) -+ x265pic_lyrptr_out[i] = &x265pic_layers_out[i]; -+ -+ ret = ctx->api->encoder_encode(ctx->encoder, &nal, &nnal, -+ pic ? &x265pic : NULL, x265pic_lyrptr_out); -+#else - ret = ctx->api->encoder_encode(ctx->encoder, &nal, &nnal, -- pic ? &x265pic : NULL, &x265pic_out); -+ pic ? &x265pic : NULL, &x265pic_solo_out); -+#endif - - for (i = 0; i < sei->numPayloads; i++) - av_free(sei->payloads[i].payload); -@@ -795,10 +809,16 @@ static int libx265_encode_frame(AVCodecC - pkt->flags |= AV_PKT_FLAG_KEY; - } - -- pkt->pts = x265pic_out.pts; -- pkt->dts = x265pic_out.dts; -+#if (X265_BUILD >= 210) && (X265_BUILD < 213) -+ x265pic_out = x265pic_lyrptr_out[0]; -+#else -+ x265pic_out = &x265pic_solo_out; -+#endif -+ -+ pkt->pts = x265pic_out->pts; -+ pkt->dts = x265pic_out->dts; - -- switch (x265pic_out.sliceType) { -+ switch (x265pic_out->sliceType) { - case X265_TYPE_IDR: - case X265_TYPE_I: - pict_type = AV_PICTURE_TYPE_I; -@@ -816,16 +836,16 @@ static int libx265_encode_frame(AVCodecC - } - - #if X265_BUILD >= 130 -- if (x265pic_out.sliceType == X265_TYPE_B) -+ if (x265pic_out->sliceType == X265_TYPE_B) - #else -- if (x265pic_out.frameData.sliceType == 'b') -+ if (x265pic_out->frameData.sliceType == 'b') - #endif - pkt->flags |= AV_PKT_FLAG_DISPOSABLE; - -- ff_side_data_set_encoder_stats(pkt, x265pic_out.frameData.qp * FF_QP2LAMBDA, NULL, 0, pict_type); -+ ff_side_data_set_encoder_stats(pkt, x265pic_out->frameData.qp * FF_QP2LAMBDA, NULL, 0, pict_type); - -- if (x265pic_out.userData) { -- int idx = (int)(intptr_t)x265pic_out.userData - 1; -+ if (x265pic_out->userData) { -+ int idx = (int)(intptr_t)x265pic_out->userData - 1; - ReorderedData *rd = &ctx->rd[idx]; - - pkt->duration = rd->duration; diff --git a/debian/patches/0074-fix-the-sub2video-perf-regressions.patch b/debian/patches/0069-fix-the-sub2video-perf-regressions.patch similarity index 97% rename from debian/patches/0074-fix-the-sub2video-perf-regressions.patch rename to debian/patches/0069-fix-the-sub2video-perf-regressions.patch index bc0ed5265..b7ae16c49 100644 --- a/debian/patches/0074-fix-the-sub2video-perf-regressions.patch +++ b/debian/patches/0069-fix-the-sub2video-perf-regressions.patch @@ -2,7 +2,7 @@ Index: FFmpeg/fftools/ffmpeg_filter.c =================================================================== --- FFmpeg.orig/fftools/ffmpeg_filter.c +++ FFmpeg/fftools/ffmpeg_filter.c -@@ -2458,7 +2458,8 @@ static void sub2video_heartbeat(InputFil +@@ -2651,7 +2651,8 @@ static void sub2video_heartbeat(InputFil or if we need to initialize the system, update the overlayed subpicture and its start/end times */ sub2video_update(ifp, pts2 + 1, NULL); diff --git a/debian/patches/0075-allow-vpl-qsv-to-init-with-the-legacy-msdk-path.patch b/debian/patches/0070-allow-vpl-qsv-to-init-with-the-legacy-msdk-path.patch similarity index 94% rename from debian/patches/0075-allow-vpl-qsv-to-init-with-the-legacy-msdk-path.patch rename to debian/patches/0070-allow-vpl-qsv-to-init-with-the-legacy-msdk-path.patch index ebaeeff88..47f75d333 100644 --- a/debian/patches/0075-allow-vpl-qsv-to-init-with-the-legacy-msdk-path.patch +++ b/debian/patches/0070-allow-vpl-qsv-to-init-with-the-legacy-msdk-path.patch @@ -2,7 +2,7 @@ Index: FFmpeg/configure =================================================================== --- FFmpeg.orig/configure +++ FFmpeg/configure -@@ -2528,6 +2528,7 @@ HAVE_LIST=" +@@ -2533,6 +2533,7 @@ HAVE_LIST=" xmllint zlib_gzip openvino2 @@ -10,7 +10,7 @@ Index: FFmpeg/configure " # options emitted with CONFIG_ prefix but not available on the command line -@@ -6947,6 +6948,9 @@ elif enabled libvpl; then +@@ -6989,6 +6990,9 @@ elif enabled libvpl; then die "ERROR: libvpl >= 2.6 not found" add_cflags -DMFX_DEPRECATED_OFF check_type "vpl/mfxdefs.h vpl/mfxvideo.h" "struct mfxConfigInterface" @@ -24,7 +24,7 @@ Index: FFmpeg/libavcodec/qsv.c =================================================================== --- FFmpeg.orig/libavcodec/qsv.c +++ FFmpeg/libavcodec/qsv.c -@@ -496,6 +496,17 @@ static int ff_qsv_set_display_handle(AVC +@@ -499,6 +499,17 @@ static int ff_qsv_set_display_handle(AVC } #endif //AVCODEC_QSV_LINUX_SESSION_HANDLE @@ -42,7 +42,7 @@ Index: FFmpeg/libavcodec/qsv.c #if QSV_ONEVPL static int qsv_new_mfx_loader(AVCodecContext *avctx, mfxIMPL implementation, -@@ -636,6 +647,16 @@ static int qsv_create_mfx_session(AVCode +@@ -639,6 +650,16 @@ static int qsv_create_mfx_session(AVCode return 0; fail: @@ -59,7 +59,7 @@ Index: FFmpeg/libavcodec/qsv.c if (!*ploader && loader) MFXUnload(loader); -@@ -651,6 +672,20 @@ static int qsv_create_mfx_session(AVCode +@@ -654,6 +675,20 @@ static int qsv_create_mfx_session(AVCode mfxSession *psession, void **ploader) { @@ -106,7 +106,7 @@ Index: FFmpeg/libavfilter/qsvvpp.c =================================================================== --- FFmpeg.orig/libavfilter/qsvvpp.c +++ FFmpeg/libavfilter/qsvvpp.c -@@ -1067,6 +1067,16 @@ int ff_qsvvpp_filter_frame(QSVVPPContext +@@ -1065,6 +1065,16 @@ int ff_qsvvpp_filter_frame(QSVVPPContext return 0; } @@ -123,7 +123,7 @@ Index: FFmpeg/libavfilter/qsvvpp.c #if QSV_ONEVPL int ff_qsvvpp_create_mfx_session(void *ctx, -@@ -1110,6 +1120,15 @@ int ff_qsvvpp_create_mfx_session(void *c +@@ -1108,6 +1118,15 @@ int ff_qsvvpp_create_mfx_session(void *c impl_idx++; } @@ -139,7 +139,7 @@ Index: FFmpeg/libavfilter/qsvvpp.c if (sts < 0) return ff_qsvvpp_print_error(ctx, sts, "Error creating a MFX session"); -@@ -1127,6 +1146,19 @@ int ff_qsvvpp_create_mfx_session(void *c +@@ -1125,6 +1144,19 @@ int ff_qsvvpp_create_mfx_session(void *c mfxVersion *pver, mfxSession *psession) { diff --git a/debian/patches/0076-alway-set-videotoolboxenc-pixel-buffer-info.patch b/debian/patches/0071-alway-set-videotoolboxenc-pixel-buffer-info.patch similarity index 90% rename from debian/patches/0076-alway-set-videotoolboxenc-pixel-buffer-info.patch rename to debian/patches/0071-alway-set-videotoolboxenc-pixel-buffer-info.patch index df99d8c8b..92f88fa8c 100644 --- a/debian/patches/0076-alway-set-videotoolboxenc-pixel-buffer-info.patch +++ b/debian/patches/0071-alway-set-videotoolboxenc-pixel-buffer-info.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavcodec/videotoolboxenc.c =================================================================== --- FFmpeg.orig/libavcodec/videotoolboxenc.c +++ FFmpeg/libavcodec/videotoolboxenc.c -@@ -1034,9 +1034,10 @@ static int create_cv_pixel_buffer_info(A +@@ -1035,9 +1035,10 @@ static int create_cv_pixel_buffer_info(A CFNumberRef width_num = NULL; CFNumberRef height_num = NULL; CFMutableDictionaryRef pixel_buffer_info = NULL; @@ -14,7 +14,7 @@ Index: FFmpeg/libavcodec/videotoolboxenc.c avctx->color_range, &cv_color_format, NULL); -@@ -1687,11 +1688,9 @@ static int vtenc_configure_encoder(AVCod +@@ -1692,11 +1693,9 @@ static int vtenc_configure_encoder(AVCod kCFBooleanTrue); } diff --git a/debian/patches/0077-add-remove-dovi-hdr10plus-bsf.patch b/debian/patches/0072-add-remove-dovi-hdr10plus-bsf.patch similarity index 95% rename from debian/patches/0077-add-remove-dovi-hdr10plus-bsf.patch rename to debian/patches/0072-add-remove-dovi-hdr10plus-bsf.patch index c2fcc9f4f..7c13d34df 100644 --- a/debian/patches/0077-add-remove-dovi-hdr10plus-bsf.patch +++ b/debian/patches/0072-add-remove-dovi-hdr10plus-bsf.patch @@ -1,89 +1,3 @@ -Index: FFmpeg/libavcodec/bsf/h265_metadata.c -=================================================================== ---- FFmpeg.orig/libavcodec/bsf/h265_metadata.c -+++ FFmpeg/libavcodec/bsf/h265_metadata.c -@@ -27,6 +27,7 @@ - #include "h2645data.h" - #include "hevc.h" - #include "h265_profile_level.h" -+#include "itut35.h" - - enum { - LEVEL_UNSET = -2, -@@ -62,6 +63,8 @@ typedef struct H265MetadataContext { - int level; - int level_guess; - int level_warned; -+ int remove_dovi; -+ int remove_hdr10plus; - } H265MetadataContext; - - -@@ -385,6 +388,38 @@ static int h265_metadata_update_fragment - if (err < 0) - return err; - } -+ if (ctx->remove_hdr10plus) { -+ // This implementation is not strictly correct as it does not decode the entire NAL. -+ // There could be multiple SEIs packed within a single NAL, and some of them may not be HDR10+ metadata. -+ // The current implementation simply removes the entire NAL without further inspection. -+ if (au->units[i].type == HEVC_NAL_SEI_PREFIX && au->units[i].data_size > 8 * sizeof(uint8_t)) { -+ uint8_t *nal_sei = au->units[i].data; -+ // This Matches ITU-T T.35 SMPTE ST 2094-40 -+ if (nal_sei[0] == 0x4E && nal_sei[1] == 0x01 && nal_sei[2] == 0x04) { -+ if (nal_sei[4] == ITU_T_T35_COUNTRY_CODE_US && nal_sei[6] == ITU_T_T35_PROVIDER_CODE_SMTPE) { -+ // identifier for HDR10+ -+ const uint8_t smpte2094_40_provider_oriented_code = 0x01; -+ const uint8_t smpte2094_40_application_identifier = 0x04; -+ if (nal_sei[8] == smpte2094_40_provider_oriented_code && nal_sei[9] == smpte2094_40_application_identifier) { -+ av_log(bsf, AV_LOG_DEBUG, "Found HDR10+ metadata, removing NAL\n"); -+ ff_cbs_delete_unit(au, i); -+ } -+ } -+ -+ } -+ } -+ } -+ } -+ -+ if (ctx->remove_dovi && au->nb_units) { -+ if (au->units[au->nb_units - 1].type == HEVC_NAL_UNSPEC62) { // Dolby Vision RPU -+ ff_cbs_delete_unit(au, au->nb_units - 1); -+ av_log(bsf, AV_LOG_DEBUG, "Removing Dolby Vision RPU\n"); -+ } -+ if (au->units[au->nb_units - 1].type == HEVC_NAL_UNSPEC63) { // Dolby Vision EL -+ ff_cbs_delete_unit(au, au->nb_units - 1); -+ av_log(bsf, AV_LOG_DEBUG, "Removing Dolby Vision EL\n"); -+ } - } - - return 0; -@@ -399,6 +434,11 @@ static const CBSBSFType h265_metadata_ty - - static int h265_metadata_init(AVBSFContext *bsf) - { -+ if (((H265MetadataContext *)bsf->priv_data)->remove_dovi) { -+ av_packet_side_data_remove(bsf->par_out->coded_side_data, -+ &bsf->par_out->nb_coded_side_data, -+ AV_PKT_DATA_DOVI_CONF); -+ } - return ff_cbs_bsf_generic_init(bsf, &h265_metadata_type); - } - -@@ -478,6 +518,13 @@ static const AVOption h265_metadata_opti - { LEVEL("8.5", 255) }, - #undef LEVEL - -+ { "remove_dovi", "Remove Dolby Vision EL and RPU", -+ OFFSET(remove_dovi), AV_OPT_TYPE_BOOL, -+ { .i64 = 0 }, 0, 1, FLAGS }, -+ { "remove_hdr10plus", "Remove NALs including HDR10+ metadata", -+ OFFSET(remove_hdr10plus), AV_OPT_TYPE_BOOL, -+ { .i64 = 0 }, 0, 1, FLAGS }, -+ - { NULL } - }; - Index: FFmpeg/libavcodec/bsf/av1_metadata.c =================================================================== --- FFmpeg.orig/libavcodec/bsf/av1_metadata.c @@ -184,3 +98,89 @@ Index: FFmpeg/libavcodec/bsf/av1_metadata.c { NULL } }; +Index: FFmpeg/libavcodec/bsf/h265_metadata.c +=================================================================== +--- FFmpeg.orig/libavcodec/bsf/h265_metadata.c ++++ FFmpeg/libavcodec/bsf/h265_metadata.c +@@ -26,6 +26,7 @@ + #include "cbs_h265.h" + #include "h2645data.h" + #include "h265_profile_level.h" ++#include "itut35.h" + + #include "hevc/hevc.h" + +@@ -65,6 +66,8 @@ typedef struct H265MetadataContext { + int level; + int level_guess; + int level_warned; ++ int remove_dovi; ++ int remove_hdr10plus; + } H265MetadataContext; + + +@@ -475,6 +478,38 @@ static int h265_metadata_update_fragment + if (err < 0) + return err; + } ++ if (ctx->remove_hdr10plus) { ++ // This implementation is not strictly correct as it does not decode the entire NAL. ++ // There could be multiple SEIs packed within a single NAL, and some of them may not be HDR10+ metadata. ++ // The current implementation simply removes the entire NAL without further inspection. ++ if (au->units[i].type == HEVC_NAL_SEI_PREFIX && au->units[i].data_size > 8 * sizeof(uint8_t)) { ++ uint8_t *nal_sei = au->units[i].data; ++ // This Matches ITU-T T.35 SMPTE ST 2094-40 ++ if (nal_sei[0] == 0x4E && nal_sei[1] == 0x01 && nal_sei[2] == 0x04) { ++ if (nal_sei[4] == ITU_T_T35_COUNTRY_CODE_US && nal_sei[6] == ITU_T_T35_PROVIDER_CODE_SMTPE) { ++ // identifier for HDR10+ ++ const uint8_t smpte2094_40_provider_oriented_code = 0x01; ++ const uint8_t smpte2094_40_application_identifier = 0x04; ++ if (nal_sei[8] == smpte2094_40_provider_oriented_code && nal_sei[9] == smpte2094_40_application_identifier) { ++ av_log(bsf, AV_LOG_DEBUG, "Found HDR10+ metadata, removing NAL\n"); ++ ff_cbs_delete_unit(au, i); ++ } ++ } ++ ++ } ++ } ++ } ++ } ++ ++ if (ctx->remove_dovi && au->nb_units) { ++ if (au->units[au->nb_units - 1].type == HEVC_NAL_UNSPEC62) { // Dolby Vision RPU ++ ff_cbs_delete_unit(au, au->nb_units - 1); ++ av_log(bsf, AV_LOG_DEBUG, "Removing Dolby Vision RPU\n"); ++ } ++ if (au->units[au->nb_units - 1].type == HEVC_NAL_UNSPEC63) { // Dolby Vision EL ++ ff_cbs_delete_unit(au, au->nb_units - 1); ++ av_log(bsf, AV_LOG_DEBUG, "Removing Dolby Vision EL\n"); ++ } + } + + return 0; +@@ -489,6 +524,11 @@ static const CBSBSFType h265_metadata_ty + + static int h265_metadata_init(AVBSFContext *bsf) + { ++ if (((H265MetadataContext *)bsf->priv_data)->remove_dovi) { ++ av_packet_side_data_remove(bsf->par_out->coded_side_data, ++ &bsf->par_out->nb_coded_side_data, ++ AV_PKT_DATA_DOVI_CONF); ++ } + return ff_cbs_bsf_generic_init(bsf, &h265_metadata_type); + } + +@@ -574,6 +614,13 @@ static const AVOption h265_metadata_opti + { LEVEL("8.5", 255) }, + #undef LEVEL + ++ { "remove_dovi", "Remove Dolby Vision EL and RPU", ++ OFFSET(remove_dovi), AV_OPT_TYPE_BOOL, ++ { .i64 = 0 }, 0, 1, FLAGS }, ++ { "remove_hdr10plus", "Remove NALs including HDR10+ metadata", ++ OFFSET(remove_hdr10plus), AV_OPT_TYPE_BOOL, ++ { .i64 = 0 }, 0, 1, FLAGS }, ++ + { NULL } + }; + diff --git a/debian/patches/0078-fix-atenc-layout-samplerate.patch b/debian/patches/0073-fix-atenc-layout-samplerate.patch similarity index 92% rename from debian/patches/0078-fix-atenc-layout-samplerate.patch rename to debian/patches/0073-fix-atenc-layout-samplerate.patch index 4de8cda5f..60a75feb9 100644 --- a/debian/patches/0078-fix-atenc-layout-samplerate.patch +++ b/debian/patches/0073-fix-atenc-layout-samplerate.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavcodec/audiotoolboxenc.c =================================================================== --- FFmpeg.orig/libavcodec/audiotoolboxenc.c +++ FFmpeg/libavcodec/audiotoolboxenc.c -@@ -235,8 +235,8 @@ static int get_aac_tag(const AVChannelLa +@@ -236,8 +236,8 @@ static int get_aac_tag(const AVChannelLa { AV_CHANNEL_LAYOUT_6POINT0, kAudioChannelLayoutTag_AAC_6_0 }, { AV_CHANNEL_LAYOUT_6POINT1, kAudioChannelLayoutTag_AAC_6_1 }, { AV_CHANNEL_LAYOUT_7POINT0, kAudioChannelLayoutTag_AAC_7_0 }, @@ -13,7 +13,7 @@ Index: FFmpeg/libavcodec/audiotoolboxenc.c }; int i; -@@ -633,7 +633,7 @@ static const AVOption options[] = { +@@ -635,7 +635,7 @@ static const AVOption options[] = { .version = LIBAVUTIL_VERSION_INT, \ }; @@ -22,7 +22,7 @@ Index: FFmpeg/libavcodec/audiotoolboxenc.c FFAT_ENC_CLASS(NAME) \ const FFCodec ff_##NAME##_at_encoder = { \ .p.name = #NAME "_at", \ -@@ -650,9 +650,10 @@ static const AVOption options[] = { +@@ -652,9 +652,10 @@ static const AVOption options[] = { AV_CODEC_CAP_ENCODER_FLUSH CAPS, \ .p.ch_layouts = CH_LAYOUTS, \ .p.sample_fmts = (const enum AVSampleFormat[]) { \ @@ -34,7 +34,7 @@ Index: FFmpeg/libavcodec/audiotoolboxenc.c .p.profiles = PROFILES, \ .p.wrapper_name = "at", \ }; -@@ -667,15 +668,25 @@ static const AVChannelLayout aac_at_ch_l +@@ -669,15 +670,25 @@ static const AVChannelLayout aac_at_ch_l AV_CHANNEL_LAYOUT_6POINT0, AV_CHANNEL_LAYOUT_6POINT1, AV_CHANNEL_LAYOUT_7POINT0, diff --git a/debian/patches/0079-videotoolbox-remove-opengl-compatability.patch b/debian/patches/0074-videotoolbox-remove-opengl-compatability.patch similarity index 92% rename from debian/patches/0079-videotoolbox-remove-opengl-compatability.patch rename to debian/patches/0074-videotoolbox-remove-opengl-compatability.patch index 5e6d78cb0..8cd6f309d 100644 --- a/debian/patches/0079-videotoolbox-remove-opengl-compatability.patch +++ b/debian/patches/0074-videotoolbox-remove-opengl-compatability.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavcodec/videotoolbox.c =================================================================== --- FFmpeg.orig/libavcodec/videotoolbox.c +++ FFmpeg/libavcodec/videotoolbox.c -@@ -786,11 +786,6 @@ static CFDictionaryRef videotoolbox_buff +@@ -787,11 +787,6 @@ static CFDictionaryRef videotoolbox_buff CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfacePropertiesKey, io_surface_properties); CFDictionarySetValue(buffer_attributes, kCVPixelBufferWidthKey, w); CFDictionarySetValue(buffer_attributes, kCVPixelBufferHeightKey, h); diff --git a/debian/patches/0080-use-dynamic-pool-for-vpl-qsv-hwupload.patch b/debian/patches/0075-use-dynamic-pool-for-vpl-qsv-hwupload.patch similarity index 94% rename from debian/patches/0080-use-dynamic-pool-for-vpl-qsv-hwupload.patch rename to debian/patches/0075-use-dynamic-pool-for-vpl-qsv-hwupload.patch index c18144bda..3b02e7a3b 100644 --- a/debian/patches/0080-use-dynamic-pool-for-vpl-qsv-hwupload.patch +++ b/debian/patches/0075-use-dynamic-pool-for-vpl-qsv-hwupload.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavfilter/qsvvpp.c =================================================================== --- FFmpeg.orig/libavfilter/qsvvpp.c +++ FFmpeg/libavfilter/qsvvpp.c -@@ -69,6 +69,36 @@ static const struct { +@@ -70,6 +70,36 @@ static const struct { #endif }; @@ -44,7 +44,7 @@ Index: FFmpeg/libavfilter/vf_hwupload.c --- FFmpeg.orig/libavfilter/vf_hwupload.c +++ FFmpeg/libavfilter/vf_hwupload.c @@ -32,6 +32,10 @@ - #include "internal.h" + #include "formats.h" #include "video.h" +#if CONFIG_QSVVPP @@ -54,7 +54,7 @@ Index: FFmpeg/libavfilter/vf_hwupload.c typedef struct HWUploadContext { const AVClass *class; -@@ -163,6 +167,15 @@ static int hwupload_config_output(AVFilt +@@ -165,6 +169,15 @@ static int hwupload_config_output(AVFilt ctx->hwframes->user_opaque = &texDesc; #endif diff --git a/debian/patches/0081-backport-av1-videotoolbox.patch b/debian/patches/0076-backport-av1-videotoolbox.patch similarity index 89% rename from debian/patches/0081-backport-av1-videotoolbox.patch rename to debian/patches/0076-backport-av1-videotoolbox.patch index 4c4e4e12b..9060cd6d4 100644 --- a/debian/patches/0081-backport-av1-videotoolbox.patch +++ b/debian/patches/0076-backport-av1-videotoolbox.patch @@ -1,8 +1,37 @@ +Index: FFmpeg/configure +=================================================================== +--- FFmpeg.orig/configure ++++ FFmpeg/configure +@@ -2467,6 +2467,7 @@ TYPES_LIST=" + kCMVideoCodecType_HEVC + kCMVideoCodecType_HEVCWithAlpha + kCMVideoCodecType_VP9 ++ kCMVideoCodecType_AV1 + kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange + kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange + kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange +@@ -3176,6 +3177,8 @@ av1_vaapi_hwaccel_deps="vaapi VADecPictu + av1_vaapi_hwaccel_select="av1_decoder" + av1_vdpau_hwaccel_deps="vdpau VdpPictureInfoAV1" + av1_vdpau_hwaccel_select="av1_decoder" ++av1_videotoolbox_hwaccel_deps="videotoolbox" ++av1_videotoolbox_hwaccel_select="av1_decoder" + av1_vulkan_hwaccel_deps="vulkan" + av1_vulkan_hwaccel_select="av1_decoder" + h263_vaapi_hwaccel_deps="vaapi" +@@ -6744,6 +6747,7 @@ enabled videotoolbox && { + check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_HEVC "-framework CoreMedia" + check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_HEVCWithAlpha "-framework CoreMedia" + check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_VP9 "-framework CoreMedia" ++ check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_AV1 "-framework CoreMedia" + check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange "-framework CoreVideo" + check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange "-framework CoreVideo" + check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange "-framework CoreVideo" Index: FFmpeg/libavcodec/Makefile =================================================================== --- FFmpeg.orig/libavcodec/Makefile +++ FFmpeg/libavcodec/Makefile -@@ -1010,6 +1010,7 @@ OBJS-$(CONFIG_AV1_D3D12VA_HWACCEL) +@@ -1018,6 +1018,7 @@ OBJS-$(CONFIG_AV1_D3D12VA_HWACCEL) OBJS-$(CONFIG_AV1_NVDEC_HWACCEL) += nvdec_av1.o OBJS-$(CONFIG_AV1_VAAPI_HWACCEL) += vaapi_av1.o OBJS-$(CONFIG_AV1_VDPAU_HWACCEL) += vdpau_av1.o @@ -14,7 +43,7 @@ Index: FFmpeg/libavcodec/av1dec.c =================================================================== --- FFmpeg.orig/libavcodec/av1dec.c +++ FFmpeg/libavcodec/av1dec.c -@@ -540,6 +540,7 @@ static int get_pixel_format(AVCodecConte +@@ -541,6 +541,7 @@ static int get_pixel_format(AVCodecConte CONFIG_AV1_NVDEC_HWACCEL + \ CONFIG_AV1_VAAPI_HWACCEL + \ CONFIG_AV1_VDPAU_HWACCEL + \ @@ -22,7 +51,7 @@ Index: FFmpeg/libavcodec/av1dec.c CONFIG_AV1_VULKAN_HWACCEL) enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts; -@@ -567,6 +568,9 @@ static int get_pixel_format(AVCodecConte +@@ -568,6 +569,9 @@ static int get_pixel_format(AVCodecConte #if CONFIG_AV1_VDPAU_HWACCEL *fmtp++ = AV_PIX_FMT_VDPAU; #endif @@ -32,7 +61,7 @@ Index: FFmpeg/libavcodec/av1dec.c #if CONFIG_AV1_VULKAN_HWACCEL *fmtp++ = AV_PIX_FMT_VULKAN; #endif -@@ -591,6 +595,9 @@ static int get_pixel_format(AVCodecConte +@@ -592,6 +596,9 @@ static int get_pixel_format(AVCodecConte #if CONFIG_AV1_VDPAU_HWACCEL *fmtp++ = AV_PIX_FMT_VDPAU; #endif @@ -42,7 +71,7 @@ Index: FFmpeg/libavcodec/av1dec.c #if CONFIG_AV1_VULKAN_HWACCEL *fmtp++ = AV_PIX_FMT_VULKAN; #endif -@@ -1479,6 +1486,10 @@ static int av1_receive_frame_internal(AV +@@ -1439,6 +1446,10 @@ static int av1_receive_frame_internal(AV if (raw_tile_group && (s->tile_num == raw_tile_group->tg_end + 1)) { int show_frame = s->raw_frame_header->show_frame; @@ -50,18 +79,19 @@ Index: FFmpeg/libavcodec/av1dec.c + // OBUs have been processed for this current frame. (If this + // frame gets output, we set nb_unit to this value later too.) + s->nb_unit = i + 1; - if (avctx->hwaccel && s->cur_frame.f->buf[0]) { + if (avctx->hwaccel && s->cur_frame.f) { ret = FF_HW_SIMPLE_CALL(avctx, end_frame); if (ret < 0) { -@@ -1500,6 +1511,7 @@ static int av1_receive_frame_internal(AV - goto end; - } - } -+ s->start_unit = s->nb_unit; - raw_tile_group = NULL; +@@ -1449,6 +1460,8 @@ static int av1_receive_frame_internal(AV + + update_reference_list(avctx); + ++ // Set start_unit to indicate the first OBU of the next frame. ++ s->start_unit = s->nb_unit; + raw_tile_group = NULL; s->raw_frame_header = NULL; - if (show_frame) { -@@ -1519,7 +1531,7 @@ end: + +@@ -1478,7 +1491,7 @@ end: s->raw_frame_header = NULL; av_packet_unref(s->pkt); ff_cbs_fragment_reset(&s->current_obu); @@ -70,7 +100,7 @@ Index: FFmpeg/libavcodec/av1dec.c } if (!ret && !frame->buf[0]) ret = AVERROR(EAGAIN); -@@ -1546,7 +1558,7 @@ static int av1_receive_frame(AVCodecCont +@@ -1505,7 +1518,7 @@ static int av1_receive_frame(AVCodecCont return ret; } @@ -79,7 +109,7 @@ Index: FFmpeg/libavcodec/av1dec.c av_log(avctx, AV_LOG_DEBUG, "Total OBUs on this packet: %d.\n", s->current_obu.nb_units); } -@@ -1567,7 +1579,7 @@ static void av1_decode_flush(AVCodecCont +@@ -1526,7 +1539,7 @@ static void av1_decode_flush(AVCodecCont av1_frame_unref(&s->cur_frame); s->operating_point_idc = 0; @@ -88,7 +118,7 @@ Index: FFmpeg/libavcodec/av1dec.c s->raw_frame_header = NULL; s->raw_seq = NULL; s->cll = NULL; -@@ -1633,6 +1645,9 @@ const FFCodec ff_av1_decoder = { +@@ -1594,6 +1607,9 @@ const FFCodec ff_av1_decoder = { #if CONFIG_AV1_VDPAU_HWACCEL HWACCEL_VDPAU(av1), #endif @@ -98,6 +128,20 @@ Index: FFmpeg/libavcodec/av1dec.c #if CONFIG_AV1_VULKAN_HWACCEL HWACCEL_VULKAN(av1), #endif +Index: FFmpeg/libavcodec/av1dec.h +=================================================================== +--- FFmpeg.orig/libavcodec/av1dec.h ++++ FFmpeg/libavcodec/av1dec.h +@@ -114,7 +114,8 @@ typedef struct AV1DecContext { + AV1Frame ref[AV1_NUM_REF_FRAMES]; + AV1Frame cur_frame; + +- int nb_unit; ++ int nb_unit; ///< The index of the next OBU to be processed. ++ int start_unit; ///< The index of the first OBU of the current frame. + + // AVOptions + int operating_point; Index: FFmpeg/libavcodec/hwaccels.h =================================================================== --- FFmpeg.orig/libavcodec/hwaccels.h @@ -110,37 +154,82 @@ Index: FFmpeg/libavcodec/hwaccels.h extern const struct FFHWAccel ff_av1_vulkan_hwaccel; extern const struct FFHWAccel ff_h263_vaapi_hwaccel; extern const struct FFHWAccel ff_h263_videotoolbox_hwaccel; -Index: FFmpeg/libavcodec/vt_internal.h +Index: FFmpeg/libavcodec/videotoolbox.c =================================================================== ---- FFmpeg.orig/libavcodec/vt_internal.h -+++ FFmpeg/libavcodec/vt_internal.h -@@ -56,6 +56,9 @@ int ff_videotoolbox_frame_params(AVCodec - int ff_videotoolbox_buffer_copy(VTContext *vtctx, - const uint8_t *buffer, - uint32_t size); +--- FFmpeg.orig/libavcodec/videotoolbox.c ++++ FFmpeg/libavcodec/videotoolbox.c +@@ -56,6 +56,10 @@ enum { kCMVideoCodecType_HEVC = 'hvc1' } + enum { kCMVideoCodecType_VP9 = 'vp09' }; + #endif + ++#if !HAVE_KCMVIDEOCODECTYPE_AV1 ++enum { kCMVideoCodecType_AV1 = 'av01' }; ++#endif ++ + #define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12 + + typedef struct VTHWFrame { +@@ -92,6 +96,26 @@ int ff_videotoolbox_buffer_copy(VTContex + return 0; + } + +int ff_videotoolbox_buffer_append(VTContext *vtctx, -+ const uint8_t *buffer, -+ uint32_t size); - int ff_videotoolbox_uninit(AVCodecContext *avctx); - int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx, - const uint8_t *buffer, -@@ -64,6 +67,7 @@ int ff_videotoolbox_h264_decode_slice(AV - const uint8_t *buffer, - uint32_t size); - int ff_videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame); -+CFDataRef ff_videotoolbox_av1c_extradata_create(AVCodecContext *avctx); - CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx); - CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx); - CFDataRef ff_videotoolbox_vpcc_extradata_create(AVCodecContext *avctx); ++ const uint8_t *buffer, ++ uint32_t size) ++{ ++ void *tmp; ++ ++ tmp = av_fast_realloc(vtctx->bitstream, ++ &vtctx->allocated_size, ++ vtctx->bitstream_size + size); ++ ++ if (!tmp) ++ return AVERROR(ENOMEM); ++ ++ vtctx->bitstream = tmp; ++ memcpy(vtctx->bitstream + vtctx->bitstream_size, buffer, size); ++ vtctx->bitstream_size += size; ++ ++ return 0; ++} ++ + static int videotoolbox_postproc_frame(void *avctx, AVFrame *frame) + { + int ret; +@@ -840,6 +864,13 @@ static CFDictionaryRef videotoolbox_deco + CFDictionarySetValue(avc_info, CFSTR("vpcC"), data); + break; + #endif ++#if CONFIG_AV1_VIDEOTOOLBOX_HWACCEL ++ case kCMVideoCodecType_AV1 : ++ data = ff_videotoolbox_av1c_extradata_create(avctx); ++ if (data) ++ CFDictionarySetValue(avc_info, CFSTR("av1C"), data); ++ break; ++#endif + default: + break; + } +@@ -905,6 +936,9 @@ static int videotoolbox_start(AVCodecCon + case AV_CODEC_ID_VP9 : + videotoolbox->cm_codec_type = kCMVideoCodecType_VP9; + break; ++ case AV_CODEC_ID_AV1 : ++ videotoolbox->cm_codec_type = kCMVideoCodecType_AV1; ++ break; + default : + break; + } Index: FFmpeg/libavcodec/videotoolbox_av1.c =================================================================== --- /dev/null +++ FFmpeg/libavcodec/videotoolbox_av1.c -@@ -0,0 +1,104 @@ +@@ -0,0 +1,105 @@ +/* + * Videotoolbox hardware acceleration for AV1 + * Copyright (c) 2023 Jan Ekström + * Copyright (c) 2024 Ruslan Chernenko ++ * Copyright (c) 2024 Martin Storsjö + * + * This file is part of FFmpeg. + * @@ -241,112 +330,25 @@ Index: FFmpeg/libavcodec/videotoolbox_av1.c + .uninit = ff_videotoolbox_uninit, + .priv_data_size = sizeof(VTContext), +}; -Index: FFmpeg/libavcodec/av1dec.h +Index: FFmpeg/libavcodec/vt_internal.h =================================================================== ---- FFmpeg.orig/libavcodec/av1dec.h -+++ FFmpeg/libavcodec/av1dec.h -@@ -108,7 +108,8 @@ typedef struct AV1DecContext { - AV1Frame ref[AV1_NUM_REF_FRAMES]; - AV1Frame cur_frame; - -- int nb_unit; -+ int nb_unit; ///< The index of the next OBU to be processed. -+ int start_unit; ///< The index of the first OBU of the current frame. - - // AVOptions - int operating_point; -Index: FFmpeg/configure -=================================================================== ---- FFmpeg.orig/configure -+++ FFmpeg/configure -@@ -2463,6 +2463,7 @@ TYPES_LIST=" - kCMVideoCodecType_HEVC - kCMVideoCodecType_HEVCWithAlpha - kCMVideoCodecType_VP9 -+ kCMVideoCodecType_AV1 - kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange - kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange - kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange -@@ -3159,6 +3160,8 @@ av1_vaapi_hwaccel_deps="vaapi VADecPictu - av1_vaapi_hwaccel_select="av1_decoder" - av1_vdpau_hwaccel_deps="vdpau VdpPictureInfoAV1" - av1_vdpau_hwaccel_select="av1_decoder" -+av1_videotoolbox_hwaccel_deps="videotoolbox" -+av1_videotoolbox_hwaccel_select="av1_decoder" - av1_vulkan_hwaccel_deps="vulkan" - av1_vulkan_hwaccel_select="av1_decoder" - h263_vaapi_hwaccel_deps="vaapi" -@@ -6707,6 +6710,7 @@ enabled videotoolbox && { - check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_HEVC "-framework CoreMedia" - check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_HEVCWithAlpha "-framework CoreMedia" - check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_VP9 "-framework CoreMedia" -+ check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_AV1 "-framework CoreMedia" - check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange "-framework CoreVideo" - check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange "-framework CoreVideo" - check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange "-framework CoreVideo" -Index: FFmpeg/libavcodec/videotoolbox.c -=================================================================== ---- FFmpeg.orig/libavcodec/videotoolbox.c -+++ FFmpeg/libavcodec/videotoolbox.c -@@ -55,6 +55,10 @@ enum { kCMVideoCodecType_HEVC = 'hvc1' } - enum { kCMVideoCodecType_VP9 = 'vp09' }; - #endif - -+#if !HAVE_KCMVIDEOCODECTYPE_AV1 -+enum { kCMVideoCodecType_AV1 = 'av01' }; -+#endif -+ - #define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12 - - typedef struct VTHWFrame { -@@ -91,6 +95,26 @@ int ff_videotoolbox_buffer_copy(VTContex - return 0; - } - +--- FFmpeg.orig/libavcodec/vt_internal.h ++++ FFmpeg/libavcodec/vt_internal.h +@@ -56,6 +56,9 @@ int ff_videotoolbox_frame_params(AVCodec + int ff_videotoolbox_buffer_copy(VTContext *vtctx, + const uint8_t *buffer, + uint32_t size); +int ff_videotoolbox_buffer_append(VTContext *vtctx, + const uint8_t *buffer, -+ uint32_t size) -+{ -+ void *tmp; -+ -+ tmp = av_fast_realloc(vtctx->bitstream, -+ &vtctx->allocated_size, -+ vtctx->bitstream_size + size); -+ -+ if (!tmp) -+ return AVERROR(ENOMEM); -+ -+ vtctx->bitstream = tmp; -+ memcpy(vtctx->bitstream + vtctx->bitstream_size, buffer, size); -+ vtctx->bitstream_size += (int)size; -+ -+ return 0; -+} -+ - static int videotoolbox_postproc_frame(void *avctx, AVFrame *frame) - { - int ret; -@@ -839,6 +863,13 @@ static CFDictionaryRef videotoolbox_deco - CFDictionarySetValue(avc_info, CFSTR("vpcC"), data); - break; - #endif -+#if CONFIG_AV1_VIDEOTOOLBOX_HWACCEL -+ case kCMVideoCodecType_AV1 : -+ data = ff_videotoolbox_av1c_extradata_create(avctx); -+ if (data) -+ CFDictionarySetValue(avc_info, CFSTR("av1C"), data); -+ break; -+#endif - default: - break; - } -@@ -904,6 +935,9 @@ static int videotoolbox_start(AVCodecCon - case AV_CODEC_ID_VP9 : - videotoolbox->cm_codec_type = kCMVideoCodecType_VP9; - break; -+ case AV_CODEC_ID_AV1 : -+ videotoolbox->cm_codec_type = kCMVideoCodecType_AV1; -+ break; - default : - break; - } ++ uint32_t size); + int ff_videotoolbox_uninit(AVCodecContext *avctx); + int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, +@@ -64,6 +67,7 @@ int ff_videotoolbox_h264_decode_slice(AV + const uint8_t *buffer, + uint32_t size); + int ff_videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame); ++CFDataRef ff_videotoolbox_av1c_extradata_create(AVCodecContext *avctx); + CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx); + CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx); + CFDataRef ff_videotoolbox_vpcc_extradata_create(AVCodecContext *avctx); diff --git a/debian/patches/0082-fix-ass-incorrect-null-copy.patch b/debian/patches/0077-fix-ass-incorrect-null-copy.patch similarity index 90% rename from debian/patches/0082-fix-ass-incorrect-null-copy.patch rename to debian/patches/0077-fix-ass-incorrect-null-copy.patch index 8268f816a..a7f3894af 100644 --- a/debian/patches/0082-fix-ass-incorrect-null-copy.patch +++ b/debian/patches/0077-fix-ass-incorrect-null-copy.patch @@ -2,7 +2,7 @@ Index: FFmpeg/libavformat/assenc.c =================================================================== --- FFmpeg.orig/libavformat/assenc.c +++ FFmpeg/libavformat/assenc.c -@@ -67,7 +67,8 @@ static int write_header(AVFormatContext +@@ -68,7 +68,8 @@ static int write_header(AVFormatContext ass->trailer = trailer; } diff --git a/debian/patches/0084-fix-a-race-condition-in-vaapi-csc-to-yuv420p.patch b/debian/patches/0078-fix-a-race-condition-in-vaapi-csc-to-yuv420p.patch similarity index 93% rename from debian/patches/0084-fix-a-race-condition-in-vaapi-csc-to-yuv420p.patch rename to debian/patches/0078-fix-a-race-condition-in-vaapi-csc-to-yuv420p.patch index 6d2b57f4e..a64dd3341 100644 --- a/debian/patches/0084-fix-a-race-condition-in-vaapi-csc-to-yuv420p.patch +++ b/debian/patches/0078-fix-a-race-condition-in-vaapi-csc-to-yuv420p.patch @@ -35,7 +35,7 @@ Index: FFmpeg/libavutil/hwcontext_vaapi.c return AVERROR(ENOSYS); } -@@ -446,6 +453,7 @@ static int vaapi_device_init(AVHWDeviceC +@@ -438,6 +445,7 @@ static int vaapi_device_init(AVHWDeviceC av_log(hwdev, AV_LOG_DEBUG, "Format %#x -> %s.\n", fourcc, av_get_pix_fmt_name(pix_fmt)); ctx->formats[ctx->nb_formats].pix_fmt = pix_fmt; @@ -43,7 +43,7 @@ Index: FFmpeg/libavutil/hwcontext_vaapi.c ctx->formats[ctx->nb_formats].image_format = image_list[i]; ++ctx->nb_formats; } -@@ -1022,12 +1030,6 @@ static int vaapi_map_to_memory(AVHWFrame +@@ -1014,12 +1022,6 @@ static int vaapi_map_to_memory(AVHWFrame { int err; diff --git a/debian/patches/0085-add-first-vframe-only-to-ffprobe.patch b/debian/patches/0079-add-first-vframe-only-to-ffprobe.patch similarity index 91% rename from debian/patches/0085-add-first-vframe-only-to-ffprobe.patch rename to debian/patches/0079-add-first-vframe-only-to-ffprobe.patch index e343f340a..9425c4a84 100644 --- a/debian/patches/0085-add-first-vframe-only-to-ffprobe.patch +++ b/debian/patches/0079-add-first-vframe-only-to-ffprobe.patch @@ -2,7 +2,7 @@ Index: FFmpeg/fftools/ffprobe.c =================================================================== --- FFmpeg.orig/fftools/ffprobe.c +++ FFmpeg/fftools/ffprobe.c -@@ -146,6 +146,8 @@ static int show_private_data +@@ -147,6 +147,8 @@ static int show_private_data #define SHOW_OPTIONAL_FIELDS_ALWAYS 1 static int show_optional_fields = SHOW_OPTIONAL_FIELDS_AUTO; @@ -11,7 +11,7 @@ Index: FFmpeg/fftools/ffprobe.c static char *output_format; static char *stream_specifier; static char *show_data_hash; -@@ -3086,9 +3088,10 @@ static int read_interval_packets(WriterC +@@ -3108,9 +3110,10 @@ static int read_interval_packets(WriterC AVFormatContext *fmt_ctx = ifile->fmt_ctx; AVPacket *pkt = NULL; AVFrame *frame = NULL; @@ -23,7 +23,7 @@ Index: FFmpeg/fftools/ffprobe.c av_log(NULL, AV_LOG_VERBOSE, "Processing read interval "); log_read_interval(interval, NULL, AV_LOG_VERBOSE); -@@ -3127,12 +3130,51 @@ static int read_interval_packets(WriterC +@@ -3149,12 +3152,51 @@ static int read_interval_packets(WriterC ret = AVERROR(ENOMEM); goto end; } @@ -76,7 +76,7 @@ Index: FFmpeg/fftools/ffprobe.c } if (selected_streams[pkt->stream_index]) { AVRational tb = ifile->streams[pkt->stream_index].st->time_base; -@@ -3159,6 +3201,12 @@ static int read_interval_packets(WriterC +@@ -3181,6 +3223,12 @@ static int read_interval_packets(WriterC } frame_count++; @@ -89,7 +89,7 @@ Index: FFmpeg/fftools/ffprobe.c if (do_read_packets) { if (do_show_packets) show_packet(w, ifile, pkt, i++); -@@ -3179,6 +3227,16 @@ static int read_interval_packets(WriterC +@@ -3201,6 +3249,16 @@ static int read_interval_packets(WriterC while (process_frame(w, ifile, frame, pkt, &packet_new) > 0); } @@ -106,7 +106,7 @@ Index: FFmpeg/fftools/ffprobe.c } av_packet_unref(pkt); } -@@ -3196,6 +3254,9 @@ static int read_interval_packets(WriterC +@@ -3218,6 +3276,9 @@ static int read_interval_packets(WriterC end: av_frame_free(&frame); av_packet_free(&pkt); @@ -116,7 +116,7 @@ Index: FFmpeg/fftools/ffprobe.c if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Could not read packets in interval "); log_read_interval(interval, NULL, AV_LOG_ERROR); -@@ -4587,6 +4648,7 @@ static const OptionDef real_options[] = +@@ -4609,6 +4670,7 @@ static const OptionDef real_options[] = { "print_filename", OPT_TYPE_FUNC, OPT_FUNC_ARG, {.func_arg = opt_print_filename}, "override the printed input filename", "print_file"}, { "find_stream_info", OPT_TYPE_BOOL, OPT_INPUT | OPT_EXPERT, { &find_stream_info }, "read and decode the streams to fill missing information with heuristics" }, diff --git a/debian/patches/0080-fix-auto-inserting-sw-color-conv-filters-between-hw-fmts.patch b/debian/patches/0080-fix-auto-inserting-sw-color-conv-filters-between-hw-fmts.patch new file mode 100644 index 000000000..a62aa7a19 --- /dev/null +++ b/debian/patches/0080-fix-auto-inserting-sw-color-conv-filters-between-hw-fmts.patch @@ -0,0 +1,28 @@ +Index: FFmpeg/fftools/ffmpeg_filter.c +=================================================================== +--- FFmpeg.orig/fftools/ffmpeg_filter.c ++++ FFmpeg/fftools/ffmpeg_filter.c +@@ -1543,8 +1543,21 @@ static int configure_output_video_filter + ofp->format != AV_PIX_FMT_NONE || !ofp->formats); + av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); + choose_pix_fmts(ofp, &bprint); +- choose_color_spaces(ofp, &bprint); +- choose_color_ranges(ofp, &bprint); ++ /* SW filter cannot handle color conversions between HW pixel formats. */ ++ { ++ int bprint_color_options = 1; ++ if (ofp->format != AV_PIX_FMT_NONE) { ++ const AVPixFmtDescriptor *ofp_fmt_desc; ++ ++ ofp_fmt_desc = av_pix_fmt_desc_get(ofp->format); ++ if (ofp_fmt_desc->flags & AV_PIX_FMT_FLAG_HWACCEL) ++ bprint_color_options = 0; ++ } ++ if (bprint_color_options) { ++ choose_color_spaces(ofp, &bprint); ++ choose_color_ranges(ofp, &bprint); ++ } ++ } + if (!av_bprint_is_complete(&bprint)) + return AVERROR(ENOMEM); + diff --git a/debian/patches/0081-fix-dummy-hw-frame-missing-hw-frames-ctx.patch b/debian/patches/0081-fix-dummy-hw-frame-missing-hw-frames-ctx.patch new file mode 100644 index 000000000..fa7591fb4 --- /dev/null +++ b/debian/patches/0081-fix-dummy-hw-frame-missing-hw-frames-ctx.patch @@ -0,0 +1,26 @@ +Index: FFmpeg/fftools/ffmpeg_filter.c +=================================================================== +--- FFmpeg.orig/fftools/ffmpeg_filter.c ++++ FFmpeg/fftools/ffmpeg_filter.c +@@ -2384,10 +2384,21 @@ static int close_output(OutputFilterPriv + if (!fgt->got_frame) { + AVFrame *frame = fgt->frame; + FrameData *fd; ++ const AVPixFmtDescriptor *ofp_fmt_desc; + + frame->time_base = ofp->tb_out; + frame->format = ofp->format; + ++ ofp_fmt_desc = av_pix_fmt_desc_get(ofp->format); ++ // a dummy frame with HW pixel format requires a valid hw_frames_ctx ++ if (ofp_fmt_desc->flags & AV_PIX_FMT_FLAG_HWACCEL) { ++ AVFilterContext *sink = ofp->filter; ++ AVBufferRef *hwfc = av_buffersink_get_hw_frames_ctx(sink); ++ ret = av_buffer_replace(&frame->hw_frames_ctx, hwfc); ++ if (ret < 0) ++ return ret; ++ } ++ + frame->width = ofp->width; + frame->height = ofp->height; + frame->sample_aspect_ratio = ofp->sample_aspect_ratio; diff --git a/debian/patches/0082-remove-el-when-stripping-dovi-metadata.patch b/debian/patches/0082-remove-el-when-stripping-dovi-metadata.patch new file mode 100644 index 000000000..5cf9dfd02 --- /dev/null +++ b/debian/patches/0082-remove-el-when-stripping-dovi-metadata.patch @@ -0,0 +1,24 @@ +Index: FFmpeg/libavcodec/bsf/dovi_rpu.c +=================================================================== +--- FFmpeg.orig/libavcodec/bsf/dovi_rpu.c ++++ FFmpeg/libavcodec/bsf/dovi_rpu.c +@@ -84,7 +84,8 @@ static int dovi_rpu_update_fragment_hevc + uint8_t *rpu = NULL; + int rpu_size, ret; + +- if (!nal || nal->type != HEVC_NAL_UNSPEC62) ++ // HEVC_NAL_UNSPEC62 is Dolby Vision PRU and HEVC_NAL_UNSPEC63 is Dolby Vision EL ++ if (!nal || (nal->type != HEVC_NAL_UNSPEC62 && nal->type != HEVC_NAL_UNSPEC63)) + return 0; + + if (s->strip) { +@@ -92,6 +93,9 @@ static int dovi_rpu_update_fragment_hevc + return 0; + } + ++ if (nal->type == HEVC_NAL_UNSPEC63) ++ return 0; ++ + ret = update_rpu(bsf, pkt, 0, nal->data + 2, nal->data_size - 2, &rpu, &rpu_size); + if (ret < 0) + return ret; diff --git a/debian/patches/0083-default-to-input-timebase-for-streamcopy.patch b/debian/patches/0083-default-to-input-timebase-for-streamcopy.patch deleted file mode 100644 index 0ab91e4fb..000000000 --- a/debian/patches/0083-default-to-input-timebase-for-streamcopy.patch +++ /dev/null @@ -1,48 +0,0 @@ -Index: FFmpeg/fftools/ffmpeg_mux_init.c -=================================================================== ---- FFmpeg.orig/fftools/ffmpeg_mux_init.c -+++ FFmpeg/fftools/ffmpeg_mux_init.c -@@ -962,17 +962,12 @@ static int streamcopy_init(const Muxer * - else - ost->st->avg_frame_rate = ist->st->avg_frame_rate; - -- ret = avformat_transfer_internal_stream_timing_info(mux->fc->oformat, -- ost->st, ist->st, copy_tb); -- if (ret < 0) -- goto fail; -- - // copy timebase while removing common factors - if (ost->st->time_base.num <= 0 || ost->st->time_base.den <= 0) { - if (fr.num) - ost->st->time_base = av_inv_q(fr); - else -- ost->st->time_base = av_add_q(av_stream_get_codec_timebase(ost->st), (AVRational){0, 1}); -+ ost->st->time_base = av_add_q(ist->st->time_base, (AVRational){0, 1}); - } - - if (!ms->copy_prior_start) { -Index: FFmpeg/tests/fate/ffmpeg.mak -=================================================================== ---- FFmpeg.orig/tests/fate/ffmpeg.mak -+++ FFmpeg/tests/fate/ffmpeg.mak -@@ -144,7 +144,7 @@ fate-copy-trac236: CMD = transcode mov $ - - FATE_STREAMCOPY-$(call TRANSCODE, RAWVIDEO MPEG2VIDEO, MXF, MPEGTS_DEMUXER MPEGVIDEO_PARSER MPEGAUDIO_PARSER MP2_DECODER ARESAMPLE_FILTER PCM_S16LE_DECODER) += fate-copy-trac4914 - fate-copy-trac4914: CMD = transcode mpegts $(TARGET_SAMPLES)/mpeg2/xdcam8mp2-1s_small.ts\ -- mxf "-c:a pcm_s16le -af aresample -c:v copy" -+ mxf "-c:a pcm_s16le -af aresample -c:v copy -time_base 1001/30000" - - FATE_STREAMCOPY-$(call TRANSCODE, RAWVIDEO MPEG2VIDEO, AVI, MPEGTS_DEMUXER MPEGVIDEO_PARSER MPEGAUDIO_PARSER EXTRACT_EXTRADATA_BSF MP2_DECODER ARESAMPLE_FILTER) += fate-copy-trac4914-avi - fate-copy-trac4914-avi: CMD = transcode mpegts $(TARGET_SAMPLES)/mpeg2/xdcam8mp2-1s_small.ts\ -Index: FFmpeg/tests/ref/fate/copy-trac4914-avi -=================================================================== ---- FFmpeg.orig/tests/ref/fate/copy-trac4914-avi -+++ FFmpeg/tests/ref/fate/copy-trac4914-avi -@@ -1,5 +1,5 @@ --26e4202638bc384b82d2b5eb4d33a5f0 *tests/data/fate/copy-trac4914-avi.avi --479494 tests/data/fate/copy-trac4914-avi.avi -+3b6f31b806ef421652a066f239536b0d *tests/data/fate/copy-trac4914-avi.avi -+492046 tests/data/fate/copy-trac4914-avi.avi - #tb 0: 1001/30000 - #media_type 0: video - #codec_id 0: rawvideo diff --git a/debian/patches/0083-fix-missing-allowed-extensions-in-hls-demuxer.patch b/debian/patches/0083-fix-missing-allowed-extensions-in-hls-demuxer.patch new file mode 100644 index 000000000..c6016151e --- /dev/null +++ b/debian/patches/0083-fix-missing-allowed-extensions-in-hls-demuxer.patch @@ -0,0 +1,36 @@ +Index: FFmpeg/libavformat/hls.c +=================================================================== +--- FFmpeg.orig/libavformat/hls.c ++++ FFmpeg/libavformat/hls.c +@@ -746,7 +746,7 @@ static int test_segment(AVFormatContext + + 2*(ff_match_url_ext(seg->url, c->allowed_extensions) > 0); + + if (!matchA) { +- av_log(s, AV_LOG_ERROR, "URL %s is not in allowed_extensions\n", seg->url); ++ av_log(s, AV_LOG_ERROR, "URL %s is not in allowed_extensions, consider updating hls.c and submitting a patch to ffmpeg-devel, if this should be added\n", seg->url); + return AVERROR_INVALIDDATA; + } + +@@ -754,7 +754,8 @@ static int test_segment(AVFormatContext + if (in_fmt->extensions) { + matchF = av_match_ext( seg->url, in_fmt->extensions) + + 2*(ff_match_url_ext(seg->url, in_fmt->extensions) > 0); +- if(av_match_name("mp4", in_fmt->name)) { ++ // Youtube uses aac files with .ts extension ++ if(av_match_name("mp4", in_fmt->name) || av_match_name("aac", in_fmt->name)) { + matchF |= av_match_ext( seg->url, "ts,m2t,m2ts,mts,mpg,m4s,mpeg,mpegts") + + 2*(ff_match_url_ext(seg->url, "ts,m2t,m2ts,mts,mpg,m4s,mpeg,mpegts") > 0); + } +@@ -2628,7 +2629,11 @@ static const AVOption hls_options[] = { + OFFSET(prefer_x_start), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS}, + {"allowed_extensions", "List of file extensions that hls is allowed to access", + OFFSET(allowed_extensions), AV_OPT_TYPE_STRING, +- {.str = "3gp,aac,avi,ac3,eac3,flac,mkv,m3u8,m4a,m4s,m4v,mpg,mov,mp2,mp3,mp4,mpeg,mpegts,ogg,ogv,oga,ts,vob,wav"}, ++ {.str = "3gp,aac,avi,ac3,eac3,flac,mkv,m3u8,m4a,m4s,m4v,mpg,mov,mp2,mp3,mp4,mpeg,mpegts,ogg,ogv,oga,ts,vob,wav" ++ ",cmfv,cmfa" // Ticket11526 www.nicovideo.jp ++ ",ec3" // part of Ticket11435 (Elisa Viihde (Finnish online recording service)) ++ ",fmp4" // https://github.com/yt-dlp/yt-dlp/issues/12700 ++ }, + INT_MIN, INT_MAX, FLAGS}, + {"extension_picky", "Be picky with all extensions matching", + OFFSET(extension_picky), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS}, diff --git a/debian/patches/0084-fix-avcodec-params-when-bsfs-are-enable-by-decoder.patch b/debian/patches/0084-fix-avcodec-params-when-bsfs-are-enable-by-decoder.patch new file mode 100644 index 000000000..3b03b653e --- /dev/null +++ b/debian/patches/0084-fix-avcodec-params-when-bsfs-are-enable-by-decoder.patch @@ -0,0 +1,14 @@ +Index: FFmpeg/libavcodec/decode.c +=================================================================== +--- FFmpeg.orig/libavcodec/decode.c ++++ FFmpeg/libavcodec/decode.c +@@ -207,6 +207,9 @@ static int decode_bsfs_init(AVCodecConte + ret = av_bsf_init(avci->bsf); + if (ret < 0) + goto fail; ++ ret = avcodec_parameters_to_context(avctx, avci->bsf->par_out); ++ if (ret < 0) ++ goto fail; + + return 0; + fail: diff --git a/debian/patches/0085-fix-display-matrix-not-removed-after-autorotation.patch b/debian/patches/0085-fix-display-matrix-not-removed-after-autorotation.patch new file mode 100644 index 000000000..29fbe624a --- /dev/null +++ b/debian/patches/0085-fix-display-matrix-not-removed-after-autorotation.patch @@ -0,0 +1,15 @@ +Index: FFmpeg/fftools/ffmpeg_filter.c +=================================================================== +--- FFmpeg.orig/fftools/ffmpeg_filter.c ++++ FFmpeg/fftools/ffmpeg_filter.c +@@ -1998,6 +1998,10 @@ static int configure_filtergraph(FilterG + if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE) { + sub2video_frame(&ifp->ifilter, tmp, !fgt->graph); + } else { ++ if (ifp->type_src == AVMEDIA_TYPE_VIDEO) { ++ if (ifp->displaymatrix_applied) ++ av_frame_remove_side_data(tmp, AV_FRAME_DATA_DISPLAYMATRIX); ++ } + ret = av_buffersrc_add_frame(ifp->filter, tmp); + } + av_frame_free(&tmp); diff --git a/debian/patches/0086-unbreak-build-with-latest-svtav1-3-0.patch b/debian/patches/0086-unbreak-build-with-latest-svtav1-3-0.patch new file mode 100644 index 000000000..5f393f1ab --- /dev/null +++ b/debian/patches/0086-unbreak-build-with-latest-svtav1-3-0.patch @@ -0,0 +1,16 @@ +Index: FFmpeg/libavcodec/libsvtav1.c +=================================================================== +--- FFmpeg.orig/libavcodec/libsvtav1.c ++++ FFmpeg/libavcodec/libsvtav1.c +@@ -435,7 +435,11 @@ static av_cold int eb_enc_init(AVCodecCo + + svt_enc->eos_flag = EOS_NOT_REACHED; + ++#if SVT_AV1_CHECK_VERSION(3, 0, 0) ++ svt_ret = svt_av1_enc_init_handle(&svt_enc->svt_handle, &svt_enc->enc_params); ++#else + svt_ret = svt_av1_enc_init_handle(&svt_enc->svt_handle, svt_enc, &svt_enc->enc_params); ++#endif + if (svt_ret != EB_ErrorNone) { + return svt_print_error(avctx, svt_ret, "Error initializing encoder handle"); + } diff --git a/debian/patches/0087-backport-fix-for-missing-h264-sei-build-deps.patch b/debian/patches/0087-backport-fix-for-missing-h264-sei-build-deps.patch new file mode 100644 index 000000000..7e3708531 --- /dev/null +++ b/debian/patches/0087-backport-fix-for-missing-h264-sei-build-deps.patch @@ -0,0 +1,13 @@ +Index: FFmpeg/libavcodec/Makefile +=================================================================== +--- FFmpeg.orig/libavcodec/Makefile ++++ FFmpeg/libavcodec/Makefile +@@ -108,7 +108,7 @@ OBJS-$(CONFIG_H264PARSE) + + h2645data.o h2645_parse.o h2645_vui.o + OBJS-$(CONFIG_H264PRED) += h264pred.o + OBJS-$(CONFIG_H264QPEL) += h264qpel.o +-OBJS-$(CONFIG_H264_SEI) += h264_sei.o h2645_sei.o ++OBJS-$(CONFIG_H264_SEI) += h264_sei.o h2645_sei.o aom_film_grain.o + OBJS-$(CONFIG_HEVCPARSE) += h2645data.o h2645_parse.o h2645_vui.o + OBJS-$(CONFIG_HEVC_SEI) += h2645_sei.o aom_film_grain.o \ + dynamic_hdr_vivid.o diff --git a/debian/patches/series b/debian/patches/series index 8fc89ca83..8a85a5447 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -2,7 +2,7 @@ 0002-update-cuda-func-header.patch 0003-add-enhanced-cuda-pixfmt-converter-impl.patch 0004-add-cuda-tonemap-impl.patch -0005-add-amf-refactor-and-10bit-encoding.patch +0005-add-amf-fixes-from-upstream-and-custom-tunings.patch 0006-add-opencl-scaler-and-pixfmt-converter-impl.patch 0007-add-bt2390-eetf-and-code-refactor-to-opencl-tonemap.patch 0008-add-pgs-support-to-opencl-overlay.patch @@ -13,73 +13,75 @@ 0013-add-vendor-id-option-for-d3d11.patch 0014-add-vaapi-hwupload-filter.patch 0015-disable-the-premultiplied-alpha-in-vaapi-overlay.patch -0016-add-fixes-and-hdr2hdr-for-vaapi-tonemap.patch -0017-add-fixes-for-nvdec-exceed-32-surfaces-error.patch -0018-backport-fixes-for-vaapi-from-upstream.patch -0019-backport-fixes-for-qsv-from-upstream.patch -0020-backport-fixes-for-qsv-from-cartwheel.patch -0021-add-fixes-for-qsv-vpp-filters.patch -0022-add-external-frame-support-for-qsv-enc.patch -0023-suppress-overlay-warning-logs.patch -0024-add-fixes-for-hevc-hdr-decoding-in-bsf.patch -0025-add-sub2video-option-to-subtitles-filter.patch -0026-add-alphasrc-source-video-filter.patch -0027-increase-the-default-async-depth-for-vaapi-encode.patch -0028-add-fixes-for-hevc-vaapi-encoding-on-tgl.patch -0029-add-multiple-values-tags-and-webp-support-for-id3v2.patch -0030-remove-fdk-aac-from-nonfree.patch -0031-pass-dovi-sidedata-to-hlsenc-and-mpegtsenc.patch -0032-add-pause-support-for-ffmpeg-cli.patch -0033-enable-gcc-vectorization-and-fix-cpuflags.patch -0034-tune-dxva-align-for-intel-to-avoid-copy-on-qsv.patch -0035-add-10bit-support-for-cuda-overlay.patch -0036-add-hdr-metadata-for-nvenc-hevc-encoder.patch -0037-add-d3d11va-dxva2-hevc-422-444-decoding-on-intel.patch -0038-default-vaapi-scaler-algorithm-to-fast.patch -0039-dont-fail-on-vaapi-to-drm-export-vasync.patch -0040-skip-loading-plugins-on-vpl-runtime.patch -0041-tune-the-default-bf-for-qsv-enc.patch -0042-allow-vaapi-import-drm-prime2-planar-formats.patch -0043-add-vui-info-to-the-seq-header-of-hevc-vaapi-encoder.patch -0044-sync-intel-d3d11va-textures-before-mapping-to-opencl.patch -0045-add-icon-for-windows-version-ffmpeg.patch -0046-fix-libx265-encoded-fmp4-hls-playback-on-safari.patch -0047-add-full-hwa-pipeline-for-rockchip-rk3588-platform.patch -0048-add-format-option-to-vt-scale-filter.patch -0049-backport-fixes-for-videotoolbox-from-upstream.patch -0050-add-vf-overlay-videotoolbox-filter.patch -0051-add-coreimage-based-vf-transpose-vt-filter.patch -0052-add-vf-tonemap-videotoolbox-filter.patch -0053-add-mjpeg-videotoolbox-encoder.patch -0054-add-vt-low-priority-keyframe-decoding.patch -0055-add-dummy-device-derive-to-videotoolbox-hwcontext.patch -0056-add-cuda-transpose-filter-impl.patch -0057-add-flip-feat-to-opencl-transpose-filter.patch -0058-add-customized-surf-align-for-vaapi-encoder.patch -0059-opus-allow-5point1-side-inputs.patch -0060-add-simd-optimized-tonemapx-filter.patch -0061-add-ac4-decoder-for-atsc-3-0.patch -0062-tune-the-default-inter-thread-queue-sizes.patch -0063-add-vendor-id-option-to-vaapi-hwcontext.patch -0064-backport-fixes-for-vulkan-from-upstream.patch -0065-revert-the-broken-vulkan-hwupload-rewrite.patch -0066-use-linear-contiguous-vulkan-images-for-amd-encoder.patch -0067-prefer-vulkan-device-with-higher-api-version.patch -0068-add-pgs-support-to-vulkan-overlay.patch -0069-add-fixes-x265-build-from-upstream.patch -0070-fix-yuv420p-to-p01x-unscaled-conversion.patch -0071-allow-vt-sw-decoder-for-every-codec.patch -0072-add-bwdif-videotoolbox-filter.patch -0073-add-12bit-decoding-on-videotoolbox.patch -0074-fix-the-sub2video-perf-regressions.patch -0075-allow-vpl-qsv-to-init-with-the-legacy-msdk-path.patch -0076-alway-set-videotoolboxenc-pixel-buffer-info.patch -0077-add-remove-dovi-hdr10plus-bsf.patch -0078-fix-atenc-layout-samplerate.patch -0079-videotoolbox-remove-opengl-compatability.patch -0080-use-dynamic-pool-for-vpl-qsv-hwupload.patch -0081-backport-av1-videotoolbox.patch -0082-fix-ass-incorrect-null-copy.patch -0083-default-to-input-timebase-for-streamcopy.patch -0084-fix-a-race-condition-in-vaapi-csc-to-yuv420p.patch -0085-add-first-vframe-only-to-ffprobe.patch +0016-add-fixes-for-nvdec-exceed-32-surfaces-error.patch +0017-backport-fixes-for-vaapi-from-upstream.patch +0018-backport-fixes-for-qsv-from-upstream.patch +0019-backport-fixes-for-qsv-from-cartwheel.patch +0020-add-fixes-for-qsv-vpp-filters.patch +0021-add-external-frame-support-for-qsv-enc.patch +0022-suppress-overlay-warning-logs.patch +0023-add-fixes-for-hevc-hdr-decoding-in-bsf.patch +0024-add-sub2video-option-to-subtitles-filter.patch +0025-add-alphasrc-source-video-filter.patch +0026-increase-the-default-async-depth-for-vaapi-encode.patch +0027-add-fixes-for-hevc-vaapi-encoding-on-tgl.patch +0028-add-multiple-values-tags-and-webp-support-for-id3v2.patch +0029-remove-fdk-aac-from-nonfree.patch +0030-pass-dovi-sidedata-to-hlsenc-and-mpegtsenc.patch +0031-add-pause-support-for-ffmpeg-cli.patch +0032-enable-gcc-vectorization-and-fix-cpuflags.patch +0033-tune-dxva-align-for-intel-to-avoid-copy-on-qsv.patch +0034-add-10bit-support-for-cuda-overlay.patch +0035-add-hdr-metadata-for-nvenc-hevc-encoder.patch +0036-add-d3d11va-dxva2-hevc-422-444-decoding-on-intel.patch +0037-default-vaapi-scaler-algorithm-to-fast.patch +0038-dont-fail-on-vaapi-to-drm-export-vasync.patch +0039-skip-loading-plugins-on-vpl-runtime.patch +0040-tune-the-default-bf-for-qsv-enc.patch +0041-allow-vaapi-import-drm-prime2-planar-formats.patch +0042-add-vui-info-to-the-seq-header-of-hevc-vaapi-encoder.patch +0043-sync-intel-d3d11va-textures-before-mapping-to-opencl.patch +0044-add-icon-for-windows-version-ffmpeg.patch +0045-fix-libx265-encoded-fmp4-hls-playback-on-safari.patch +0046-add-full-hwa-pipeline-for-rockchip-rk3588-platform.patch +0047-add-format-option-to-vt-scale-filter.patch +0048-add-vf-overlay-videotoolbox-filter.patch +0049-add-coreimage-based-vf-transpose-vt-filter.patch +0050-add-vf-tonemap-videotoolbox-filter.patch +0051-add-mjpeg-videotoolbox-encoder.patch +0052-add-vt-low-priority-keyframe-decoding.patch +0053-add-dummy-device-derive-to-videotoolbox-hwcontext.patch +0054-add-cuda-transpose-filter-impl.patch +0055-add-flip-feat-to-opencl-transpose-filter.patch +0056-opus-allow-5point1-side-inputs.patch +0057-add-simd-optimized-tonemapx-filter.patch +0058-add-ac4-decoder-for-atsc-3-0.patch +0059-tune-the-default-inter-thread-queue-sizes.patch +0060-backport-fixes-for-vulkan-from-upstream.patch +0061-revert-the-broken-vulkan-hwupload-rewrite.patch +0062-use-linear-contiguous-vulkan-images-for-amd-encoder.patch +0063-prefer-vulkan-device-with-higher-api-version.patch +0064-add-pgs-support-to-vulkan-overlay.patch +0065-fix-yuv420p-to-p01x-unscaled-conversion.patch +0066-allow-vt-sw-decoder-for-every-codec.patch +0067-add-bwdif-videotoolbox-filter.patch +0068-add-12bit-decoding-on-videotoolbox.patch +0069-fix-the-sub2video-perf-regressions.patch +0070-allow-vpl-qsv-to-init-with-the-legacy-msdk-path.patch +0071-alway-set-videotoolboxenc-pixel-buffer-info.patch +0072-add-remove-dovi-hdr10plus-bsf.patch +0073-fix-atenc-layout-samplerate.patch +0074-videotoolbox-remove-opengl-compatability.patch +0075-use-dynamic-pool-for-vpl-qsv-hwupload.patch +0076-backport-av1-videotoolbox.patch +0077-fix-ass-incorrect-null-copy.patch +0078-fix-a-race-condition-in-vaapi-csc-to-yuv420p.patch +0079-add-first-vframe-only-to-ffprobe.patch +0080-fix-auto-inserting-sw-color-conv-filters-between-hw-fmts.patch +0081-fix-dummy-hw-frame-missing-hw-frames-ctx.patch +0082-remove-el-when-stripping-dovi-metadata.patch +0083-fix-missing-allowed-extensions-in-hls-demuxer.patch +0084-fix-avcodec-params-when-bsfs-are-enable-by-decoder.patch +0085-fix-display-matrix-not-removed-after-autorotation.patch +0086-unbreak-build-with-latest-svtav1-3-0.patch +0087-backport-fix-for-missing-h264-sei-build-deps.patch