[FFmpeg-devel] [PATCH 1/3] libavcodec/vaapi_encode: Change the way to call async to increase performance
Fix: #7706. After commit 5fdcf85bbffe7451c2, vaapi encoder's performance decrease. The reason is that vaRenderPicture() and vaSyncSurface() are called at the same time (vaRenderPicture() always followed by a vaSyncSurface()). When we encode stream with B frames, we need buffer to reorder frames, so we can send serveral frames to HW at once to increase performance. Now I changed them to be called in a asynchronous way, which will make better use of hardware. 1080p transcoding increases about 17% fps on my environment. Signed-off-by: Wenbin Chen --- libavcodec/vaapi_encode.c | 41 --- libavcodec/vaapi_encode.h | 3 +++ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index ec054ae701..5927849233 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -951,8 +951,10 @@ static int vaapi_encode_pick_next(AVCodecContext *avctx, if (!pic && ctx->end_of_stream) { --b_counter; pic = ctx->pic_end; -if (pic->encode_issued) +if (pic->encode_complete) return AVERROR_EOF; +else if (pic->encode_issued) +return AVERROR(EAGAIN); } if (!pic) { @@ -1177,20 +1179,31 @@ int ff_vaapi_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) return AVERROR(EAGAIN); } -pic = NULL; -err = vaapi_encode_pick_next(avctx, &pic); -if (err < 0) -return err; -av_assert0(pic); +while (av_fifo_size(ctx->encode_fifo) <= MAX_PICTURE_REFERENCES * sizeof(VAAPIEncodePicture *)) { +pic = NULL; +err = vaapi_encode_pick_next(avctx, &pic); +if (err < 0) +break; +av_assert0(pic); -pic->encode_order = ctx->encode_order++; +pic->encode_order = ctx->encode_order + +(av_fifo_size(ctx->encode_fifo) / sizeof(VAAPIEncodePicture *)); -err = vaapi_encode_issue(avctx, pic); -if (err < 0) { -av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err); -return err; +err = vaapi_encode_issue(avctx, pic); +if (err < 0) { +av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err); +return err; +} + +av_fifo_generic_write(ctx->encode_fifo, &pic, sizeof(pic), NULL); } +if (!av_fifo_size(ctx->encode_fifo)) +return err; + +av_fifo_generic_read(ctx->encode_fifo, &pic, sizeof(pic), NULL); +ctx->encode_order = pic->encode_order + 1; + err = vaapi_encode_output(avctx, pic, pkt); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Output failed: %d.\n", err); @@ -2520,6 +2533,11 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) } } +ctx->encode_fifo = av_fifo_alloc((MAX_PICTURE_REFERENCES + 1) * + sizeof(VAAPIEncodePicture *)); +if (!ctx->encode_fifo) +return AVERROR(ENOMEM); + return 0; fail: @@ -2552,6 +2570,7 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx) av_freep(&ctx->codec_sequence_params); av_freep(&ctx->codec_picture_params); +av_fifo_freep(&ctx->encode_fifo); av_buffer_unref(&ctx->recon_frames_ref); av_buffer_unref(&ctx->input_frames_ref); diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index b41604a883..89fe8de466 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -29,6 +29,7 @@ #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_vaapi.h" +#include "libavutil/fifo.h" #include "avcodec.h" #include "hwconfig.h" @@ -345,6 +346,8 @@ typedef struct VAAPIEncodeContext { int roi_warned; AVFrame *frame; + +AVFifoBuffer *encode_fifo; } VAAPIEncodeContext; enum { -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 2/3] libavcodec/vaapi_encode: Add new API adaption to vaapi_encode
Add vaSyncBuffer to VAAPI encoder. Old version API vaSyncSurface wait surface to complete. When surface is used for multiple operation, it wait all operation to finish. vaSyncBuffer only wait one channel to finish. Add wait param to vaapi_encode_wait() to prepare for the async_depth option. "wait=1" means wait until operation ready. "wait=0" means query operation's status. If ready return 0, if still in progress return EAGAIN. Signed-off-by: Wenbin Chen --- libavcodec/vaapi_encode.c | 47 +-- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 5927849233..db0ae136a1 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -134,7 +134,8 @@ static int vaapi_encode_make_misc_param_buffer(AVCodecContext *avctx, } static int vaapi_encode_wait(AVCodecContext *avctx, - VAAPIEncodePicture *pic) + VAAPIEncodePicture *pic, + uint8_t wait) { VAAPIEncodeContext *ctx = avctx->priv_data; VAStatus vas; @@ -150,11 +151,43 @@ static int vaapi_encode_wait(AVCodecContext *avctx, "(input surface %#x).\n", pic->display_order, pic->encode_order, pic->input_surface); -vas = vaSyncSurface(ctx->hwctx->display, pic->input_surface); -if (vas != VA_STATUS_SUCCESS) { -av_log(avctx, AV_LOG_ERROR, "Failed to sync to picture completion: " - "%d (%s).\n", vas, vaErrorStr(vas)); +#if VA_CHECK_VERSION(1, 9, 0) +// Try vaSyncBuffer. +vas = vaSyncBuffer(ctx->hwctx->display, + pic->output_buffer, + wait ? VA_TIMEOUT_INFINITE : 0); +if (vas == VA_STATUS_ERROR_TIMEDOUT) { +return AVERROR(EAGAIN); +} else if (vas != VA_STATUS_SUCCESS && vas != VA_STATUS_ERROR_UNIMPLEMENTED) { +av_log(avctx, AV_LOG_ERROR, "Failed to sync to output buffer completion: " +"%d (%s).\n", vas, vaErrorStr(vas)); return AVERROR(EIO); +} else if (vas == VA_STATUS_ERROR_UNIMPLEMENTED) +// If vaSyncBuffer is not implemented, try old version API. +#endif +{ +if (!wait) { +VASurfaceStatus surface_status; +vas = vaQuerySurfaceStatus(ctx->hwctx->display, +pic->input_surface, +&surface_status); +if (vas == VA_STATUS_SUCCESS && +surface_status != VASurfaceReady && +surface_status != VASurfaceSkipped) { +return AVERROR(EAGAIN); +} else if (vas != VA_STATUS_SUCCESS) { +av_log(avctx, AV_LOG_ERROR, "Failed to query surface status: " +"%d (%s).\n", vas, vaErrorStr(vas)); +return AVERROR(EIO); +} +} else { +vas = vaSyncSurface(ctx->hwctx->display, pic->input_surface); +if (vas != VA_STATUS_SUCCESS) { +av_log(avctx, AV_LOG_ERROR, "Failed to sync to picture completion: " +"%d (%s).\n", vas, vaErrorStr(vas)); +return AVERROR(EIO); +} +} } // Input is definitely finished with now. @@ -633,7 +666,7 @@ static int vaapi_encode_output(AVCodecContext *avctx, uint8_t *ptr; int err; -err = vaapi_encode_wait(avctx, pic); +err = vaapi_encode_wait(avctx, pic, 1); if (err < 0) return err; @@ -695,7 +728,7 @@ fail: static int vaapi_encode_discard(AVCodecContext *avctx, VAAPIEncodePicture *pic) { -vaapi_encode_wait(avctx, pic); +vaapi_encode_wait(avctx, pic, 1); if (pic->output_buffer_ref) { av_log(avctx, AV_LOG_DEBUG, "Discard output for pic " -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 3/3] libavcodec/vaapi_encode: Add async_depth to vaapi_encoder to increase performance
Add async_depth to increase encoder's performance. Reuse encode_fifo as async buffer. Encoder puts all reordered frame to HW and then check fifo size. If fifo < async_depth and the top frame is not ready, it will return AVERROR(EAGAIN) to require more frames. 1080p transcoding (no B frames) with -async_depth=4 can increase 20% performance on my environment. The async increases performance but also introduces frame delay. Signed-off-by: Wenbin Chen --- libavcodec/vaapi_encode.c | 20 +++- libavcodec/vaapi_encode.h | 12 ++-- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index db0ae136a1..616fb7c089 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1158,7 +1158,8 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) if (ctx->input_order == ctx->decode_delay) ctx->dts_pts_diff = pic->pts - ctx->first_pts; if (ctx->output_delay > 0) -ctx->ts_ring[ctx->input_order % (3 * ctx->output_delay)] = pic->pts; +ctx->ts_ring[ctx->input_order % +(3 * ctx->output_delay + ctx->async_depth)] = pic->pts; pic->display_order = ctx->input_order; ++ctx->input_order; @@ -1212,7 +1213,8 @@ int ff_vaapi_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) return AVERROR(EAGAIN); } -while (av_fifo_size(ctx->encode_fifo) <= MAX_PICTURE_REFERENCES * sizeof(VAAPIEncodePicture *)) { +while (av_fifo_size(ctx->encode_fifo) < +MAX_ASYNC_DEPTH * sizeof(VAAPIEncodePicture *)) { pic = NULL; err = vaapi_encode_pick_next(avctx, &pic); if (err < 0) @@ -1234,6 +1236,14 @@ int ff_vaapi_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) if (!av_fifo_size(ctx->encode_fifo)) return err; +if (av_fifo_size(ctx->encode_fifo) < ctx->async_depth * sizeof(VAAPIEncodePicture *) && +!ctx->end_of_stream) { +av_fifo_generic_peek(ctx->encode_fifo, &pic, sizeof(pic), NULL); +err = vaapi_encode_wait(avctx, pic, 0); +if (err < 0) +return err; +} + av_fifo_generic_read(ctx->encode_fifo, &pic, sizeof(pic), NULL); ctx->encode_order = pic->encode_order + 1; @@ -1252,7 +1262,7 @@ int ff_vaapi_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) pkt->dts = ctx->ts_ring[pic->encode_order] - ctx->dts_pts_diff; } else { pkt->dts = ctx->ts_ring[(pic->encode_order - ctx->decode_delay) % -(3 * ctx->output_delay)]; +(3 * ctx->output_delay + ctx->async_depth)]; } av_log(avctx, AV_LOG_DEBUG, "Output packet: pts %"PRId64" dts %"PRId64".\n", pkt->pts, pkt->dts); @@ -2566,8 +2576,8 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) } } -ctx->encode_fifo = av_fifo_alloc((MAX_PICTURE_REFERENCES + 1) * - sizeof(VAAPIEncodePicture *)); +ctx->encode_fifo = av_fifo_alloc(MAX_ASYNC_DEPTH * + sizeof(VAAPIEncodePicture *)); if (!ctx->encode_fifo) return AVERROR(ENOMEM); diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index 89fe8de466..1bf5d7c337 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -48,6 +48,7 @@ enum { MAX_TILE_ROWS = 22, // A.4.1: table A.6 allows at most 20 tile columns for any level. MAX_TILE_COLS = 20, +MAX_ASYNC_DEPTH= 64, }; extern const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[]; @@ -298,7 +299,8 @@ typedef struct VAAPIEncodeContext { // Timestamp handling. int64_t first_pts; int64_t dts_pts_diff; -int64_t ts_ring[MAX_REORDER_DELAY * 3]; +int64_t ts_ring[MAX_REORDER_DELAY * 3 + +MAX_ASYNC_DEPTH]; // Slice structure. int slice_block_rows; @@ -348,6 +350,8 @@ typedef struct VAAPIEncodeContext { AVFrame *frame; AVFifoBuffer *encode_fifo; + +int async_depth; } VAAPIEncodeContext; enum { @@ -458,7 +462,11 @@ int ff_vaapi_encode_close(AVCodecContext *avctx); { "b_depth", \ "Maximum B-frame reference depth", \ OFFSET(common.desired_b_depth), AV_OPT_TYPE_INT, \ - { .i64 = 1 }, 1, INT_MAX, FLAGS } + { .i64 = 1 }, 1, INT_MAX, FLAGS }, \ +{ "async_depth", "Maximum processing parallelism. " \ + "Increase this to improve single channel performance", \ + OFFSET(common.async_depth), AV_OPT_TYPE_INT, \ + {
[FFmpeg-devel] [PATCH 1/4] libavutil/hwcontext_d3d11va: Add nb_surfaces to AVD3D11VAFramesContext
Adding nb_surfaces in AVD3D11VAFramesContext in the end of the structure to support flexible size of this arrays and align to AVDXVA2FramesContext and AVVAAPIFramesContext. Signed-off-by Wenbin Chen --- libavutil/hwcontext_d3d11va.c | 3 +-- libavutil/hwcontext_d3d11va.h | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c index 8ab96bad25..086e7b9daa 100644 --- a/libavutil/hwcontext_d3d11va.c +++ b/libavutil/hwcontext_d3d11va.c @@ -72,7 +72,6 @@ static av_cold void load_functions(void) } typedef struct D3D11VAFramesContext { -int nb_surfaces; int nb_surfaces_used; DXGI_FORMAT format; @@ -287,7 +286,7 @@ static int d3d11va_frames_init(AVHWFramesContext *ctx) hwctx->texture_infos = av_calloc(ctx->initial_pool_size, sizeof(*hwctx->texture_infos)); if (!hwctx->texture_infos) return AVERROR(ENOMEM); -s->nb_surfaces = ctx->initial_pool_size; +hwctx->nb_surfaces = ctx->initial_pool_size; ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(AVD3D11FrameDescriptor), ctx, d3d11va_pool_alloc, NULL); diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h index 77d2d72f1b..b0df470190 100644 --- a/libavutil/hwcontext_d3d11va.h +++ b/libavutil/hwcontext_d3d11va.h @@ -173,6 +173,8 @@ typedef struct AVD3D11VAFramesContext { * This field is ignored/invalid if a user-allocated texture is provided. */ AVD3D11FrameDescriptor *texture_infos; + +int nb_surfaces; } AVD3D11VAFramesContext; #endif /* AVUTIL_HWCONTEXT_D3D11VA_H */ -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 2/4] libavutil/hwcontext_qsv: fix a bug when malloc handle_pairs_internal
This commandline cause core dumped: ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 \ -hwaccel_output_format vaapi -i input.264 \ -vf "hwmap=derive_device=qsv,format=qsv" \ -c:v h264_qsv output.264 reason: We use nb_surfaces to assign surface to handle_pairs_internal but handle_pairs_internal is alloced with the size of init_pool_size. This lead to access to illegal address. Now change it to use nb_surfaces to allocate handle_pairs_internal and the core dumped error is unseen. Also change D3D11VA to use nb_surfaces to align to VAAPI and DXVA2. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_qsv.c | 13 ++--- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index c18747f7eb..5a285fd25b 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -1123,8 +1123,7 @@ static int qsv_frames_derive_to(AVHWFramesContext *dst_ctx, case AV_HWDEVICE_TYPE_VAAPI: { AVVAAPIFramesContext *src_hwctx = src_ctx->hwctx; -s->handle_pairs_internal = av_calloc(src_ctx->initial_pool_size, - sizeof(*s->handle_pairs_internal)); +s->handle_pairs_internal = av_calloc(src_hwctx->nb_surfaces, sizeof(*s->handle_pairs_internal)); if (!s->handle_pairs_internal) return AVERROR(ENOMEM); s->surfaces_internal = av_calloc(src_hwctx->nb_surfaces, @@ -1146,15 +1145,15 @@ static int qsv_frames_derive_to(AVHWFramesContext *dst_ctx, case AV_HWDEVICE_TYPE_D3D11VA: { AVD3D11VAFramesContext *src_hwctx = src_ctx->hwctx; -s->handle_pairs_internal = av_calloc(src_ctx->initial_pool_size, +s->handle_pairs_internal = av_calloc(src_ctx->nb_surfaces, sizeof(*s->handle_pairs_internal)); if (!s->handle_pairs_internal) return AVERROR(ENOMEM); -s->surfaces_internal = av_calloc(src_ctx->initial_pool_size, +s->surfaces_internal = av_calloc(src_ctx->nb_surfaces, sizeof(*s->surfaces_internal)); if (!s->surfaces_internal) return AVERROR(ENOMEM); -for (i = 0; i < src_ctx->initial_pool_size; i++) { +for (i = 0; i < src_ctx->nb_surfaces; i++) { qsv_init_surface(dst_ctx, &s->surfaces_internal[i]); s->handle_pairs_internal[i].first = (mfxMemId)src_hwctx->texture_infos[i].texture; if (src_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) { @@ -1164,7 +1163,7 @@ static int qsv_frames_derive_to(AVHWFramesContext *dst_ctx, } s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i]; } -dst_hwctx->nb_surfaces = src_ctx->initial_pool_size; +dst_hwctx->nb_surfaces = src_ctx->nb_surfaces; if (src_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) { dst_hwctx->frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET; } else { @@ -1177,7 +1176,7 @@ static int qsv_frames_derive_to(AVHWFramesContext *dst_ctx, case AV_HWDEVICE_TYPE_DXVA2: { AVDXVA2FramesContext *src_hwctx = src_ctx->hwctx; -s->handle_pairs_internal = av_calloc(src_ctx->initial_pool_size, +s->handle_pairs_internal = av_calloc(src_ctx->nb_surfaces, sizeof(*s->handle_pairs_internal)); if (!s->handle_pairs_internal) return AVERROR(ENOMEM); -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 3/4] libavutil/hwcontext_qsv: fix a bug for mapping vaapi frame to qsv
From: nyanmisaka The data stored in data[3] in VAAPI AVFrame is VASurfaceID while the data stored in pair->first is the pointer of VASurfaceID, so we need to do cast to make following commandline works: ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 \ -hwaccel_output_format vaapi -i input.264 \ -vf "hwmap=derive_device=qsv,format=qsv" -c:v h264_qsv output.264 Signed-off-by: nyanmisaka Signed-off-by: Wenbin Chen --- libavutil/hwcontext_qsv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 5a285fd25b..8075c27862 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -1219,7 +1219,7 @@ static int qsv_map_to(AVHWFramesContext *dst_ctx, case AV_PIX_FMT_VAAPI: { mfxHDLPair *pair = (mfxHDLPair*)hwctx->surfaces[i].Data.MemId; -if (pair->first == src->data[3]) { +if (*(VASurfaceID*)pair->first == (VASurfaceID)src->data[3]) { index = i; break; } -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 4/4] libavutil/hwcontext_opencl: fix a bug for mapping qsv frame to opencl
From: nyanmisaka mfxHDLPair was added to qsv, so modify qsv->opencl map function as well. Now the following commandline works: ffmpeg -v verbose -init_hw_device vaapi=va:/dev/dri/renderD128 \ -init_hw_device qsv=qs@va -init_hw_device opencl=ocl@va -filter_hw_device ocl \ -hwaccel qsv -hwaccel_output_format qsv -hwaccel_device qs -c:v h264_qsv \ -i input.264 -vf "hwmap=derive_device=opencl,format=opencl,avgblur_opencl, \ hwmap=derive_device=qsv:reverse=1:extra_hw_frames=32,format=qsv" \ -c:v h264_qsv output.264 Signed-off-by: nyanmisaka Signed-off-by: Wenbin Chen --- libavutil/hwcontext_opencl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c index 26a3a24593..4b6e74ff6f 100644 --- a/libavutil/hwcontext_opencl.c +++ b/libavutil/hwcontext_opencl.c @@ -2249,7 +2249,8 @@ static int opencl_map_from_qsv(AVHWFramesContext *dst_fc, AVFrame *dst, #if CONFIG_LIBMFX if (src->format == AV_PIX_FMT_QSV) { mfxFrameSurface1 *mfx_surface = (mfxFrameSurface1*)src->data[3]; -va_surface = *(VASurfaceID*)mfx_surface->Data.MemId; +mfxHDLPair *pair = (mfxHDLPair*)mfx_surface->Data.MemId; +va_surface = *(VASurfaceID*)pair->first; } else #endif if (src->format == AV_PIX_FMT_VAAPI) { -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 1/7] hwcontext_vaapi: Use PRIME_2 memory type for modifiers.
From: Bas Nieuwenhuizen This way we can pass explicit modifiers in. Sometimes the modifier matters for the number of memory planes that libva accepts, in particular when dealing with driver-compressed textures. Furthermore the driver might not actually be able to determine the implicit modifier if all the buffer-passing has used explicit modifier. All these issues should be resolved by passing in the modifier, and for that we switch to using the PRIME_2 memory type. Tested with experimental radeonsi patches for modifiers and kmsgrab. Also tested with radeonsi without the patches to double-check it works without PRIME_2 support. v2: Cache PRIME_2 support to avoid doing two calls every time on libva drivers that do not support it. v3: Remove prime2_vas usage. Signed-off-by: Bas Nieuwenhuizen --- libavutil/hwcontext_vaapi.c | 158 ++-- 1 file changed, 114 insertions(+), 44 deletions(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 83e542876d..75acc851d6 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -79,6 +79,9 @@ typedef struct VAAPIFramesContext { unsigned int rt_format; // Whether vaDeriveImage works. int derive_works; +// Caches whether VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2 is unsupported for +// surface imports. +int prime_2_import_unsupported; } VAAPIFramesContext; typedef struct VAAPIMapping { @@ -1022,32 +1025,17 @@ static void vaapi_unmap_from_drm(AVHWFramesContext *dst_fc, static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, const AVFrame *src, int flags) { +VAAPIFramesContext *src_vafc = src_fc->internal->priv; AVHWFramesContext *dst_fc = (AVHWFramesContext*)dst->hw_frames_ctx->data; AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; const AVDRMFrameDescriptor *desc; const VAAPIFormatDescriptor *format_desc; VASurfaceID surface_id; -VAStatus vas; +VAStatus vas = VA_STATUS_SUCCESS; +int use_prime2; uint32_t va_fourcc; -int err, i, j, k; - -unsigned long buffer_handle; -VASurfaceAttribExternalBuffers buffer_desc; -VASurfaceAttrib attrs[2] = { -{ -.type = VASurfaceAttribMemoryType, -.flags = VA_SURFACE_ATTRIB_SETTABLE, -.value.type= VAGenericValueTypeInteger, -.value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME, -}, -{ -.type = VASurfaceAttribExternalBufferDescriptor, -.flags = VA_SURFACE_ATTRIB_SETTABLE, -.value.type= VAGenericValueTypePointer, -.value.value.p = &buffer_desc, -} -}; +int err, i, j; desc = (AVDRMFrameDescriptor*)src->data[0]; @@ -1083,35 +1071,117 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, format_desc = vaapi_format_from_fourcc(va_fourcc); av_assert0(format_desc); -buffer_handle = desc->objects[0].fd; -buffer_desc.pixel_format = va_fourcc; -buffer_desc.width= src_fc->width; -buffer_desc.height = src_fc->height; -buffer_desc.data_size= desc->objects[0].size; -buffer_desc.buffers = &buffer_handle; -buffer_desc.num_buffers = 1; -buffer_desc.flags= 0; - -k = 0; -for (i = 0; i < desc->nb_layers; i++) { -for (j = 0; j < desc->layers[i].nb_planes; j++) { -buffer_desc.pitches[k] = desc->layers[i].planes[j].pitch; -buffer_desc.offsets[k] = desc->layers[i].planes[j].offset; -++k; +use_prime2 = !src_vafc->prime_2_import_unsupported && + desc->objects[0].format_modifier != DRM_FORMAT_MOD_INVALID; +if (use_prime2) { +VADRMPRIMESurfaceDescriptor prime_desc; +VASurfaceAttrib prime_attrs[2] = { +{ +.type = VASurfaceAttribMemoryType, +.flags = VA_SURFACE_ATTRIB_SETTABLE, +.value.type= VAGenericValueTypeInteger, +.value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, +}, +{ +.type = VASurfaceAttribExternalBufferDescriptor, +.flags = VA_SURFACE_ATTRIB_SETTABLE, +.value.type= VAGenericValueTypePointer, +.value.value.p = &prime_desc, +} +}; +prime_desc.fourcc = va_fourcc; +prime_desc.width = src_fc->width; +prime_desc.height = src_fc->height; +prime_desc.num_objects = desc->nb_objects; +for (i = 0; i < desc->nb_objects; ++i) { +prime_desc.objects[i].fd = desc->objects[i].fd; +prime_desc.objects[i].size = desc->objects[i].size; +prime_desc.objects[i].drm_format_modifier = +desc->objects[i].format_modifier; } -} -buffer_desc.num_planes = k; -if (format_desc->chroma_planes
[FFmpeg-devel] [PATCH 3/7] libavutil/hwcontext_vulkan: Add one_memory flag to make vulkan compatible with vaapi device.
Vaapi can import external surface, but all the planes of the external frames should be in the same drm object. A new flag is introduced and vulkan can choose to allocate planes in one memory according this flag. This flag will be enabled when the vulkan device is derived from vaapi device, so that this change will not affect current vulkan behaviour. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 12 +++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 6041580117..ccf3e58f49 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -100,6 +100,9 @@ typedef struct VulkanDevicePriv { /* Settings */ int use_linear_images; +/* map all planes to one memory */ +int use_one_memory; + /* Nvidia */ int dev_is_nvidia; } VulkanDevicePriv; @@ -1245,6 +1248,11 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, if (opt_d) p->use_linear_images = strtol(opt_d->value, NULL, 10); +opt_d = av_dict_get(opts, "one_memory", NULL, 0); +if (opt_d) +p->use_one_memory = strtol(opt_d->value, NULL, 10); + + hwctx->enabled_dev_extensions = dev_info.ppEnabledExtensionNames; hwctx->nb_enabled_dev_extensions = dev_info.enabledExtensionCount; @@ -1365,8 +1373,10 @@ static int vulkan_device_derive(AVHWDeviceContext *ctx, return AVERROR_EXTERNAL; } -if (strstr(vendor, "Intel")) +if (strstr(vendor, "Intel")) { +av_dict_set_int(&opts, "one_memory", 1, 0); dev_select.vendor_id = 0x8086; +} if (strstr(vendor, "AMD")) dev_select.vendor_id = 0x1002; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 2/7] libavutil/hwcontext_vaapi: Add a new nv12 format map to support vulkan frame
Vulkan will map nv12 to R8 and GR88, so add this map to vaapi to support vulkan frame. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vaapi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 75acc851d6..994b744e4d 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -992,6 +992,7 @@ static const struct { } vaapi_drm_format_map[] = { #ifdef DRM_FORMAT_R8 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88), +DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_GR88), #endif DRM_MAP(NV12, 1, DRM_FORMAT_NV12), #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16) -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 6/7] libavutil/hwcontext_vulkan: fix a sem_wait bug when export drm
sem_sig_val is wrongly assigned to pWaitSemaphoreValues when export drm. Now fix it. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index b857d1a9ed..29ade94b7f 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1718,7 +1718,7 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; -uint64_t sem_sig_val[AV_NUM_DATA_POINTERS]; +uint64_t sem_sig_val[AV_NUM_DATA_POINTERS], sem_wait_val[AV_NUM_DATA_POINTERS]; VkImageMemoryBarrier img_bar[AV_NUM_DATA_POINTERS] = { 0 }; @@ -1738,6 +1738,7 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, VkPipelineStageFlagBits wait_st[AV_NUM_DATA_POINTERS]; for (int i = 0; i < planes; i++) { wait_st[i] = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; +sem_wait_val[i] = frame->sem_value[i]; sem_sig_val[i] = frame->sem_value[i] + 1; } @@ -1756,7 +1757,7 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, new_layout = VK_IMAGE_LAYOUT_GENERAL; new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; dst_qf = VK_QUEUE_FAMILY_EXTERNAL_KHR; -s_timeline_sem_info.pWaitSemaphoreValues = sem_sig_val; +s_timeline_sem_info.pWaitSemaphoreValues = sem_wait_val; s_timeline_sem_info.waitSemaphoreValueCount = planes; s_info.pWaitSemaphores = frame->sem; s_info.pWaitDstStageMask = wait_st; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 4/7] libavutil/hwcontext_vulkan: Allocate vkFrame in one memory
The vaapi can import external frame, but the planes of the external frames should be in the same drm object. I add a new function to allocate vkFrame in one memory and vulkan device will choose a way to allocate memory according to one_memory flag. A new variable is added to AVVKFrame to store the offset of each plane. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 46 +++- libavutil/hwcontext_vulkan.h | 1 + 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index ccf3e58f49..f7878ed9c3 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1600,6 +1600,9 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, FFVulkanFunctions *vk = &p->vkfn; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { { 0 } }; +VkMemoryRequirements memory_requirements = { 0 }; +int mem_size = 0; +int mem_size_list[AV_NUM_DATA_POINTERS] = { 0 }; AVVulkanDeviceContext *hwctx = ctx->hwctx; @@ -1627,6 +1630,23 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, req.memoryRequirements.size = FFALIGN(req.memoryRequirements.size, p->props.properties.limits.minMemoryMapAlignment); +if (p->use_one_memory) { +if (ded_req.prefersDedicatedAllocation | ded_req.requiresDedicatedAllocation) { +av_log(hwfc, AV_LOG_ERROR, "Cannot use dedicated allocation for intel vaapi\n"); +return AVERROR(EINVAL); +} +if (memory_requirements.size == 0) { +memory_requirements = req.memoryRequirements; +} else if (memory_requirements.memoryTypeBits != req.memoryRequirements.memoryTypeBits) { +av_log(hwfc, AV_LOG_ERROR, "the param for each planes are not the same\n"); +return AVERROR(EINVAL); +} + +mem_size_list[i] = req.memoryRequirements.size; +mem_size += mem_size_list[i]; +continue; +} + /* In case the implementation prefers/requires dedicated allocation */ use_ded_mem = ded_req.prefersDedicatedAllocation | ded_req.requiresDedicatedAllocation; @@ -1648,6 +1668,29 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, bind_info[i].memory = f->mem[i]; } +if (p->use_one_memory) { +memory_requirements.size = mem_size; + +/* Allocate memory */ +if ((err = alloc_mem(ctx, &memory_requirements, +f->tiling == VK_IMAGE_TILING_LINEAR ? +VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT : +VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, +(void *)(((uint8_t *)alloc_pnext)), +&f->flags, &f->mem[0]))) +return err; + +f->size[0] = memory_requirements.size; + +for (int i = 0; i < planes; i++) { +bind_info[i].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; +bind_info[i].image = f->img[i]; +bind_info[i].memory = f->mem[0]; +bind_info[i].memoryOffset = i == 0 ? 0 : mem_size_list[i-1]; +f->offset[i] = bind_info[i].memoryOffset; +} +} + /* Bind the allocated memory to the images */ ret = vk->BindImageMemory2(hwctx->act_dev, planes, bind_info); if (ret != VK_SUCCESS) { @@ -2924,7 +2967,8 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, continue; vk->GetImageSubresourceLayout(hwctx->act_dev, f->img[i], &sub, &layout); -drm_desc->layers[i].planes[0].offset = layout.offset; +drm_desc->layers[i].planes[0].offset = p->use_one_memory ? +f->offset[i] : layout.offset; drm_desc->layers[i].planes[0].pitch= layout.rowPitch; } diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h index 9264f70dbf..efb602ef27 100644 --- a/libavutil/hwcontext_vulkan.h +++ b/libavutil/hwcontext_vulkan.h @@ -189,6 +189,7 @@ typedef struct AVVkFrame { */ VkDeviceMemory mem[AV_NUM_DATA_POINTERS]; size_t size[AV_NUM_DATA_POINTERS]; +size_t offset[AV_NUM_DATA_POINTERS]; /** * OR'd flags for all memory allocated -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 5/7] libavutil/hwcontext_vulkan: Add hwupload and hwdownload support when using one_memory flag.
Add hwupload and hwdownload support to vulkan when frames are allocated in one memory Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index f7878ed9c3..b857d1a9ed 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2138,7 +2138,7 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { VkResult ret; -int err, mapped_mem_count = 0; +int err, mapped_mem_count = 0, loop = 0; AVVkFrame *f = (AVVkFrame *)src->data[0]; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); @@ -2167,7 +2167,8 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, dst->width = src->width; dst->height = src->height; -for (int i = 0; i < planes; i++) { +loop = p->use_one_memory ? 1 : planes; +for (int i = 0; i < loop; i++) { ret = vk->MapMemory(hwctx->act_dev, f->mem[i], 0, VK_WHOLE_SIZE, 0, (void **)&dst->data[i]); if (ret != VK_SUCCESS) { @@ -2178,6 +2179,11 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, } mapped_mem_count++; } +if (p->use_one_memory) { +for (int i = 0; i < planes; i++) { +dst->data[i] = dst->data[0] + f->offset[i]; +} +} /* Check if the memory contents matter */ if (((flags & AV_HWFRAME_MAP_READ) || !(flags & AV_HWFRAME_MAP_OVERWRITE)) && -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 7/7] libavutil/hwcontext_vulkan: specify the modifier to create VKImage
When vulkan image exports to drm, the tilling need to be VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT. Now add code to create vulkan image using this format. Now the following command line works: ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format \ vaapi -i input_1080p.264 -vf "hwmap=derive_device=vulkan,format=vulkan, \ scale_vulkan=1920:1080,hwmap=derive_device=vaapi,format=vaapi" -c:v h264_vaapi output.264 Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 76 +--- libavutil/hwcontext_vulkan.h | 5 +++ 2 files changed, 75 insertions(+), 6 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 29ade94b7f..e252c2177e 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1919,6 +1919,7 @@ static void try_export_flags(AVHWFramesContext *hwfc, AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; +const int has_modifiers = hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; VkExternalImageFormatProperties eprops = { .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR, }; @@ -1926,9 +1927,18 @@ static void try_export_flags(AVHWFramesContext *hwfc, .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, .pNext = &eprops, }; +VkPhysicalDeviceImageDrmFormatModifierInfoEXT phy_dev_mod_info = { +.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, +.pNext = NULL, +.pQueueFamilyIndices = p->qfs, +.queueFamilyIndexCount = p->num_qfs, +.sharingMode = p->num_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : + VK_SHARING_MODE_EXCLUSIVE, +}; VkPhysicalDeviceExternalImageFormatInfo enext = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, .handleType = exp, +.pNext = has_modifiers ? &phy_dev_mod_info : NULL, }; VkPhysicalDeviceImageFormatInfo2 pinfo = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, @@ -1940,11 +1950,15 @@ static void try_export_flags(AVHWFramesContext *hwfc, .flags = VK_IMAGE_CREATE_ALIAS_BIT, }; -ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, - &pinfo, &props); -if (ret == VK_SUCCESS) { -*iexp |= exp; -*comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; +for (int i = 0; i < (has_modifiers ? hwctx->modifier_count : 1); i++) { +if (has_modifiers && hwctx->modifier_count) +phy_dev_mod_info.drmFormatModifier = hwctx->modifiers[i]; +ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, +&pinfo, &props); +if (ret == VK_SUCCESS) { +*iexp |= exp; +*comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; +} } } @@ -2007,6 +2021,7 @@ fail: static void vulkan_frames_uninit(AVHWFramesContext *hwfc) { VulkanFramesPriv *fp = hwfc->internal->priv; +AVVulkanFramesContext *hwctx = hwfc->hwctx; free_exec_ctx(hwfc, &fp->conv_ctx); free_exec_ctx(hwfc, &fp->upload_ctx); @@ -2021,11 +2036,60 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) VulkanFramesPriv *fp = hwfc->internal->priv; AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; +const int has_modifiers = !!(p->extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS); /* Default pool flags */ -hwctx->tiling = hwctx->tiling ? hwctx->tiling : p->use_linear_images ? +hwctx->tiling = hwctx->tiling ? hwctx->tiling : has_modifiers ? +VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT : p->use_linear_images ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL; +/* get the supported modifier */ +if (has_modifiers) { +const VkFormat *fmt = av_vkfmt_from_pixfmt(hwfc->sw_format); +FFVulkanFunctions *vk = &p->vkfn; +VkDrmFormatModifierPropertiesEXT mod_props[MAX_VULKAN_MODIFIERS]; + +VkDrmFormatModifierPropertiesListEXT mod_props_list = { +.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT, +.pNext = NULL, +.drmFormatModifierCount = 0, +.pDrmFormatModifierProperties = NULL, +}; +VkFormatProperties2 prop = { +.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, +.pNext = &mod
[FFmpeg-devel] [PATCH 1/3] libavcodec/vaapi_decode: fix the problem that init_pool_size < nb_surface
For vaapi if the init_pool_size is not zero, the pool size is fixed. This means max surfaces is init_pool_size, but when mapping vaapi frame to qsv frame, the init_pool_size < nb_surface. The cause is that vaapi_decode_make_config() config the init_pool_size and it is called twice. The first time is to init frame_context and the second time is to init codec. On the second time the init_pool_size is changed to original value so the init_pool_size is lower than the reall size because pool_size used to initialize frame_context need to plus thread_count and 3 (guarantee 4 base work surfaces). Now add code to make sure init_pool_size is only set once. Now the following commandline works: ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 \ -hwaccel_output_format vaapi -i input.264 \ -vf "hwmap=derive_device=qsv,format=qsv" \ -c:v h264_qsv output.264 Signed-off-by: Wenbin Chen --- libavcodec/vaapi_decode.c | 34 ++ 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index 665af370ed..aab8162989 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -572,22 +572,24 @@ static int vaapi_decode_make_config(AVCodecContext *avctx, 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 (!frames->initial_pool_size) { +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; +} } } -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 2/3] libavutil/hwcontext_qsv: fix a bug for mapping vaapi frame to qsv
From: nyanmisaka The data stored in data[3] in VAAPI AVFrame is VASurfaceID while the data stored in pair->first is the pointer of VASurfaceID, so we need to do cast to make following commandline works: ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 \ -hwaccel_output_format vaapi -i input.264 \ -vf "hwmap=derive_device=qsv,format=qsv" -c:v h264_qsv output.264 Signed-off-by: nyanmisaka Signed-off-by: Wenbin Chen --- libavutil/hwcontext_qsv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index c18747f7eb..d83754193a 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -1220,7 +1220,7 @@ static int qsv_map_to(AVHWFramesContext *dst_ctx, case AV_PIX_FMT_VAAPI: { mfxHDLPair *pair = (mfxHDLPair*)hwctx->surfaces[i].Data.MemId; -if (pair->first == src->data[3]) { +if (*(VASurfaceID*)pair->first == (VASurfaceID)src->data[3]) { index = i; break; } -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 3/3] libavutil/hwcontext_opencl: fix a bug for mapping qsv frame to opencl
From: nyanmisaka mfxHDLPair was added to qsv, so modify qsv->opencl map function as well. Now the following commandline works: ffmpeg -v verbose -init_hw_device vaapi=va:/dev/dri/renderD128 \ -init_hw_device qsv=qs@va -init_hw_device opencl=ocl@va -filter_hw_device ocl \ -hwaccel qsv -hwaccel_output_format qsv -hwaccel_device qs -c:v h264_qsv \ -i input.264 -vf "hwmap=derive_device=opencl,format=opencl,avgblur_opencl, \ hwmap=derive_device=qsv:reverse=1:extra_hw_frames=32,format=qsv" \ -c:v h264_qsv output.264 Signed-off-by: nyanmisaka Signed-off-by: Wenbin Chen --- libavutil/hwcontext_opencl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c index 26a3a24593..4b6e74ff6f 100644 --- a/libavutil/hwcontext_opencl.c +++ b/libavutil/hwcontext_opencl.c @@ -2249,7 +2249,8 @@ static int opencl_map_from_qsv(AVHWFramesContext *dst_fc, AVFrame *dst, #if CONFIG_LIBMFX if (src->format == AV_PIX_FMT_QSV) { mfxFrameSurface1 *mfx_surface = (mfxFrameSurface1*)src->data[3]; -va_surface = *(VASurfaceID*)mfx_surface->Data.MemId; +mfxHDLPair *pair = (mfxHDLPair*)mfx_surface->Data.MemId; +va_surface = *(VASurfaceID*)pair->first; } else #endif if (src->format == AV_PIX_FMT_VAAPI) { -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V2 2/5] libavutil/hwcontext_vaapi: Add a new nv12 format map to support vulkan frame
Vulkan will map nv12 to R8 and GR88, so add this map to vaapi to support vulkan frame. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vaapi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 75acc851d6..994b744e4d 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -992,6 +992,7 @@ static const struct { } vaapi_drm_format_map[] = { #ifdef DRM_FORMAT_R8 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88), +DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_GR88), #endif DRM_MAP(NV12, 1, DRM_FORMAT_NV12), #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16) -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V2 3/5] libavutil/hwcontext_vulkan: Allocate vkFrame in one memory
The vaapi can import external frame, but the planes of the external frames should be in the same drm object. A new option "contiguous_planes" is added to device. This flag tells device to allocate places in one memory. When device is derived from vaapi this flag will be enabled. A new flag frame_flag is also added to AVVulkanFramesContext. User can use this flag to force enable or disable this behaviour. A new variable "offset "is added to AVVKFrame. It describe describe the offset from the memory currently bound to the VkImage. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 62 ++-- libavutil/hwcontext_vulkan.h | 22 + 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index f1e750cd3e..4100e8b0a2 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -103,6 +103,9 @@ typedef struct VulkanDevicePriv { /* Settings */ int use_linear_images; +/* allocate planes in a contiguous memory */ +int contiguous_planes; + /* Nvidia */ int dev_is_nvidia; } VulkanDevicePriv; @@ -1266,6 +1269,11 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, if (opt_d) p->use_linear_images = strtol(opt_d->value, NULL, 10); +opt_d = av_dict_get(opts, "contiguous_planes", NULL, 0); +if (opt_d) +p->contiguous_planes = strtol(opt_d->value, NULL, 10); + + hwctx->enabled_dev_extensions = dev_info.ppEnabledExtensionNames; hwctx->nb_enabled_dev_extensions = dev_info.enabledExtensionCount; @@ -1410,8 +1418,10 @@ static int vulkan_device_derive(AVHWDeviceContext *ctx, return AVERROR_EXTERNAL; } -if (strstr(vendor, "Intel")) +if (strstr(vendor, "Intel")) { +av_dict_set_int(&opts, "contiguous_planes", 1, 0); dev_select.vendor_id = 0x8086; +} if (strstr(vendor, "AMD")) dev_select.vendor_id = 0x1002; @@ -1634,8 +1644,12 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, AVHWDeviceContext *ctx = hwfc->device_ctx; VulkanDevicePriv *p = ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; +AVVulkanFramesContext *hwfctx = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { { 0 } }; +VkMemoryRequirements memory_requirements = { 0 }; +int mem_size = 0; +int mem_size_list[AV_NUM_DATA_POINTERS] = { 0 }; AVVulkanDeviceContext *hwctx = ctx->hwctx; @@ -1663,6 +1677,19 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, req.memoryRequirements.size = FFALIGN(req.memoryRequirements.size, p->props.properties.limits.minMemoryMapAlignment); +if (hwfctx->contiguous_planes == AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY) { +if (memory_requirements.size == 0) { +memory_requirements = req.memoryRequirements; +} else if (memory_requirements.memoryTypeBits != req.memoryRequirements.memoryTypeBits) { +av_log(hwfc, AV_LOG_ERROR, "the param for each planes are not the same\n"); +return AVERROR(EINVAL); +} + +mem_size_list[i] = req.memoryRequirements.size; +mem_size += mem_size_list[i]; +continue; +} + /* In case the implementation prefers/requires dedicated allocation */ use_ded_mem = ded_req.prefersDedicatedAllocation | ded_req.requiresDedicatedAllocation; @@ -1684,6 +1711,29 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, bind_info[i].memory = f->mem[i]; } +if (hwfctx->contiguous_planes == AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY) { +memory_requirements.size = mem_size; + +/* Allocate memory */ +if ((err = alloc_mem(ctx, &memory_requirements, +f->tiling == VK_IMAGE_TILING_LINEAR ? +VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT : +VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, +(void *)(((uint8_t *)alloc_pnext)), +&f->flags, &f->mem[0]))) +return err; + +f->size[0] = memory_requirements.size; + +for (int i = 0; i < planes; i++) { +bind_info[i].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; +bind_info[i].image = f->img[i]; +bind_info[i].memory = f->mem[0]; +bind_info[i].memoryOffset = i == 0 ? 0 : mem_size_list[i-1]; +f->offset[i] = bind_info[i].memoryOffset; +} +
[FFmpeg-devel] [PATCH V2 1/5] hwcontext_vaapi: Use PRIME_2 memory type for modifiers.
From: Bas Nieuwenhuizen This way we can pass explicit modifiers in. Sometimes the modifier matters for the number of memory planes that libva accepts, in particular when dealing with driver-compressed textures. Furthermore the driver might not actually be able to determine the implicit modifier if all the buffer-passing has used explicit modifier. All these issues should be resolved by passing in the modifier, and for that we switch to using the PRIME_2 memory type. Tested with experimental radeonsi patches for modifiers and kmsgrab. Also tested with radeonsi without the patches to double-check it works without PRIME_2 support. v2: Cache PRIME_2 support to avoid doing two calls every time on libva drivers that do not support it. v3: Remove prime2_vas usage. Signed-off-by: Bas Nieuwenhuizen --- libavutil/hwcontext_vaapi.c | 158 ++-- 1 file changed, 114 insertions(+), 44 deletions(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 83e542876d..75acc851d6 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -79,6 +79,9 @@ typedef struct VAAPIFramesContext { unsigned int rt_format; // Whether vaDeriveImage works. int derive_works; +// Caches whether VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2 is unsupported for +// surface imports. +int prime_2_import_unsupported; } VAAPIFramesContext; typedef struct VAAPIMapping { @@ -1022,32 +1025,17 @@ static void vaapi_unmap_from_drm(AVHWFramesContext *dst_fc, static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, const AVFrame *src, int flags) { +VAAPIFramesContext *src_vafc = src_fc->internal->priv; AVHWFramesContext *dst_fc = (AVHWFramesContext*)dst->hw_frames_ctx->data; AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; const AVDRMFrameDescriptor *desc; const VAAPIFormatDescriptor *format_desc; VASurfaceID surface_id; -VAStatus vas; +VAStatus vas = VA_STATUS_SUCCESS; +int use_prime2; uint32_t va_fourcc; -int err, i, j, k; - -unsigned long buffer_handle; -VASurfaceAttribExternalBuffers buffer_desc; -VASurfaceAttrib attrs[2] = { -{ -.type = VASurfaceAttribMemoryType, -.flags = VA_SURFACE_ATTRIB_SETTABLE, -.value.type= VAGenericValueTypeInteger, -.value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME, -}, -{ -.type = VASurfaceAttribExternalBufferDescriptor, -.flags = VA_SURFACE_ATTRIB_SETTABLE, -.value.type= VAGenericValueTypePointer, -.value.value.p = &buffer_desc, -} -}; +int err, i, j; desc = (AVDRMFrameDescriptor*)src->data[0]; @@ -1083,35 +1071,117 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, format_desc = vaapi_format_from_fourcc(va_fourcc); av_assert0(format_desc); -buffer_handle = desc->objects[0].fd; -buffer_desc.pixel_format = va_fourcc; -buffer_desc.width= src_fc->width; -buffer_desc.height = src_fc->height; -buffer_desc.data_size= desc->objects[0].size; -buffer_desc.buffers = &buffer_handle; -buffer_desc.num_buffers = 1; -buffer_desc.flags= 0; - -k = 0; -for (i = 0; i < desc->nb_layers; i++) { -for (j = 0; j < desc->layers[i].nb_planes; j++) { -buffer_desc.pitches[k] = desc->layers[i].planes[j].pitch; -buffer_desc.offsets[k] = desc->layers[i].planes[j].offset; -++k; +use_prime2 = !src_vafc->prime_2_import_unsupported && + desc->objects[0].format_modifier != DRM_FORMAT_MOD_INVALID; +if (use_prime2) { +VADRMPRIMESurfaceDescriptor prime_desc; +VASurfaceAttrib prime_attrs[2] = { +{ +.type = VASurfaceAttribMemoryType, +.flags = VA_SURFACE_ATTRIB_SETTABLE, +.value.type= VAGenericValueTypeInteger, +.value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, +}, +{ +.type = VASurfaceAttribExternalBufferDescriptor, +.flags = VA_SURFACE_ATTRIB_SETTABLE, +.value.type= VAGenericValueTypePointer, +.value.value.p = &prime_desc, +} +}; +prime_desc.fourcc = va_fourcc; +prime_desc.width = src_fc->width; +prime_desc.height = src_fc->height; +prime_desc.num_objects = desc->nb_objects; +for (i = 0; i < desc->nb_objects; ++i) { +prime_desc.objects[i].fd = desc->objects[i].fd; +prime_desc.objects[i].size = desc->objects[i].size; +prime_desc.objects[i].drm_format_modifier = +desc->objects[i].format_modifier; } -} -buffer_desc.num_planes = k; -if (format_desc->chroma_planes
[FFmpeg-devel] [PATCH V2 4/5] libavutil/hwcontext_vulkan: Add hwupload and hwdownload support when using contiguous_planes flag.
Add hwupload and hwdownload support to vulkan when frames are allocated in one memory Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 4100e8b0a2..6421115385 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2212,9 +2212,10 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { VkResult ret; -int err, mapped_mem_count = 0; +int err, mapped_mem_count = 0, loop = 0; AVVkFrame *f = (AVVkFrame *)src->data[0]; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; +AVVulkanFramesContext *hwfctx = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; @@ -2241,7 +2242,9 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, dst->width = src->width; dst->height = src->height; -for (int i = 0; i < planes; i++) { +loop = hwfctx->contiguous_planes == AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY ? + 1 : planes; +for (int i = 0; i < loop; i++) { ret = vk->MapMemory(hwctx->act_dev, f->mem[i], 0, VK_WHOLE_SIZE, 0, (void **)&dst->data[i]); if (ret != VK_SUCCESS) { @@ -2252,6 +2255,11 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, } mapped_mem_count++; } +if (hwfctx->contiguous_planes == AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY) { +for (int i = 0; i < planes; i++) { +dst->data[i] = dst->data[0] + f->offset[i]; +} +} /* Check if the memory contents matter */ if (((flags & AV_HWFRAME_MAP_READ) || !(flags & AV_HWFRAME_MAP_OVERWRITE)) && -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V2 5/5] libavutil/hwcontext_vulkan: specify the modifier to create VKImage
When vulkan image exports to drm, the tilling need to be VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT. Now add code to create vulkan image using this format. Now the following command line works: ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format \ vaapi -i input_1080p.264 -vf "hwmap=derive_device=vulkan,format=vulkan, \ scale_vulkan=1920:1080,hwmap=derive_device=vaapi,format=vaapi" -c:v h264_vaapi output.264 Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 130 +-- 1 file changed, 124 insertions(+), 6 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 6421115385..4b951fb202 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -230,6 +230,28 @@ const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p) return NULL; } +static void *find_in_structure_list(VkBaseOutStructure *stru_list, VkStructureType sType) { +if (!stru_list) +return NULL; + +for(;stru_list;stru_list = stru_list->pNext) +if (stru_list->sType == sType) +return stru_list; + +return NULL; +} + +static void append_to_structure_list(VkBaseOutStructure **stru_list, VkBaseOutStructure *added_stru) { +VkBaseOutStructure *p; +if (!*stru_list) { +*stru_list = added_stru; +return; +} +for(p = *stru_list; p->pNext; p = p->pNext); +p->pNext = added_stru; +return; +} + static int pixfmt_is_supported(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p, int linear) { @@ -1979,6 +2001,10 @@ static void try_export_flags(AVHWFramesContext *hwfc, AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; +const int has_modifiers = hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; +int loop_count; +VkImageDrmFormatModifierListCreateInfoEXT *modifier_info = find_in_structure_list(hwctx->create_pnext, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT); VkExternalImageFormatProperties eprops = { .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR, }; @@ -1986,9 +2012,18 @@ static void try_export_flags(AVHWFramesContext *hwfc, .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, .pNext = &eprops, }; +VkPhysicalDeviceImageDrmFormatModifierInfoEXT phy_dev_mod_info = { +.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, +.pNext = NULL, +.pQueueFamilyIndices = p->qfs, +.queueFamilyIndexCount = p->num_qfs, +.sharingMode = p->num_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : + VK_SHARING_MODE_EXCLUSIVE, +}; VkPhysicalDeviceExternalImageFormatInfo enext = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, .handleType = exp, +.pNext = has_modifiers && modifier_info ? &phy_dev_mod_info : NULL, }; VkPhysicalDeviceImageFormatInfo2 pinfo = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, @@ -2000,11 +2035,16 @@ static void try_export_flags(AVHWFramesContext *hwfc, .flags = VK_IMAGE_CREATE_ALIAS_BIT, }; -ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, - &pinfo, &props); -if (ret == VK_SUCCESS) { -*iexp |= exp; -*comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; +loop_count = has_modifiers && modifier_info ? modifier_info->drmFormatModifierCount : 1; +for (int i = 0; i < loop_count; i++) { +if (has_modifiers && modifier_info) +phy_dev_mod_info.drmFormatModifier = modifier_info->pDrmFormatModifiers[i]; +ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, +&pinfo, &props); +if (ret == VK_SUCCESS) { +*iexp |= exp; +*comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; +} } } @@ -2074,6 +2114,20 @@ fail: static void vulkan_frames_uninit(AVHWFramesContext *hwfc) { VulkanFramesPriv *fp = hwfc->internal->priv; +AVVulkanFramesContext *hwctx = hwfc->hwctx; +VkBaseOutStructure *structure_p_next,*structure_p = hwctx->create_pnext; +VkImageDrmFormatModifierListCreateInfoEXT *modifier_info; +while (structure_p) { +structure_p_next = structure_p->pNext; +switch (structure_p->sType) { +case VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INF
[FFmpeg-devel] [PATCH V3 1/5] hwcontext_vaapi: Use PRIME_2 memory type for modifiers.
From: Bas Nieuwenhuizen This way we can pass explicit modifiers in. Sometimes the modifier matters for the number of memory planes that libva accepts, in particular when dealing with driver-compressed textures. Furthermore the driver might not actually be able to determine the implicit modifier if all the buffer-passing has used explicit modifier. All these issues should be resolved by passing in the modifier, and for that we switch to using the PRIME_2 memory type. Tested with experimental radeonsi patches for modifiers and kmsgrab. Also tested with radeonsi without the patches to double-check it works without PRIME_2 support. v2: Cache PRIME_2 support to avoid doing two calls every time on libva drivers that do not support it. v3: Remove prime2_vas usage. Signed-off-by: Bas Nieuwenhuizen --- libavutil/hwcontext_vaapi.c | 158 ++-- 1 file changed, 114 insertions(+), 44 deletions(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 83e542876d..75acc851d6 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -79,6 +79,9 @@ typedef struct VAAPIFramesContext { unsigned int rt_format; // Whether vaDeriveImage works. int derive_works; +// Caches whether VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2 is unsupported for +// surface imports. +int prime_2_import_unsupported; } VAAPIFramesContext; typedef struct VAAPIMapping { @@ -1022,32 +1025,17 @@ static void vaapi_unmap_from_drm(AVHWFramesContext *dst_fc, static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, const AVFrame *src, int flags) { +VAAPIFramesContext *src_vafc = src_fc->internal->priv; AVHWFramesContext *dst_fc = (AVHWFramesContext*)dst->hw_frames_ctx->data; AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; const AVDRMFrameDescriptor *desc; const VAAPIFormatDescriptor *format_desc; VASurfaceID surface_id; -VAStatus vas; +VAStatus vas = VA_STATUS_SUCCESS; +int use_prime2; uint32_t va_fourcc; -int err, i, j, k; - -unsigned long buffer_handle; -VASurfaceAttribExternalBuffers buffer_desc; -VASurfaceAttrib attrs[2] = { -{ -.type = VASurfaceAttribMemoryType, -.flags = VA_SURFACE_ATTRIB_SETTABLE, -.value.type= VAGenericValueTypeInteger, -.value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME, -}, -{ -.type = VASurfaceAttribExternalBufferDescriptor, -.flags = VA_SURFACE_ATTRIB_SETTABLE, -.value.type= VAGenericValueTypePointer, -.value.value.p = &buffer_desc, -} -}; +int err, i, j; desc = (AVDRMFrameDescriptor*)src->data[0]; @@ -1083,35 +1071,117 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, format_desc = vaapi_format_from_fourcc(va_fourcc); av_assert0(format_desc); -buffer_handle = desc->objects[0].fd; -buffer_desc.pixel_format = va_fourcc; -buffer_desc.width= src_fc->width; -buffer_desc.height = src_fc->height; -buffer_desc.data_size= desc->objects[0].size; -buffer_desc.buffers = &buffer_handle; -buffer_desc.num_buffers = 1; -buffer_desc.flags= 0; - -k = 0; -for (i = 0; i < desc->nb_layers; i++) { -for (j = 0; j < desc->layers[i].nb_planes; j++) { -buffer_desc.pitches[k] = desc->layers[i].planes[j].pitch; -buffer_desc.offsets[k] = desc->layers[i].planes[j].offset; -++k; +use_prime2 = !src_vafc->prime_2_import_unsupported && + desc->objects[0].format_modifier != DRM_FORMAT_MOD_INVALID; +if (use_prime2) { +VADRMPRIMESurfaceDescriptor prime_desc; +VASurfaceAttrib prime_attrs[2] = { +{ +.type = VASurfaceAttribMemoryType, +.flags = VA_SURFACE_ATTRIB_SETTABLE, +.value.type= VAGenericValueTypeInteger, +.value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, +}, +{ +.type = VASurfaceAttribExternalBufferDescriptor, +.flags = VA_SURFACE_ATTRIB_SETTABLE, +.value.type= VAGenericValueTypePointer, +.value.value.p = &prime_desc, +} +}; +prime_desc.fourcc = va_fourcc; +prime_desc.width = src_fc->width; +prime_desc.height = src_fc->height; +prime_desc.num_objects = desc->nb_objects; +for (i = 0; i < desc->nb_objects; ++i) { +prime_desc.objects[i].fd = desc->objects[i].fd; +prime_desc.objects[i].size = desc->objects[i].size; +prime_desc.objects[i].drm_format_modifier = +desc->objects[i].format_modifier; } -} -buffer_desc.num_planes = k; -if (format_desc->chroma_planes
[FFmpeg-devel] [PATCH V3 2/5] libavutil/hwcontext_vaapi: Add a new nv12 format map to support vulkan frame
Vulkan will map nv12 to R8 and GR88, so add this map to vaapi to support vulkan frame. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vaapi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 75acc851d6..994b744e4d 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -992,6 +992,7 @@ static const struct { } vaapi_drm_format_map[] = { #ifdef DRM_FORMAT_R8 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88), +DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_GR88), #endif DRM_MAP(NV12, 1, DRM_FORMAT_NV12), #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16) -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V3 3/5] libavutil/hwcontext_vulkan: Allocate vkFrame in one memory
The vaapi can import external frame, but the planes of the external frames should be in the same drm object. A new option "contiguous_planes" is added to device. This flag tells device to allocate places in one memory. When device is derived from vaapi this flag will be enabled. A new flag frame_flag is also added to AVVulkanFramesContext. User can use this flag to force enable or disable this behaviour. A new variable "offset "is added to AVVKFrame. It describe describe the offset from the memory currently bound to the VkImage. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 67 +++- libavutil/hwcontext_vulkan.h | 24 + 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 644ed947f8..b8076fb425 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -103,8 +103,14 @@ typedef struct VulkanDevicePriv { /* Settings */ int use_linear_images; +/* allocate planes in a contiguous memory */ +int contiguous_planes; + /* Nvidia */ int dev_is_nvidia; + +/* Intel */ +int dev_is_intel; } VulkanDevicePriv; typedef struct VulkanFramesPriv { @@ -146,6 +152,8 @@ typedef struct AVVkFrameInternal { } \ } while(0) +#define VKF_FLAG(x, f) (((x) & (~AV_VK_FRAME_FLAG_NONE)) & (f)) + static const struct { enum AVPixelFormat pixfmt; const VkFormat vkfmts[4]; @@ -1268,6 +1276,13 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, if (opt_d) p->use_linear_images = strtol(opt_d->value, NULL, 10); +opt_d = av_dict_get(opts, "contiguous_planes", NULL, 0); +if (opt_d) +p->contiguous_planes = strtol(opt_d->value, NULL, 10); +else +p->contiguous_planes = -1; + + hwctx->enabled_dev_extensions = dev_info.ppEnabledExtensionNames; hwctx->nb_enabled_dev_extensions = dev_info.enabledExtensionCount; @@ -1319,6 +1334,8 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) p->dev_is_nvidia = (p->props.properties.vendorID == 0x10de); +p->dev_is_intel = (p->props.properties.vendorID == 0x8086); + vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &queue_num, NULL); if (!queue_num) { av_log(ctx, AV_LOG_ERROR, "Failed to get queues!\n"); @@ -1636,8 +1653,12 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, AVHWDeviceContext *ctx = hwfc->device_ctx; VulkanDevicePriv *p = ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; +AVVulkanFramesContext *hwfctx = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { { 0 } }; +VkMemoryRequirements memory_requirements = { 0 }; +int mem_size = 0; +int mem_size_list[AV_NUM_DATA_POINTERS] = { 0 }; AVVulkanDeviceContext *hwctx = ctx->hwctx; @@ -1665,6 +1686,19 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, req.memoryRequirements.size = FFALIGN(req.memoryRequirements.size, p->props.properties.limits.minMemoryMapAlignment); +if (VKF_FLAG(hwfctx->flags, AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY)) { +if (memory_requirements.size == 0) { +memory_requirements = req.memoryRequirements; +} else if (memory_requirements.memoryTypeBits != req.memoryRequirements.memoryTypeBits) { +av_log(hwfc, AV_LOG_ERROR, "the param for each planes are not the same\n"); +return AVERROR(EINVAL); +} + +mem_size_list[i] = req.memoryRequirements.size; +mem_size += mem_size_list[i]; +continue; +} + /* In case the implementation prefers/requires dedicated allocation */ use_ded_mem = ded_req.prefersDedicatedAllocation | ded_req.requiresDedicatedAllocation; @@ -1686,6 +1720,29 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, bind_info[i].memory = f->mem[i]; } +if (VKF_FLAG(hwfctx->flags, AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY)) { +memory_requirements.size = mem_size; + +/* Allocate memory */ +if ((err = alloc_mem(ctx, &memory_requirements, +f->tiling == VK_IMAGE_TILING_LINEAR ? +VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT : +VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, +(void *)(((uint8_t *)alloc_pnext)), +&f->flags, &f->mem[0]))) +return err; + +f
[FFmpeg-devel] [PATCH V3 4/5] libavutil/hwcontext_vulkan: Add support to hwmap to software frame when using contiguous_planes flag.
Add support to map vulkan frames to software frames when using contiguous_planes flag. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index b8076fb425..0648e59243 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2221,9 +2221,10 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { VkResult ret; -int err, mapped_mem_count = 0; +int err, mapped_mem_count = 0, loop = 0; AVVkFrame *f = (AVVkFrame *)src->data[0]; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; +AVVulkanFramesContext *hwfctx = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; @@ -2250,7 +2251,9 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, dst->width = src->width; dst->height = src->height; -for (int i = 0; i < planes; i++) { +loop = VKF_FLAG(hwfctx->flags, AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY) ? + 1 : planes; +for (int i = 0; i < loop; i++) { ret = vk->MapMemory(hwctx->act_dev, f->mem[i], 0, VK_WHOLE_SIZE, 0, (void **)&dst->data[i]); if (ret != VK_SUCCESS) { @@ -2261,6 +2264,10 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, } mapped_mem_count++; } +if (VKF_FLAG(hwfctx->flags, AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY)) { +for (int i = 0; i < planes; i++) +dst->data[i] = dst->data[0] + f->offset[i]; +} /* Check if the memory contents matter */ if (((flags & AV_HWFRAME_MAP_READ) || !(flags & AV_HWFRAME_MAP_OVERWRITE)) && -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V3 5/5] libavutil/hwcontext_vulkan: specify the modifier to create VKImage
When vulkan image exports to drm, the tilling need to be VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT. Now add code to create vulkan image using this format. Now the following command line works: ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format \ vaapi -i input_1080p.264 -vf "hwmap=derive_device=vulkan,format=vulkan, \ scale_vulkan=1920:1080,hwmap=derive_device=vaapi,format=vaapi" -c:v h264_vaapi output.264 Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 127 +-- 1 file changed, 121 insertions(+), 6 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 0648e59243..903a75618a 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -120,6 +120,9 @@ typedef struct VulkanFramesPriv { /* Image transfers */ VulkanExecCtx upload_ctx; VulkanExecCtx download_ctx; + +/*modifier info*/ +VkImageDrmFormatModifierListCreateInfoEXT *modifier_info; } VulkanFramesPriv; typedef struct AVVkFrameInternal { @@ -235,6 +238,28 @@ const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p) return NULL; } +static void *find_in_structure_list(VkBaseOutStructure *stru_list, VkStructureType sType) { +if (!stru_list) +return NULL; + +for(;stru_list;stru_list = stru_list->pNext) +if (stru_list->sType == sType) +return stru_list; + +return NULL; +} + +static void append_to_structure_list(VkBaseOutStructure **stru_list, VkBaseOutStructure *added_stru) { +VkBaseOutStructure *p; +if (!*stru_list) { +*stru_list = added_stru; +return; +} +for(p = *stru_list; p->pNext; p = p->pNext); +p->pNext = added_stru; +return; +} + static int pixfmt_is_supported(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p, int linear) { @@ -1988,6 +2013,10 @@ static void try_export_flags(AVHWFramesContext *hwfc, AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; +const int has_modifiers = hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; +int loop_count; +VkImageDrmFormatModifierListCreateInfoEXT *modifier_info = find_in_structure_list(hwctx->create_pnext, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT); VkExternalImageFormatProperties eprops = { .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR, }; @@ -1995,9 +2024,18 @@ static void try_export_flags(AVHWFramesContext *hwfc, .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, .pNext = &eprops, }; +VkPhysicalDeviceImageDrmFormatModifierInfoEXT phy_dev_mod_info = { +.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, +.pNext = NULL, +.pQueueFamilyIndices = p->qfs, +.queueFamilyIndexCount = p->num_qfs, +.sharingMode = p->num_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : + VK_SHARING_MODE_EXCLUSIVE, +}; VkPhysicalDeviceExternalImageFormatInfo enext = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, .handleType = exp, +.pNext = has_modifiers && modifier_info ? &phy_dev_mod_info : NULL, }; VkPhysicalDeviceImageFormatInfo2 pinfo = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, @@ -2009,11 +2047,16 @@ static void try_export_flags(AVHWFramesContext *hwfc, .flags = VK_IMAGE_CREATE_ALIAS_BIT, }; -ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, - &pinfo, &props); -if (ret == VK_SUCCESS) { -*iexp |= exp; -*comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; +loop_count = has_modifiers && modifier_info ? modifier_info->drmFormatModifierCount : 1; +for (int i = 0; i < loop_count; i++) { +if (has_modifiers && modifier_info) +phy_dev_mod_info.drmFormatModifier = modifier_info->pDrmFormatModifiers[i]; +ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, +&pinfo, &props); +if (ret == VK_SUCCESS) { +*iexp |= exp; +*comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; +} } } @@ -2084,6 +2127,12 @@ static void vulkan_frames_uninit(AVHWFramesContext *hwfc) { VulkanFramesPriv *fp = hwfc->internal->priv; +if (fp->modifier_info) { +if (fp->modifier_info->pDrmFormatModifiers) +
[FFmpeg-devel] [PATCH V4 1/5] hwcontext_vaapi: Use PRIME_2 memory type for modifiers.
From: Bas Nieuwenhuizen This way we can pass explicit modifiers in. Sometimes the modifier matters for the number of memory planes that libva accepts, in particular when dealing with driver-compressed textures. Furthermore the driver might not actually be able to determine the implicit modifier if all the buffer-passing has used explicit modifier. All these issues should be resolved by passing in the modifier, and for that we switch to using the PRIME_2 memory type. Tested with experimental radeonsi patches for modifiers and kmsgrab. Also tested with radeonsi without the patches to double-check it works without PRIME_2 support. v2: Cache PRIME_2 support to avoid doing two calls every time on libva drivers that do not support it. v3: Remove prime2_vas usage. Signed-off-by: Bas Nieuwenhuizen --- libavutil/hwcontext_vaapi.c | 158 ++-- 1 file changed, 114 insertions(+), 44 deletions(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 83e542876d..75acc851d6 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -79,6 +79,9 @@ typedef struct VAAPIFramesContext { unsigned int rt_format; // Whether vaDeriveImage works. int derive_works; +// Caches whether VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2 is unsupported for +// surface imports. +int prime_2_import_unsupported; } VAAPIFramesContext; typedef struct VAAPIMapping { @@ -1022,32 +1025,17 @@ static void vaapi_unmap_from_drm(AVHWFramesContext *dst_fc, static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, const AVFrame *src, int flags) { +VAAPIFramesContext *src_vafc = src_fc->internal->priv; AVHWFramesContext *dst_fc = (AVHWFramesContext*)dst->hw_frames_ctx->data; AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; const AVDRMFrameDescriptor *desc; const VAAPIFormatDescriptor *format_desc; VASurfaceID surface_id; -VAStatus vas; +VAStatus vas = VA_STATUS_SUCCESS; +int use_prime2; uint32_t va_fourcc; -int err, i, j, k; - -unsigned long buffer_handle; -VASurfaceAttribExternalBuffers buffer_desc; -VASurfaceAttrib attrs[2] = { -{ -.type = VASurfaceAttribMemoryType, -.flags = VA_SURFACE_ATTRIB_SETTABLE, -.value.type= VAGenericValueTypeInteger, -.value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME, -}, -{ -.type = VASurfaceAttribExternalBufferDescriptor, -.flags = VA_SURFACE_ATTRIB_SETTABLE, -.value.type= VAGenericValueTypePointer, -.value.value.p = &buffer_desc, -} -}; +int err, i, j; desc = (AVDRMFrameDescriptor*)src->data[0]; @@ -1083,35 +1071,117 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, format_desc = vaapi_format_from_fourcc(va_fourcc); av_assert0(format_desc); -buffer_handle = desc->objects[0].fd; -buffer_desc.pixel_format = va_fourcc; -buffer_desc.width= src_fc->width; -buffer_desc.height = src_fc->height; -buffer_desc.data_size= desc->objects[0].size; -buffer_desc.buffers = &buffer_handle; -buffer_desc.num_buffers = 1; -buffer_desc.flags= 0; - -k = 0; -for (i = 0; i < desc->nb_layers; i++) { -for (j = 0; j < desc->layers[i].nb_planes; j++) { -buffer_desc.pitches[k] = desc->layers[i].planes[j].pitch; -buffer_desc.offsets[k] = desc->layers[i].planes[j].offset; -++k; +use_prime2 = !src_vafc->prime_2_import_unsupported && + desc->objects[0].format_modifier != DRM_FORMAT_MOD_INVALID; +if (use_prime2) { +VADRMPRIMESurfaceDescriptor prime_desc; +VASurfaceAttrib prime_attrs[2] = { +{ +.type = VASurfaceAttribMemoryType, +.flags = VA_SURFACE_ATTRIB_SETTABLE, +.value.type= VAGenericValueTypeInteger, +.value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, +}, +{ +.type = VASurfaceAttribExternalBufferDescriptor, +.flags = VA_SURFACE_ATTRIB_SETTABLE, +.value.type= VAGenericValueTypePointer, +.value.value.p = &prime_desc, +} +}; +prime_desc.fourcc = va_fourcc; +prime_desc.width = src_fc->width; +prime_desc.height = src_fc->height; +prime_desc.num_objects = desc->nb_objects; +for (i = 0; i < desc->nb_objects; ++i) { +prime_desc.objects[i].fd = desc->objects[i].fd; +prime_desc.objects[i].size = desc->objects[i].size; +prime_desc.objects[i].drm_format_modifier = +desc->objects[i].format_modifier; } -} -buffer_desc.num_planes = k; -if (format_desc->chroma_planes
[FFmpeg-devel] [PATCH V4 2/5] libavutil/hwcontext_vaapi: Add a new nv12 format map to support vulkan frame
Vulkan will map nv12 to R8 and GR88, so add this map to vaapi to support vulkan frame. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vaapi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 75acc851d6..994b744e4d 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -992,6 +992,7 @@ static const struct { } vaapi_drm_format_map[] = { #ifdef DRM_FORMAT_R8 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88), +DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_GR88), #endif DRM_MAP(NV12, 1, DRM_FORMAT_NV12), #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16) -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V4 3/5] libavutil/hwcontext_vulkan: Allocate vkFrame in one memory
The vaapi can import external frame, but the planes of the external frames should be in the same drm object. A new option "contiguous_planes" is added to device. This flag tells device to allocate places in one memory. When device is derived from vaapi this flag will be enabled. A new flag frame_flag is also added to AVVulkanFramesContext. User can use this flag to force enable or disable this behaviour. A new variable "offset "is added to AVVKFrame. It describe describe the offset from the memory currently bound to the VkImage. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 68 +++- libavutil/hwcontext_vulkan.h | 24 + 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index a0437c9661..eef9009ae1 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -103,8 +103,14 @@ typedef struct VulkanDevicePriv { /* Settings */ int use_linear_images; +/* allocate planes in a contiguous memory */ +int contiguous_planes; + /* Nvidia */ int dev_is_nvidia; + +/* Intel */ +int dev_is_intel; } VulkanDevicePriv; typedef struct VulkanFramesPriv { @@ -153,6 +159,8 @@ typedef struct AVVkFrameInternal { av_free((void *)props); \ } +#define VKF_FLAG(x, f) (((x) & (~AV_VK_FRAME_FLAG_NONE)) & (f)) + static const struct { enum AVPixelFormat pixfmt; const VkFormat vkfmts[4]; @@ -1374,6 +1382,13 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, if (opt_d) p->use_linear_images = strtol(opt_d->value, NULL, 10); +opt_d = av_dict_get(opts, "contiguous_planes", NULL, 0); +if (opt_d) +p->contiguous_planes = strtol(opt_d->value, NULL, 10); +else +p->contiguous_planes = -1; + + hwctx->enabled_dev_extensions = dev_info.ppEnabledExtensionNames; hwctx->nb_enabled_dev_extensions = dev_info.enabledExtensionCount; @@ -1425,6 +1440,8 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) p->dev_is_nvidia = (p->props.properties.vendorID == 0x10de); +p->dev_is_intel = (p->props.properties.vendorID == 0x8086); + vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &queue_num, NULL); if (!queue_num) { av_log(ctx, AV_LOG_ERROR, "Failed to get queues!\n"); @@ -1742,8 +1759,12 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, AVHWDeviceContext *ctx = hwfc->device_ctx; VulkanDevicePriv *p = ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; +AVVulkanFramesContext *hwfctx = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { { 0 } }; +VkMemoryRequirements memory_requirements = { 0 }; +int mem_size = 0; +int mem_size_list[AV_NUM_DATA_POINTERS] = { 0 }; AVVulkanDeviceContext *hwctx = ctx->hwctx; @@ -1771,6 +1792,19 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, req.memoryRequirements.size = FFALIGN(req.memoryRequirements.size, p->props.properties.limits.minMemoryMapAlignment); +if (VKF_FLAG(hwfctx->flags, AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY)) { +if (memory_requirements.size == 0) { +memory_requirements = req.memoryRequirements; +} else if (memory_requirements.memoryTypeBits != req.memoryRequirements.memoryTypeBits) { +av_log(hwfc, AV_LOG_ERROR, "the param for each planes are not the same\n"); +return AVERROR(EINVAL); +} + +mem_size_list[i] = req.memoryRequirements.size; +mem_size += mem_size_list[i]; +continue; +} + /* In case the implementation prefers/requires dedicated allocation */ use_ded_mem = ded_req.prefersDedicatedAllocation | ded_req.requiresDedicatedAllocation; @@ -1792,6 +1826,29 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, bind_info[i].memory = f->mem[i]; } +if (VKF_FLAG(hwfctx->flags, AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY)) { +memory_requirements.size = mem_size; + +/* Allocate memory */ +if ((err = alloc_mem(ctx, &memory_requirements, +f->tiling == VK_IMAGE_TILING_LINEAR ? +VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT : +VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, +(void *)(((uint8_t *)alloc_pnext)), +&f->flags, &f->mem[0]))) +return err; + +f
[FFmpeg-devel] [PATCH V4 4/5] libavutil/hwcontext_vulkan: Add support to hwmap to software frame when using contiguous_planes flag.
Add support to map vulkan frames to software frames when using contiguous_planes flag. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index eef9009ae1..f980b72720 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2327,9 +2327,10 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { VkResult ret; -int err, mapped_mem_count = 0; +int err, mapped_mem_count = 0, loop = 0; AVVkFrame *f = (AVVkFrame *)src->data[0]; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; +AVVulkanFramesContext *hwfctx = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; @@ -2356,7 +2357,9 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, dst->width = src->width; dst->height = src->height; -for (int i = 0; i < planes; i++) { +loop = VKF_FLAG(hwfctx->flags, AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY) ? + 1 : planes; +for (int i = 0; i < loop; i++) { ret = vk->MapMemory(hwctx->act_dev, f->mem[i], 0, VK_WHOLE_SIZE, 0, (void **)&dst->data[i]); if (ret != VK_SUCCESS) { @@ -2367,6 +2370,10 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, } mapped_mem_count++; } +if (VKF_FLAG(hwfctx->flags, AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY)) { +for (int i = 0; i < planes; i++) +dst->data[i] = dst->data[0] + f->offset[i]; +} /* Check if the memory contents matter */ if (((flags & AV_HWFRAME_MAP_READ) || !(flags & AV_HWFRAME_MAP_OVERWRITE)) && -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V4 5/5] libavutil/hwcontext_vulkan: specify the modifier to create VKImage
When vulkan image exports to drm, the tilling need to be VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT. Now add code to create vulkan image using this format. Now the following command line works: ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format \ vaapi -i input_1080p.264 -vf "hwmap=derive_device=vulkan,format=vulkan, \ scale_vulkan=1920:1080,hwmap=derive_device=vaapi,format=vaapi" -c:v h264_vaapi output.264 Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 127 +-- 1 file changed, 121 insertions(+), 6 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index f980b72720..8224c0d4e4 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -120,6 +120,9 @@ typedef struct VulkanFramesPriv { /* Image transfers */ VulkanExecCtx upload_ctx; VulkanExecCtx download_ctx; + +/*modifier info*/ +VkImageDrmFormatModifierListCreateInfoEXT *modifier_info; } VulkanFramesPriv; typedef struct AVVkFrameInternal { @@ -242,6 +245,28 @@ const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p) return NULL; } +static void *find_in_structure_list(VkBaseOutStructure *stru_list, VkStructureType sType) { +if (!stru_list) +return NULL; + +for(;stru_list;stru_list = stru_list->pNext) +if (stru_list->sType == sType) +return stru_list; + +return NULL; +} + +static void append_to_structure_list(VkBaseOutStructure **stru_list, VkBaseOutStructure *added_stru) { +VkBaseOutStructure *p; +if (!*stru_list) { +*stru_list = added_stru; +return; +} +for(p = *stru_list; p->pNext; p = p->pNext); +p->pNext = added_stru; +return; +} + static int pixfmt_is_supported(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p, int linear) { @@ -2094,6 +2119,10 @@ static void try_export_flags(AVHWFramesContext *hwfc, AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; +const int has_modifiers = hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; +int loop_count; +VkImageDrmFormatModifierListCreateInfoEXT *modifier_info = find_in_structure_list(hwctx->create_pnext, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT); VkExternalImageFormatProperties eprops = { .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR, }; @@ -2101,9 +2130,18 @@ static void try_export_flags(AVHWFramesContext *hwfc, .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, .pNext = &eprops, }; +VkPhysicalDeviceImageDrmFormatModifierInfoEXT phy_dev_mod_info = { +.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, +.pNext = NULL, +.pQueueFamilyIndices = p->qfs, +.queueFamilyIndexCount = p->num_qfs, +.sharingMode = p->num_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : + VK_SHARING_MODE_EXCLUSIVE, +}; VkPhysicalDeviceExternalImageFormatInfo enext = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, .handleType = exp, +.pNext = has_modifiers && modifier_info ? &phy_dev_mod_info : NULL, }; VkPhysicalDeviceImageFormatInfo2 pinfo = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, @@ -2115,11 +2153,16 @@ static void try_export_flags(AVHWFramesContext *hwfc, .flags = VK_IMAGE_CREATE_ALIAS_BIT, }; -ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, - &pinfo, &props); -if (ret == VK_SUCCESS) { -*iexp |= exp; -*comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; +loop_count = has_modifiers && modifier_info ? modifier_info->drmFormatModifierCount : 1; +for (int i = 0; i < loop_count; i++) { +if (has_modifiers && modifier_info) +phy_dev_mod_info.drmFormatModifier = modifier_info->pDrmFormatModifiers[i]; +ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, +&pinfo, &props); +if (ret == VK_SUCCESS) { +*iexp |= exp; +*comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; +} } } @@ -2190,6 +2233,12 @@ static void vulkan_frames_uninit(AVHWFramesContext *hwfc) { VulkanFramesPriv *fp = hwfc->internal->priv; +if (fp->modifier_info) { +if (fp->modifier_info->pDrmFormatModifiers) +
[FFmpeg-devel] [PATCH V2 1/3] libavcodec/vaapi_decode: fix the problem that init_pool_size < nb_surface
For vaapi if the init_pool_size is not zero, the pool size is fixed. This means max surfaces is init_pool_size, but when mapping vaapi frame to qsv frame, the init_pool_size < nb_surface. The cause is that vaapi_decode_make_config() config the init_pool_size and it is called twice. The first time is to init frame_context and the second time is to init codec. On the second time the init_pool_size is changed to original value so the init_pool_size is lower than the reall size because pool_size used to initialize frame_context need to plus thread_count and 3 (guarantee 4 base work surfaces). Now add code to make sure init_pool_size is only set once. Now the following commandline works: ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 \ -hwaccel_output_format vaapi -i input.264 \ -vf "hwmap=derive_device=qsv,format=qsv" \ -c:v h264_qsv output.264 Signed-off-by: Wenbin Chen --- libavcodec/vaapi_decode.c | 34 ++ 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index 665af370ed..aab8162989 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -572,22 +572,24 @@ static int vaapi_decode_make_config(AVCodecContext *avctx, 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 (!frames->initial_pool_size) { +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; +} } } -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V2 2/3] libavutil/hwcontext_qsv: fix a bug for mapping vaapi frame to qsv
From: nyanmisaka The data stored in data[3] in VAAPI AVFrame is VASurfaceID while the data stored in pair->first is the pointer of VASurfaceID, so we need to do cast to make following commandline works: ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 \ -hwaccel_output_format vaapi -i input.264 \ -vf "hwmap=derive_device=qsv,format=qsv" -c:v h264_qsv output.264 Signed-off-by: nyanmisaka Signed-off-by: Wenbin Chen --- libavutil/hwcontext_qsv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 268be9f8a1..a5d154a24d 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -1218,7 +1218,7 @@ static int qsv_map_to(AVHWFramesContext *dst_ctx, case AV_PIX_FMT_VAAPI: { mfxHDLPair *pair = (mfxHDLPair*)hwctx->surfaces[i].Data.MemId; -if (pair->first == src->data[3]) { +if (*(VASurfaceID*)pair->first == (VASurfaceID)src->data[3]) { index = i; break; } -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V2 3/3] libavutil/hwcontext_opencl: fix a bug for mapping qsv frame to opencl
From: nyanmisaka mfxHDLPair was added to qsv, so modify qsv->opencl map function as well. Now the following commandline works: ffmpeg -v verbose -init_hw_device vaapi=va:/dev/dri/renderD128 \ -init_hw_device qsv=qs@va -init_hw_device opencl=ocl@va -filter_hw_device ocl \ -hwaccel qsv -hwaccel_output_format qsv -hwaccel_device qs -c:v h264_qsv \ -i input.264 -vf "hwmap=derive_device=opencl,format=opencl,avgblur_opencl, \ hwmap=derive_device=qsv:reverse=1:extra_hw_frames=32,format=qsv" \ -c:v h264_qsv output.264 Signed-off-by: nyanmisaka Signed-off-by: Wenbin Chen --- libavutil/hwcontext_opencl.c | 3 ++- libavutil/hwcontext_qsv.h| 5 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c index 26a3a24593..ab812999cd 100644 --- a/libavutil/hwcontext_opencl.c +++ b/libavutil/hwcontext_opencl.c @@ -48,6 +48,7 @@ #if HAVE_OPENCL_VAAPI_INTEL_MEDIA #if CONFIG_LIBMFX #include +#include "hwcontext_qsv.h" #endif #include #include @@ -2249,7 +2250,7 @@ static int opencl_map_from_qsv(AVHWFramesContext *dst_fc, AVFrame *dst, #if CONFIG_LIBMFX if (src->format == AV_PIX_FMT_QSV) { mfxFrameSurface1 *mfx_surface = (mfxFrameSurface1*)src->data[3]; -va_surface = *(VASurfaceID*)mfx_surface->Data.MemId; +va_surface = *MFXSURFACEP_TO_VASURFACEP(mfx_surface); } else #endif if (src->format == AV_PIX_FMT_VAAPI) { diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h index b98d611cfc..957df01ef1 100644 --- a/libavutil/hwcontext_qsv.h +++ b/libavutil/hwcontext_qsv.h @@ -29,6 +29,11 @@ * contain AVBufferRefs whose data pointer points to an mfxFrameSurface1 struct. */ +#if CONFIG_VAAPI +#define MFXSURFACEP_TO_VASURFACEP(surf) \ +(VASurfaceID*)(((mfxHDLPair*)surf->Data.MemId)->first) +#endif + /** * This struct is allocated as AVHWDeviceContext.hwctx */ -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V5 1/5] hwcontext_vaapi: Use PRIME_2 memory type for modifiers.
From: Bas Nieuwenhuizen This way we can pass explicit modifiers in. Sometimes the modifier matters for the number of memory planes that libva accepts, in particular when dealing with driver-compressed textures. Furthermore the driver might not actually be able to determine the implicit modifier if all the buffer-passing has used explicit modifier. All these issues should be resolved by passing in the modifier, and for that we switch to using the PRIME_2 memory type. Tested with experimental radeonsi patches for modifiers and kmsgrab. Also tested with radeonsi without the patches to double-check it works without PRIME_2 support. v2: Cache PRIME_2 support to avoid doing two calls every time on libva drivers that do not support it. v3: Remove prime2_vas usage. Signed-off-by: Bas Nieuwenhuizen --- libavutil/hwcontext_vaapi.c | 158 ++-- 1 file changed, 114 insertions(+), 44 deletions(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 83e542876d..75acc851d6 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -79,6 +79,9 @@ typedef struct VAAPIFramesContext { unsigned int rt_format; // Whether vaDeriveImage works. int derive_works; +// Caches whether VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2 is unsupported for +// surface imports. +int prime_2_import_unsupported; } VAAPIFramesContext; typedef struct VAAPIMapping { @@ -1022,32 +1025,17 @@ static void vaapi_unmap_from_drm(AVHWFramesContext *dst_fc, static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, const AVFrame *src, int flags) { +VAAPIFramesContext *src_vafc = src_fc->internal->priv; AVHWFramesContext *dst_fc = (AVHWFramesContext*)dst->hw_frames_ctx->data; AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; const AVDRMFrameDescriptor *desc; const VAAPIFormatDescriptor *format_desc; VASurfaceID surface_id; -VAStatus vas; +VAStatus vas = VA_STATUS_SUCCESS; +int use_prime2; uint32_t va_fourcc; -int err, i, j, k; - -unsigned long buffer_handle; -VASurfaceAttribExternalBuffers buffer_desc; -VASurfaceAttrib attrs[2] = { -{ -.type = VASurfaceAttribMemoryType, -.flags = VA_SURFACE_ATTRIB_SETTABLE, -.value.type= VAGenericValueTypeInteger, -.value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME, -}, -{ -.type = VASurfaceAttribExternalBufferDescriptor, -.flags = VA_SURFACE_ATTRIB_SETTABLE, -.value.type= VAGenericValueTypePointer, -.value.value.p = &buffer_desc, -} -}; +int err, i, j; desc = (AVDRMFrameDescriptor*)src->data[0]; @@ -1083,35 +1071,117 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, format_desc = vaapi_format_from_fourcc(va_fourcc); av_assert0(format_desc); -buffer_handle = desc->objects[0].fd; -buffer_desc.pixel_format = va_fourcc; -buffer_desc.width= src_fc->width; -buffer_desc.height = src_fc->height; -buffer_desc.data_size= desc->objects[0].size; -buffer_desc.buffers = &buffer_handle; -buffer_desc.num_buffers = 1; -buffer_desc.flags= 0; - -k = 0; -for (i = 0; i < desc->nb_layers; i++) { -for (j = 0; j < desc->layers[i].nb_planes; j++) { -buffer_desc.pitches[k] = desc->layers[i].planes[j].pitch; -buffer_desc.offsets[k] = desc->layers[i].planes[j].offset; -++k; +use_prime2 = !src_vafc->prime_2_import_unsupported && + desc->objects[0].format_modifier != DRM_FORMAT_MOD_INVALID; +if (use_prime2) { +VADRMPRIMESurfaceDescriptor prime_desc; +VASurfaceAttrib prime_attrs[2] = { +{ +.type = VASurfaceAttribMemoryType, +.flags = VA_SURFACE_ATTRIB_SETTABLE, +.value.type= VAGenericValueTypeInteger, +.value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, +}, +{ +.type = VASurfaceAttribExternalBufferDescriptor, +.flags = VA_SURFACE_ATTRIB_SETTABLE, +.value.type= VAGenericValueTypePointer, +.value.value.p = &prime_desc, +} +}; +prime_desc.fourcc = va_fourcc; +prime_desc.width = src_fc->width; +prime_desc.height = src_fc->height; +prime_desc.num_objects = desc->nb_objects; +for (i = 0; i < desc->nb_objects; ++i) { +prime_desc.objects[i].fd = desc->objects[i].fd; +prime_desc.objects[i].size = desc->objects[i].size; +prime_desc.objects[i].drm_format_modifier = +desc->objects[i].format_modifier; } -} -buffer_desc.num_planes = k; -if (format_desc->chroma_planes
[FFmpeg-devel] [PATCH V5 2/5] libavutil/hwcontext_vaapi: Add a new nv12 format map to support vulkan frame
Vulkan will map nv12 to R8 and GR88, so add this map to vaapi to support vulkan frame. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vaapi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 75acc851d6..994b744e4d 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -992,6 +992,7 @@ static const struct { } vaapi_drm_format_map[] = { #ifdef DRM_FORMAT_R8 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88), +DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_GR88), #endif DRM_MAP(NV12, 1, DRM_FORMAT_NV12), #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16) -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V5 3/5] libavutil/hwcontext_vulkan: Allocate vkFrame in one memory
The vaapi can import external frame, but the planes of the external frames should be in the same drm object. A new option "contiguous_planes" is added to device. This flag tells device to allocate places in one memory. When device is derived from vaapi this flag will be enabled. A new flag frame_flag is also added to AVVulkanFramesContext. User can use this flag to force enable or disable this behaviour. A new variable "offset "is added to AVVKFrame. It describe describe the offset from the memory currently bound to the VkImage. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 68 +++- libavutil/hwcontext_vulkan.h | 24 + 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index a0437c9661..eef9009ae1 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -103,8 +103,14 @@ typedef struct VulkanDevicePriv { /* Settings */ int use_linear_images; +/* allocate planes in a contiguous memory */ +int contiguous_planes; + /* Nvidia */ int dev_is_nvidia; + +/* Intel */ +int dev_is_intel; } VulkanDevicePriv; typedef struct VulkanFramesPriv { @@ -153,6 +159,8 @@ typedef struct AVVkFrameInternal { av_free((void *)props); \ } +#define VKF_FLAG(x, f) (((x) & (~AV_VK_FRAME_FLAG_NONE)) & (f)) + static const struct { enum AVPixelFormat pixfmt; const VkFormat vkfmts[4]; @@ -1374,6 +1382,13 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, if (opt_d) p->use_linear_images = strtol(opt_d->value, NULL, 10); +opt_d = av_dict_get(opts, "contiguous_planes", NULL, 0); +if (opt_d) +p->contiguous_planes = strtol(opt_d->value, NULL, 10); +else +p->contiguous_planes = -1; + + hwctx->enabled_dev_extensions = dev_info.ppEnabledExtensionNames; hwctx->nb_enabled_dev_extensions = dev_info.enabledExtensionCount; @@ -1425,6 +1440,8 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) p->dev_is_nvidia = (p->props.properties.vendorID == 0x10de); +p->dev_is_intel = (p->props.properties.vendorID == 0x8086); + vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &queue_num, NULL); if (!queue_num) { av_log(ctx, AV_LOG_ERROR, "Failed to get queues!\n"); @@ -1742,8 +1759,12 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, AVHWDeviceContext *ctx = hwfc->device_ctx; VulkanDevicePriv *p = ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; +AVVulkanFramesContext *hwfctx = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { { 0 } }; +VkMemoryRequirements memory_requirements = { 0 }; +int mem_size = 0; +int mem_size_list[AV_NUM_DATA_POINTERS] = { 0 }; AVVulkanDeviceContext *hwctx = ctx->hwctx; @@ -1771,6 +1792,19 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, req.memoryRequirements.size = FFALIGN(req.memoryRequirements.size, p->props.properties.limits.minMemoryMapAlignment); +if (VKF_FLAG(hwfctx->flags, AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY)) { +if (memory_requirements.size == 0) { +memory_requirements = req.memoryRequirements; +} else if (memory_requirements.memoryTypeBits != req.memoryRequirements.memoryTypeBits) { +av_log(hwfc, AV_LOG_ERROR, "the param for each planes are not the same\n"); +return AVERROR(EINVAL); +} + +mem_size_list[i] = req.memoryRequirements.size; +mem_size += mem_size_list[i]; +continue; +} + /* In case the implementation prefers/requires dedicated allocation */ use_ded_mem = ded_req.prefersDedicatedAllocation | ded_req.requiresDedicatedAllocation; @@ -1792,6 +1826,29 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, bind_info[i].memory = f->mem[i]; } +if (VKF_FLAG(hwfctx->flags, AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY)) { +memory_requirements.size = mem_size; + +/* Allocate memory */ +if ((err = alloc_mem(ctx, &memory_requirements, +f->tiling == VK_IMAGE_TILING_LINEAR ? +VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT : +VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, +(void *)(((uint8_t *)alloc_pnext)), +&f->flags, &f->mem[0]))) +return err; + +f
[FFmpeg-devel] [PATCH V5 4/5] libavutil/hwcontext_vulkan: Add support to hwmap to software frame when using contiguous_planes flag.
Add support to map vulkan frames to software frames when using contiguous_planes flag. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index eef9009ae1..f980b72720 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2327,9 +2327,10 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { VkResult ret; -int err, mapped_mem_count = 0; +int err, mapped_mem_count = 0, loop = 0; AVVkFrame *f = (AVVkFrame *)src->data[0]; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; +AVVulkanFramesContext *hwfctx = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; @@ -2356,7 +2357,9 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, dst->width = src->width; dst->height = src->height; -for (int i = 0; i < planes; i++) { +loop = VKF_FLAG(hwfctx->flags, AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY) ? + 1 : planes; +for (int i = 0; i < loop; i++) { ret = vk->MapMemory(hwctx->act_dev, f->mem[i], 0, VK_WHOLE_SIZE, 0, (void **)&dst->data[i]); if (ret != VK_SUCCESS) { @@ -2367,6 +2370,10 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, } mapped_mem_count++; } +if (VKF_FLAG(hwfctx->flags, AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY)) { +for (int i = 0; i < planes; i++) +dst->data[i] = dst->data[0] + f->offset[i]; +} /* Check if the memory contents matter */ if (((flags & AV_HWFRAME_MAP_READ) || !(flags & AV_HWFRAME_MAP_OVERWRITE)) && -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V5 5/5] libavutil/hwcontext_vulkan: specify the modifier to create VKImage
When vulkan image exports to drm, the tilling need to be VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT. Now add code to create vulkan image using this format. Now the following command line works: ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format \ vaapi -i input_1080p.264 -vf "hwmap=derive_device=vulkan,format=vulkan, \ scale_vulkan=1920:1080,hwmap=derive_device=vaapi,format=vaapi" -c:v h264_vaapi output.264 Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 127 +-- 1 file changed, 121 insertions(+), 6 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index f980b72720..8224c0d4e4 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -120,6 +120,9 @@ typedef struct VulkanFramesPriv { /* Image transfers */ VulkanExecCtx upload_ctx; VulkanExecCtx download_ctx; + +/*modifier info*/ +VkImageDrmFormatModifierListCreateInfoEXT *modifier_info; } VulkanFramesPriv; typedef struct AVVkFrameInternal { @@ -242,6 +245,28 @@ const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p) return NULL; } +static void *find_in_structure_list(VkBaseOutStructure *stru_list, VkStructureType sType) { +if (!stru_list) +return NULL; + +for(;stru_list;stru_list = stru_list->pNext) +if (stru_list->sType == sType) +return stru_list; + +return NULL; +} + +static void append_to_structure_list(VkBaseOutStructure **stru_list, VkBaseOutStructure *added_stru) { +VkBaseOutStructure *p; +if (!*stru_list) { +*stru_list = added_stru; +return; +} +for(p = *stru_list; p->pNext; p = p->pNext); +p->pNext = added_stru; +return; +} + static int pixfmt_is_supported(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p, int linear) { @@ -2094,6 +2119,10 @@ static void try_export_flags(AVHWFramesContext *hwfc, AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; +const int has_modifiers = hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; +int loop_count; +VkImageDrmFormatModifierListCreateInfoEXT *modifier_info = find_in_structure_list(hwctx->create_pnext, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT); VkExternalImageFormatProperties eprops = { .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR, }; @@ -2101,9 +2130,18 @@ static void try_export_flags(AVHWFramesContext *hwfc, .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, .pNext = &eprops, }; +VkPhysicalDeviceImageDrmFormatModifierInfoEXT phy_dev_mod_info = { +.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, +.pNext = NULL, +.pQueueFamilyIndices = p->qfs, +.queueFamilyIndexCount = p->num_qfs, +.sharingMode = p->num_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : + VK_SHARING_MODE_EXCLUSIVE, +}; VkPhysicalDeviceExternalImageFormatInfo enext = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, .handleType = exp, +.pNext = has_modifiers && modifier_info ? &phy_dev_mod_info : NULL, }; VkPhysicalDeviceImageFormatInfo2 pinfo = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, @@ -2115,11 +2153,16 @@ static void try_export_flags(AVHWFramesContext *hwfc, .flags = VK_IMAGE_CREATE_ALIAS_BIT, }; -ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, - &pinfo, &props); -if (ret == VK_SUCCESS) { -*iexp |= exp; -*comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; +loop_count = has_modifiers && modifier_info ? modifier_info->drmFormatModifierCount : 1; +for (int i = 0; i < loop_count; i++) { +if (has_modifiers && modifier_info) +phy_dev_mod_info.drmFormatModifier = modifier_info->pDrmFormatModifiers[i]; +ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, +&pinfo, &props); +if (ret == VK_SUCCESS) { +*iexp |= exp; +*comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; +} } } @@ -2190,6 +2233,12 @@ static void vulkan_frames_uninit(AVHWFramesContext *hwfc) { VulkanFramesPriv *fp = hwfc->internal->priv; +if (fp->modifier_info) { +if (fp->modifier_info->pDrmFormatModifiers) +
[FFmpeg-devel] [PATCH] libavutil/hwcontext_qsv: clean padding when upload qsv frames
When we upload a frame that is not padded as MSDK requires, we create a new AVFrame to copy data. The frame's padding data is uninitialized so it brings run to run problem. For example, If we run the following command serveral times we will get different outputs. ffmpeg -init_hw_device qsv=qsv:hw -qsv_device /dev/dri/renderD128 -filter_hw_device qsv -f rawvideo -s 192x200 -pix_fmt p010 -i 192x200_P010.yuv -vf "format=nv12,hwupload=extra_hw_frames=16" -c:v hevc_qsv output.265 According to https://github.com/Intel-Media-SDK/MediaSDK/blob/master/doc/mediasdk-man.md#encoding-procedures "Note: It is the application's responsibility to fill pixels outside of crop window when it is smaller than frame to be encoded. Especially in cases when crops are not aligned to minimum coding block size (16 for AVC, 8 for HEVC and VP9)" I add a function to fill padding area with border pixel to fix this run2run problem, and also move the new AVFrame to global structure to reduce redundant allocation operation to increase preformance. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_qsv.c | 96 +-- 1 file changed, 83 insertions(+), 13 deletions(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 268be9f8a1..983494666b 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -47,6 +47,7 @@ #include "pixfmt.h" #include "pixdesc.h" #include "time.h" +#include "imgutils.h" #define QSV_VERSION_ATLEAST(MAJOR, MINOR) \ (MFX_VERSION_MAJOR > (MAJOR) || \ @@ -90,6 +91,7 @@ typedef struct QSVFramesContext { mfxExtOpaqueSurfaceAlloc opaque_alloc; mfxExtBuffer *ext_buffers[1]; +AVFrame realigned_tmp_frame; } QSVFramesContext; static const struct { @@ -137,6 +139,54 @@ static uint32_t qsv_get_d3d11va_bind_flags(int mem_type) } #endif +static int qsv_fill_border(AVFrame *dst, const AVFrame *src) +{ +const AVPixFmtDescriptor *desc; +int i, planes_nb = 0; +if (dst->format != src->format) +return AVERROR(EINVAL); + +desc = av_pix_fmt_desc_get(dst->format); + +for (i = 0; i < desc->nb_components; i++) +planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1); + +for (i = 0; i < planes_nb; i++) { +int sheight, dheight, y; +ptrdiff_t swidth = av_image_get_linesize(src->format, + src->width, + i); +ptrdiff_t dwidth = av_image_get_linesize(dst->format, + dst->width, + i); +const AVComponentDescriptor comp = desc->comp[i]; +if (swidth < 0 || dwidth < 0) { +av_log(NULL, AV_LOG_ERROR, "av_image_get_linesize failed\n"); +return AVERROR(EINVAL); +} +sheight = src->height; +dheight = dst->height; +if (i) { +sheight = AV_CEIL_RSHIFT(src->height, desc->log2_chroma_h); +dheight = AV_CEIL_RSHIFT(dst->height, desc->log2_chroma_h); +} +//fill right padding +for (y = 0; y < sheight; y++) { +void *line_ptr = dst->data[i] + y*dst->linesize[i] + swidth; +av_memcpy_backptr(line_ptr, + comp.depth > 8 ? 2 : 1, + dwidth - swidth); +} +//fill bottom padding +for (y = sheight; y < dheight; y++) { +memcpy(dst->data[i]+y*dst->linesize[i], + dst->data[i]+(sheight-1)*dst->linesize[i], + dwidth); +} +} +return 0; +} + static int qsv_device_init(AVHWDeviceContext *ctx) { AVQSVDeviceContext *hwctx = ctx->hwctx; @@ -220,6 +270,7 @@ static void qsv_frames_uninit(AVHWFramesContext *ctx) av_freep(&s->surface_ptrs); av_freep(&s->surfaces_internal); av_freep(&s->handle_pairs_internal); +av_frame_unref(&s->realigned_tmp_frame); av_buffer_unref(&s->child_frames_ref); } @@ -1014,12 +1065,13 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, QSVFramesContext *s = ctx->internal->priv; mfxFrameSurface1 in = {{ 0 }}; mfxFrameSurface1 *out = (mfxFrameSurface1*)dst->data[3]; +mfxFrameInfo tmp_info; mfxSyncPoint sync = NULL; mfxStatus err; int ret = 0; /* make a copy if the input is not padded as libmfx requires */ -AVFrame tmp_frame; +AVFrame *tmp_frame = &s->realigned_tmp_frame; const AVFrame *src_frame; int realigned = 0; @@ -1048,24 +1100,40 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, if (ret < 0) return ret; +/* According to MSDK spec
[FFmpeg-devel] [PATCH] libavcodec/qsvdec: skip non-key frame after "seek" function
From: "Chen,Wenbin" Fix #9095. Qsv decoder assume that after calling seek funcion, the first frame should be key frame. However this is not true for some videos. If the frame is not key frame after seek(), there will be error. Conditional statements are added to skip these frame until reading a key frame. Signed-off-by: Wenbin Chen --- libavcodec/qsvdec.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index d10f90a0db..8133406085 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -616,6 +616,13 @@ int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, } if (!q->initialized) { + +/* skip non-key frame when decoder is reinitialized. +Adding before will skip all the non-key frames so add +it here */ +if (ret < 0) +return ret; + ret = qsv_decode_init_context(avctx, q, ¶m); if (ret < 0) goto reinit_fail; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] libavcodec/vaapi_encode: Change libva call to async way
From: "Chen,Wenbin" Fix: #7706. After commit 5fdcf85bbffe7451c2, vaapi encoder's performance drop 20~30%. One reason is that vaRenderPicture() and vaSyncSurface() are called at the same time (vaRenderPicture() always followed by a vaSyncSurface()). Now I changed them to be called in a asynchronous way, which will make better use of hardware. Another reason of performance drop is that in old version, ffmpeg-vaapi use CQP as default while the ffmpeg-vaapi of lastest version does not, so the same command line will have a even bigger performance gap. To test this patch you'd better specify the bitrate (-b:v XXX). Signed-off-by: Wenbin CHEN --- libavcodec/vaapi_encode.c | 42 +-- libavcodec/vaapi_encode.h | 3 +++ 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 518e5b2c00..851dea3fc2 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -950,8 +950,10 @@ static int vaapi_encode_pick_next(AVCodecContext *avctx, if (!pic && ctx->end_of_stream) { --b_counter; pic = ctx->pic_end; -if (pic->encode_issued) +if (pic->encode_complete) return AVERROR_EOF; +else if (pic->encode_issued) +return AVERROR(EAGAIN); } if (!pic) { @@ -1176,20 +1178,34 @@ int ff_vaapi_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) return AVERROR(EAGAIN); } -pic = NULL; -err = vaapi_encode_pick_next(avctx, &pic); -if (err < 0) -return err; -av_assert0(pic); +if (av_fifo_size(ctx->encode_fifo) == 0) { +while (!err) { +pic = NULL; +err = vaapi_encode_pick_next(avctx, &pic); +if (err == AVERROR(EAGAIN)) +break; +else if (err < 0) +return err; +av_assert0(pic); -pic->encode_order = ctx->encode_order++; +pic->encode_order = ctx->encode_order++; -err = vaapi_encode_issue(avctx, pic); -if (err < 0) { -av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err); -return err; +err = vaapi_encode_issue(avctx, pic); +if (err < 0) { +av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err); +return err; +} + +av_fifo_generic_write(ctx->encode_fifo, &pic, sizeof(pic), NULL); +} } +if (av_fifo_size(ctx->encode_fifo) == 0) +return err; + +av_fifo_generic_read(ctx->encode_fifo, &pic, sizeof(pic), NULL); +ctx->encode_order = pic->encode_order+1; + err = vaapi_encode_output(avctx, pic, pkt); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Output failed: %d.\n", err); @@ -2519,6 +2535,10 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) } } +ctx->encode_fifo = av_fifo_alloc((MAX_PICTURE_REFERENCES+1)* sizeof(VAAPIEncodePicture *)); +if (!ctx->encode_fifo) +return AVERROR(ENOMEM); + return 0; fail: diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index b41604a883..89fe8de466 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -29,6 +29,7 @@ #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_vaapi.h" +#include "libavutil/fifo.h" #include "avcodec.h" #include "hwconfig.h" @@ -345,6 +346,8 @@ typedef struct VAAPIEncodeContext { int roi_warned; AVFrame *frame; + +AVFifoBuffer *encode_fifo; } VAAPIEncodeContext; enum { -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] libavcodec/qsvdec.c: using queue count to unref frame
From: "Chen,Wenbin" MSDK vc1 and av1 sometimes output frame into the same suface, but ffmpeg-qsv assume the surface will be used only once, so it will unref the frame when it receives the outpur surface. Now change it to unref frame according to queue count. Signed-off-by Wenbin Chen --- libavcodec/qsvdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index d10f90a0db..e073e10699 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -470,7 +470,7 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, return AVERROR_BUG; } -out_frame->queued = 1; +out_frame->queued += 1; av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL); av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL); } else { @@ -483,7 +483,7 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL); av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL); -out_frame->queued = 0; +out_frame->queued -= 1; if (avctx->pix_fmt != AV_PIX_FMT_QSV) { do { -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V2] libavcodec/qsvdec.c: using queue count to unref frame
From: "Chen,Wenbin" MSDK vc1 and av1 sometimes output frame into the same suface, but ffmpeg-qsv assume the surface will be used only once, so it will unref the frame when it receives the output surface. Now change it to unref frame according to queue count. Signed-off-by Wenbin Chen --- libavcodec/qsvdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 5f2e641373..3abd7bd4a2 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -513,7 +513,7 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, return AVERROR_BUG; } -out_frame->queued = 1; +out_frame->queued += 1; av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL); av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL); } else { @@ -526,7 +526,7 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL); av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL); -out_frame->queued = 0; +out_frame->queued -= 1; if (avctx->pix_fmt != AV_PIX_FMT_QSV) { do { -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] libavcodec/qsvdec: reinit decoder according to decode() return value
From: "Chen,Wenbin" FFmpeg-qsv decoder reinit codec when width and height change, but there are not only resolution change need to reinit codec. I change it to use return value from DecodeFrameAsync() to decide whether decoder need to be reinitialized. Signed-off-by Wenbin Chen --- libavcodec/qsvdec.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index bca6e217fa..124f3e0a7a 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -438,6 +438,12 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE); +if (ret == MFX_ERR_INCOMPATIBLE_VIDEO_PARAM) { +q->reinit_flag = 1; +av_log(avctx, AV_LOG_VERBOSE, "Video parameter change\n"); +return 0; +} + if (ret != MFX_ERR_NONE && ret != MFX_ERR_MORE_DATA && ret != MFX_WRN_VIDEO_PARAM_CHANGED && @@ -591,9 +597,9 @@ int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, ret = qsv_decode_header(avctx, q, pkt, pix_fmt, ¶m); -if (ret >= 0 && (q->orig_pix_fmt != ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC) || +if (q->reinit_flag || (ret >= 0 && (q->orig_pix_fmt != ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC) || avctx->coded_width != param.mfx.FrameInfo.Width || -avctx->coded_height != param.mfx.FrameInfo.Height)) { +avctx->coded_height != param.mfx.FrameInfo.Height))) { AVPacket zero_pkt = {0}; if (q->buffered_count) { -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] libavcodec/qsvdec: use the param from decodeHeader to configure surface
From: "Chen,Wenbin" MSDK recognizes both yuv420p10 and yuv420p9 as MFX_FOURCC_P010, but param are different. When decode yuv420p9 video, ffmpeg-qsv will use yuv420p10le to configure surface which is different with param from DecoderHeader and this will lead to error. Now change it use param from decoderHeader to configure surface. Signed-off-by Wenbin Chen --- libavcodec/qsvdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 569ccd4fba..3ab48ea7a2 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -309,13 +309,13 @@ static int alloc_frame(AVCodecContext *avctx, QSVContext *q, QSVFrame *frame) if (frame->frame->format == AV_PIX_FMT_QSV) { frame->surface = *(mfxFrameSurface1*)frame->frame->data[3]; } else { -frame->surface.Info = q->frame_info; - frame->surface.Data.PitchLow = frame->frame->linesize[0]; frame->surface.Data.Y= frame->frame->data[0]; frame->surface.Data.UV = frame->frame->data[1]; } +frame->surface.Info = q->frame_info; + if (q->frames_ctx.mids) { ret = ff_qsv_find_surface_idx(&q->frames_ctx, frame); if (ret < 0) -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] libavcodec/qsvenc: add more ChromaFormat support for mjpeg-qsv
From: "Chen,Wenbin" ChromaForamt for mjpeg-qsv is always set to yuv420, and this will be wrong when encode other pixel format (for example yuyv422). I change this assignment to be adaptive to pix_fmt. Signed-off-by: Wenbin Chen --- libavcodec/qsvenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 566a5c8552..a0fc206364 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -445,7 +445,8 @@ static int init_video_param_jpeg(AVCodecContext *avctx, QSVEncContext *q) q->param.mfx.FrameInfo.CropH = avctx->height; q->param.mfx.FrameInfo.AspectRatioW = avctx->sample_aspect_ratio.num; q->param.mfx.FrameInfo.AspectRatioH = avctx->sample_aspect_ratio.den; -q->param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; +q->param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420 + +!desc->log2_chroma_w + !desc->log2_chroma_h; q->param.mfx.FrameInfo.BitDepthLuma = desc->comp[0].depth; q->param.mfx.FrameInfo.BitDepthChroma = desc->comp[0].depth; q->param.mfx.FrameInfo.Shift = desc->comp[0].depth > 8; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] libavfilter/qsvvpp: change the output frame's width and height
From: "Chen,Wenbin" qsvvpp align the width and height with 16, and that may lead to error. For example, when we use qsvvpp to resize frame to 1080p, qsvvpp will align frame to 1088 which is different from the height of encoder (1080) and this will be treated as resolution change. Now I assign the out_link's w/h to output frame to overwrite the w/h got from hw_frame_ctx. Signed-off-by: Wenbin Chen --- libavfilter/qsvvpp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index f216b3f248..8658a70083 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -476,6 +476,9 @@ static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink) return NULL; } +out_frame->frame->width = outlink->w; +out_frame->frame->height = outlink->h; + out_frame->surface = (mfxFrameSurface1 *)out_frame->frame->data[3]; } else { /* Get a frame with aligned dimensions. -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V2] libavcodec/qsvdec: reinit decoder according to decode() return value
From: "Chen,Wenbin" FFmpeg-qsv decoder reinit codec when width and height change, but there are not only resolution change need to reinit codec. I change it to use return value from DecodeFrameAsync() to decide whether decoder need to be reinitialized. Signed-off-by Wenbin Chen --- libavcodec/qsvdec.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 5f2e641373..88232f5d8d 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -481,6 +481,13 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE); +if (ret == MFX_ERR_INCOMPATIBLE_VIDEO_PARAM) { +q->reinit_flag = 1; +av_log(avctx, AV_LOG_DEBUG, "Video parameter change\n"); +av_freep(&sync); +return 0; +} + if (ret != MFX_ERR_NONE && ret != MFX_ERR_MORE_DATA && ret != MFX_WRN_VIDEO_PARAM_CHANGED && @@ -632,9 +639,9 @@ static int qsv_process_data(AVCodecContext *avctx, QSVContext *q, ret = qsv_decode_header(avctx, q, pkt, pix_fmt, ¶m); -if (ret >= 0 && (q->orig_pix_fmt != ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC) || +if (q->reinit_flag || (ret >= 0 && (q->orig_pix_fmt != ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC) || avctx->coded_width != param.mfx.FrameInfo.Width || -avctx->coded_height != param.mfx.FrameInfo.Height)) { +avctx->coded_height != param.mfx.FrameInfo.Height))) { AVPacket zero_pkt = {0}; if (q->buffered_count) { -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V2] libavfilter/qsvvpp: change the output frame's width and height
From: "Chen,Wenbin" qsvvpp align the width and height with 16, and that may lead to error. For example, when we use qsvvpp to resize frame to 1080p, qsvvpp will align frame to 1088 which is different from the height of encoder (1080) and this will be treated as resolution change. Now I assign the out_link's w/h to output frame to overwrite the w/h got from hw_frame_ctx. Signed-off-by: Wenbin Chen --- libavfilter/qsvvpp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index f216b3f248..70d6cb49e3 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -486,9 +486,6 @@ static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink) if (!out_frame->frame) return NULL; -out_frame->frame->width = outlink->w; -out_frame->frame->height = outlink->h; - ret = map_frame_to_surface(out_frame->frame, &out_frame->surface_internal); if (ret < 0) @@ -497,6 +494,8 @@ static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink) out_frame->surface = &out_frame->surface_internal; } +out_frame->frame->width = outlink->w; +out_frame->frame->height = outlink->h; out_frame->surface->Info = s->vpp_param.vpp.Out; return out_frame; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V3] libavfilter/qsvvpp: change the output frame's width and height
From: "Chen,Wenbin" qsvvpp align the width and height with 16, and that right. But qsvvpp asign this value to frame->width and frame->height, and that may lead to error. For example, when we use qsvvpp to resize frame to 1080p, qsvvpp will align frame to 1088 and set frame->height to 1088, which is different from the height of encoder (1080) and this will be treated as resolution change. The aligend value can be kept in hw_frame_ctx as it is hardware dependent. Now I assign the out_link's w/h to output frame to overwrite the w/h got from hw_frame_ctx. Signed-off-by: Wenbin Chen --- libavfilter/qsvvpp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index f216b3f248..70d6cb49e3 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -486,9 +486,6 @@ static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink) if (!out_frame->frame) return NULL; -out_frame->frame->width = outlink->w; -out_frame->frame->height = outlink->h; - ret = map_frame_to_surface(out_frame->frame, &out_frame->surface_internal); if (ret < 0) @@ -497,6 +494,8 @@ static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink) out_frame->surface = &out_frame->surface_internal; } +out_frame->frame->width = outlink->w; +out_frame->frame->height = outlink->h; out_frame->surface->Info = s->vpp_param.vpp.Out; return out_frame; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] libavcodec/qsvenc: add mbbrc to hevc_qsv
From: "Chen,Wenbin" Add mbbrc to hevc_qsv For detailed description, please see "mbbrc" part in: https://github.com/Intel-Media-SDK/MediaSDK/blob/master/doc/mediasdk-man.md#mfxextcodingoption2 Signed-off-by: Wenbin Chen --- libavcodec/qsvenc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 566a5c8552..19e246a8fb 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -701,8 +701,6 @@ FF_ENABLE_DEPRECATION_WARNINGS if (q->bitrate_limit >= 0) q->extco2.BitrateLimit = q->bitrate_limit ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; -if (q->mbbrc >= 0) -q->extco2.MBBRC = q->mbbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; if (q->max_frame_size >= 0) q->extco2.MaxFrameSize = q->max_frame_size; @@ -755,6 +753,9 @@ FF_ENABLE_DEPRECATION_WARNINGS q->extco2.MaxQPP = q->extco2.MaxQPB = q->extco2.MaxQPI; } #endif +if (q->mbbrc >= 0) +q->extco2.MBBRC = q->mbbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + q->extco2.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2; q->extco2.Header.BufferSz = sizeof(q->extco2); -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 1/3] libavcodec/qsvdec: reinit decoder according to decode() return value
From: "Chen,Wenbin" FFmpeg-qsv decoder reinit codec when width and height change, but there are not only resolution change need to reinit codec. I change it to use return value from DecodeFrameAsync() to decide whether decoder need to be reinitialized. Signed-off-by Wenbin Chen Signed-off-by Guangxin Xu --- libavcodec/qsvdec.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 5f2e641373..88232f5d8d 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -481,6 +481,13 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE); +if (ret == MFX_ERR_INCOMPATIBLE_VIDEO_PARAM) { +q->reinit_flag = 1; +av_log(avctx, AV_LOG_DEBUG, "Video parameter change\n"); +av_freep(&sync); +return 0; +} + if (ret != MFX_ERR_NONE && ret != MFX_ERR_MORE_DATA && ret != MFX_WRN_VIDEO_PARAM_CHANGED && @@ -632,9 +639,9 @@ static int qsv_process_data(AVCodecContext *avctx, QSVContext *q, ret = qsv_decode_header(avctx, q, pkt, pix_fmt, ¶m); -if (ret >= 0 && (q->orig_pix_fmt != ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC) || +if (q->reinit_flag || (ret >= 0 && (q->orig_pix_fmt != ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC) || avctx->coded_width != param.mfx.FrameInfo.Width || -avctx->coded_height != param.mfx.FrameInfo.Height)) { +avctx->coded_height != param.mfx.FrameInfo.Height))) { AVPacket zero_pkt = {0}; if (q->buffered_count) { -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 2/3] libavcodec/qsvdec: remove redundant decodeHeader()
From: "Chen,Wenbin" Since ffmpeg-qsv uses return value to reinit decoder, it doesn't need to decode header each time. Move qsv_decode_header's position so that it will be called only if codec needed to be reinitialized. Rearrange the code of flushing decoder and re-init decoder operation. Remove the buffer_count and use the got_frame to decide whether the decoder is drain. Signed-off-by: Wenbin Chen Signed-off-by Guangxin Xu --- libavcodec/qsvdec.c | 26 -- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 88232f5d8d..fe416e74ca 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -63,7 +63,6 @@ typedef struct QSVContext { AVFifoBuffer *async_fifo; int zero_consume_run; -int buffered_count; int reinit_flag; enum AVPixelFormat orig_pix_fmt; @@ -504,8 +503,6 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, ++q->zero_consume_run; if (q->zero_consume_run > 1) ff_qsv_print_warning(avctx, ret, "A decode call did not consume any data"); -} else if (!*sync && bs.DataOffset) { -++q->buffered_count; } else { q->zero_consume_run = 0; } @@ -637,20 +634,21 @@ static int qsv_process_data(AVCodecContext *avctx, QSVContext *q, if (!avctx->coded_height) avctx->coded_height = 720; -ret = qsv_decode_header(avctx, q, pkt, pix_fmt, ¶m); - -if (q->reinit_flag || (ret >= 0 && (q->orig_pix_fmt != ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC) || -avctx->coded_width != param.mfx.FrameInfo.Width || -avctx->coded_height != param.mfx.FrameInfo.Height))) { +/* decode zero-size pkt to flush the buffered pkt before reinit */ +if (q->reinit_flag) { AVPacket zero_pkt = {0}; +ret = qsv_decode(avctx, q, frame, got_frame, &zero_pkt); +if (*got_frame) +return ret; +} -if (q->buffered_count) { -q->reinit_flag = 1; -/* decode zero-size pkt to flush the buffered pkt before reinit */ -q->buffered_count--; -return qsv_decode(avctx, q, frame, got_frame, &zero_pkt); -} +if (q->reinit_flag || !q->session) { q->reinit_flag = 0; +ret = qsv_decode_header(avctx, q, pkt, pix_fmt, ¶m); +if (ret < 0) { +av_log(avctx, AV_LOG_ERROR, "Error decoding header\n"); +goto reinit_fail; +} q->orig_pix_fmt = avctx->pix_fmt = pix_fmt = ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC); -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 3/3] libavcodec/qsvdec: using suggested num to set init_pool_size
From: Wenbinc-Bin The init_pool_size is set to be 64 and it is too many. Use IOSurfQuery to get NumFrameSuggest which is the suggested number of frame that needed to be allocated when initializing the decoder. Considering that the hevc_qsv encoder uses the most frame buffer, async is 4 (default) and max_b_frames is 8 (default) and decoder may followed by VPP, use NumFrameSuggest + 16 to set init_pool_size. Sigend-off-by Wenbin Chen Signed-off-by Guangxin Xu --- fftools/ffmpeg_qsv.c | 9 - libavcodec/qsvdec.c | 14 ++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/fftools/ffmpeg_qsv.c b/fftools/ffmpeg_qsv.c index 960c88b69d..3862dc1e7d 100644 --- a/fftools/ffmpeg_qsv.c +++ b/fftools/ffmpeg_qsv.c @@ -74,6 +74,7 @@ int qsv_init(AVCodecContext *s) InputStream *ist = s->opaque; AVHWFramesContext *frames_ctx; AVQSVFramesContext *frames_hwctx; +int suggest_pool_size; int ret; if (!hw_device_ctx) { @@ -82,6 +83,12 @@ int qsv_init(AVCodecContext *s) return ret; } +suggest_pool_size = 0; +if (ist->hw_frames_ctx) { +frames_ctx = (AVHWFramesContext *)ist->hw_frames_ctx->data; +suggest_pool_size = frames_ctx->initial_pool_size; +} + av_buffer_unref(&ist->hw_frames_ctx); ist->hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx); if (!ist->hw_frames_ctx) @@ -94,7 +101,7 @@ int qsv_init(AVCodecContext *s) frames_ctx->height= FFALIGN(s->coded_height, 32); frames_ctx->format= AV_PIX_FMT_QSV; frames_ctx->sw_format = s->sw_pix_fmt; -frames_ctx->initial_pool_size = 64 + s->extra_hw_frames; +frames_ctx->initial_pool_size = suggest_pool_size + 16 + s->extra_hw_frames; frames_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; ret = av_hwframe_ctx_init(ist->hw_frames_ctx); diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index fe416e74ca..f7cd33cc74 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -643,18 +643,32 @@ static int qsv_process_data(AVCodecContext *avctx, QSVContext *q, } if (q->reinit_flag || !q->session) { +mfxFrameAllocRequest request; +AVHWFramesContext *hw_frames_ctx; +memset(&request, 0, sizeof(request)); + q->reinit_flag = 0; ret = qsv_decode_header(avctx, q, pkt, pix_fmt, ¶m); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error decoding header\n"); goto reinit_fail; } +param.IOPattern = q->iopattern; q->orig_pix_fmt = avctx->pix_fmt = pix_fmt = ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC); avctx->coded_width = param.mfx.FrameInfo.Width; avctx->coded_height = param.mfx.FrameInfo.Height; +ret = MFXVideoDECODE_QueryIOSurf(q->session, ¶m, &request); +if (ret < 0) +return ff_qsv_print_error(avctx, ret, "Error querying IO surface"); + +if (avctx->hw_frames_ctx) { +hw_frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data; +hw_frames_ctx->initial_pool_size = request.NumFrameSuggested; +} + ret = qsv_decode_preinit(avctx, q, pix_fmt, ¶m); if (ret < 0) goto reinit_fail; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v2 1/7] libavcodec/qsvenc: skip parameter resetting on mjpeg_qsv
mjpeg_qsv don't support dynamic resetting, so skip it. Signed-off-by: Wenbin Chen --- libavcodec/qsvenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 7ac5390f10..842cfb845e 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -1680,7 +1680,7 @@ static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, { int needReset = 0, ret = 0; -if (!frame) +if (!frame || avctx->codec_id == AV_CODEC_ID_MJPEG) return 0; needReset = update_qp(avctx, q); -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v2 2/7] libavcodec/qsvenc: Add max_frame_size reset support to qsv
Signed-off-by: Wenbin Chen --- doc/encoders.texi | 4 libavcodec/qsvenc.c | 20 libavcodec/qsvenc.h | 2 ++ 3 files changed, 26 insertions(+) diff --git a/doc/encoders.texi b/doc/encoders.texi index d36464d629..aadb6ab9fd 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -3344,6 +3344,10 @@ Following options can be used durning qsv encoding. @item @var{b_quant_offset} Supported in h264_qsv and hevc_qsv. Change these value to reset qsv codec's qp configuration. + +@item @var{max_frame_size} +Supported in h264_qsv and hevc_qsv. +Change this value to reset qsv codec's MaxFrameSize configuration. @end table @subsection H264 options diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 842cfb845e..915a1abd26 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -824,6 +824,7 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->extco2.ExtBRC = q->extbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; if (q->max_frame_size >= 0) q->extco2.MaxFrameSize = q->max_frame_size; +q->old_max_frame_size = q->max_frame_size; if (q->int_ref_type >= 0) q->extco2.IntRefType = q->int_ref_type; if (q->int_ref_cycle_size >= 0) @@ -1675,6 +1676,24 @@ static int update_qp(AVCodecContext *avctx, QSVEncContext *q) return updated; } +static int update_max_frame_size(AVCodecContext *avctx, QSVEncContext *q) +{ +int updated = 0; + +if (avctx->codec_id != AV_CODEC_ID_H264 && avctx->codec_id != AV_CODEC_ID_HEVC) +return 0; + +UPDATE_PARAM(q->old_max_frame_size, q->max_frame_size); +if (!updated) +return 0; + +q->extco2.MaxFrameSize = FFMAX(0, q->max_frame_size); +av_log(avctx, AV_LOG_DEBUG, + "Reset MaxFrameSize: %d;\n", q->extco2.MaxFrameSize); + +return updated; +} + static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, const AVFrame *frame) { @@ -1684,6 +1703,7 @@ static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, return 0; needReset = update_qp(avctx, q); +needReset |= update_max_frame_size(avctx, q); if (!needReset) return 0; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index a983651dda..3984ae7dd8 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -249,6 +249,8 @@ typedef struct QSVEncContext { float old_i_quant_offset; float old_b_quant_factor; float old_b_quant_offset; +// This is used for max_frame_size reset +int old_max_frame_size; } QSVEncContext; int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q); -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v2 3/7] libavcodec/qsvenc: Add gop_size reset support to qsvenc
Signed-off-by: Wenbin Chen --- doc/encoders.texi | 3 +++ libavcodec/qsvenc.c | 16 libavcodec/qsvenc.h | 2 ++ 3 files changed, 21 insertions(+) diff --git a/doc/encoders.texi b/doc/encoders.texi index aadb6ab9fd..bc1a4dae38 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -3348,6 +3348,9 @@ Change these value to reset qsv codec's qp configuration. @item @var{max_frame_size} Supported in h264_qsv and hevc_qsv. Change this value to reset qsv codec's MaxFrameSize configuration. + +@item @var{gop_size} +Change this value to reset qsv codec's gop configuration. @end table @subsection H264 options diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 915a1abd26..9a0431630a 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -636,6 +636,7 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->param.mfx.CodecProfile = q->profile; q->param.mfx.TargetUsage= avctx->compression_level; q->param.mfx.GopPicSize = FFMAX(0, avctx->gop_size); +q->old_gop_size = avctx->gop_size; q->param.mfx.GopRefDist = FFMAX(-1, avctx->max_b_frames) + 1; q->param.mfx.GopOptFlag = avctx->flags & AV_CODEC_FLAG_CLOSED_GOP ? MFX_GOP_CLOSED : MFX_GOP_STRICT; @@ -1694,6 +1695,20 @@ static int update_max_frame_size(AVCodecContext *avctx, QSVEncContext *q) return updated; } +static int update_gop_size(AVCodecContext *avctx, QSVEncContext *q) +{ +int updated = 0; +UPDATE_PARAM(q->old_gop_size, avctx->gop_size); +if (!updated) +return 0; + +q->param.mfx.GopPicSize = FFMAX(0, avctx->gop_size); +av_log(avctx, AV_LOG_DEBUG, "reset GopPicSize to %d\n", + q->param.mfx.GopPicSize); + +return updated; +} + static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, const AVFrame *frame) { @@ -1704,6 +1719,7 @@ static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, needReset = update_qp(avctx, q); needReset |= update_max_frame_size(avctx, q); +needReset |= update_gop_size(avctx, q); if (!needReset) return 0; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 3984ae7dd8..5f6955a3a7 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -251,6 +251,8 @@ typedef struct QSVEncContext { float old_b_quant_offset; // This is used for max_frame_size reset int old_max_frame_size; +// This is used for gop reset +int old_gop_size; } QSVEncContext; int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q); -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v2 4/7] libavcodec/qsvenc: Add "slice" intra refresh type to qsvenc
Add "slice" intra refresh type to h264_qsv and hevc_qsv. This type means horizontal refresh by slices without overlapping. Also update the doc. Signed-off-by: Wenbin Chen --- doc/encoders.texi| 12 libavcodec/qsvenc_h264.c | 1 + libavcodec/qsvenc_hevc.c | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/doc/encoders.texi b/doc/encoders.texi index bc1a4dae38..d5d695d39c 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -3454,8 +3454,10 @@ Specifies intra refresh type. The major goal of intra refresh is improvement of error resilience without significant impact on encoded bitstream size caused by I frames. The SDK encoder achieves this by encoding part of each frame in refresh cycle using intra MBs. @var{none} means no refresh. @var{vertical} means -vertical refresh, by column of MBs. To enable intra refresh, B frame should be -set to 0. +vertical refresh, by column of MBs. @var{horizontal} means horizontal refresh, +by rows of MBs. @var{slice} means horizontal refresh by slices without +overlapping. In case of @var{slice}, in_ref_cycle_size is ignored. To enable +intra refresh, B frame should be set to 0. @item @var{int_ref_cycle_size} Specifies number of pictures within refresh cycle starting from 2. 0 and 1 are @@ -3641,8 +3643,10 @@ Specifies intra refresh type. The major goal of intra refresh is improvement of error resilience without significant impact on encoded bitstream size caused by I frames. The SDK encoder achieves this by encoding part of each frame in refresh cycle using intra MBs. @var{none} means no refresh. @var{vertical} means -vertical refresh, by column of MBs. To enable intra refresh, B frame should be -set to 0. +vertical refresh, by column of MBs. @var{horizontal} means horizontal refresh, +by rows of MBs. @var{slice} means horizontal refresh by slices without +overlapping. In case of @var{slice}, in_ref_cycle_size is ignored. To enable +intra refresh, B frame should be set to 0. @item @var{int_ref_cycle_size} Specifies number of pictures within refresh cycle starting from 2. 0 and 1 are diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index 1bbdc45203..8bc4ef95d2 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -139,6 +139,7 @@ static const AVOption options[] = { { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, .flags = VE, "int_ref_type" }, { "vertical", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, .flags = VE, "int_ref_type" }, { "horizontal", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, .flags = VE, "int_ref_type" }, +{ "slice" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3 }, .flags = VE, "int_ref_type" }, { "int_ref_cycle_size", "Number of frames in the intra refresh cycle", OFFSET(qsv.int_ref_cycle_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE }, { "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 }, { "recovery_point_sei", "Insert recovery point SEI messages", OFFSET(qsv.recovery_point_sei), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index 5986c3f1a6..ba7cb6fba6 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -270,6 +270,7 @@ static const AVOption options[] = { { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, .flags = VE, "int_ref_type" }, { "vertical", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, .flags = VE, "int_ref_type" }, { "horizontal", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, .flags = VE, "int_ref_type" }, +{ "slice" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3 }, .flags = VE, "int_ref_type" }, { "int_ref_cycle_size", "Number of frames in the intra refresh cycle", OFFSET(qsv.int_ref_cycle_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE }, { "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 }, -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v2 5/7] libavcodec/qsvenc: Add intra refresh reset support to qsvenc
Signed-off-by: Wenbin Chen --- doc/encoders.texi | 7 +++ libavcodec/qsvenc.c | 33 + libavcodec/qsvenc.h | 5 + 3 files changed, 45 insertions(+) diff --git a/doc/encoders.texi b/doc/encoders.texi index d5d695d39c..da56159858 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -3351,6 +3351,13 @@ Change this value to reset qsv codec's MaxFrameSize configuration. @item @var{gop_size} Change this value to reset qsv codec's gop configuration. + +@item @var{int_ref_type} +@item @var{int_ref_cycle_size} +@item @var{int_ref_qp_delta} +@item @var{int_ref_cycle_dist} +Supported in h264_qsv and hevc_qsv. +Change these value to reset qsv codec's Intra Refresh configuration. @end table @subsection H264 options diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 9a0431630a..cd0549b249 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -828,10 +828,13 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->old_max_frame_size = q->max_frame_size; if (q->int_ref_type >= 0) q->extco2.IntRefType = q->int_ref_type; +q->old_int_ref_type = q->int_ref_type; if (q->int_ref_cycle_size >= 0) q->extco2.IntRefCycleSize = q->int_ref_cycle_size; +q->old_int_ref_cycle_size = q->int_ref_cycle_size; if (q->int_ref_qp_delta != INT16_MIN) q->extco2.IntRefQPDelta = q->int_ref_qp_delta; +q->old_int_ref_qp_delta = q->int_ref_qp_delta; if (q->max_slice_size >= 0) q->extco2.MaxSliceSize = q->max_slice_size; q->extco2.DisableDeblockingIdc = q->dblk_idc; @@ -920,6 +923,7 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) } if (q->int_ref_cycle_dist >= 0) q->extco3.IntRefCycleDist = q->int_ref_cycle_dist; +q->old_int_ref_cycle_dist = q->int_ref_cycle_dist; if (q->low_delay_brc >= 0) q->extco3.LowDelayBRC = q->low_delay_brc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; if (q->max_frame_size_i >= 0) @@ -1709,6 +1713,34 @@ static int update_gop_size(AVCodecContext *avctx, QSVEncContext *q) return updated; } +static int update_rir(AVCodecContext *avctx, QSVEncContext *q) +{ +int updated = 0; + +if (avctx->codec_id != AV_CODEC_ID_H264 && avctx->codec_id != AV_CODEC_ID_HEVC) +return 0; + +UPDATE_PARAM(q->old_int_ref_type, q->int_ref_type); +UPDATE_PARAM(q->old_int_ref_cycle_size, q->int_ref_cycle_size); +UPDATE_PARAM(q->old_int_ref_qp_delta, q->int_ref_qp_delta); +UPDATE_PARAM(q->old_int_ref_cycle_dist, q->int_ref_cycle_dist); +if (!updated) +return 0; + +q->extco2.IntRefType = FFMAX(0, q->int_ref_type); +q->extco2.IntRefCycleSize = FFMAX(0, q->int_ref_cycle_size); +q->extco2.IntRefQPDelta = +q->int_ref_qp_delta != INT16_MIN ? q->int_ref_qp_delta : 0; +q->extco3.IntRefCycleDist = FFMAX(0, q->int_ref_cycle_dist); +av_log(avctx, AV_LOG_DEBUG, + "Reset IntRefType: %d; IntRefCycleSize: %d; " + "IntRefQPDelta: %d; IntRefCycleDist: %d\n", + q->extco2.IntRefType, q->extco2.IntRefCycleSize, + q->extco2.IntRefQPDelta, q->extco3.IntRefCycleDist); + +return updated; +} + static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, const AVFrame *frame) { @@ -1720,6 +1752,7 @@ static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, needReset = update_qp(avctx, q); needReset |= update_max_frame_size(avctx, q); needReset |= update_gop_size(avctx, q); +needReset |= update_rir(avctx, q); if (!needReset) return 0; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 5f6955a3a7..2eada6ab26 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -253,6 +253,11 @@ typedef struct QSVEncContext { int old_max_frame_size; // This is used for gop reset int old_gop_size; +// These are used for intra refresh reset +int old_int_ref_type; +int old_int_ref_cycle_size; +int old_int_ref_qp_delta; +int old_int_ref_cycle_dist; } QSVEncContext; int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q); -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v2 6/7] libavcodec/qsvenc: Add max/min qp reset support in qsvenc
Signed-off-by: Wenbin Chen --- doc/encoders.texi | 11 +++ libavcodec/qsvenc.c | 78 + libavcodec/qsvenc.h | 9 ++ 3 files changed, 98 insertions(+) diff --git a/doc/encoders.texi b/doc/encoders.texi index da56159858..850e3c261c 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -3358,6 +3358,17 @@ Change this value to reset qsv codec's gop configuration. @item @var{int_ref_cycle_dist} Supported in h264_qsv and hevc_qsv. Change these value to reset qsv codec's Intra Refresh configuration. + +@item @var{qmax} +@item @var{qmin} +@item @var{max_qp_i} +@item @var{min_qp_i} +@item @var{max_qp_p} +@item @var{min_qp_p} +@item @var{max_qp_b} +@item @var{min_qp_b} +Supported in h264_qsv. +Change these value to reset qsv codec's max/min qp configuration. @end table @subsection H264 options diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index cd0549b249..215e5930ef 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -858,22 +858,30 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->extco2.MinQPI = avctx->qmin > 51 ? 51 : avctx->qmin; q->extco2.MinQPP = q->extco2.MinQPB = q->extco2.MinQPI; } +q->old_qmin = avctx->qmin; if (avctx->qmax >= 0) { q->extco2.MaxQPI = avctx->qmax > 51 ? 51 : avctx->qmax; q->extco2.MaxQPP = q->extco2.MaxQPB = q->extco2.MaxQPI; } +q->old_qmax = avctx->qmax; if (q->min_qp_i >= 0) q->extco2.MinQPI = q->min_qp_i > 51 ? 51 : q->min_qp_i; +q->old_min_qp_i = q->min_qp_i; if (q->max_qp_i >= 0) q->extco2.MaxQPI = q->max_qp_i > 51 ? 51 : q->max_qp_i; +q->old_max_qp_i = q->max_qp_i; if (q->min_qp_p >= 0) q->extco2.MinQPP = q->min_qp_p > 51 ? 51 : q->min_qp_p; +q->old_min_qp_p = q->min_qp_p; if (q->max_qp_p >= 0) q->extco2.MaxQPP = q->max_qp_p > 51 ? 51 : q->max_qp_p; +q->old_max_qp_p = q->max_qp_p; if (q->min_qp_b >= 0) q->extco2.MinQPB = q->min_qp_b > 51 ? 51 : q->min_qp_b; +q->old_min_qp_b = q->min_qp_b; if (q->max_qp_b >= 0) q->extco2.MaxQPB = q->max_qp_b > 51 ? 51 : q->max_qp_b; +q->old_max_qp_b = q->max_qp_b; if (q->mbbrc >= 0) q->extco2.MBBRC = q->mbbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; @@ -1741,6 +1749,71 @@ static int update_rir(AVCodecContext *avctx, QSVEncContext *q) return updated; } +static int update_min_max_qp(AVCodecContext *avctx, QSVEncContext *q) +{ +int updated = 0; + +if (avctx->codec_id != AV_CODEC_ID_H264) +return 0; + +UPDATE_PARAM(q->old_qmax, avctx->qmin); +UPDATE_PARAM(q->old_qmax, avctx->qmin); +UPDATE_PARAM(q->old_min_qp_i, q->min_qp_i); +UPDATE_PARAM(q->old_max_qp_i, q->max_qp_i); +UPDATE_PARAM(q->old_min_qp_p, q->min_qp_p); +UPDATE_PARAM(q->old_max_qp_p, q->max_qp_p); +UPDATE_PARAM(q->old_min_qp_b, q->min_qp_b); +UPDATE_PARAM(q->old_max_qp_b, q->max_qp_b); +if (!updated) +return 0; + +if ((avctx->qmin >= 0 && avctx->qmax >= 0 && avctx->qmin > avctx->qmax) || +(q->max_qp_i >= 0 && q->min_qp_i >= 0 && q->min_qp_i > q->max_qp_i) || +(q->max_qp_p >= 0 && q->min_qp_p >= 0 && q->min_qp_p > q->max_qp_p) || +(q->max_qp_b >= 0 && q->min_qp_b >= 0 && q->min_qp_b > q->max_qp_b)) { +av_log(avctx, AV_LOG_ERROR, +"qmin and or qmax are set but invalid," +" please make sure min <= max\n"); +return AVERROR(EINVAL); +} + +q->extco2.MinQPI = 0; +q->extco2.MaxQPI = 0; +q->extco2.MinQPP = 0; +q->extco2.MaxQPP = 0; +q->extco2.MinQPB = 0; +q->extco2.MaxQPB = 0; +if (avctx->qmin >= 0) { +q->extco2.MinQPI = avctx->qmin > 51 ? 51 : avctx->qmin; +q->extco2.MinQPB = q->extco2.MinQPP = q->extco2.MinQPI; +} +if (avctx->qmax >= 0) { +q->extco2.MaxQPI = avctx->qmax > 51 ? 51 : avctx->qmax; +q->extco2.MaxQPB = q->extco2.MaxQPP = q->extco2.MaxQPI; +} +if (q->min_qp_i >= 0) +q->extco2.MinQPI = q->min_qp_i > 51 ? 51 : q->min_qp_i; +if (q->max_qp_i >= 0) +q->extco2.MaxQPI = q->max_qp_i > 5
[FFmpeg-devel] [PATCH v2 7/7] libavcodec/qsvenc: Add low_delay_brc reset support to qsvenc
Signed-off-by: Wenbin Chen --- doc/encoders.texi | 4 libavcodec/qsvenc.c | 23 ++- libavcodec/qsvenc.h | 2 ++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/doc/encoders.texi b/doc/encoders.texi index 850e3c261c..453150f3e7 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -3369,6 +3369,10 @@ Change these value to reset qsv codec's Intra Refresh configuration. @item @var{min_qp_b} Supported in h264_qsv. Change these value to reset qsv codec's max/min qp configuration. + +@item @var{low_delay_brc} +Supported in h264_qsv and hevc_qsv. +Change this value to reset qsv codec's low_delay_brc configuration. @end table @subsection H264 options diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 215e5930ef..58900d56a7 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -934,6 +934,7 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->old_int_ref_cycle_dist = q->int_ref_cycle_dist; if (q->low_delay_brc >= 0) q->extco3.LowDelayBRC = q->low_delay_brc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; +q->old_low_delay_brc = q->low_delay_brc; if (q->max_frame_size_i >= 0) q->extco3.MaxFrameSizeI = q->max_frame_size_i; if (q->max_frame_size_p >= 0) @@ -1814,6 +1815,26 @@ static int update_min_max_qp(AVCodecContext *avctx, QSVEncContext *q) return updated; } +static int update_low_delay_brc(AVCodecContext *avctx, QSVEncContext *q) +{ +int updated = 0; + +if (avctx->codec_id != AV_CODEC_ID_H264 && avctx->codec_id != AV_CODEC_ID_HEVC) +return 0; + +UPDATE_PARAM(q->old_low_delay_brc, q->low_delay_brc); +if (!updated) +return 0; + +q->extco3.LowDelayBRC = MFX_CODINGOPTION_UNKNOWN; +if (q->low_delay_brc >= 0) +q->extco3.LowDelayBRC = q->low_delay_brc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; +av_log(avctx, AV_LOG_DEBUG, "Reset LowDelayBRC: %s\n", + print_threestate(q->extco3.LowDelayBRC)); + +return updated; +} + static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, const AVFrame *frame) { @@ -1826,7 +1847,7 @@ static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, needReset |= update_max_frame_size(avctx, q); needReset |= update_gop_size(avctx, q); needReset |= update_rir(avctx, q); - +needReset |= update_low_delay_brc(avctx, q); ret = update_min_max_qp(avctx, q); if (ret < 0) return ret; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 3ed20f757b..54e5cf89d3 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -267,6 +267,8 @@ typedef struct QSVEncContext { int old_min_qp_p; int old_max_qp_b; int old_min_qp_b; +// This is used for low_delay_brc reset +int old_low_delay_brc; } QSVEncContext; int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q); -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v4] libavcodec/cbs_av1: Add size check before parse obu
cbs_av1_write_obu() check pbc size after parsing obu frame, and return AVERROR(ENOSPC) if pbc is small. pbc will be reallocated and this obu frame will be parsed again, but this may cause error because CodedBitstreamAV1Context has already been updated, for example ref_order_hint is updated and will not match the same obu frame. Now size check is added before parsing obu frame to avoid this error. Signed-off-by: Wenbin Chen --- libavcodec/cbs_av1.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c index 154d9156cf..9c51a8c7c8 100644 --- a/libavcodec/cbs_av1.c +++ b/libavcodec/cbs_av1.c @@ -1075,6 +1075,9 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx, put_bits32(pbc, 0); } +if (8 * (unit->data_size + obu->obu_size) > put_bits_left(pbc)) +return AVERROR(ENOSPC); + td = NULL; start_pos = put_bits_count(pbc); -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 1/3] libavcodec/qsvenc: Add framerate reset support to qsv
Signed-off-by: Wenbin Chen --- doc/encoders.texi | 3 +++ libavcodec/qsvenc.c | 26 ++ libavcodec/qsvenc.h | 2 ++ 3 files changed, 31 insertions(+) diff --git a/doc/encoders.texi b/doc/encoders.texi index ac71f50ad2..4ed7ce1bb0 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -3360,6 +3360,9 @@ Change these value to reset qsv codec's max/min qp configuration. @item @var{low_delay_brc} Supported in h264_qsv and hevc_qsv. Change this value to reset qsv codec's low_delay_brc configuration. + +@item @var{framerate} +Change this value to reset qsv codec's framerate configuration. @end table @subsection H264 options diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 84c6e292aa..ce00cd302b 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -705,6 +705,7 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->param.mfx.FrameInfo.FrameRateExtN = avctx->time_base.den; q->param.mfx.FrameInfo.FrameRateExtD = avctx->time_base.num; } +q->old_framerate = avctx->framerate; ret = select_rc_mode(avctx, q); if (ret < 0) @@ -1838,6 +1839,30 @@ static int update_low_delay_brc(AVCodecContext *avctx, QSVEncContext *q) return updated; } +static int update_frame_rate(AVCodecContext *avctx, QSVEncContext *q) +{ +int updated = 0; + +UPDATE_PARAM(q->old_framerate.num, avctx->framerate.num); +UPDATE_PARAM(q->old_framerate.den, avctx->framerate.den); +if (!updated) +return 0; + +if (avctx->framerate.den > 0 && avctx->framerate.num > 0) { +q->param.mfx.FrameInfo.FrameRateExtN = avctx->framerate.num; +q->param.mfx.FrameInfo.FrameRateExtD = avctx->framerate.den; +} else { +q->param.mfx.FrameInfo.FrameRateExtN = avctx->time_base.den; +q->param.mfx.FrameInfo.FrameRateExtD = avctx->time_base.num; +} +av_log(avctx, AV_LOG_DEBUG, "Reset framerate: %d/%d (%.2f fps).\n", + q->param.mfx.FrameInfo.FrameRateExtN, + q->param.mfx.FrameInfo.FrameRateExtD, + (double)q->param.mfx.FrameInfo.FrameRateExtN / q->param.mfx.FrameInfo.FrameRateExtD); + +return updated; +} + static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, const AVFrame *frame) { @@ -1851,6 +1876,7 @@ static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, needReset |= update_gop_size(avctx, q); needReset |= update_rir(avctx, q); needReset |= update_low_delay_brc(avctx, q); +needReset |= update_frame_rate(avctx, q); ret = update_min_max_qp(avctx, q); if (ret < 0) return ret; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index f2b7ee361f..960197f159 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -271,6 +271,8 @@ typedef struct QSVEncContext { int old_min_qp_b; // This is used for low_delay_brc reset int old_low_delay_brc; +// This is used for framerate reset +AVRational old_framerate; } QSVEncContext; int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q); -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 2/3] libavcodec/qsvenc: Add bitrate reset support to qsvenc
Signed-off-by: Wenbin Chen --- doc/encoders.texi | 6 ++ libavcodec/qsvenc.c | 38 ++ libavcodec/qsvenc.h | 5 + 3 files changed, 49 insertions(+) diff --git a/doc/encoders.texi b/doc/encoders.texi index 4ed7ce1bb0..2b6412dbec 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -3363,6 +3363,12 @@ Change this value to reset qsv codec's low_delay_brc configuration. @item @var{framerate} Change this value to reset qsv codec's framerate configuration. + +@item @var{bit_rate} +@item @var{rc_buffer_size} +@item @var{rc_initial_buffer_occupancy} +@item @var{rc_max_rate} +Change these value to reset qsv codec's bitrate control configuration. @end table @subsection H264 options diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index ce00cd302b..3371711872 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -718,6 +718,10 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) max_bitrate_kbps = avctx->rc_max_rate / 1000; brc_param_multiplier = (FFMAX(FFMAX3(target_bitrate_kbps, max_bitrate_kbps, buffer_size_in_kilobytes), initial_delay_in_kilobytes) + 0x1) / 0x1; +q->old_rc_buffer_size = avctx->rc_buffer_size; +q->old_rc_initial_buffer_occupancy = avctx->rc_initial_buffer_occupancy; +q->old_bit_rate = avctx->bit_rate; +q->old_rc_max_rate = avctx->rc_max_rate; switch (q->param.mfx.RateControlMethod) { case MFX_RATECONTROL_CBR: @@ -1863,6 +1867,39 @@ static int update_frame_rate(AVCodecContext *avctx, QSVEncContext *q) return updated; } +static int update_bitrate(AVCodecContext *avctx, QSVEncContext *q) +{ +int updated = 0; +int target_bitrate_kbps, max_bitrate_kbps, brc_param_multiplier; +int buffer_size_in_kilobytes, initial_delay_in_kilobytes; + +UPDATE_PARAM(q->old_rc_buffer_size, avctx->rc_buffer_size); +UPDATE_PARAM(q->old_rc_initial_buffer_occupancy, avctx->rc_initial_buffer_occupancy); +UPDATE_PARAM(q->old_bit_rate, avctx->bit_rate); +UPDATE_PARAM(q->old_rc_max_rate, avctx->rc_max_rate); +if (!updated) +return 0; + +buffer_size_in_kilobytes = avctx->rc_buffer_size / 8000; +initial_delay_in_kilobytes = avctx->rc_initial_buffer_occupancy / 8000; +target_bitrate_kbps= avctx->bit_rate / 1000; +max_bitrate_kbps = avctx->rc_max_rate / 1000; +brc_param_multiplier = (FFMAX(FFMAX3(target_bitrate_kbps, max_bitrate_kbps, buffer_size_in_kilobytes), +initial_delay_in_kilobytes) + 0x1) / 0x1; + +q->param.mfx.BufferSizeInKB = buffer_size_in_kilobytes / brc_param_multiplier; +q->param.mfx.InitialDelayInKB = initial_delay_in_kilobytes / brc_param_multiplier; +q->param.mfx.TargetKbps = target_bitrate_kbps / brc_param_multiplier; +q->param.mfx.MaxKbps = max_bitrate_kbps / brc_param_multiplier; +q->param.mfx.BRCParamMultiplier = brc_param_multiplier; +av_log(avctx, AV_LOG_VERBOSE, +"Reset BufferSizeInKB: %d; InitialDelayInKB: %d; " +"TargetKbps: %d; MaxKbps: %d; BRCParamMultiplier: %d\n", +q->param.mfx.BufferSizeInKB, q->param.mfx.InitialDelayInKB, +q->param.mfx.TargetKbps, q->param.mfx.MaxKbps, q->param.mfx.BRCParamMultiplier); +return updated; +} + static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, const AVFrame *frame) { @@ -1877,6 +1914,7 @@ static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, needReset |= update_rir(avctx, q); needReset |= update_low_delay_brc(avctx, q); needReset |= update_frame_rate(avctx, q); +needReset |= update_bitrate(avctx, q); ret = update_min_max_qp(avctx, q); if (ret < 0) return ret; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 960197f159..6e1132d2e3 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -273,6 +273,11 @@ typedef struct QSVEncContext { int old_low_delay_brc; // This is used for framerate reset AVRational old_framerate; +// These are used for bitrate control reset +int old_bit_rate; +int old_rc_buffer_size; +int old_rc_initial_buffer_occupancy; +int old_rc_max_rate; } QSVEncContext; int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q); -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 3/3] libavcodec/qsvenc: Add pic_timing_sei reset support to qsv
Signed-off-by: Wenbin Chen --- doc/encoders.texi | 4 libavcodec/qsvenc.c | 21 + libavcodec/qsvenc.h | 2 ++ 3 files changed, 27 insertions(+) diff --git a/doc/encoders.texi b/doc/encoders.texi index 2b6412dbec..741d545ea1 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -3369,6 +3369,10 @@ Change this value to reset qsv codec's framerate configuration. @item @var{rc_initial_buffer_occupancy} @item @var{rc_max_rate} Change these value to reset qsv codec's bitrate control configuration. + +@item @var{pic_timing_sei} +Supported in h264_qsv and hevc_qsv. +Change this value to reset qsv codec's pic_timing_sei configuration. @end table @subsection H264 options diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 3371711872..c1a601f0b3 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -784,6 +784,7 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->extco.PicTimingSEI = q->pic_timing_sei ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_UNKNOWN; +q->old_pic_timing_sei = q->pic_timing_sei; if (q->rdo >= 0) q->extco.RateDistortionOpt = q->rdo > 0 ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; @@ -1900,6 +1901,25 @@ static int update_bitrate(AVCodecContext *avctx, QSVEncContext *q) return updated; } +static int update_pic_timing_sei(AVCodecContext *avctx, QSVEncContext *q) +{ +int updated = 0; + +if (avctx->codec_id != AV_CODEC_ID_H264 && avctx->codec_id != AV_CODEC_ID_HEVC) +return 0; + +UPDATE_PARAM(q->old_pic_timing_sei, q->pic_timing_sei); +if (!updated) +return 0; + +q->extco.PicTimingSEI = q->pic_timing_sei ? +MFX_CODINGOPTION_ON : MFX_CODINGOPTION_UNKNOWN; +av_log(avctx, AV_LOG_DEBUG, "Reset PicTimingSEI: %s\n", + print_threestate(q->extco.PicTimingSEI)); + +return updated; +} + static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, const AVFrame *frame) { @@ -1915,6 +1935,7 @@ static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, needReset |= update_low_delay_brc(avctx, q); needReset |= update_frame_rate(avctx, q); needReset |= update_bitrate(avctx, q); +needReset |= update_pic_timing_sei(avctx, q); ret = update_min_max_qp(avctx, q); if (ret < 0) return ret; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 6e1132d2e3..486c996fc6 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -278,6 +278,8 @@ typedef struct QSVEncContext { int old_rc_buffer_size; int old_rc_initial_buffer_occupancy; int old_rc_max_rate; +// This is used for SEI Timing reset +int old_pic_timing_sei; } QSVEncContext; int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q); -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 1/2] libavcodec/qsvenc: Let runtime to set default parameter.
Unset qsv_h264 and qsv_hevc's default settings. Let runtime to decide these parameters, so that it can choose the best parameter and ffmpeg-qsv can keep up with runtime's update. Signed-off-by: Wenbin Chen --- libavcodec/qsvenc_h264.c | 4 ++-- libavcodec/qsvenc_hevc.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index 85826ae4be..fe777a6ae3 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -177,8 +177,8 @@ static const FFCodecDefault qsv_enc_defaults[] = { { "b", "1M"}, { "refs", "0" }, // same as the x264 default -{ "g", "250" }, -{ "bf","3" }, +{ "g", "-1"}, +{ "bf","-1"}, { "qmin", "-1"}, { "qmax", "-1"}, { "trellis", "-1"}, diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index 6ec6230999..0c5bec231d 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -290,7 +290,7 @@ static const FFCodecDefault qsv_enc_defaults[] = { { "b", "1M"}, { "refs", "0" }, // same as the x264 default -{ "g", "248" }, +{ "g", "-1"}, { "bf","-1"}, { "qmin", "-1"}, { "qmax", "-1"}, -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 2/2] libavcodec/qsvenc: Let runtime to decide targetUsage
Set preset default value to MFX_TARGETUSAGE_UNKNOWN. Let runtime to decide the targetUsage, so that ffmpeg-qsv can keep up with runtime's update. Signed-off-by: Wenbin Chen --- libavcodec/qsvenc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index f2b7ee361f..4315463cd2 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -52,7 +52,7 @@ #define QSV_COMMON_OPTS \ { "async_depth", "Maximum processing parallelism", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VE }, \ -{ "preset", NULL, OFFSET(qsv.preset), AV_OPT_TYPE_INT, { .i64 = MFX_TARGETUSAGE_BALANCED }, MFX_TARGETUSAGE_BEST_QUALITY, MFX_TARGETUSAGE_BEST_SPEED, VE, "preset" }, \ +{ "preset", NULL, OFFSET(qsv.preset), AV_OPT_TYPE_INT, { .i64 = MFX_TARGETUSAGE_UNKNOWN }, MFX_TARGETUSAGE_UNKNOWN, MFX_TARGETUSAGE_BEST_SPEED, VE, "preset" }, \ { "veryfast",NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_SPEED }, INT_MIN, INT_MAX, VE, "preset" }, \ { "faster", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_6 }, INT_MIN, INT_MAX, VE, "preset" }, \ { "fast",NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_5 }, INT_MIN, INT_MAX, VE, "preset" }, \ -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v2 2/2] libavcodec/qsvenc: Let runtime to decide targetUsage
Set preset default value to MFX_TARGETUSAGE_UNKNOWN. Let runtime to decide the targetUsage, so that ffmpeg-qsv can keep up with runtime's update. Signed-off-by: Wenbin Chen --- libavcodec/qsvenc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index f2b7ee361f..4315463cd2 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -52,7 +52,7 @@ #define QSV_COMMON_OPTS \ { "async_depth", "Maximum processing parallelism", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VE }, \ -{ "preset", NULL, OFFSET(qsv.preset), AV_OPT_TYPE_INT, { .i64 = MFX_TARGETUSAGE_BALANCED }, MFX_TARGETUSAGE_BEST_QUALITY, MFX_TARGETUSAGE_BEST_SPEED, VE, "preset" }, \ +{ "preset", NULL, OFFSET(qsv.preset), AV_OPT_TYPE_INT, { .i64 = MFX_TARGETUSAGE_UNKNOWN }, MFX_TARGETUSAGE_UNKNOWN, MFX_TARGETUSAGE_BEST_SPEED, VE, "preset" }, \ { "veryfast",NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_SPEED }, INT_MIN, INT_MAX, VE, "preset" }, \ { "faster", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_6 }, INT_MIN, INT_MAX, VE, "preset" }, \ { "fast",NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_5 }, INT_MIN, INT_MAX, VE, "preset" }, \ -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v2 1/2] libavcodec/qsvenc: Let runtime to set default parameter.
Unset qsv_h264 and qsv_hevc's default settings. Let runtime to decide these parameters, so that it can choose the best parameter and ffmpeg-qsv can keep up with runtime's update. Signed-off-by: Wenbin Chen --- libavcodec/qsvenc_h264.c | 5 ++--- libavcodec/qsvenc_hevc.c | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index 85826ae4be..11aaabbd1b 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -176,9 +176,8 @@ static const AVClass class = { static const FFCodecDefault qsv_enc_defaults[] = { { "b", "1M"}, { "refs", "0" }, -// same as the x264 default -{ "g", "250" }, -{ "bf","3" }, +{ "g", "-1"}, +{ "bf","-1"}, { "qmin", "-1"}, { "qmax", "-1"}, { "trellis", "-1"}, diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index 6ec6230999..a5bf915954 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -289,8 +289,7 @@ static const AVClass class = { static const FFCodecDefault qsv_enc_defaults[] = { { "b", "1M"}, { "refs", "0" }, -// same as the x264 default -{ "g", "248" }, +{ "g", "-1"}, { "bf","-1"}, { "qmin", "-1"}, { "qmax", "-1"}, -- 2.32.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] libavcodec/qsvenc.c: add max_frame_size support for hevc_qsv
From: Wenbinc-Bin The max_frame_size parameter is set only when codec is h264. Now I add hevc in that conditional statement. Signed-off-by: Wenbin CHEN --- libavcodec/qsvenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 2bd2a56227..aba98dd689 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -691,7 +691,7 @@ FF_ENABLE_DEPRECATION_WARNINGS q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco; #if QSV_HAVE_CO2 -if (avctx->codec_id == AV_CODEC_ID_H264) { +if (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_HEVC) { if (q->int_ref_type >= 0) q->extco2.IntRefType = q->int_ref_type; if (q->int_ref_cycle_size >= 0) -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] libavcodec/qsvenc: add max_frame_size support for hevc_qsv
From: Wenbinc-Bin The max_frame_size parameter is set only when codec is h264. Now I add hevc in that conditional statement. Signed-off-by: Wenbin CHEN --- libavcodec/qsvenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 2bd2a56227..aba98dd689 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -691,7 +691,7 @@ FF_ENABLE_DEPRECATION_WARNINGS q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco; #if QSV_HAVE_CO2 -if (avctx->codec_id == AV_CODEC_ID_H264) { +if (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_HEVC) { if (q->int_ref_type >= 0) q->extco2.IntRefType = q->int_ref_type; if (q->int_ref_cycle_size >= 0) -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] libavcodec/qsvenc: add DisableDeblockingIdc support for qsv
From: Wenbinc-Bin MediaSDK already has a flag to control deblocking (DisableDeblockingIdc). Add dblk_idc parameter in ffmpeg to expose this flag to user. Sigend-off-by: Wenbin Chen --- libavcodec/qsvenc.c | 4 libavcodec/qsvenc.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index aba98dd689..0d20d1968f 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -710,6 +710,10 @@ FF_ENABLE_DEPRECATION_WARNINGS if (q->max_slice_size >= 0) q->extco2.MaxSliceSize = q->max_slice_size; #endif +#if QSV_HAVE_DISABLEDEBLOCKIDC +if(q->dblk_idc >= 0) +q->extco2.DisableDeblockingIdc = q->dblk_idc; +#endif #if QSV_HAVE_TRELLIS if (avctx->trellis >= 0) diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 6d305f87dd..3720320789 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -44,6 +44,7 @@ #define QSV_HAVE_TRELLIS QSV_VERSION_ATLEAST(1, 8) #define QSV_HAVE_MAX_SLICE_SIZE QSV_VERSION_ATLEAST(1, 9) +#define QSV_HAVE_DISABLEDEBLOCKIDC QSV_VERSION_ATLEAST(1, 9) #define QSV_HAVE_BREF_TYPE QSV_VERSION_ATLEAST(1, 8) #define QSV_HAVE_LA QSV_VERSION_ATLEAST(1, 7) @@ -97,6 +98,7 @@ { "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy),AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "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 = 0}, 0, 1, VE},\ +{ "dblk_idc", "value of DisableDeblockingIdc (default is 0), in range [0,2]", OFFSET(qsv.dblk_idc), AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, 2, VE},\ extern const AVCodecHWConfigInternal *const ff_qsv_enc_hw_configs[]; @@ -167,6 +169,7 @@ typedef struct QSVEncContext { int rdo; int max_frame_size; int max_slice_size; +int dblk_idc; int tile_cols; int tile_rows; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] libavcodec/qsvenc: add low latency P-pyramid support for qsv
From: Wenbinc-Bin Add low latency P-pyramid support for qsv, and it relates to a new command line parameter "-p_strategy". To enable this flag, user also need to set "-bf" to -1 or 0. Signed-off-by Wenbin Chen --- libavcodec/qsvenc.c | 22 ++ libavcodec/qsvenc.h | 2 ++ 2 files changed, 24 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 2bd2a56227..c3b41374e4 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -268,6 +268,13 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, case MFX_B_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; default:av_log(avctx, AV_LOG_VERBOSE, "auto"); break; } +av_log(avctx, AV_LOG_VERBOSE, "; PRefType: "); +switch(co3->PRefType){ +case MFX_P_REF_DEFAULT: av_log(avctx, AV_LOG_VERBOSE, "default"); break; +case MFX_P_REF_SIMPLE: av_log(avctx, AV_LOG_VERBOSE, "simple"); break; +case MFX_P_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; +default:break; +} av_log(avctx, AV_LOG_VERBOSE, "\n"); #endif @@ -777,6 +784,21 @@ FF_ENABLE_DEPRECATION_WARNINGS #if QSV_HAVE_CO3 q->extco3.Header.BufferId = MFX_EXTBUFF_CODING_OPTION3; q->extco3.Header.BufferSz = sizeof(q->extco3); +switch(q->p_strategy){ +case 0: +q->extco3.PRefType = MFX_P_REF_DEFAULT; +break; +case 1: +q->extco3.PRefType = MFX_P_REF_SIMPLE; +break; +case 2: +q->extco3.PRefType = MFX_P_REF_PYRAMID; +break; +default: +q->extco3.PRefType = MFX_P_REF_DEFAULT; +av_log(avctx, AV_LOG_VERBOSE, "invalid p_strategy, set to default\n"); +break; +} #if QSV_HAVE_GPB if (avctx->codec_id == AV_CODEC_ID_HEVC) q->extco3.GPB = q->gpb ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 6d305f87dd..30aaf72ebd 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -95,6 +95,7 @@ { "adaptive_i", "Adaptive I-frame placement", OFFSET(qsv.adaptive_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "adaptive_b", "Adaptive B-frame placement", OFFSET(qsv.adaptive_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy),AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ +{ "p_strategy", "enable P-pyramid 0-default 1-simple 2-pyramis", OFFSET(qsv.p_strategy), AV_OPT_TYPE_INT,{ .i64 = 0}, 0,2, VE }, \ { "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 = 0}, 0, 1, VE},\ @@ -182,6 +183,7 @@ typedef struct QSVEncContext { int adaptive_i; int adaptive_b; int b_strategy; +int p_strategy; int cavlc; int int_ref_type; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V2] libavcodec/qsvenc: add low latency P-pyramid support for qsv
From: Wenbinc-Bin Add low latency P-pyramid support for qsv, and it relates to a new command line parameter "-p_strategy". To enable this flag, user also need to set "-bf" to -1 or 0. Signed-off-by Wenbin Chen --- libavcodec/qsvenc.c | 23 +++ libavcodec/qsvenc.h | 2 ++ 2 files changed, 25 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 0d20d1968f..8cb0ecff89 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -268,6 +268,14 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, case MFX_B_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; default:av_log(avctx, AV_LOG_VERBOSE, "auto"); break; } + +av_log(avctx, AV_LOG_VERBOSE, "; PRefType: "); +switch(co3->PRefType){ +case MFX_P_REF_DEFAULT: av_log(avctx, AV_LOG_VERBOSE, "default"); break; +case MFX_P_REF_SIMPLE: av_log(avctx, AV_LOG_VERBOSE, "simple"); break; +case MFX_P_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; +default:break; +} av_log(avctx, AV_LOG_VERBOSE, "\n"); #endif @@ -781,6 +789,21 @@ FF_ENABLE_DEPRECATION_WARNINGS #if QSV_HAVE_CO3 q->extco3.Header.BufferId = MFX_EXTBUFF_CODING_OPTION3; q->extco3.Header.BufferSz = sizeof(q->extco3); +switch(q->p_strategy){ +case 0: +q->extco3.PRefType = MFX_P_REF_DEFAULT; +break; +case 1: +q->extco3.PRefType = MFX_P_REF_SIMPLE; +break; +case 2: +q->extco3.PRefType = MFX_P_REF_PYRAMID; +break; +default: +q->extco3.PRefType = MFX_P_REF_DEFAULT; +av_log(avctx, AV_LOG_VERBOSE, "invalid p_strategy, set to default\n"); +break; +} #if QSV_HAVE_GPB if (avctx->codec_id == AV_CODEC_ID_HEVC) q->extco3.GPB = q->gpb ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 3720320789..a074561ca8 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -96,6 +96,7 @@ { "adaptive_i", "Adaptive I-frame placement", OFFSET(qsv.adaptive_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "adaptive_b", "Adaptive B-frame placement", OFFSET(qsv.adaptive_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy),AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ +{ "p_strategy", "enable P-pyramid 0-default 1-simple 2-pyramid", OFFSET(qsv.p_strategy), AV_OPT_TYPE_INT,{ .i64 = 0}, 0,2, VE }, \ { "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 = 0}, 0, 1, VE},\ { "dblk_idc", "value of DisableDeblockingIdc (default is 0), in range [0,2]", OFFSET(qsv.dblk_idc), AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, 2, VE},\ @@ -185,6 +186,7 @@ typedef struct QSVEncContext { int adaptive_i; int adaptive_b; int b_strategy; +int p_strategy; int cavlc; int int_ref_type; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V3] libavcodec/qsvenc: add low latency P-pyramid support for qsv
From: Wenbinc-Bin Add low latency P-pyramid support for qsv, and it relates to a new command line parameter "-p_strategy". To enable this flag, user also need to set "-bf" to 0. P-strategy has two modes "simple" and "pyramid". The details of these model refers to https://github.com/Intel-Media-SDK/MediaSDK/blob/master/doc/mediasdk-man.md#PRefType Signed-off-by Wenbin Chen --- libavcodec/qsvenc.c | 32 libavcodec/qsvenc.h | 2 ++ 2 files changed, 34 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 2bd2a56227..3b75a83432 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -268,6 +268,15 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, case MFX_B_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; default:av_log(avctx, AV_LOG_VERBOSE, "auto"); break; } + +av_log(avctx, AV_LOG_VERBOSE, "; PRefType: "); +switch(co3->PRefType){ +case MFX_P_REF_DEFAULT: av_log(avctx, AV_LOG_VERBOSE, "default"); break; +case MFX_P_REF_SIMPLE: av_log(avctx, AV_LOG_VERBOSE, "simple");break; +case MFX_P_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; +default:av_log(avctx, AV_LOG_VERBOSE, "unknown"); break; +} + av_log(avctx, AV_LOG_VERBOSE, "\n"); #endif @@ -777,6 +786,29 @@ FF_ENABLE_DEPRECATION_WARNINGS #if QSV_HAVE_CO3 q->extco3.Header.BufferId = MFX_EXTBUFF_CODING_OPTION3; q->extco3.Header.BufferSz = sizeof(q->extco3); + +switch(q->p_strategy){ +case 0: +q->extco3.PRefType = MFX_P_REF_DEFAULT; +break; +case 1: +q->extco3.PRefType = MFX_P_REF_SIMPLE; +break; +case 2: +q->extco3.PRefType = MFX_P_REF_PYRAMID; +break; +default: +q->extco3.PRefType = MFX_P_REF_DEFAULT; +av_log(avctx, AV_LOG_WARNING, "invalid p_strategy, set to default\n"); +break; +} +if((q->extco3.PRefType == MFX_P_REF_SIMPLE || +q->extco3.PRefType == MFX_P_REF_PYRAMID) && +avctx->max_b_frames != 0){ +av_log(avctx, AV_LOG_WARNING, "Please set max_b_frames(-bf) to 0 to enable P-pyramid\n"); +} + + #if QSV_HAVE_GPB if (avctx->codec_id == AV_CODEC_ID_HEVC) q->extco3.GPB = q->gpb ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 6d305f87dd..1b6149cccf 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -95,6 +95,7 @@ { "adaptive_i", "Adaptive I-frame placement", OFFSET(qsv.adaptive_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "adaptive_b", "Adaptive B-frame placement", OFFSET(qsv.adaptive_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy),AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ +{ "p_strategy", "enable P-pyramid 0-default 1-simple 2-pyramid", OFFSET(qsv.p_strategy), AV_OPT_TYPE_INT,{ .i64 = 0}, 0,2, VE }, \ { "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 = 0}, 0, 1, VE},\ @@ -181,6 +182,7 @@ typedef struct QSVEncContext { int extbrc; int adaptive_i; int adaptive_b; +int p_strategy; int b_strategy; int cavlc; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V4] libavcodec/qsvenc: add low latency P-pyramid support for qsv
From: Wenbinc-Bin Add low latency P-pyramid support for qsv, and it relates to a new command line parameter "-p_strategy". To enable this flag, user also need to set "-bf" to 0. P-strategy has two modes "simple" and "pyramid". The details of these model refers to https://github.com/Intel-Media-SDK/MediaSDK/blob/master/doc/mediasdk-man.md#PRefType patch V4: modify the coding style problem. Signed-off-by Wenbin Chen --- libavcodec/qsvenc.c | 32 libavcodec/qsvenc.h | 2 ++ 2 files changed, 34 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 2bd2a56227..646b9f948e 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -268,6 +268,15 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, case MFX_B_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; default:av_log(avctx, AV_LOG_VERBOSE, "auto"); break; } + +av_log(avctx, AV_LOG_VERBOSE, "; PRefType: "); +switch (co3->PRefType) { +case MFX_P_REF_DEFAULT: av_log(avctx, AV_LOG_VERBOSE, "default"); break; +case MFX_P_REF_SIMPLE: av_log(avctx, AV_LOG_VERBOSE, "simple");break; +case MFX_P_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; +default:av_log(avctx, AV_LOG_VERBOSE, "unknown"); break; +} + av_log(avctx, AV_LOG_VERBOSE, "\n"); #endif @@ -777,6 +786,29 @@ FF_ENABLE_DEPRECATION_WARNINGS #if QSV_HAVE_CO3 q->extco3.Header.BufferId = MFX_EXTBUFF_CODING_OPTION3; q->extco3.Header.BufferSz = sizeof(q->extco3); + +switch (q->p_strategy) { +case 0: +q->extco3.PRefType = MFX_P_REF_DEFAULT; +break; +case 1: +q->extco3.PRefType = MFX_P_REF_SIMPLE; +break; +case 2: +q->extco3.PRefType = MFX_P_REF_PYRAMID; +break; +default: +q->extco3.PRefType = MFX_P_REF_DEFAULT; +av_log(avctx, AV_LOG_WARNING, "invalid p_strategy, set to default\n"); +break; +} +if((q->extco3.PRefType == MFX_P_REF_SIMPLE || +q->extco3.PRefType == MFX_P_REF_PYRAMID) && +avctx->max_b_frames != 0){ +av_log(avctx, AV_LOG_WARNING, "Please set max_b_frames(-bf) to 0 to enable P-pyramid\n"); +} + + #if QSV_HAVE_GPB if (avctx->codec_id == AV_CODEC_ID_HEVC) q->extco3.GPB = q->gpb ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 6d305f87dd..1b6149cccf 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -95,6 +95,7 @@ { "adaptive_i", "Adaptive I-frame placement", OFFSET(qsv.adaptive_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "adaptive_b", "Adaptive B-frame placement", OFFSET(qsv.adaptive_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy),AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ +{ "p_strategy", "enable P-pyramid 0-default 1-simple 2-pyramid", OFFSET(qsv.p_strategy), AV_OPT_TYPE_INT,{ .i64 = 0}, 0,2, VE }, \ { "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 = 0}, 0, 1, VE},\ @@ -181,6 +182,7 @@ typedef struct QSVEncContext { int extbrc; int adaptive_i; int adaptive_b; +int p_strategy; int b_strategy; int cavlc; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V5] libavcodec/qsvenc: add low latency P-pyramid support for qsv
From: Wenbinc-Bin Add low latency P-pyramid support for qsv, and it relates to a new command line parameter "-p_strategy". To enable this flag, user also need to set "-bf" to 0. P-strategy has two modes "simple" and "pyramid". The details of these model refers to https://github.com/Intel-Media-SDK/MediaSDK/blob/master/doc/mediasdk-man.md#PRefType patch V2~V4: modify the coding style problem. patch V5: forget to change "if" statement's coding style and fix it in V5. Signed-off-by Wenbin Chen --- libavcodec/qsvenc.c | 32 libavcodec/qsvenc.h | 2 ++ 2 files changed, 34 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 2bd2a56227..07df6f2364 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -268,6 +268,15 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, case MFX_B_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; default:av_log(avctx, AV_LOG_VERBOSE, "auto"); break; } + +av_log(avctx, AV_LOG_VERBOSE, "; PRefType: "); +switch (co3->PRefType) { +case MFX_P_REF_DEFAULT: av_log(avctx, AV_LOG_VERBOSE, "default"); break; +case MFX_P_REF_SIMPLE: av_log(avctx, AV_LOG_VERBOSE, "simple");break; +case MFX_P_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; +default:av_log(avctx, AV_LOG_VERBOSE, "unknown"); break; +} + av_log(avctx, AV_LOG_VERBOSE, "\n"); #endif @@ -777,6 +786,29 @@ FF_ENABLE_DEPRECATION_WARNINGS #if QSV_HAVE_CO3 q->extco3.Header.BufferId = MFX_EXTBUFF_CODING_OPTION3; q->extco3.Header.BufferSz = sizeof(q->extco3); + +switch (q->p_strategy) { +case 0: +q->extco3.PRefType = MFX_P_REF_DEFAULT; +break; +case 1: +q->extco3.PRefType = MFX_P_REF_SIMPLE; +break; +case 2: +q->extco3.PRefType = MFX_P_REF_PYRAMID; +break; +default: +q->extco3.PRefType = MFX_P_REF_DEFAULT; +av_log(avctx, AV_LOG_WARNING, "invalid p_strategy, set to default\n"); +break; +} +if ((q->extco3.PRefType == MFX_P_REF_SIMPLE || +q->extco3.PRefType == MFX_P_REF_PYRAMID) && +avctx->max_b_frames != 0) { +av_log(avctx, AV_LOG_WARNING, "Please set max_b_frames(-bf) to 0 to enable P-pyramid\n"); +} + + #if QSV_HAVE_GPB if (avctx->codec_id == AV_CODEC_ID_HEVC) q->extco3.GPB = q->gpb ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 6d305f87dd..1b6149cccf 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -95,6 +95,7 @@ { "adaptive_i", "Adaptive I-frame placement", OFFSET(qsv.adaptive_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "adaptive_b", "Adaptive B-frame placement", OFFSET(qsv.adaptive_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy),AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ +{ "p_strategy", "enable P-pyramid 0-default 1-simple 2-pyramid", OFFSET(qsv.p_strategy), AV_OPT_TYPE_INT,{ .i64 = 0}, 0,2, VE }, \ { "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 = 0}, 0, 1, VE},\ @@ -181,6 +182,7 @@ typedef struct QSVEncContext { int extbrc; int adaptive_i; int adaptive_b; +int p_strategy; int b_strategy; int cavlc; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V6] libavcodec/qsvenc: add low latency P-pyramid support for qsv
From: Wenbinc-Bin Add low latency P-pyramid support for qsv, and it relates to a new command line parameter "-p_strategy". To enable this flag, user also need to set "-bf" to 0. P-strategy has two modes "1-simple" and "2-pyramid". Signed-off-by Wenbin Chen --- The details of the two models refer to https://github.com/Intel-Media-SDK/MediaSDK/blob/master/doc/mediasdk-man.md#PRefType patch V2~V4: modify the coding style problem. patch V5: Forget to change "if" statement's coding style and fix it in V5. patch V6: Change the patch description's position in patch. libavcodec/qsvenc.c | 32 libavcodec/qsvenc.h | 2 ++ 2 files changed, 34 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 2bd2a56227..07df6f2364 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -268,6 +268,15 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, case MFX_B_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; default:av_log(avctx, AV_LOG_VERBOSE, "auto"); break; } + +av_log(avctx, AV_LOG_VERBOSE, "; PRefType: "); +switch (co3->PRefType) { +case MFX_P_REF_DEFAULT: av_log(avctx, AV_LOG_VERBOSE, "default"); break; +case MFX_P_REF_SIMPLE: av_log(avctx, AV_LOG_VERBOSE, "simple");break; +case MFX_P_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; +default:av_log(avctx, AV_LOG_VERBOSE, "unknown"); break; +} + av_log(avctx, AV_LOG_VERBOSE, "\n"); #endif @@ -777,6 +786,29 @@ FF_ENABLE_DEPRECATION_WARNINGS #if QSV_HAVE_CO3 q->extco3.Header.BufferId = MFX_EXTBUFF_CODING_OPTION3; q->extco3.Header.BufferSz = sizeof(q->extco3); + +switch (q->p_strategy) { +case 0: +q->extco3.PRefType = MFX_P_REF_DEFAULT; +break; +case 1: +q->extco3.PRefType = MFX_P_REF_SIMPLE; +break; +case 2: +q->extco3.PRefType = MFX_P_REF_PYRAMID; +break; +default: +q->extco3.PRefType = MFX_P_REF_DEFAULT; +av_log(avctx, AV_LOG_WARNING, "invalid p_strategy, set to default\n"); +break; +} +if ((q->extco3.PRefType == MFX_P_REF_SIMPLE || +q->extco3.PRefType == MFX_P_REF_PYRAMID) && +avctx->max_b_frames != 0) { +av_log(avctx, AV_LOG_WARNING, "Please set max_b_frames(-bf) to 0 to enable P-pyramid\n"); +} + + #if QSV_HAVE_GPB if (avctx->codec_id == AV_CODEC_ID_HEVC) q->extco3.GPB = q->gpb ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 6d305f87dd..1b6149cccf 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -95,6 +95,7 @@ { "adaptive_i", "Adaptive I-frame placement", OFFSET(qsv.adaptive_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "adaptive_b", "Adaptive B-frame placement", OFFSET(qsv.adaptive_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy),AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ +{ "p_strategy", "enable P-pyramid 0-default 1-simple 2-pyramid", OFFSET(qsv.p_strategy), AV_OPT_TYPE_INT,{ .i64 = 0}, 0,2, VE }, \ { "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 = 0}, 0, 1, VE},\ @@ -181,6 +182,7 @@ typedef struct QSVEncContext { int extbrc; int adaptive_i; int adaptive_b; +int p_strategy; int b_strategy; int cavlc; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 01/10] libavcodec/qsvenc.c: add max_frame_size support for hevc_qsv
From: Wenbinc-Bin The max_frame_size parameter is set only when codec is h264. Now I add hevc in that conditional statement. Signed-off-by: Wenbin Chen --- libavcodec/qsvenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 566a5c8552..0bca4f30e3 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -691,7 +691,7 @@ FF_ENABLE_DEPRECATION_WARNINGS q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco; #if QSV_HAVE_CO2 -if (avctx->codec_id == AV_CODEC_ID_H264) { +if (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_HEVC) { if (q->int_ref_type >= 0) q->extco2.IntRefType = q->int_ref_type; if (q->int_ref_cycle_size >= 0) -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 02/10] libavcodec/qsvenc: add DisableDeblockingIdc support for qsv
From: Wenbinc-Bin MediaSDK already has a flag to control deblocking (DisableDeblockingIdc). Add dblk_idc parameter in ffmpeg to expose this flag to user. Sigend-off-by: Wenbin Chen --- libavcodec/qsvenc.c | 6 ++ libavcodec/qsvenc.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 0bca4f30e3..2434feb660 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -295,6 +295,8 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, av_log(avctx, AV_LOG_VERBOSE, "FrameRateExtD: %"PRIu32"; FrameRateExtN: %"PRIu32" \n", info->FrameInfo.FrameRateExtD, info->FrameInfo.FrameRateExtN); +av_log(avctx, AV_LOG_VERBOSE, "DisableDeblockingIdc: %"PRIu32" \n", co2->DisableDeblockingIdc); + } static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q) @@ -710,6 +712,10 @@ FF_ENABLE_DEPRECATION_WARNINGS if (q->max_slice_size >= 0) q->extco2.MaxSliceSize = q->max_slice_size; #endif +#if QSV_HAVE_DISABLEDEBLOCKIDC +if(q->dblk_idc >= 0) +q->extco2.DisableDeblockingIdc = q->dblk_idc; +#endif #if QSV_HAVE_TRELLIS if (avctx->trellis >= 0) diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 6d305f87dd..3720320789 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -44,6 +44,7 @@ #define QSV_HAVE_TRELLIS QSV_VERSION_ATLEAST(1, 8) #define QSV_HAVE_MAX_SLICE_SIZE QSV_VERSION_ATLEAST(1, 9) +#define QSV_HAVE_DISABLEDEBLOCKIDC QSV_VERSION_ATLEAST(1, 9) #define QSV_HAVE_BREF_TYPE QSV_VERSION_ATLEAST(1, 8) #define QSV_HAVE_LA QSV_VERSION_ATLEAST(1, 7) @@ -97,6 +98,7 @@ { "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy),AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "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 = 0}, 0, 1, VE},\ +{ "dblk_idc", "value of DisableDeblockingIdc (default is 0), in range [0,2]", OFFSET(qsv.dblk_idc), AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, 2, VE},\ extern const AVCodecHWConfigInternal *const ff_qsv_enc_hw_configs[]; @@ -167,6 +169,7 @@ typedef struct QSVEncContext { int rdo; int max_frame_size; int max_slice_size; +int dblk_idc; int tile_cols; int tile_rows; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 03/10] libavcodec/qsvenc: add low latency P-pyramid support for qsv
From: Wenbinc-Bin Add low latency P-pyramid support for qsv, and it relates to a new command line parameter "-p_strategy". To enable this flag, user also need to set "-bf" to 0. P-strategy has two modes "1-simple" and "2-pyramid". The details of the two models refer to https://github.com/Intel-Media-SDK/MediaSDK/blob/master/doc/mediasdk-man.md#PRefType Signed-off-by Wenbin Chen --- libavcodec/qsvenc.c | 30 ++ libavcodec/qsvenc.h | 2 ++ 2 files changed, 32 insertions(+) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 2434feb660..a811d06329 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -268,6 +268,14 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, case MFX_B_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; default:av_log(avctx, AV_LOG_VERBOSE, "auto"); break; } + +av_log(avctx, AV_LOG_VERBOSE, "; PRefType: "); +switch (co3->PRefType) { +case MFX_P_REF_DEFAULT: av_log(avctx, AV_LOG_VERBOSE, "default"); break; +case MFX_P_REF_SIMPLE: av_log(avctx, AV_LOG_VERBOSE, "simple");break; +case MFX_P_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; +default:av_log(avctx, AV_LOG_VERBOSE, "unknown"); break; +} av_log(avctx, AV_LOG_VERBOSE, "\n"); #endif @@ -783,6 +791,28 @@ FF_ENABLE_DEPRECATION_WARNINGS #if QSV_HAVE_CO3 q->extco3.Header.BufferId = MFX_EXTBUFF_CODING_OPTION3; q->extco3.Header.BufferSz = sizeof(q->extco3); + +switch (q->p_strategy) { +case 0: +q->extco3.PRefType = MFX_P_REF_DEFAULT; +break; +case 1: +q->extco3.PRefType = MFX_P_REF_SIMPLE; +break; +case 2: +q->extco3.PRefType = MFX_P_REF_PYRAMID; +break; +default: +q->extco3.PRefType = MFX_P_REF_DEFAULT; +av_log(avctx, AV_LOG_WARNING, "invalid p_strategy, set to default\n"); +break; +} +if ((q->extco3.PRefType == MFX_P_REF_SIMPLE || +q->extco3.PRefType == MFX_P_REF_PYRAMID) && +avctx->max_b_frames != 0) { +av_log(avctx, AV_LOG_WARNING, "Please set max_b_frames(-bf) to 0 to enable P-pyramid\n"); +} + #if QSV_HAVE_GPB if (avctx->codec_id == AV_CODEC_ID_HEVC) q->extco3.GPB = q->gpb ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 3720320789..7da6e0a50f 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -95,6 +95,7 @@ { "extbrc", "Extended bitrate control", OFFSET(qsv.extbrc), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "adaptive_i", "Adaptive I-frame placement", OFFSET(qsv.adaptive_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "adaptive_b", "Adaptive B-frame placement", OFFSET(qsv.adaptive_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ +{ "p_strategy", "enable P-pyramid 0-default 1-simple 2-pyramid", OFFSET(qsv.p_strategy), AV_OPT_TYPE_INT,{ .i64 = 0}, 0,2, VE }, \ { "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy),AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ { "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 = 0}, 0, 1, VE},\ @@ -185,6 +186,7 @@ typedef struct QSVEncContext { int adaptive_i; int adaptive_b; int b_strategy; +int p_strategy; int cavlc; int int_ref_type; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 04/10] libavcodec/qsvdec.c: extract frame packing arrangement data
From: Wenbinc-Bin Use h264_sei to parse SEI data got from MediaSDK. Extract frame packing arrangement information from SEI data and config AVStereo3D side data for decoded frame. Sigend-off-by: Wenbin Chen --- libavcodec/qsv_internal.h | 2 + libavcodec/qsvdec.c | 149 ++ libavcodec/qsvdec.h | 6 ++ 3 files changed, 157 insertions(+) diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h index 6b2fbbe252..aa3da97c99 100644 --- a/libavcodec/qsv_internal.h +++ b/libavcodec/qsv_internal.h @@ -52,6 +52,8 @@ #define QSV_MAX_ENC_PAYLOAD 2 // # of mfxEncodeCtrl payloads supported +#define QSV_PAYLOAD_SIZE 1024 + #define QSV_VERSION_ATLEAST(MAJOR, MINOR) \ (MFX_VERSION_MAJOR > (MAJOR) || \ MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR)) diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index d10f90a0db..5cb49cfb4a 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -36,10 +36,12 @@ #include "libavutil/pixfmt.h" #include "libavutil/time.h" #include "libavutil/imgutils.h" +#include "libavutil/stereo3d.h" #include "avcodec.h" #include "internal.h" #include "decode.h" +#include "get_bits.h" #include "qsv.h" #include "qsv_internal.h" #include "qsvdec.h" @@ -398,6 +400,147 @@ static QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf) return NULL; } +static int h264_decode_fpa(H264SEIFramePacking *fpa, AVFrame *frame) +{ +if (!fpa || !frame) { +return AVERROR(EINVAL); +} + +if (!fpa->arrangement_cancel_flag && +fpa->arrangement_type <= 6 && +fpa->content_interpretation_type > 0 && +fpa->content_interpretation_type < 3) { +AVStereo3D *stereo = av_stereo3d_create_side_data(frame); +if (stereo) { +switch (fpa->arrangement_type) { +case 0: +stereo->type = AV_STEREO3D_CHECKERBOARD; +break; +case 1: +stereo->type = AV_STEREO3D_COLUMNS; +break; +case 2: +stereo->type = AV_STEREO3D_LINES; +break; +case 3: +if (fpa->quincunx_sampling_flag) +stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX; +else +stereo->type = AV_STEREO3D_SIDEBYSIDE; +break; +case 4: +stereo->type = AV_STEREO3D_TOPBOTTOM; +break; +case 5: +stereo->type = AV_STEREO3D_FRAMESEQUENCE; +if (fpa->current_frame_is_frame0_flag) +stereo->view = AV_STEREO3D_VIEW_LEFT; +else +stereo->view = AV_STEREO3D_VIEW_RIGHT; +break; +case 6: +stereo->type = AV_STEREO3D_2D; +break; +} + +if (fpa->content_interpretation_type == 2) +stereo->flags = AV_STEREO3D_FLAG_INVERT; +} +} +return 0; +} + +static int h264_parse_side_data(AVCodecContext *avctx, QSVContext *q, AVFrame *frame) +{ +GetBitContext gb_payload; +uint8_t *sei_buffer; +int sei_buffer_index; +int ret; + +/* remove emulation prevention bytes */ +sei_buffer = (uint8_t *)av_mallocz(q->payload.NumBit / 8); +if (!sei_buffer) { +av_freep(&sei_buffer); +return AVERROR(ENOMEM); +} +sei_buffer_index = 0; +for (int i = 0; i < q->payload.NumBit / 8; i++) { +if (q->payload.Data[i] == 3) +i++; +sei_buffer[sei_buffer_index] = q->payload.Data[i]; +sei_buffer_index += 1; +} + +ret = init_get_bits8(&gb_payload, sei_buffer, sei_buffer_index+1); +if (ret < 0) { +av_freep(&sei_buffer); +return ret; +} + +ret = ff_h264_sei_decode(&q->sei, &gb_payload, &q->ps, avctx); +if (ret < 0) { +av_freep(&sei_buffer); +return ret; +} + +switch (q->payload.Type) { +case SEI_TYPE_FRAME_PACKING_ARRANGEMENT: +ret = h264_decode_fpa(&q->sei.frame_packing, frame); +break; +default: +break; +} + +av_freep(&sei_buffer); +return ret; +} + +static int extract_frame_side_data(AVCodecContext *avctx, QSVContext *q, AVFrame *frame) +{ +mfxU64 ts; +mfxStatus sts; +int ret; + +if (q->payload.BufSize == 0) { +q->payload.Data = av_mallocz(QSV_PAYLOAD_SIZE); +if (!q->payload.Data) { +av_freep(&q->payload.Data); +return AVERROR(ENOMEM); +} +q->payload.BufSize = QSV_PAYLOAD_SIZE; +} + +st
[FFmpeg-devel] [PATCH 05/10] libavcodec/qsvenc: Add transform skip for hevc_qsv
From: Wenbinc-Bin Add transform skip option for hevc_qsv. Command line option is "transform_skip". By enabling this option, the transform_skip_enabled_flag in PPS will be set to 1. This option is only supported in the platform newer than ICL. Signed-off-by Wenbin Chen --- libavcodec/qsvenc.c | 10 -- libavcodec/qsvenc.h | 1 + libavcodec/qsvenc_hevc.c | 3 +++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index a811d06329..f2fcd09ae0 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -304,7 +304,9 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, info->FrameInfo.FrameRateExtD, info->FrameInfo.FrameRateExtN); av_log(avctx, AV_LOG_VERBOSE, "DisableDeblockingIdc: %"PRIu32" \n", co2->DisableDeblockingIdc); - +#if QSV_VERSION_ATLEAST(1, 26) +av_log(avctx, AV_LOG_VERBOSE, "TransformSkip: %s \n", print_threestate(co3->TransformSkip)); +#endif } static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q) @@ -813,10 +815,14 @@ FF_ENABLE_DEPRECATION_WARNINGS av_log(avctx, AV_LOG_WARNING, "Please set max_b_frames(-bf) to 0 to enable P-pyramid\n"); } +if (avctx->codec_id == AV_CODEC_ID_HEVC) { +#if QSV_VERSION_ATLEAST(1, 26) +q->extco3.TransformSkip = q->transform_skip ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; +#endif #if QSV_HAVE_GPB -if (avctx->codec_id == AV_CODEC_ID_HEVC) q->extco3.GPB = q->gpb ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; #endif +} q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco3; #endif } diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 7da6e0a50f..d1de914724 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -197,6 +197,7 @@ typedef struct QSVEncContext { int repeat_pps; int low_power; int gpb; +int transform_skip; int a53_cc; diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index 347f30655e..07a7e3b2be 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -246,6 +246,9 @@ static const AVOption options[] = { { "tile_cols", "Number of columns for tiled encoding", OFFSET(qsv.tile_cols),AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE }, { "tile_rows", "Number of rows for tiled encoding", OFFSET(qsv.tile_rows),AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE }, +#if QSV_VERSION_ATLEAST(1, 26) +{ "transform_skip", "Turn this option ON to enable transformskip", OFFSET(qsv.transform_skip), AV_OPT_TYPE_INT,{ .i64 = -1}, -1, 1, VE}, +#endif { NULL }, }; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 07/10] libavocdec/qsvenc_hevc: encode RGB format rawvideo
From: Wenbinc-Bin Add support for hevc_qsv to input RGB format frame. It will transform frame to yuv inside MediaSDK instead of using auto scale. Hevc_qsv supports directly encoding BGRA and X2RGB10Le format. X2RGB10Le is only supported in VDENC (-low_power 1). The X2RGB10Le correspond to the A2RGB20 format in MediaSDK, and for A2RGB10 the two MSBs is A channels while this two bits in X2RGB10Le is undefined. MediaSDK team is discussing about this, so I leave an interface here. Sigend-of-by: Wenbin Chen --- libavcodec/qsv.c | 16 libavcodec/qsvenc.c | 19 +-- libavcodec/qsvenc_hevc.c | 6 ++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index 6e3154e1a3..7ade53e278 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -196,6 +196,12 @@ int ff_qsv_print_warning(void *log_ctx, mfxStatus err, enum AVPixelFormat ff_qsv_map_fourcc(uint32_t fourcc) { switch (fourcc) { +#if QSV_VERSION_ATLEAST(1, 9) +case MFX_FOURCC_A2RGB10: return AV_PIX_FMT_X2RGB10LE; +#endif +#if QSV_VERSION_ATLEAST(1, 17) +case MFX_FOURCC_RGB4: return AV_PIX_FMT_BGRA; +#endif case MFX_FOURCC_NV12: return AV_PIX_FMT_NV12; case MFX_FOURCC_P010: return AV_PIX_FMT_P010; case MFX_FOURCC_P8: return AV_PIX_FMT_PAL8; @@ -222,6 +228,16 @@ int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc) *fourcc = MFX_FOURCC_P010; return AV_PIX_FMT_P010; #if CONFIG_VAAPI +#if QSV_VERSION_ATLEAST(1, 9) +case AV_PIX_FMT_BGRA: +*fourcc = MFX_FOURCC_RGB4; +return AV_PIX_FMT_BGRA; +#endif +#if QSV_VERSION_ATLEAST(1, 17) +case AV_PIX_FMT_X2RGB10LE: +*fourcc = MFX_FOURCC_A2RGB10; +return AV_PIX_FMT_X2RGB10LE; +#endif case AV_PIX_FMT_YUV422P: case AV_PIX_FMT_YUYV422: *fourcc = MFX_FOURCC_YUY2; diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index addc61bf89..4b345aca0a 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -613,6 +613,13 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) brc_param_multiplier = (FFMAX(FFMAX3(target_bitrate_kbps, max_bitrate_kbps, buffer_size_in_kilobytes), initial_delay_in_kilobytes) + 0x1) / 0x1; +#if QSV_VERSION_ATLEAST(1, 9) +if (sw_format == AV_PIX_FMT_X2RGB10LE && q->low_power != 1) { +av_log(avctx, AV_LOG_ERROR, "Only VDENC support encoding x2rgb10\n"); +return AVERROR(EINVAL); +} +#endif + switch (q->param.mfx.RateControlMethod) { case MFX_RATECONTROL_CBR: case MFX_RATECONTROL_VBR: @@ -1422,8 +1429,16 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame, qf->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING; qf->surface.Data.PitchLow = qf->frame->linesize[0]; -qf->surface.Data.Y = qf->frame->data[0]; -qf->surface.Data.UV= qf->frame->data[1]; +if (frame->format == AV_PIX_FMT_X2RGB10LE || +frame->format == AV_PIX_FMT_BGRA) { +qf->surface.Data.B = qf->frame->data[0]; +qf->surface.Data.G = qf->frame->data[0] + 1; +qf->surface.Data.R = qf->frame->data[0] + 2; +qf->surface.Data.A = qf->frame->data[0] + 3; +} else { +qf->surface.Data.Y = qf->frame->data[0]; +qf->surface.Data.UV= qf->frame->data[1]; +} } qf->surface.Data.TimeStamp = av_rescale_q(frame->pts, q->avctx->time_base, (AVRational){1, 9}); diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index 07a7e3b2be..18e110d140 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -289,6 +289,12 @@ AVCodec ff_hevc_qsv_encoder = { .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_P010, AV_PIX_FMT_QSV, +#if QSV_VERSION_ATLEAST(1, 17) +AV_PIX_FMT_BGRA, +#endif +#if QSV_VERSION_ATLEAST(1, 9) +AV_PIX_FMT_X2RGB10LE, +#endif AV_PIX_FMT_NONE }, .priv_class = &class, .defaults = qsv_enc_defaults, -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 06/10] libavcodec/qsvenc.c: add ROI support to qsv encoder
From: Wenbinc-Bin Use the mfxEncoderCtrl parameter to enable ROI. Get side data "AVRegionOfInterest" from filter "addroi" and use it to configure "mfxExtEncoderROI" which is the MediaSDK's ROI configuration. It is the first time to use encoderCtrl feature in ffmpeg-qsv, so add allocate and free process as well. Sigend-off-by: Wenbin Chen --- libavcodec/qsv_internal.h | 3 ++ libavcodec/qsvenc.c | 74 +++ 2 files changed, 77 insertions(+) diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h index aa3da97c99..d846a2741a 100644 --- a/libavcodec/qsv_internal.h +++ b/libavcodec/qsv_internal.h @@ -51,6 +51,9 @@ #define ASYNC_DEPTH_DEFAULT 4 // internal parallelism #define QSV_MAX_ENC_PAYLOAD 2 // # of mfxEncodeCtrl payloads supported +#define QSV_MAX_ENC_EXTPARAM 2 + +#define QSV_MAX_ROI_NUM 256 #define QSV_PAYLOAD_SIZE 1024 diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index f2fcd09ae0..addc61bf89 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -1291,6 +1291,13 @@ static void clear_unused_frames(QSVEncContext *q) QSVFrame *cur = q->work_frames; while (cur) { if (cur->used && !cur->surface.Data.Locked) { + +for (int i = 0; i < cur->enc_ctrl.NumExtParam; i++) { +if (cur->enc_ctrl.ExtParam[i]) +av_freep(&(cur->enc_ctrl.ExtParam[i])); +} +cur->enc_ctrl.NumExtParam = 0; + free_encoder_ctrl_payloads(&cur->enc_ctrl); if (cur->frame->format == AV_PIX_FMT_QSV) { av_frame_unref(cur->frame); @@ -1333,6 +1340,12 @@ static int get_free_frame(QSVEncContext *q, QSVFrame **f) av_freep(&frame); return AVERROR(ENOMEM); } +frame->enc_ctrl.ExtParam = av_mallocz(sizeof(mfxExtBuffer*) * QSV_MAX_ENC_EXTPARAM); +if (!frame->enc_ctrl.ExtParam) { +av_free(frame->enc_ctrl.Payload); +av_freep(&frame); +return AVERROR(ENOMEM); +} *last = frame; *f = frame; @@ -1436,6 +1449,7 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, const AVFrame *frame) { AVPacket new_pkt = { 0 }; +AVFrameSideData *sd; mfxBitstream *bs; #if QSV_VERSION_ATLEAST(1, 26) mfxExtAVCEncodedFrameInfo *enc_info; @@ -1446,6 +1460,7 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, mfxSyncPoint *sync = NULL; QSVFrame *qsv_frame = NULL; mfxEncodeCtrl* enc_ctrl = NULL; +mfxExtEncoderROI *enc_roi = NULL; int ret; if (frame) { @@ -1480,6 +1495,8 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, bs->Data = new_pkt.data; bs->MaxLength = new_pkt.size; +enc_info = NULL; +enc_buf = NULL; #if QSV_VERSION_ATLEAST(1, 26) if (avctx->codec_id == AV_CODEC_ID_H264) { enc_info = av_mallocz(sizeof(*enc_info)); @@ -1502,6 +1519,62 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, q->set_encode_ctrl_cb(avctx, frame, &qsv_frame->enc_ctrl); } +#if QSV_VERSION_ATLEAST(1, 22) +sd = NULL; +if (frame) { +sd = av_frame_get_side_data(frame, +AV_FRAME_DATA_REGIONS_OF_INTEREST); +} +if (sd) { +AVRegionOfInterest *roi; +uint32_t roi_size; +int nb_roi, i; + +enc_roi = (mfxExtEncoderROI *)av_mallocz(sizeof(*enc_roi)); +if (!enc_roi) { +av_packet_unref(&new_pkt); +if (bs) +av_freep(bs); +if (enc_info) +av_freep(&enc_info); +if (enc_buf) +av_freep(&enc_buf); +return AVERROR(ENOMEM); +} +roi = (AVRegionOfInterest *)sd->data; +roi_size = roi->self_size; +av_assert0(roi_size && sd->size % roi_size == 0); +nb_roi = sd->size / roi_size; +if (nb_roi > QSV_MAX_ROI_NUM) { +av_log(avctx, AV_LOG_WARNING, "More ROIs set than " +"supported by driver (%d > %d).\n", +nb_roi, QSV_MAX_ROI_NUM); +nb_roi = QSV_MAX_ROI_NUM; +} +enc_roi->Header.BufferId = MFX_EXTBUFF_ENCODER_ROI; +enc_roi->Header.BufferSz = sizeof(*enc_roi); +enc_roi->NumROI = nb_roi; +enc_roi->ROIMode = MFX_ROI_MODE_QP_DELTA; +// For overlapping regions, the first in the array takes priority. +for (i = 0; i < nb_roi; i++) { +roi = (AVRegionOfInterest*)(sd->data + roi_size * i); +av_assert0(roi->qoffset.den != 0); + +enc_roi->ROI[i].Top = roi->top & 0xfff0; +enc_roi->ROI[i].Bottom = roi->bottom &am
[FFmpeg-devel] [PATCH 08/10] libavcodec/qsvenc: add horizontal intra refresh and refresh cycle dist
From: Wenbinc-Bin Add an new intra refresh type: "horizontal", and an new param ref_cycle_dist. This param specify the distance between the beginnings of the intra-refresh cycles in frames. Signed-off-by: Wenbin Chen --- libavcodec/qsvenc.c | 13 +++-- libavcodec/qsvenc.h | 1 + libavcodec/qsvenc_h264.c | 5 - 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 4b345aca0a..d16f1094c8 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -217,8 +217,10 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, #if QSV_HAVE_CO2 av_log(avctx, AV_LOG_VERBOSE, - "RecoveryPointSEI: %s IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n", - print_threestate(co->RecoveryPointSEI), co2->IntRefType, co2->IntRefCycleSize, co2->IntRefQPDelta); + "RecoveryPointSEI: %s IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16 + "; IntRefQPDelta: %"PRId16"; IntRefCycleDist: %"PRId16"\n", + print_threestate(co->RecoveryPointSEI), co2->IntRefType, co2->IntRefCycleSize, + co2->IntRefQPDelta, co3->IntRefCycleDist); av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSize: %d; ", co2->MaxFrameSize); #if QSV_HAVE_MAX_SLICE_SIZE @@ -822,6 +824,13 @@ FF_ENABLE_DEPRECATION_WARNINGS av_log(avctx, AV_LOG_WARNING, "Please set max_b_frames(-bf) to 0 to enable P-pyramid\n"); } +#if QSV_VERSION_ATLEAST(1, 16) +if (avctx->codec_id == AV_CODEC_ID_H264) { +if (q->int_ref_cycle_dist) +q->extco3.IntRefCycleDist = q->int_ref_cycle_dist; +} +#endif + if (avctx->codec_id == AV_CODEC_ID_HEVC) { #if QSV_VERSION_ATLEAST(1, 26) q->extco3.TransformSkip = q->transform_skip ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index d1de914724..99befefde1 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -192,6 +192,7 @@ typedef struct QSVEncContext { int int_ref_type; int int_ref_cycle_size; int int_ref_qp_delta; +int int_ref_cycle_dist; int recovery_point_sei; int repeat_pps; diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index ddafc45ec3..47583621b4 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -129,10 +129,13 @@ static const AVOption options[] = { { "int_ref_type", "Intra refresh type", OFFSET(qsv.int_ref_type),AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE, "int_ref_type" }, { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, .flags = VE, "int_ref_type" }, { "vertical", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, .flags = VE, "int_ref_type" }, +{ "horizontal", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, .flags = VE, "int_ref_type" }, { "int_ref_cycle_size", "Number of frames in the intra refresh cycle", OFFSET(qsv.int_ref_cycle_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE }, { "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 }, { "recovery_point_sei", "Insert recovery point SEI messages", OFFSET(qsv.recovery_point_sei), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, - +#if QSV_VERSION_ATLEAST(1, 16) +{ "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 }, +#endif { "profile", NULL, OFFSET(qsv.profile), AV_OPT_TYPE_INT, { .i64 = MFX_PROFILE_UNKNOWN }, 0, INT_MAX, VE, "profile" }, { "unknown" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, "profile" }, { "baseline", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 09/10] libavcodec/qsvdec: using suggested num to set init_pool_size
From: Wenbinc-Bin The init_pool_size is set to be 64 and it is too many. Use IOSurfQuery to get NumFrameSuggest which is the suggested number of frame that needed to be allocated when initial the decoder Considering the hevc_qsv encoder's async is 4 (default) and max_b_frames is 8 (default) and decoder may followed by VPP, use NumFrameSuggest + 16 to set init_pool_size. Sigend-off-by Wenbin Chen --- fftools/ffmpeg_qsv.c | 9 - libavcodec/qsvdec.c | 28 +++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg_qsv.c b/fftools/ffmpeg_qsv.c index 960c88b69d..3862dc1e7d 100644 --- a/fftools/ffmpeg_qsv.c +++ b/fftools/ffmpeg_qsv.c @@ -74,6 +74,7 @@ int qsv_init(AVCodecContext *s) InputStream *ist = s->opaque; AVHWFramesContext *frames_ctx; AVQSVFramesContext *frames_hwctx; +int suggest_pool_size; int ret; if (!hw_device_ctx) { @@ -82,6 +83,12 @@ int qsv_init(AVCodecContext *s) return ret; } +suggest_pool_size = 0; +if (ist->hw_frames_ctx) { +frames_ctx = (AVHWFramesContext *)ist->hw_frames_ctx->data; +suggest_pool_size = frames_ctx->initial_pool_size; +} + av_buffer_unref(&ist->hw_frames_ctx); ist->hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx); if (!ist->hw_frames_ctx) @@ -94,7 +101,7 @@ int qsv_init(AVCodecContext *s) frames_ctx->height= FFALIGN(s->coded_height, 32); frames_ctx->format= AV_PIX_FMT_QSV; frames_ctx->sw_format = s->sw_pix_fmt; -frames_ctx->initial_pool_size = 64 + s->extra_hw_frames; +frames_ctx->initial_pool_size = suggest_pool_size + 16 + s->extra_hw_frames; frames_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; ret = av_hwframe_ctx_init(ist->hw_frames_ctx); diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 5cb49cfb4a..fba7d9cee6 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -720,6 +720,7 @@ int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, AVFrame *frame, int *got_frame, AVPacket *pkt) { int ret; +int first_init; mfxVideoParam param = { 0 }; enum AVPixelFormat pix_fmt = AV_PIX_FMT_NV12; @@ -738,12 +739,20 @@ int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, if (!avctx->coded_height) avctx->coded_height = 720; +first_init = 0; +if (!q->session) +first_init = 1; + ret = qsv_decode_header(avctx, q, pkt, pix_fmt, ¶m); if (ret >= 0 && (q->orig_pix_fmt != ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC) || avctx->coded_width != param.mfx.FrameInfo.Width || -avctx->coded_height != param.mfx.FrameInfo.Height)) { +avctx->coded_height != param.mfx.FrameInfo.Height || +first_init == 1)) { AVPacket zero_pkt = {0}; +mfxFrameAllocRequest request; +AVHWFramesContext *hw_frames_ctx; +memset(&request, 0, sizeof(request)); if (q->buffered_count) { q->reinit_flag = 1; @@ -758,6 +767,23 @@ int ff_qsv_process_data(AVCodecContext *avctx, QSVContext *q, avctx->coded_width = param.mfx.FrameInfo.Width; avctx->coded_height = param.mfx.FrameInfo.Height; +if (first_init == 0) { +hw_frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data; +hw_frames_ctx->initial_pool_size = 0; +ret = qsv_decode_preinit(avctx, q, pix_fmt, ¶m); +if (ret < 0) +goto reinit_fail; +} + +ret = MFXVideoDECODE_QueryIOSurf(q->session, ¶m, &request); +if (ret < 0) +return ff_qsv_print_error(avctx, ret, "Error querying IO surface"); + +if (avctx->hw_frames_ctx) { +hw_frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data; +hw_frames_ctx->initial_pool_size = request.NumFrameSuggested; +} + ret = qsv_decode_preinit(avctx, q, pix_fmt, ¶m); if (ret < 0) goto reinit_fail; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH 10/10] libavcodec/qsvdec: move unref before get_format
From: Wenbinc-Bin Qsv decoder needs to call preinit() twice to get NumFrameSuggest to config init_pool_size. The hw_frame_ctx is released at the second time calling preinit(). The hw_frame_ctx is AVBufferRef, so it release the source when the last unref is called. When the old context is released, the new one is already created, and somehow the device memory is stil be taken, even if the destory memory function is called. Moving unref before creating new context can solve this problem. Signed-off-by Wenbin Chen --- libavcodec/qsvdec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index fba7d9cee6..23494c217d 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -179,6 +179,8 @@ static int qsv_decode_preinit(AVCodecContext *avctx, QSVContext *q, enum AVPixel pix_fmt,/* system memory format obtained from bitstream parser */ AV_PIX_FMT_NONE }; +av_buffer_unref(&q->frames_ctx.mids_buf); +av_buffer_unref(&q->frames_ctx.hw_frames_ctx); ret = ff_get_format(avctx, pix_fmts); if (ret < 0) { q->orig_pix_fmt = avctx->pix_fmt = AV_PIX_FMT_NONE; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V6 1/5] hwcontext_vaapi: Use PRIME_2 memory type for modifiers.
From: Bas Nieuwenhuizen This way we can pass explicit modifiers in. Sometimes the modifier matters for the number of memory planes that libva accepts, in particular when dealing with driver-compressed textures. Furthermore the driver might not actually be able to determine the implicit modifier if all the buffer-passing has used explicit modifier. All these issues should be resolved by passing in the modifier, and for that we switch to using the PRIME_2 memory type. Tested with experimental radeonsi patches for modifiers and kmsgrab. Also tested with radeonsi without the patches to double-check it works without PRIME_2 support. v2: Cache PRIME_2 support to avoid doing two calls every time on libva drivers that do not support it. v3: Remove prime2_vas usage. Signed-off-by: Bas Nieuwenhuizen --- libavutil/hwcontext_vaapi.c | 158 ++-- 1 file changed, 114 insertions(+), 44 deletions(-) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 83e542876d..75acc851d6 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -79,6 +79,9 @@ typedef struct VAAPIFramesContext { unsigned int rt_format; // Whether vaDeriveImage works. int derive_works; +// Caches whether VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2 is unsupported for +// surface imports. +int prime_2_import_unsupported; } VAAPIFramesContext; typedef struct VAAPIMapping { @@ -1022,32 +1025,17 @@ static void vaapi_unmap_from_drm(AVHWFramesContext *dst_fc, static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, const AVFrame *src, int flags) { +VAAPIFramesContext *src_vafc = src_fc->internal->priv; AVHWFramesContext *dst_fc = (AVHWFramesContext*)dst->hw_frames_ctx->data; AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; const AVDRMFrameDescriptor *desc; const VAAPIFormatDescriptor *format_desc; VASurfaceID surface_id; -VAStatus vas; +VAStatus vas = VA_STATUS_SUCCESS; +int use_prime2; uint32_t va_fourcc; -int err, i, j, k; - -unsigned long buffer_handle; -VASurfaceAttribExternalBuffers buffer_desc; -VASurfaceAttrib attrs[2] = { -{ -.type = VASurfaceAttribMemoryType, -.flags = VA_SURFACE_ATTRIB_SETTABLE, -.value.type= VAGenericValueTypeInteger, -.value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME, -}, -{ -.type = VASurfaceAttribExternalBufferDescriptor, -.flags = VA_SURFACE_ATTRIB_SETTABLE, -.value.type= VAGenericValueTypePointer, -.value.value.p = &buffer_desc, -} -}; +int err, i, j; desc = (AVDRMFrameDescriptor*)src->data[0]; @@ -1083,35 +1071,117 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, format_desc = vaapi_format_from_fourcc(va_fourcc); av_assert0(format_desc); -buffer_handle = desc->objects[0].fd; -buffer_desc.pixel_format = va_fourcc; -buffer_desc.width= src_fc->width; -buffer_desc.height = src_fc->height; -buffer_desc.data_size= desc->objects[0].size; -buffer_desc.buffers = &buffer_handle; -buffer_desc.num_buffers = 1; -buffer_desc.flags= 0; - -k = 0; -for (i = 0; i < desc->nb_layers; i++) { -for (j = 0; j < desc->layers[i].nb_planes; j++) { -buffer_desc.pitches[k] = desc->layers[i].planes[j].pitch; -buffer_desc.offsets[k] = desc->layers[i].planes[j].offset; -++k; +use_prime2 = !src_vafc->prime_2_import_unsupported && + desc->objects[0].format_modifier != DRM_FORMAT_MOD_INVALID; +if (use_prime2) { +VADRMPRIMESurfaceDescriptor prime_desc; +VASurfaceAttrib prime_attrs[2] = { +{ +.type = VASurfaceAttribMemoryType, +.flags = VA_SURFACE_ATTRIB_SETTABLE, +.value.type= VAGenericValueTypeInteger, +.value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, +}, +{ +.type = VASurfaceAttribExternalBufferDescriptor, +.flags = VA_SURFACE_ATTRIB_SETTABLE, +.value.type= VAGenericValueTypePointer, +.value.value.p = &prime_desc, +} +}; +prime_desc.fourcc = va_fourcc; +prime_desc.width = src_fc->width; +prime_desc.height = src_fc->height; +prime_desc.num_objects = desc->nb_objects; +for (i = 0; i < desc->nb_objects; ++i) { +prime_desc.objects[i].fd = desc->objects[i].fd; +prime_desc.objects[i].size = desc->objects[i].size; +prime_desc.objects[i].drm_format_modifier = +desc->objects[i].format_modifier; } -} -buffer_desc.num_planes = k; -if (format_desc->chroma_planes
[FFmpeg-devel] [PATCH V6 2/5] libavutil/hwcontext_vaapi: Add a new nv12 format map to support vulkan frame
Vulkan will map nv12 to R8 and GR88, so add this map to vaapi to support vulkan frame. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vaapi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 75acc851d6..994b744e4d 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -992,6 +992,7 @@ static const struct { } vaapi_drm_format_map[] = { #ifdef DRM_FORMAT_R8 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88), +DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_GR88), #endif DRM_MAP(NV12, 1, DRM_FORMAT_NV12), #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16) -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V6 3/5] libavutil/hwcontext_vulkan: Allocate vkFrame in one memory
The vaapi can import external frame, but the planes of the external frames should be in the same drm object. A new option "contiguous_planes" is added to device. This flag tells device to allocate places in one memory. When device is derived from vaapi this flag will be enabled. A new flag frame_flag is also added to AVVulkanFramesContext. User can use this flag to force enable or disable this behaviour. A new variable "offset "is added to AVVKFrame. It describe describe the offset from the memory currently bound to the VkImage. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 68 +++- libavutil/hwcontext_vulkan.h | 24 + 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index a0437c9661..eef9009ae1 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -103,8 +103,14 @@ typedef struct VulkanDevicePriv { /* Settings */ int use_linear_images; +/* allocate planes in a contiguous memory */ +int contiguous_planes; + /* Nvidia */ int dev_is_nvidia; + +/* Intel */ +int dev_is_intel; } VulkanDevicePriv; typedef struct VulkanFramesPriv { @@ -153,6 +159,8 @@ typedef struct AVVkFrameInternal { av_free((void *)props); \ } +#define VKF_FLAG(x, f) (((x) & (~AV_VK_FRAME_FLAG_NONE)) & (f)) + static const struct { enum AVPixelFormat pixfmt; const VkFormat vkfmts[4]; @@ -1374,6 +1382,13 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, if (opt_d) p->use_linear_images = strtol(opt_d->value, NULL, 10); +opt_d = av_dict_get(opts, "contiguous_planes", NULL, 0); +if (opt_d) +p->contiguous_planes = strtol(opt_d->value, NULL, 10); +else +p->contiguous_planes = -1; + + hwctx->enabled_dev_extensions = dev_info.ppEnabledExtensionNames; hwctx->nb_enabled_dev_extensions = dev_info.enabledExtensionCount; @@ -1425,6 +1440,8 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) p->dev_is_nvidia = (p->props.properties.vendorID == 0x10de); +p->dev_is_intel = (p->props.properties.vendorID == 0x8086); + vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &queue_num, NULL); if (!queue_num) { av_log(ctx, AV_LOG_ERROR, "Failed to get queues!\n"); @@ -1742,8 +1759,12 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, AVHWDeviceContext *ctx = hwfc->device_ctx; VulkanDevicePriv *p = ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; +AVVulkanFramesContext *hwfctx = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { { 0 } }; +VkMemoryRequirements memory_requirements = { 0 }; +int mem_size = 0; +int mem_size_list[AV_NUM_DATA_POINTERS] = { 0 }; AVVulkanDeviceContext *hwctx = ctx->hwctx; @@ -1771,6 +1792,19 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, req.memoryRequirements.size = FFALIGN(req.memoryRequirements.size, p->props.properties.limits.minMemoryMapAlignment); +if (VKF_FLAG(hwfctx->flags, AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY)) { +if (memory_requirements.size == 0) { +memory_requirements = req.memoryRequirements; +} else if (memory_requirements.memoryTypeBits != req.memoryRequirements.memoryTypeBits) { +av_log(hwfc, AV_LOG_ERROR, "the param for each planes are not the same\n"); +return AVERROR(EINVAL); +} + +mem_size_list[i] = req.memoryRequirements.size; +mem_size += mem_size_list[i]; +continue; +} + /* In case the implementation prefers/requires dedicated allocation */ use_ded_mem = ded_req.prefersDedicatedAllocation | ded_req.requiresDedicatedAllocation; @@ -1792,6 +1826,29 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, bind_info[i].memory = f->mem[i]; } +if (VKF_FLAG(hwfctx->flags, AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY)) { +memory_requirements.size = mem_size; + +/* Allocate memory */ +if ((err = alloc_mem(ctx, &memory_requirements, +f->tiling == VK_IMAGE_TILING_LINEAR ? +VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT : +VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, +(void *)(((uint8_t *)alloc_pnext)), +&f->flags, &f->mem[0]))) +return err; + +f
[FFmpeg-devel] [PATCH V6 4/5] libavutil/hwcontext_vulkan: Add support to hwmap to software frame when using contiguous_planes flag.
Add support to map vulkan frames to software frames when using contiguous_planes flag. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index eef9009ae1..f980b72720 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -2327,9 +2327,10 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { VkResult ret; -int err, mapped_mem_count = 0; +int err, mapped_mem_count = 0, loop = 0; AVVkFrame *f = (AVVkFrame *)src->data[0]; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; +AVVulkanFramesContext *hwfctx = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; @@ -2356,7 +2357,9 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, dst->width = src->width; dst->height = src->height; -for (int i = 0; i < planes; i++) { +loop = VKF_FLAG(hwfctx->flags, AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY) ? + 1 : planes; +for (int i = 0; i < loop; i++) { ret = vk->MapMemory(hwctx->act_dev, f->mem[i], 0, VK_WHOLE_SIZE, 0, (void **)&dst->data[i]); if (ret != VK_SUCCESS) { @@ -2367,6 +2370,10 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, } mapped_mem_count++; } +if (VKF_FLAG(hwfctx->flags, AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY)) { +for (int i = 0; i < planes; i++) +dst->data[i] = dst->data[0] + f->offset[i]; +} /* Check if the memory contents matter */ if (((flags & AV_HWFRAME_MAP_READ) || !(flags & AV_HWFRAME_MAP_OVERWRITE)) && -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V6 5/5] libavutil/hwcontext_vulkan: specify the modifier to create VKImage
When vulkan image exports to drm, the tilling need to be VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT. Now add code to create vulkan image using this format. Now the following command line works: ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format \ vaapi -i input_1080p.264 -vf "hwmap=derive_device=vulkan,format=vulkan, \ scale_vulkan=1920:1080,hwmap=derive_device=vaapi,format=vaapi" -c:v h264_vaapi output.264 Signed-off-by: Wenbin Chen --- libavutil/hwcontext_vulkan.c | 133 +-- 1 file changed, 127 insertions(+), 6 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index f980b72720..11c4260e86 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -120,6 +120,9 @@ typedef struct VulkanFramesPriv { /* Image transfers */ VulkanExecCtx upload_ctx; VulkanExecCtx download_ctx; + +/*modifier info*/ +VkImageDrmFormatModifierListCreateInfoEXT *modifier_info; } VulkanFramesPriv; typedef struct AVVkFrameInternal { @@ -242,6 +245,31 @@ const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p) return NULL; } +static const void *vk_find_struct(const void *chain, VkStructureType stype) +{ +const VkBaseInStructure *in = chain; +while (in) { +if (in->sType == stype) +return in; + +in = in->pNext; +} + +return NULL; +} + +static void vk_link_struct(void *chain, void *in) +{ +VkBaseOutStructure *out = chain; +if (!in) +return; + +while (out->pNext) +out = out->pNext; + +out->pNext = in; +} + static int pixfmt_is_supported(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p, int linear) { @@ -2094,6 +2122,10 @@ static void try_export_flags(AVHWFramesContext *hwfc, AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; +const int has_modifiers = hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; +int loop_count; +const VkImageDrmFormatModifierListCreateInfoEXT *modifier_info = vk_find_struct(hwctx->create_pnext, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT); VkExternalImageFormatProperties eprops = { .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR, }; @@ -2101,9 +2133,18 @@ static void try_export_flags(AVHWFramesContext *hwfc, .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, .pNext = &eprops, }; +VkPhysicalDeviceImageDrmFormatModifierInfoEXT phy_dev_mod_info = { +.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, +.pNext = NULL, +.pQueueFamilyIndices = p->qfs, +.queueFamilyIndexCount = p->num_qfs, +.sharingMode = p->num_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : + VK_SHARING_MODE_EXCLUSIVE, +}; VkPhysicalDeviceExternalImageFormatInfo enext = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, .handleType = exp, +.pNext = has_modifiers && modifier_info ? &phy_dev_mod_info : NULL, }; VkPhysicalDeviceImageFormatInfo2 pinfo = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, @@ -2115,11 +2156,16 @@ static void try_export_flags(AVHWFramesContext *hwfc, .flags = VK_IMAGE_CREATE_ALIAS_BIT, }; -ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, - &pinfo, &props); -if (ret == VK_SUCCESS) { -*iexp |= exp; -*comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; +loop_count = has_modifiers && modifier_info ? modifier_info->drmFormatModifierCount : 1; +for (int i = 0; i < loop_count; i++) { +if (has_modifiers && modifier_info) +phy_dev_mod_info.drmFormatModifier = modifier_info->pDrmFormatModifiers[i]; +ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, +&pinfo, &props); +if (ret == VK_SUCCESS) { +*iexp |= exp; +*comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; +} } } @@ -2190,6 +2236,12 @@ static void vulkan_frames_uninit(AVHWFramesContext *hwfc) { VulkanFramesPriv *fp = hwfc->internal->priv; +if (fp->modifier_info) { +if (fp->modifier_info->pDrmFormatModifiers) +av_freep(&fp->modifier_info->pDrmFormatModifiers); +av_freep(&fp->modifier_info); +} + free_exec_
[FFmpeg-devel] [PATCH] libavfilter/vf_overlay_qsv: Use format of first input to set output format for overlay_qsv
overlay_qsv hard coded to use nv12 as output format. Now use the format of the first input to set output format. Now the following command works: ffmpeg -hwaccel qsv -c:v hevc_qsv -i input_p010.265 -hwaccel qsv -c:v hevc_qsv \ -i input2_p010.265 -filter_complex "[0:v][1:v]overlay_qsv=x=0:y=0:alpha=255, \ hwdownload,format=p010le" -f rawvideo -y output_p010.yuv Signed-off-by: Wenbin Chen --- libavfilter/vf_overlay_qsv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavfilter/vf_overlay_qsv.c b/libavfilter/vf_overlay_qsv.c index 7e76b39aa9..d947a1faa1 100644 --- a/libavfilter/vf_overlay_qsv.c +++ b/libavfilter/vf_overlay_qsv.c @@ -276,6 +276,7 @@ static int config_output(AVFilterLink *outlink) int ret; av_log(ctx, AV_LOG_DEBUG, "Output is of %s.\n", av_get_pix_fmt_name(outlink->format)); +vpp->qsv_param.out_sw_format = in0->format; if ((in0->format == AV_PIX_FMT_QSV && in1->format != AV_PIX_FMT_QSV) || (in0->format != AV_PIX_FMT_QSV && in1->format == AV_PIX_FMT_QSV)) { av_log(ctx, AV_LOG_ERROR, "Mixing hardware and software pixel formats is not supported.\n"); @@ -288,6 +289,7 @@ static int config_output(AVFilterLink *outlink) av_log(ctx, AV_LOG_ERROR, "Inputs with different underlying QSV devices are forbidden.\n"); return AVERROR(EINVAL); } +vpp->qsv_param.out_sw_format = hw_frame0->sw_format; } outlink->w = vpp->var_values[VAR_MW]; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V3 1/2] libavcodec/vaapi_decode: fix the problem that init_pool_size < nb_surface
For vaapi if the init_pool_size is not zero, the pool size is fixed. This means max surfaces is init_pool_size, but when mapping vaapi frame to qsv frame, the init_pool_size < nb_surface. The cause is that vaapi_decode_make_config() config the init_pool_size and it is called twice. The first time is to init frame_context and the second time is to init codec. On the second time the init_pool_size is changed to original value so the init_pool_size is lower than the reall size because pool_size used to initialize frame_context need to plus thread_count and 3 (guarantee 4 base work surfaces). Now add code to make sure init_pool_size is only set once. Now the following commandline works: ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 \ -hwaccel_output_format vaapi -i input.264 \ -vf "hwmap=derive_device=qsv,format=qsv" \ -c:v h264_qsv output.264 Signed-off-by: Wenbin Chen --- libavcodec/vaapi_decode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index 665af370ed..da0e72b10b 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -650,7 +650,7 @@ int ff_vaapi_decode_init(AVCodecContext *avctx) ctx->hwctx = ctx->device->hwctx; err = vaapi_decode_make_config(avctx, ctx->frames->device_ref, - &ctx->va_config, avctx->hw_frames_ctx); + &ctx->va_config, NULL); if (err) goto fail; -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V3 2/2] libavutil/hwcontext_opencl: fix a bug for mapping qsv frame to opencl
From: nyanmisaka mfxHDLPair was added to qsv, so modify qsv->opencl map function as well. Now the following commandline works: ffmpeg -v verbose -init_hw_device vaapi=va:/dev/dri/renderD128 \ -init_hw_device qsv=qs@va -init_hw_device opencl=ocl@va -filter_hw_device ocl \ -hwaccel qsv -hwaccel_output_format qsv -hwaccel_device qs -c:v h264_qsv \ -i input.264 -vf "hwmap=derive_device=opencl,format=opencl,avgblur_opencl, \ hwmap=derive_device=qsv:reverse=1:extra_hw_frames=32,format=qsv" \ -c:v h264_qsv output.264 Signed-off-by: nyanmisaka Signed-off-by: Wenbin Chen --- libavutil/hwcontext_opencl.c | 3 ++- libavutil/hwcontext_qsv.h| 5 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c index 26a3a24593..ab812999cd 100644 --- a/libavutil/hwcontext_opencl.c +++ b/libavutil/hwcontext_opencl.c @@ -48,6 +48,7 @@ #if HAVE_OPENCL_VAAPI_INTEL_MEDIA #if CONFIG_LIBMFX #include +#include "hwcontext_qsv.h" #endif #include #include @@ -2249,7 +2250,7 @@ static int opencl_map_from_qsv(AVHWFramesContext *dst_fc, AVFrame *dst, #if CONFIG_LIBMFX if (src->format == AV_PIX_FMT_QSV) { mfxFrameSurface1 *mfx_surface = (mfxFrameSurface1*)src->data[3]; -va_surface = *(VASurfaceID*)mfx_surface->Data.MemId; +va_surface = *MFXSURFACEP_TO_VASURFACEP(mfx_surface); } else #endif if (src->format == AV_PIX_FMT_VAAPI) { diff --git a/libavutil/hwcontext_qsv.h b/libavutil/hwcontext_qsv.h index b98d611cfc..957df01ef1 100644 --- a/libavutil/hwcontext_qsv.h +++ b/libavutil/hwcontext_qsv.h @@ -29,6 +29,11 @@ * contain AVBufferRefs whose data pointer points to an mfxFrameSurface1 struct. */ +#if CONFIG_VAAPI +#define MFXSURFACEP_TO_VASURFACEP(surf) \ +(VASurfaceID*)(((mfxHDLPair*)surf->Data.MemId)->first) +#endif + /** * This struct is allocated as AVHWDeviceContext.hwctx */ -- 2.25.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH V2] libavutil/hwcontext_qsv: clean padding when upload qsv frames
Fix #7830 When we upload a frame that is not padded as MSDK requires, we create a new AVFrame to copy data. The frame's padding data is uninitialized so it brings run to run problem. For example, If we run the following command serveral times we will get different outputs. ffmpeg -init_hw_device qsv=qsv:hw -qsv_device /dev/dri/renderD128 \ -filter_hw_device qsv -f rawvideo -s 192x200 -pix_fmt p010 \ -i 192x200_P010.yuv -vf "format=nv12,hwupload=extra_hw_frames=16" \ -c:v hevc_qsv output.265 According to https://github.com/Intel-Media-SDK/MediaSDK/blob/master/doc/mediasdk-man.md#encoding-procedures "Note: It is the application's responsibility to fill pixels outside of crop window when it is smaller than frame to be encoded. Especially in cases when crops are not aligned to minimum coding block size (16 for AVC, 8 for HEVC and VP9)" I add a function to fill padding area with border pixel to fix this run2run problem, and also move the new AVFrame to global structure to reduce redundant allocation operation to increase preformance. Signed-off-by: Wenbin Chen --- libavutil/hwcontext_qsv.c | 96 +-- 1 file changed, 83 insertions(+), 13 deletions(-) diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index a5d154a24d..853fb7f60d 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -47,6 +47,7 @@ #include "pixfmt.h" #include "pixdesc.h" #include "time.h" +#include "imgutils.h" #define QSV_VERSION_ATLEAST(MAJOR, MINOR) \ (MFX_VERSION_MAJOR > (MAJOR) || \ @@ -90,6 +91,7 @@ typedef struct QSVFramesContext { mfxExtOpaqueSurfaceAlloc opaque_alloc; mfxExtBuffer *ext_buffers[1]; +AVFrame realigned_tmp_frame; } QSVFramesContext; static const struct { @@ -137,6 +139,54 @@ static uint32_t qsv_get_d3d11va_bind_flags(int mem_type) } #endif +static int qsv_fill_border(AVFrame *dst, const AVFrame *src) +{ +const AVPixFmtDescriptor *desc; +int i, planes_nb = 0; +if (dst->format != src->format) +return AVERROR(EINVAL); + +desc = av_pix_fmt_desc_get(dst->format); + +for (i = 0; i < desc->nb_components; i++) +planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1); + +for (i = 0; i < planes_nb; i++) { +int sheight, dheight, y; +ptrdiff_t swidth = av_image_get_linesize(src->format, + src->width, + i); +ptrdiff_t dwidth = av_image_get_linesize(dst->format, + dst->width, + i); +const AVComponentDescriptor comp = desc->comp[i]; +if (swidth < 0 || dwidth < 0) { +av_log(NULL, AV_LOG_ERROR, "av_image_get_linesize failed\n"); +return AVERROR(EINVAL); +} +sheight = src->height; +dheight = dst->height; +if (i) { +sheight = AV_CEIL_RSHIFT(src->height, desc->log2_chroma_h); +dheight = AV_CEIL_RSHIFT(dst->height, desc->log2_chroma_h); +} +//fill right padding +for (y = 0; y < sheight; y++) { +void *line_ptr = dst->data[i] + y*dst->linesize[i] + swidth; +av_memcpy_backptr(line_ptr, + comp.depth > 8 ? 2 : 1, + dwidth - swidth); +} +//fill bottom padding +for (y = sheight; y < dheight; y++) { +memcpy(dst->data[i]+y*dst->linesize[i], + dst->data[i]+(sheight-1)*dst->linesize[i], + dwidth); +} +} +return 0; +} + static int qsv_device_init(AVHWDeviceContext *ctx) { AVQSVDeviceContext *hwctx = ctx->hwctx; @@ -220,6 +270,7 @@ static void qsv_frames_uninit(AVHWFramesContext *ctx) av_freep(&s->surface_ptrs); av_freep(&s->surfaces_internal); av_freep(&s->handle_pairs_internal); +av_frame_unref(&s->realigned_tmp_frame); av_buffer_unref(&s->child_frames_ref); } @@ -1014,12 +1065,13 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, QSVFramesContext *s = ctx->internal->priv; mfxFrameSurface1 in = {{ 0 }}; mfxFrameSurface1 *out = (mfxFrameSurface1*)dst->data[3]; +mfxFrameInfo tmp_info; mfxSyncPoint sync = NULL; mfxStatus err; int ret = 0; /* make a copy if the input is not padded as libmfx requires */ -AVFrame tmp_frame; +AVFrame *tmp_frame = &s->realigned_tmp_frame; const AVFrame *src_frame; int realigned = 0; @@ -1048,24 +1100,40 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, if (ret < 0) return ret; +/* Accor
[FFmpeg-devel] [PATCH] doc/encoders.texi Add doc for qsv
Add doc for qsv decoder. Add more option's introduction to qsv encoder. Signed-off-by: Wenbin Chen --- doc/decoders.texi | 42 doc/encoders.texi | 253 +- 2 files changed, 292 insertions(+), 3 deletions(-) diff --git a/doc/decoders.texi b/doc/decoders.texi index 49ab735dce..de2429abba 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -126,6 +126,48 @@ Set amount of frame threads to use during decoding. The default value is 0 (auto @end table +@section QSV Decoders + +The family of Intel QuickSync Video decoders (VC1, MPEG-2, H.264, HEVC, +JPEG/MJPEG, VP8, VP9, AV1). + +@subsection Common Options + +The following options are supported by all qsv decoders. + +@table @option + +@item @var{async_depth} +Internal parallelization depth, the higher the value the higher the latency. + +@item @var{gpu_copy} +A GPU-accelerated copy between video and system memory +@table @samp +@item default +@item on +@item off +@end table + +@end table + +@subsection HEVC Options +Extra options for hevc_qsv. + +@table @option + +@item @var{load_plugin} +A user plugin to load in an internal session +@table @samp +@item none +@item hevc_sw +@item hevc_hw +@end table + +@item @var{load_plugins} +A :-separate list of hexadecimal plugin UIDs to load in an internal session + +@end table + @c man end VIDEO DECODERS @chapter Audio Decoders diff --git a/doc/encoders.texi b/doc/encoders.texi index e3b61de5a1..7cc8be1209 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -3123,12 +3123,13 @@ Setting a higher @option{bits_per_mb} limit will improve the speed. For the fastest encoding speed set the @option{qscale} parameter (4 is the recommended value) and do not set a size constraint. -@section QSV encoders +@section QSV Encoders -The family of Intel QuickSync Video encoders (MPEG-2, H.264, HEVC, JPEG/MJPEG and VP9) +The family of Intel QuickSync Video encoders (MPEG-2, H.264, HEVC, JPEG/MJPEG +and VP9) +@subsection Ratecontrol Method The ratecontrol method is selected as follows: - @itemize @bullet @item When @option{global_quality} is specified, a quality-based mode is used. @@ -3176,6 +3177,7 @@ Note that depending on your system, a different mode than the one you specified may be selected by the encoder. Set the verbosity level to @var{verbose} or higher to see the actual settings used by the QSV runtime. +@subsection Global Options -> MSDK Options Additional libavcodec global options are mapped to MSDK options as follows: @itemize @@ -3212,6 +3214,251 @@ encoder use CAVLC instead of CABAC. @end itemize +@subsection Common Options +Following options are used by all qsv encoders. + +@table @option +@item @var{async_depth} +Specifies how many asynchronous operations an application performs +before the application explicitly synchronizes the result. If zero, +the value is not specified. + +@item @var{avbr_accuracy} +Accuracy of the AVBR ratecontrol (unit of tenth of percent). + +@item @var{avbr_convergence} +Convergence of the AVBR ratecontrol (unit of 100 frames) + +The parameters @var{avbr_accuracy} and @var{avbr_convergence} are for the +average variable bitrate control (AVBR) algorithm. +The algorithm focuses on overall encoding quality while meeting the specified +bitrate, @var{target_bitrate}, within the accuracy range @var{avbr_accuracy}, +after a @var{avbr_Convergence} period. This method does not follow HRD and the +instant bitrate is not capped or padded. + +@item @var{preset} +This option itemizes a range of choices from veryfast (best speed) to veryslow +(best quality). +@table @samp +@item veryfast +@item faster +@item fast +@item medium +@item slow +@item slower +@item veryslow +@end table + +@item @var{forced_idr} +Forcing I frames as IDR frames. + +@item @var{low_power} +For encoders set this flag to ON to reduce power consumption and GPU usage. +@end table + +@subsection H264 options +These options are used by h264_qsv + +@table @option +@item @var{extbrc} +Extended bitrate control. + +@item @var{recovery_point_sei} +Set this flag to insert the recovery point SEI message at the beginning of every +intra refresh cycle. + +@item @var{rdo} +Enable rate distortion optimization. + +@item @var{max_frame_size} +Maximum encoded frame size in bytes. + +@item @var{max_slice_size} +Maximum encoded slice size in bytes. + +@item @var{bitrate_limit} +Toggle bitrate limitations. +Modifies bitrate to be in the range imposed by the QSV encoder. Setting this +flag off may lead to violation of HRD conformance. Mind that specifying bitrate +below the QSV encoder range might significantly affect quality. If on this +option takes effect in non CQP modes: if bitrate is not in the range imposed +by the QSV encoder, it will be changed to be in the range. + +@item @var{mbbrc} +Setting this flag enables macroblock level bitrate control that generally +improves subjective visual quality. Enabling this flag may have negative im