[FFmpeg-devel] [PATCH v9 01/13] avcodec/vaapi_encode: introduce a base layer for vaapi encode
From: Tong Wu Since VAAPI and future D3D12VA implementation may share some common parameters, a base layer encode context is introduced as vaapi context's base. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 56 + libavcodec/vaapi_encode.h | 39 +- 2 files changed, 63 insertions(+), 32 deletions(-) create mode 100644 libavcodec/hw_base_encode.h diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h new file mode 100644 index 00..1996179456 --- /dev/null +++ b/libavcodec/hw_base_encode.h @@ -0,0 +1,56 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_HW_BASE_ENCODE_H +#define AVCODEC_HW_BASE_ENCODE_H + +#define MAX_DPB_SIZE 16 +#define MAX_PICTURE_REFERENCES 2 +#define MAX_REORDER_DELAY 16 +#define MAX_ASYNC_DEPTH 64 +#define MAX_REFERENCE_LIST_NUM 2 + +enum { +PICTURE_TYPE_IDR = 0, +PICTURE_TYPE_I = 1, +PICTURE_TYPE_P = 2, +PICTURE_TYPE_B = 3, +}; + +enum { +// Codec supports controlling the subdivision of pictures into slices. +FLAG_SLICE_CONTROL = 1 << 0, +// Codec only supports constant quality (no rate control). +FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, +// Codec is intra-only. +FLAG_INTRA_ONLY= 1 << 2, +// Codec supports B-pictures. +FLAG_B_PICTURES= 1 << 3, +// Codec supports referencing B-pictures. +FLAG_B_PICTURE_REFERENCES = 1 << 4, +// Codec supports non-IDR key pictures (that is, key pictures do +// not necessarily empty the DPB). +FLAG_NON_IDR_KEY_PICTURES = 1 << 5, +}; + +typedef struct HWBaseEncodeContext { +const AVClass *class; +} HWBaseEncodeContext; + +#endif /* AVCODEC_HW_BASE_ENCODE_H */ + diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index 0eed9691ca..f5c9be8973 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -33,34 +33,27 @@ #include "avcodec.h" #include "hwconfig.h" +#include "hw_base_encode.h" struct VAAPIEncodeType; struct VAAPIEncodePicture; +// Codec output packet without timestamp delay, which means the +// output packet has same PTS and DTS. +#define FLAG_TIMESTAMP_NO_DELAY 1 << 6 + enum { MAX_CONFIG_ATTRIBUTES = 4, MAX_GLOBAL_PARAMS = 4, -MAX_DPB_SIZE = 16, -MAX_PICTURE_REFERENCES = 2, -MAX_REORDER_DELAY = 16, MAX_PARAM_BUFFER_SIZE = 1024, // A.4.1: table A.6 allows at most 22 tile rows for any level. 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, -MAX_REFERENCE_LIST_NUM = 2, }; extern const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[]; -enum { -PICTURE_TYPE_IDR = 0, -PICTURE_TYPE_I = 1, -PICTURE_TYPE_P = 2, -PICTURE_TYPE_B = 3, -}; - typedef struct VAAPIEncodeSlice { int index; int row_start; @@ -193,7 +186,8 @@ typedef struct VAAPIEncodeRCMode { } VAAPIEncodeRCMode; typedef struct VAAPIEncodeContext { -const AVClass *class; +// Base context. +HWBaseEncodeContext base; // Codec-specific hooks. const struct VAAPIEncodeType *codec; @@ -397,25 +391,6 @@ typedef struct VAAPIEncodeContext { AVPacket*tail_pkt; } VAAPIEncodeContext; -enum { -// Codec supports controlling the subdivision of pictures into slices. -FLAG_SLICE_CONTROL = 1 << 0, -// Codec only supports constant quality (no rate control). -FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, -// Codec is intra-only. -FLAG_INTRA_ONLY= 1 << 2, -// Codec supports B-pictures. -FLAG_B_PICTURES= 1 << 3, -// Codec supports referencing B-pictures. -FLAG_B_PICTURE_REFERENCES = 1 << 4, -// Codec supports non-IDR key pictures (that is, key pictures do -// not necessarily empty the DPB). -FLAG_NON_IDR_KEY_PICTURES = 1 << 5, -// Codec output packet without timestamp delay, which means the -// output packet has same PTS and DTS. -FLAG_TIMESTAMP_NO_DELAY= 1 << 6, -}; - typedef struct VAAPIEncodeType { // List of supported profiles and correspond
[FFmpeg-devel] [PATCH v9 02/13] avcodec/vaapi_encode: add async_depth to common options
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 10 +- libavcodec/vaapi_encode.c | 13 - libavcodec/vaapi_encode.h | 7 --- libavcodec/vaapi_encode_av1.c | 1 + libavcodec/vaapi_encode_h264.c | 1 + libavcodec/vaapi_encode_h265.c | 1 + libavcodec/vaapi_encode_mjpeg.c | 1 + libavcodec/vaapi_encode_mpeg2.c | 1 + libavcodec/vaapi_encode_vp8.c | 1 + libavcodec/vaapi_encode_vp9.c | 1 + 10 files changed, 24 insertions(+), 13 deletions(-) diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 1996179456..5272f2836d 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -50,7 +50,15 @@ enum { typedef struct HWBaseEncodeContext { const AVClass *class; + +// Max number of frame buffered in encoder. +int async_depth; } HWBaseEncodeContext; -#endif /* AVCODEC_HW_BASE_ENCODE_H */ +#define HW_BASE_ENCODE_COMMON_OPTIONS \ +{ "async_depth", "Maximum processing parallelism. " \ + "Increase this to improve single channel performance.", \ + OFFSET(common.base.async_depth), AV_OPT_TYPE_INT, \ + { .i64 = 2 }, 1, MAX_ASYNC_DEPTH, FLAGS } +#endif /* AVCODEC_HW_BASE_ENCODE_H */ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index f54b2579ec..9373512417 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -669,7 +669,8 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, VAAPIEncodePicture *pic, AVPacket *pkt) { -VAAPIEncodeContext *ctx = avctx->priv_data; +HWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; if (pic->type == PICTURE_TYPE_IDR) pkt->flags |= AV_PKT_FLAG_KEY; @@ -699,7 +700,7 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, 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 + ctx->async_depth)]; +(3 * ctx->output_delay + base_ctx->async_depth)]; } return 0; @@ -1320,6 +1321,7 @@ static int vaapi_encode_check_frame(AVCodecContext *avctx, static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) { +HWBaseEncodeContext *base_ctx = avctx->priv_data; VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic; int err; @@ -1365,7 +1367,7 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) ctx->dts_pts_diff = pic->pts - ctx->first_pts; if (ctx->output_delay > 0) ctx->ts_ring[ctx->input_order % -(3 * ctx->output_delay + ctx->async_depth)] = pic->pts; +(3 * ctx->output_delay + base_ctx->async_depth)] = pic->pts; pic->display_order = ctx->input_order; ++ctx->input_order; @@ -2773,7 +2775,8 @@ static av_cold int vaapi_encode_create_recon_frames(AVCodecContext *avctx) av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) { -VAAPIEncodeContext *ctx = avctx->priv_data; +HWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; AVVAAPIFramesContext *recon_hwctx = NULL; VAStatus vas; int err; @@ -2966,7 +2969,7 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) vas = vaSyncBuffer(ctx->hwctx->display, VA_INVALID_ID, 0); if (vas != VA_STATUS_ERROR_UNIMPLEMENTED) { ctx->has_sync_buffer_func = 1; -ctx->encode_fifo = av_fifo_alloc2(ctx->async_depth, +ctx->encode_fifo = av_fifo_alloc2(base_ctx->async_depth, sizeof(VAAPIEncodePicture *), 0); if (!ctx->encode_fifo) diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index f5c9be8973..02410c72ec 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -374,8 +374,6 @@ typedef struct VAAPIEncodeContext { int has_sync_buffer_func; // Store buffered pic AVFifo *encode_fifo; -// Max number of frame buffered in encoder. -int async_depth; /** Head data for current output pkt, used only for AV1. */ //void *header_data; @@ -491,11 +489,6 @@ int ff_vaapi_encode_close(AVCodecContext *avctx); "Maximum B-frame reference depth", \ OFFSET(common.desired_b_depth), AV_OPT_TYPE_INT, \ { .i64 = 1 }, 1, INT_MAX, FLAGS }, \ -{ "async_depth", "Maximum processing parallelism. " \ - "Increase this to improve single channel performance. This option " \ - "doesn't work if driver doesn't implement vaSyncBuffer function.", \ - OFFSET(common.async_depth), A
[FFmpeg-devel] [PATCH v9 03/13] avcodec/vaapi_encode: add picture type name to base
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 5 + libavcodec/vaapi_encode.c | 4 +--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 5272f2836d..a578db8c06 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -25,6 +25,11 @@ #define MAX_ASYNC_DEPTH 64 #define MAX_REFERENCE_LIST_NUM 2 +static inline const char *ff_hw_base_encode_get_pictype_name(const int type) { +const char * const picture_type_name[] = { "IDR", "I", "P", "B" }; +return picture_type_name[type]; +} + enum { PICTURE_TYPE_IDR = 0, PICTURE_TYPE_I = 1, diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 9373512417..2d22e4bd85 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -38,8 +38,6 @@ const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[] = { NULL, }; -static const char * const picture_type_name[] = { "IDR", "I", "P", "B" }; - static int vaapi_encode_make_packed_header(AVCodecContext *avctx, VAAPIEncodePicture *pic, int type, char *data, size_t bit_len) @@ -277,7 +275,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Issuing encode for pic %"PRId64"/%"PRId64" " "as type %s.\n", pic->display_order, pic->encode_order, - picture_type_name[pic->type]); + ff_hw_base_encode_get_pictype_name(pic->type)); if (pic->nb_refs[0] == 0 && pic->nb_refs[1] == 0) { av_log(avctx, AV_LOG_DEBUG, "No reference pictures.\n"); } else { -- 2.41.0.windows.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 v9 04/13] avcodec/vaapi_encode: move pic->input_surface initialization to encode_alloc
From: Tong Wu When allocating the VAAPIEncodePicture, pic->input_surface can be initialized right in the place. This movement simplifies the send_frame logic and is the preparation for moving vaapi_encode_send_frame to the base layer. Signed-off-by: Tong Wu --- libavcodec/vaapi_encode.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 2d22e4bd85..227cccae64 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -878,7 +878,8 @@ static int vaapi_encode_discard(AVCodecContext *avctx, return 0; } -static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx) +static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx, + const AVFrame *frame) { VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic; @@ -895,7 +896,7 @@ static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx) } } -pic->input_surface = VA_INVALID_ID; +pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; pic->recon_surface = VA_INVALID_ID; pic->output_buffer = VA_INVALID_ID; @@ -1332,7 +1333,7 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) if (err < 0) return err; -pic = vaapi_encode_alloc(avctx); +pic = vaapi_encode_alloc(avctx, frame); if (!pic) return AVERROR(ENOMEM); @@ -1345,7 +1346,6 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) if (ctx->input_order == 0 || frame->pict_type == AV_PICTURE_TYPE_I) pic->force_idr = 1; -pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; pic->pts = frame->pts; pic->duration = frame->duration; -- 2.41.0.windows.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 v9 05/13] avcodec/vaapi_encode: move the dpb logic from VAAPI to base layer
From: Tong Wu Move receive_packet function to base. This requires adding *alloc, *issue, *output, *free as hardware callbacks. HWBaseEncodePicture is introduced as the base layer structure. The related parameters in VAAPIEncodeContext are also extracted to HWBaseEncodeContext. Then DPB management logic can be fully extracted to base layer as-is. Signed-off-by: Tong Wu --- libavcodec/Makefile | 2 +- libavcodec/hw_base_encode.c | 597 libavcodec/hw_base_encode.h | 124 + libavcodec/vaapi_encode.c | 793 +--- libavcodec/vaapi_encode.h | 102 +--- libavcodec/vaapi_encode_av1.c | 35 +- libavcodec/vaapi_encode_h264.c | 84 ++-- libavcodec/vaapi_encode_h265.c | 53 ++- libavcodec/vaapi_encode_mjpeg.c | 13 +- libavcodec/vaapi_encode_mpeg2.c | 33 +- libavcodec/vaapi_encode_vp8.c | 18 +- libavcodec/vaapi_encode_vp9.c | 24 +- 12 files changed, 988 insertions(+), 890 deletions(-) create mode 100644 libavcodec/hw_base_encode.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2443d2c6fd..998f6b7e12 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -165,7 +165,7 @@ OBJS-$(CONFIG_STARTCODE) += startcode.o OBJS-$(CONFIG_TEXTUREDSP) += texturedsp.o OBJS-$(CONFIG_TEXTUREDSPENC) += texturedspenc.o OBJS-$(CONFIG_TPELDSP) += tpeldsp.o -OBJS-$(CONFIG_VAAPI_ENCODE)+= vaapi_encode.o +OBJS-$(CONFIG_VAAPI_ENCODE)+= vaapi_encode.o hw_base_encode.o OBJS-$(CONFIG_AV1_AMF_ENCODER) += amfenc_av1.o OBJS-$(CONFIG_VC1DSP) += vc1dsp.o OBJS-$(CONFIG_VIDEODSP)+= videodsp.o diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c new file mode 100644 index 00..ec7178d2dc --- /dev/null +++ b/libavcodec/hw_base_encode.c @@ -0,0 +1,597 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" + +#include "encode.h" +#include "avcodec.h" +#include "hw_base_encode.h" + +static void hw_base_encode_add_ref(AVCodecContext *avctx, + HWBaseEncodePicture *pic, + HWBaseEncodePicture *target, + int is_ref, int in_dpb, int prev) +{ +int refs = 0; + +if (is_ref) { +av_assert0(pic != target); +av_assert0(pic->nb_refs[0] < MAX_PICTURE_REFERENCES && + pic->nb_refs[1] < MAX_PICTURE_REFERENCES); +if (target->display_order < pic->display_order) +pic->refs[0][pic->nb_refs[0]++] = target; +else +pic->refs[1][pic->nb_refs[1]++] = target; +++refs; +} + +if (in_dpb) { +av_assert0(pic->nb_dpb_pics < MAX_DPB_SIZE); +pic->dpb[pic->nb_dpb_pics++] = target; +++refs; +} + +if (prev) { +av_assert0(!pic->prev); +pic->prev = target; +++refs; +} + +target->ref_count[0] += refs; +target->ref_count[1] += refs; +} + +static void hw_base_encode_remove_refs(AVCodecContext *avctx, + HWBaseEncodePicture *pic, + int level) +{ +int i; + +if (pic->ref_removed[level]) +return; + +for (i = 0; i < pic->nb_refs[0]; i++) { +av_assert0(pic->refs[0][i]); +--pic->refs[0][i]->ref_count[level]; +av_assert0(pic->refs[0][i]->ref_count[level] >= 0); +} + +for (i = 0; i < pic->nb_refs[1]; i++) { +av_assert0(pic->refs[1][i]); +--pic->refs[1][i]->ref_count[level]; +av_assert0(pic->refs[1][i]->ref_count[level] >= 0); +} + +for (i = 0; i < pic->nb_dpb_pics; i++) { +av_assert0(pic->dpb[i]); +--pic->dpb[i]->ref_count[level]; +av_assert0(pic->dpb[i]->ref_count[level] >= 0); +} + +av_assert0(pic->prev || pic->type == PICTURE_TYPE_IDR); +if (pic->prev) { +--pic->prev->ref_count[level]; +av_assert0(pic->prev->ref_count[level] >= 0); +} + +pic->ref_removed[l
[FFmpeg-devel] [PATCH v9 06/13] avcodec/vaapi_encode: extract the init and close function to base layer
From: Tong Wu Related parameters such as device context, frame context are also moved to base layer. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 49 ++ libavcodec/hw_base_encode.h | 17 +++ libavcodec/vaapi_encode.c | 90 +++-- libavcodec/vaapi_encode.h | 10 libavcodec/vaapi_encode_av1.c | 2 +- libavcodec/vaapi_encode_h264.c | 2 +- libavcodec/vaapi_encode_h265.c | 2 +- libavcodec/vaapi_encode_mjpeg.c | 6 ++- 8 files changed, 102 insertions(+), 76 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index ec7178d2dc..f2b6ef4a3a 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -595,3 +595,52 @@ end: return 0; } + +int ff_hw_base_encode_init(AVCodecContext *avctx) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; + +ctx->frame = av_frame_alloc(); +if (!ctx->frame) +return AVERROR(ENOMEM); + +if (!avctx->hw_frames_ctx) { +av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is " + "required to associate the encoding device.\n"); +return AVERROR(EINVAL); +} + +ctx->input_frames_ref = av_buffer_ref(avctx->hw_frames_ctx); +if (!ctx->input_frames_ref) +return AVERROR(ENOMEM); + +ctx->input_frames = (AVHWFramesContext *)ctx->input_frames_ref->data; + +ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref); +if (!ctx->device_ref) +return AVERROR(ENOMEM); + +ctx->device = (AVHWDeviceContext *)ctx->device_ref->data; + +ctx->tail_pkt = av_packet_alloc(); +if (!ctx->tail_pkt) +return AVERROR(ENOMEM); + +return 0; +} + +int ff_hw_base_encode_close(AVCodecContext *avctx) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; + +av_fifo_freep2(&ctx->encode_fifo); + +av_frame_free(&ctx->frame); +av_packet_free(&ctx->tail_pkt); + +av_buffer_unref(&ctx->device_ref); +av_buffer_unref(&ctx->input_frames_ref); +av_buffer_unref(&ctx->recon_frames_ref); + +return 0; +} diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 2667ae61cd..7e20f57b9c 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -19,6 +19,7 @@ #ifndef AVCODEC_HW_BASE_ENCODE_H #define AVCODEC_HW_BASE_ENCODE_H +#include "libavutil/hwcontext.h" #include "libavutil/fifo.h" #define MAX_DPB_SIZE 16 @@ -118,6 +119,18 @@ typedef struct HWBaseEncodeContext { // Hardware-specific hooks. const struct HWEncodePictureOperation *op; +// The hardware device context. +AVBufferRef*device_ref; +AVHWDeviceContext *device; + +// The hardware frame context containing the input frames. +AVBufferRef*input_frames_ref; +AVHWFramesContext *input_frames; + +// The hardware frame context containing the reconstructed frames. +AVBufferRef*recon_frames_ref; +AVHWFramesContext *recon_frames; + // Current encoding window, in display (input) order. HWBaseEncodePicture *pic_start, *pic_end; // The next picture to use as the previous reference picture in @@ -184,6 +197,10 @@ typedef struct HWBaseEncodeContext { int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); +int ff_hw_base_encode_init(AVCodecContext *avctx); + +int ff_hw_base_encode_close(AVCodecContext *avctx); + #define HW_BASE_ENCODE_COMMON_OPTIONS \ { "async_depth", "Maximum processing parallelism. " \ "Increase this to improve single channel performance.", \ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index c4bb93c520..c3ab0fc192 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -314,7 +314,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Input surface is %#x.\n", pic->input_surface); -err = av_hwframe_get_buffer(ctx->recon_frames_ref, base_pic->recon_image, 0); +err = av_hwframe_get_buffer(base_ctx->recon_frames_ref, base_pic->recon_image, 0); if (err < 0) { err = AVERROR(ENOMEM); goto fail; @@ -996,9 +996,10 @@ static const VAEntrypoint vaapi_encode_entrypoints_low_power[] = { static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx) { -VAAPIEncodeContext *ctx = avctx->priv_data; -VAProfile*va_profiles= NULL; -VAEntrypoint *va_entrypoints = NULL; +HWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; +VAProfile *va_profiles= NULL; +VAEntrypoint *va_entrypoints = NULL; VAStatus vas; const VAEntrypoint *usable_entrypoints; const VAAPIEncodeProfile *profile; @@ -1021,10 +1022,10 @@ static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx) usable_entrypoints = vaapi_encode_entrypoints_normal; } -desc = av_pix_fmt_desc_get(ctx->input_frames->sw_format); +
[FFmpeg-devel] [PATCH v9 08/13] avcodec/vaapi_encode: extract set_output_property to base layer
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 40 + libavcodec/hw_base_encode.h | 3 +++ libavcodec/vaapi_encode.c | 44 ++--- 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index dfe20c4e67..df820c2f83 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -491,6 +491,46 @@ fail: return err; } +int ff_hw_base_encode_set_output_property(AVCodecContext *avctx, + HWBaseEncodePicture *pic, + AVPacket *pkt, int flag_no_delay) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; + +if (pic->type == PICTURE_TYPE_IDR) +pkt->flags |= AV_PKT_FLAG_KEY; + +pkt->pts = pic->pts; +pkt->duration = pic->duration; + +// for no-delay encoders this is handled in generic codec +if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY && +avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { +pkt->opaque = pic->opaque; +pkt->opaque_ref = pic->opaque_ref; +pic->opaque_ref = NULL; +} + +if (flag_no_delay) { +pkt->dts = pkt->pts; +return 0; +} + +if (ctx->output_delay == 0) { +pkt->dts = pkt->pts; +} else if (pic->encode_order < ctx->decode_delay) { +if (ctx->ts_ring[pic->encode_order] < INT64_MIN + ctx->dts_pts_diff) +pkt->dts = INT64_MIN; +else +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 + ctx->async_depth)]; +} + +return 0; +} + int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) { HWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 07936bf9bb..d363819329 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -203,6 +203,9 @@ typedef struct HWBaseEncodeContext { AVPacket*tail_pkt; } HWBaseEncodeContext; +int ff_hw_base_encode_set_output_property(AVCodecContext *avctx, HWBaseEncodePicture *pic, + AVPacket *pkt, int flag_no_delay); + int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 4db64b686b..6ab1b633ed 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -660,47 +660,6 @@ fail_at_end: return err; } -static int vaapi_encode_set_output_property(AVCodecContext *avctx, -HWBaseEncodePicture *pic, -AVPacket *pkt) -{ -HWBaseEncodeContext *base_ctx = avctx->priv_data; -VAAPIEncodeContext *ctx = avctx->priv_data; - -if (pic->type == PICTURE_TYPE_IDR) -pkt->flags |= AV_PKT_FLAG_KEY; - -pkt->pts = pic->pts; -pkt->duration = pic->duration; - -// for no-delay encoders this is handled in generic codec -if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY && -avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { -pkt->opaque = pic->opaque; -pkt->opaque_ref = pic->opaque_ref; -pic->opaque_ref = NULL; -} - -if (ctx->codec->flags & FLAG_TIMESTAMP_NO_DELAY) { -pkt->dts = pkt->pts; -return 0; -} - -if (base_ctx->output_delay == 0) { -pkt->dts = pkt->pts; -} else if (pic->encode_order < base_ctx->decode_delay) { -if (base_ctx->ts_ring[pic->encode_order] < INT64_MIN + base_ctx->dts_pts_diff) -pkt->dts = INT64_MIN; -else -pkt->dts = base_ctx->ts_ring[pic->encode_order] - base_ctx->dts_pts_diff; -} else { -pkt->dts = base_ctx->ts_ring[(pic->encode_order - base_ctx->decode_delay) % - (3 * base_ctx->output_delay + base_ctx->async_depth)]; -} - -return 0; -} - static int vaapi_encode_get_coded_buffer_size(AVCodecContext *avctx, VABufferID buf_id) { VAAPIEncodeContext *ctx = avctx->priv_data; @@ -852,7 +811,8 @@ static int vaapi_encode_output(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n", base_pic->display_order, base_pic->encode_order); -vaapi_encode_set_output_property(avctx, (HWBaseEncodePicture*)pic, pkt_ptr); +ff_hw_base_encode_set_output_property(avctx, (HWBaseEncodePicture*)base_pic, pkt_ptr, + ctx->codec->flags & FLAG_TIMESTAMP_NO_DELAY); end: ff_refstruct_unref(&pic->output_buffer_ref); -- 2.41.0.windows.1 _
[FFmpeg-devel] [PATCH v9 09/13] avcodec/vaapi_encode: extract a get_recon_format function to base layer
From: Tong Wu Surface size and block size parameters are also moved to base layer. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 58 +++ libavcodec/hw_base_encode.h | 12 + libavcodec/vaapi_encode.c | 81 - libavcodec/vaapi_encode.h | 10 libavcodec/vaapi_encode_av1.c | 10 ++-- libavcodec/vaapi_encode_h264.c | 11 +++-- libavcodec/vaapi_encode_h265.c | 25 +- libavcodec/vaapi_encode_mjpeg.c | 5 +- libavcodec/vaapi_encode_vp9.c | 6 +-- 9 files changed, 118 insertions(+), 100 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index df820c2f83..42c40cb48f 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -690,6 +690,64 @@ int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32 return 0; } +int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; +AVHWFramesConstraints *constraints = NULL; +enum AVPixelFormat recon_format; +int err, i; + +constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref, + hwconfig); +if (!constraints) { +err = AVERROR(ENOMEM); +goto fail; +} + +// Probably we can use the input surface format as the surface format +// of the reconstructed frames. If not, we just pick the first (only?) +// format in the valid list and hope that it all works. +recon_format = AV_PIX_FMT_NONE; +if (constraints->valid_sw_formats) { +for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { +if (ctx->input_frames->sw_format == +constraints->valid_sw_formats[i]) { +recon_format = ctx->input_frames->sw_format; +break; +} +} +if (recon_format == AV_PIX_FMT_NONE) { +// No match. Just use the first in the supported list and +// hope for the best. +recon_format = constraints->valid_sw_formats[0]; +} +} else { +// No idea what to use; copy input format. +recon_format = ctx->input_frames->sw_format; +} +av_log(avctx, AV_LOG_DEBUG, "Using %s as format of " + "reconstructed frames.\n", av_get_pix_fmt_name(recon_format)); + +if (ctx->surface_width < constraints->min_width || +ctx->surface_height < constraints->min_height || +ctx->surface_width > constraints->max_width || +ctx->surface_height > constraints->max_height) { +av_log(avctx, AV_LOG_ERROR, "Hardware does not support encoding at " + "size %dx%d (constraints: width %d-%d height %d-%d).\n", + ctx->surface_width, ctx->surface_height, + constraints->min_width, constraints->max_width, + constraints->min_height, constraints->max_height); +err = AVERROR(EINVAL); +goto fail; +} + +*fmt = recon_format; +err = 0; +fail: +av_hwframe_constraints_free(&constraints); +return err; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { HWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index d363819329..7d40da039c 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -127,6 +127,16 @@ typedef struct HWBaseEncodeContext { // Desired B frame reference depth. int desired_b_depth; +// The required size of surfaces. This is probably the input +// size (AVCodecContext.width|height) aligned up to whatever +// block size is required by the codec. +int surface_width; +int surface_height; + +// The block size for slice calculations. +int slice_block_width; +int slice_block_height; + // The hardware device context. AVBufferRef*device_ref; AVHWDeviceContext *device; @@ -211,6 +221,8 @@ int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, int flags, int prediction_pre_only); +int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 6ab1b633ed..98b8c82da3 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1777,6 +1777,7 @@ static av_cold int vaapi_encode_init_tile_slice_structure(AVCodecContext *avctx, static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) { +HWBaseEncodeContext *base_ctx = avctx->pr
[FFmpeg-devel] [PATCH v9 10/13] avcodec/vaapi_encode: extract a free funtion to base layer
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 11 +++ libavcodec/hw_base_encode.h | 2 ++ libavcodec/vaapi_encode.c | 6 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 42c40cb48f..f743d119cd 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -748,6 +748,17 @@ fail: return err; } +int ff_hw_base_encode_free(AVCodecContext *avctx, HWBaseEncodePicture *pic) +{ +av_frame_free(&pic->input_image); +av_frame_free(&pic->recon_image); + +av_buffer_unref(&pic->opaque_ref); +av_freep(&pic->priv_data); + +return 0; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { HWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 7d40da039c..76a39e2d97 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -223,6 +223,8 @@ int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32 int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt); +int ff_hw_base_encode_free(AVCodecContext *avctx, HWBaseEncodePicture *pic); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 98b8c82da3..e89d6e01af 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -878,17 +878,13 @@ static int vaapi_encode_free(AVCodecContext *avctx, av_freep(&pic->slices[i].codec_slice_params); } -av_frame_free(&base_pic->input_image); -av_frame_free(&base_pic->recon_image); - -av_buffer_unref(&base_pic->opaque_ref); +ff_hw_base_encode_free(avctx, base_pic); av_freep(&pic->param_buffers); av_freep(&pic->slices); // Output buffer should already be destroyed. av_assert0(pic->output_buffer == VA_INVALID_ID); -av_freep(&base_pic->priv_data); av_freep(&pic->codec_picture_params); av_freep(&pic->roi); -- 2.41.0.windows.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 v9 11/13] avutil/hwcontext_d3d12va: add Flags for resource creation
From: Tong Wu Flags field is added to support diffferent resource creation. Signed-off-by: Tong Wu --- doc/APIchanges| 3 +++ libavutil/hwcontext_d3d12va.c | 2 +- libavutil/hwcontext_d3d12va.h | 8 libavutil/version.h | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 269fd36559..808ba02f2d 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2024-03-07 API changes, most recent first: +2024-01-xx - xx - lavu 59.20.100 - hwcontext_d3d12va.h + Add AVD3D12VAFramesContext.flags + 2024-05-xx - xx - lavu 59.19.100 - hwcontext_qsv.h Add AVQSVFramesContext.info diff --git a/libavutil/hwcontext_d3d12va.c b/libavutil/hwcontext_d3d12va.c index cfc016315d..6507cf69c1 100644 --- a/libavutil/hwcontext_d3d12va.c +++ b/libavutil/hwcontext_d3d12va.c @@ -247,7 +247,7 @@ static AVBufferRef *d3d12va_pool_alloc(void *opaque, size_t size) .Format = hwctx->format, .SampleDesc = {.Count = 1, .Quality = 0 }, .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, -.Flags= D3D12_RESOURCE_FLAG_NONE, +.Flags= hwctx->flags, }; frame = av_mallocz(sizeof(AVD3D12VAFrame)); diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h index ff06e6f2ef..608dbac97f 100644 --- a/libavutil/hwcontext_d3d12va.h +++ b/libavutil/hwcontext_d3d12va.h @@ -129,6 +129,14 @@ typedef struct AVD3D12VAFramesContext { * If unset, will be automatically set. */ DXGI_FORMAT format; + +/** + * This field is used to specify options for working with resources. + * If unset, this will be D3D12_RESOURCE_FLAG_NONE. + * + * @see: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_resource_flags. + */ +D3D12_RESOURCE_FLAGS flags; } AVD3D12VAFramesContext; #endif /* AVUTIL_HWCONTEXT_D3D12VA_H */ diff --git a/libavutil/version.h b/libavutil/version.h index 3221c4c592..9c7146c228 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 59 -#define LIBAVUTIL_VERSION_MINOR 19 +#define LIBAVUTIL_VERSION_MINOR 20 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ -- 2.41.0.windows.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 v9 12/13] avcodec: add D3D12VA hardware HEVC encoder
From: Tong Wu This implementation is based on D3D12 Video Encoding Spec: https://microsoft.github.io/DirectX-Specs/d3d/D3D12VideoEncoding.html Sample command line for transcoding: ffmpeg.exe -hwaccel d3d12va -hwaccel_output_format d3d12 -i input.mp4 -c:v hevc_d3d12va output.mp4 Signed-off-by: Tong Wu --- configure|6 + libavcodec/Makefile |5 +- libavcodec/allcodecs.c |1 + libavcodec/d3d12va_encode.c | 1558 ++ libavcodec/d3d12va_encode.h | 334 +++ libavcodec/d3d12va_encode_hevc.c | 1007 +++ 6 files changed, 2910 insertions(+), 1 deletion(-) create mode 100644 libavcodec/d3d12va_encode.c create mode 100644 libavcodec/d3d12va_encode.h create mode 100644 libavcodec/d3d12va_encode_hevc.c diff --git a/configure b/configure index b16722d83d..127d68e60c 100755 --- a/configure +++ b/configure @@ -2551,6 +2551,7 @@ CONFIG_EXTRA=" cbs_mpeg2 cbs_vp8 cbs_vp9 +d3d12va_encode deflate_wrapper dirac_parse dnn @@ -3287,6 +3288,7 @@ wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel" # hardware-accelerated codecs +d3d12va_encode_deps="d3d12va ID3D12VideoEncoder d3d12_encoder_feature" mediafoundation_deps="mftransform_h MFCreateAlignedMemoryBuffer" omx_deps="libdl pthreads" omx_rpi_select="omx" @@ -3354,6 +3356,7 @@ h264_v4l2m2m_encoder_deps="v4l2_m2m h264_v4l2_m2m" hevc_amf_encoder_deps="amf" hevc_cuvid_decoder_deps="cuvid" hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf" +hevc_d3d12va_encoder_select="cbs_h265 d3d12va_encode" hevc_mediacodec_decoder_deps="mediacodec" hevc_mediacodec_decoder_select="hevc_mp4toannexb_bsf hevc_parser" hevc_mediacodec_encoder_deps="mediacodec" @@ -6725,6 +6728,9 @@ check_type "windows.h d3d11.h" "ID3D11VideoDecoder" check_type "windows.h d3d11.h" "ID3D11VideoContext" check_type "windows.h d3d12.h" "ID3D12Device" check_type "windows.h d3d12video.h" "ID3D12VideoDecoder" +check_type "windows.h d3d12video.h" "ID3D12VideoEncoder" +test_code cc "windows.h d3d12video.h" "D3D12_FEATURE_VIDEO feature = D3D12_FEATURE_VIDEO_ENCODER_CODEC" && \ +test_code cc "windows.h d3d12video.h" "D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOURCE_REQUIREMENTS req" && enable d3d12_encoder_feature check_type "windows.h" "DPI_AWARENESS_CONTEXT" -D_WIN32_WINNT=0x0A00 check_type "d3d9.h dxva2api.h" DXVA2_ConfigPictureDecode -D_WIN32_WINNT=0x0602 check_func_headers mfapi.h MFCreateAlignedMemoryBuffer -lmfplat diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 998f6b7e12..6c4500ce6d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -86,6 +86,7 @@ OBJS-$(CONFIG_CBS_JPEG)+= cbs_jpeg.o OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o OBJS-$(CONFIG_CBS_VP8) += cbs_vp8.o vp8data.o OBJS-$(CONFIG_CBS_VP9) += cbs_vp9.o +OBJS-$(CONFIG_D3D12VA_ENCODE) += d3d12va_encode.o hw_base_encode.o OBJS-$(CONFIG_DEFLATE_WRAPPER) += zlib_wrapper.o OBJS-$(CONFIG_DOVI_RPUDEC) += dovi_rpu.o dovi_rpudec.o OBJS-$(CONFIG_DOVI_RPUENC) += dovi_rpu.o dovi_rpuenc.o @@ -436,6 +437,8 @@ OBJS-$(CONFIG_HEVC_DECODER)+= hevcdec.o hevc_mvs.o \ h274.o aom_film_grain.o OBJS-$(CONFIG_HEVC_AMF_ENCODER)+= amfenc_hevc.o OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o +OBJS-$(CONFIG_HEVC_D3D12VA_ENCODER)+= d3d12va_encode_hevc.o h265_profile_level.o \ + h2645data.o OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_HEVC_MEDIACODEC_ENCODER) += mediacodecenc.o OBJS-$(CONFIG_HEVC_MF_ENCODER) += mfenc.o mf_utils.o @@ -1265,7 +1268,7 @@ SKIPHEADERS+= %_tablegen.h \ SKIPHEADERS-$(CONFIG_AMF) += amfenc.h SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h -SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h +SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h d3d12va_encode.h SKIPHEADERS-$(CONFIG_DXVA2)+= dxva2.h dxva2_internal.h SKIPHEADERS-$(CONFIG_JNI) += ffjni.h SKIPHEADERS-$(CONFIG_LCMS2)+= fflcms2.h diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index b102a8069e..463ffbbd08 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -848,6 +848,7 @@ extern const FFCodec ff_h264_vaapi_encoder; extern const FFCodec ff_h264_videotoolbox_encoder; extern const FFCodec ff_hevc_amf_encoder; extern const FFCodec ff_hevc_cuvid_decoder; +extern const FFCodec ff_hevc_d3d12va_encoder; extern const FFCodec ff_hevc_mediacodec_decoder; extern const FFCodec ff_hevc_mediacodec_encoder; extern const FFCodec ff_hevc_mf_encoder; diff --git a/libavcodec/d3d12va_encode.c b/libavcodec/d3d12va_encode.c new file mode 100644 index 00..a20e6cc961 --- /
[FFmpeg-devel] [PATCH v9 07/13] avcodec/vaapi_encode: extract gop configuration and two options to base layer
From: Tong Wu idr_interval and desired_b_depth are moved to HW_BASE_ENCODE_COMMON_OPTIONS. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 54 + libavcodec/hw_base_encode.h | 19 + libavcodec/vaapi_encode.c | 52 +++ libavcodec/vaapi_encode.h | 16 --- 4 files changed, 77 insertions(+), 64 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index f2b6ef4a3a..dfe20c4e67 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -596,6 +596,60 @@ end: return 0; } +int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, + int flags, int prediction_pre_only) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; + +if (flags & FLAG_INTRA_ONLY || avctx->gop_size <= 1) { +av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n"); +ctx->gop_size = 1; +} else if (ref_l0 < 1) { +av_log(avctx, AV_LOG_ERROR, "Driver does not support any " + "reference frames.\n"); +return AVERROR(EINVAL); +} else if (!(flags & FLAG_B_PICTURES) || ref_l1 < 1 || + avctx->max_b_frames < 1 || prediction_pre_only) { +if (ctx->p_to_gpb) + av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " + "(supported references: %d / %d).\n", + ref_l0, ref_l1); +else +av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames " + "(supported references: %d / %d).\n", ref_l0, ref_l1); +ctx->gop_size = avctx->gop_size; +ctx->p_per_i = INT_MAX; +ctx->b_per_p = 0; +} else { + if (ctx->p_to_gpb) + av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " + "(supported references: %d / %d).\n", + ref_l0, ref_l1); + else + av_log(avctx, AV_LOG_VERBOSE, "Using intra, P- and B-frames " + "(supported references: %d / %d).\n", ref_l0, ref_l1); +ctx->gop_size = avctx->gop_size; +ctx->p_per_i = INT_MAX; +ctx->b_per_p = avctx->max_b_frames; +if (flags & FLAG_B_PICTURE_REFERENCES) { +ctx->max_b_depth = FFMIN(ctx->desired_b_depth, + av_log2(ctx->b_per_p) + 1); +} else { +ctx->max_b_depth = 1; +} +} + +if (flags & FLAG_NON_IDR_KEY_PICTURES) { +ctx->closed_gop = !!(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP); +ctx->gop_per_idr = ctx->idr_interval + 1; +} else { +ctx->closed_gop = 1; +ctx->gop_per_idr = 1; +} + +return 0; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { HWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 7e20f57b9c..07936bf9bb 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -119,6 +119,14 @@ typedef struct HWBaseEncodeContext { // Hardware-specific hooks. const struct HWEncodePictureOperation *op; +// Global options. + +// Number of I frames between IDR frames. +int idr_interval; + +// Desired B frame reference depth. +int desired_b_depth; + // The hardware device context. AVBufferRef*device_ref; AVHWDeviceContext *device; @@ -197,11 +205,22 @@ typedef struct HWBaseEncodeContext { int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); +int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, + int flags, int prediction_pre_only); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); #define HW_BASE_ENCODE_COMMON_OPTIONS \ +{ "idr_interval", \ + "Distance (in I-frames) between key frames", \ + OFFSET(common.base.idr_interval), AV_OPT_TYPE_INT, \ + { .i64 = 0 }, 0, INT_MAX, FLAGS }, \ +{ "b_depth", \ + "Maximum B-frame reference depth", \ + OFFSET(common.base.desired_b_depth), AV_OPT_TYPE_INT, \ + { .i64 = 1 }, 1, INT_MAX, FLAGS }, \ { "async_depth", "Maximum processing parallelism. " \ "Increase this to improve single channel performance.", \ OFFSET(common.base.async_depth), AV_OPT_TYPE_INT, \ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index c3ab0fc192..4db64b686b 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1638,7 +1638,7 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) VAStatus vas; VAConfigAttrib attr = { VAConfigAttribEncMaxRefFrames }; uint32_t ref_l0, ref_l1; -int prediction_pre_only; +int prediction_pre_only, err; vas = vaGetConfigAttributes(ctx->hwctx->display,
[FFmpeg-devel] [PATCH v9 13/13] Changelog: add D3D12VA HEVC encoder changelog
From: Tong Wu Signed-off-by: Tong Wu --- Changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog b/Changelog index dd25715d6b..c3f802617f 100644 --- a/Changelog +++ b/Changelog @@ -10,7 +10,7 @@ version : - vf_scale supports secondary ref input and framesync options - vf_scale2ref deprecated - qsv_params option added for QSV encoders - +- D3D12VA HEVC encoder version 7.0: - DXV DXT1 encoder -- 2.41.0.windows.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 v10 01/13] avcodec/vaapi_encode: introduce a base layer for vaapi encode
From: Tong Wu Since VAAPI and future D3D12VA implementation may share some common parameters, a base layer encode context is introduced as vaapi context's base. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 56 + libavcodec/vaapi_encode.h | 39 +- 2 files changed, 63 insertions(+), 32 deletions(-) create mode 100644 libavcodec/hw_base_encode.h diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h new file mode 100644 index 00..1996179456 --- /dev/null +++ b/libavcodec/hw_base_encode.h @@ -0,0 +1,56 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_HW_BASE_ENCODE_H +#define AVCODEC_HW_BASE_ENCODE_H + +#define MAX_DPB_SIZE 16 +#define MAX_PICTURE_REFERENCES 2 +#define MAX_REORDER_DELAY 16 +#define MAX_ASYNC_DEPTH 64 +#define MAX_REFERENCE_LIST_NUM 2 + +enum { +PICTURE_TYPE_IDR = 0, +PICTURE_TYPE_I = 1, +PICTURE_TYPE_P = 2, +PICTURE_TYPE_B = 3, +}; + +enum { +// Codec supports controlling the subdivision of pictures into slices. +FLAG_SLICE_CONTROL = 1 << 0, +// Codec only supports constant quality (no rate control). +FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, +// Codec is intra-only. +FLAG_INTRA_ONLY= 1 << 2, +// Codec supports B-pictures. +FLAG_B_PICTURES= 1 << 3, +// Codec supports referencing B-pictures. +FLAG_B_PICTURE_REFERENCES = 1 << 4, +// Codec supports non-IDR key pictures (that is, key pictures do +// not necessarily empty the DPB). +FLAG_NON_IDR_KEY_PICTURES = 1 << 5, +}; + +typedef struct HWBaseEncodeContext { +const AVClass *class; +} HWBaseEncodeContext; + +#endif /* AVCODEC_HW_BASE_ENCODE_H */ + diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index 0eed9691ca..f5c9be8973 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -33,34 +33,27 @@ #include "avcodec.h" #include "hwconfig.h" +#include "hw_base_encode.h" struct VAAPIEncodeType; struct VAAPIEncodePicture; +// Codec output packet without timestamp delay, which means the +// output packet has same PTS and DTS. +#define FLAG_TIMESTAMP_NO_DELAY 1 << 6 + enum { MAX_CONFIG_ATTRIBUTES = 4, MAX_GLOBAL_PARAMS = 4, -MAX_DPB_SIZE = 16, -MAX_PICTURE_REFERENCES = 2, -MAX_REORDER_DELAY = 16, MAX_PARAM_BUFFER_SIZE = 1024, // A.4.1: table A.6 allows at most 22 tile rows for any level. 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, -MAX_REFERENCE_LIST_NUM = 2, }; extern const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[]; -enum { -PICTURE_TYPE_IDR = 0, -PICTURE_TYPE_I = 1, -PICTURE_TYPE_P = 2, -PICTURE_TYPE_B = 3, -}; - typedef struct VAAPIEncodeSlice { int index; int row_start; @@ -193,7 +186,8 @@ typedef struct VAAPIEncodeRCMode { } VAAPIEncodeRCMode; typedef struct VAAPIEncodeContext { -const AVClass *class; +// Base context. +HWBaseEncodeContext base; // Codec-specific hooks. const struct VAAPIEncodeType *codec; @@ -397,25 +391,6 @@ typedef struct VAAPIEncodeContext { AVPacket*tail_pkt; } VAAPIEncodeContext; -enum { -// Codec supports controlling the subdivision of pictures into slices. -FLAG_SLICE_CONTROL = 1 << 0, -// Codec only supports constant quality (no rate control). -FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, -// Codec is intra-only. -FLAG_INTRA_ONLY= 1 << 2, -// Codec supports B-pictures. -FLAG_B_PICTURES= 1 << 3, -// Codec supports referencing B-pictures. -FLAG_B_PICTURE_REFERENCES = 1 << 4, -// Codec supports non-IDR key pictures (that is, key pictures do -// not necessarily empty the DPB). -FLAG_NON_IDR_KEY_PICTURES = 1 << 5, -// Codec output packet without timestamp delay, which means the -// output packet has same PTS and DTS. -FLAG_TIMESTAMP_NO_DELAY= 1 << 6, -}; - typedef struct VAAPIEncodeType { // List of supported profiles and correspond
[FFmpeg-devel] [PATCH v10 02/13] avcodec/vaapi_encode: add async_depth to common options
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 10 +- libavcodec/vaapi_encode.c | 13 - libavcodec/vaapi_encode.h | 7 --- libavcodec/vaapi_encode_av1.c | 1 + libavcodec/vaapi_encode_h264.c | 1 + libavcodec/vaapi_encode_h265.c | 1 + libavcodec/vaapi_encode_mjpeg.c | 1 + libavcodec/vaapi_encode_mpeg2.c | 1 + libavcodec/vaapi_encode_vp8.c | 1 + libavcodec/vaapi_encode_vp9.c | 1 + 10 files changed, 24 insertions(+), 13 deletions(-) diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 1996179456..5272f2836d 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -50,7 +50,15 @@ enum { typedef struct HWBaseEncodeContext { const AVClass *class; + +// Max number of frame buffered in encoder. +int async_depth; } HWBaseEncodeContext; -#endif /* AVCODEC_HW_BASE_ENCODE_H */ +#define HW_BASE_ENCODE_COMMON_OPTIONS \ +{ "async_depth", "Maximum processing parallelism. " \ + "Increase this to improve single channel performance.", \ + OFFSET(common.base.async_depth), AV_OPT_TYPE_INT, \ + { .i64 = 2 }, 1, MAX_ASYNC_DEPTH, FLAGS } +#endif /* AVCODEC_HW_BASE_ENCODE_H */ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index f54b2579ec..9373512417 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -669,7 +669,8 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, VAAPIEncodePicture *pic, AVPacket *pkt) { -VAAPIEncodeContext *ctx = avctx->priv_data; +HWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; if (pic->type == PICTURE_TYPE_IDR) pkt->flags |= AV_PKT_FLAG_KEY; @@ -699,7 +700,7 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, 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 + ctx->async_depth)]; +(3 * ctx->output_delay + base_ctx->async_depth)]; } return 0; @@ -1320,6 +1321,7 @@ static int vaapi_encode_check_frame(AVCodecContext *avctx, static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) { +HWBaseEncodeContext *base_ctx = avctx->priv_data; VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic; int err; @@ -1365,7 +1367,7 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) ctx->dts_pts_diff = pic->pts - ctx->first_pts; if (ctx->output_delay > 0) ctx->ts_ring[ctx->input_order % -(3 * ctx->output_delay + ctx->async_depth)] = pic->pts; +(3 * ctx->output_delay + base_ctx->async_depth)] = pic->pts; pic->display_order = ctx->input_order; ++ctx->input_order; @@ -2773,7 +2775,8 @@ static av_cold int vaapi_encode_create_recon_frames(AVCodecContext *avctx) av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) { -VAAPIEncodeContext *ctx = avctx->priv_data; +HWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; AVVAAPIFramesContext *recon_hwctx = NULL; VAStatus vas; int err; @@ -2966,7 +2969,7 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) vas = vaSyncBuffer(ctx->hwctx->display, VA_INVALID_ID, 0); if (vas != VA_STATUS_ERROR_UNIMPLEMENTED) { ctx->has_sync_buffer_func = 1; -ctx->encode_fifo = av_fifo_alloc2(ctx->async_depth, +ctx->encode_fifo = av_fifo_alloc2(base_ctx->async_depth, sizeof(VAAPIEncodePicture *), 0); if (!ctx->encode_fifo) diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index f5c9be8973..02410c72ec 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -374,8 +374,6 @@ typedef struct VAAPIEncodeContext { int has_sync_buffer_func; // Store buffered pic AVFifo *encode_fifo; -// Max number of frame buffered in encoder. -int async_depth; /** Head data for current output pkt, used only for AV1. */ //void *header_data; @@ -491,11 +489,6 @@ int ff_vaapi_encode_close(AVCodecContext *avctx); "Maximum B-frame reference depth", \ OFFSET(common.desired_b_depth), AV_OPT_TYPE_INT, \ { .i64 = 1 }, 1, INT_MAX, FLAGS }, \ -{ "async_depth", "Maximum processing parallelism. " \ - "Increase this to improve single channel performance. This option " \ - "doesn't work if driver doesn't implement vaSyncBuffer function.", \ - OFFSET(common.async_depth), A
[FFmpeg-devel] [PATCH v10 03/13] avcodec/vaapi_encode: add picture type name to base
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 5 + libavcodec/vaapi_encode.c | 4 +--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 5272f2836d..a578db8c06 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -25,6 +25,11 @@ #define MAX_ASYNC_DEPTH 64 #define MAX_REFERENCE_LIST_NUM 2 +static inline const char *ff_hw_base_encode_get_pictype_name(const int type) { +const char * const picture_type_name[] = { "IDR", "I", "P", "B" }; +return picture_type_name[type]; +} + enum { PICTURE_TYPE_IDR = 0, PICTURE_TYPE_I = 1, diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 9373512417..2d22e4bd85 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -38,8 +38,6 @@ const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[] = { NULL, }; -static const char * const picture_type_name[] = { "IDR", "I", "P", "B" }; - static int vaapi_encode_make_packed_header(AVCodecContext *avctx, VAAPIEncodePicture *pic, int type, char *data, size_t bit_len) @@ -277,7 +275,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Issuing encode for pic %"PRId64"/%"PRId64" " "as type %s.\n", pic->display_order, pic->encode_order, - picture_type_name[pic->type]); + ff_hw_base_encode_get_pictype_name(pic->type)); if (pic->nb_refs[0] == 0 && pic->nb_refs[1] == 0) { av_log(avctx, AV_LOG_DEBUG, "No reference pictures.\n"); } else { -- 2.41.0.windows.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 v10 04/13] avcodec/vaapi_encode: move pic->input_surface initialization to encode_alloc
From: Tong Wu When allocating the VAAPIEncodePicture, pic->input_surface can be initialized right in the place. This movement simplifies the send_frame logic and is the preparation for moving vaapi_encode_send_frame to the base layer. Signed-off-by: Tong Wu --- libavcodec/vaapi_encode.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 2d22e4bd85..227cccae64 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -878,7 +878,8 @@ static int vaapi_encode_discard(AVCodecContext *avctx, return 0; } -static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx) +static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx, + const AVFrame *frame) { VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic; @@ -895,7 +896,7 @@ static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx) } } -pic->input_surface = VA_INVALID_ID; +pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; pic->recon_surface = VA_INVALID_ID; pic->output_buffer = VA_INVALID_ID; @@ -1332,7 +1333,7 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) if (err < 0) return err; -pic = vaapi_encode_alloc(avctx); +pic = vaapi_encode_alloc(avctx, frame); if (!pic) return AVERROR(ENOMEM); @@ -1345,7 +1346,6 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) if (ctx->input_order == 0 || frame->pict_type == AV_PICTURE_TYPE_I) pic->force_idr = 1; -pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; pic->pts = frame->pts; pic->duration = frame->duration; -- 2.41.0.windows.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 v10 07/13] avcodec/vaapi_encode: extract gop configuration and two options to base layer
From: Tong Wu idr_interval and desired_b_depth are moved to HW_BASE_ENCODE_COMMON_OPTIONS. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 54 + libavcodec/hw_base_encode.h | 19 + libavcodec/vaapi_encode.c | 52 +++ libavcodec/vaapi_encode.h | 16 --- 4 files changed, 77 insertions(+), 64 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index f2b6ef4a3a..dfe20c4e67 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -596,6 +596,60 @@ end: return 0; } +int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, + int flags, int prediction_pre_only) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; + +if (flags & FLAG_INTRA_ONLY || avctx->gop_size <= 1) { +av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n"); +ctx->gop_size = 1; +} else if (ref_l0 < 1) { +av_log(avctx, AV_LOG_ERROR, "Driver does not support any " + "reference frames.\n"); +return AVERROR(EINVAL); +} else if (!(flags & FLAG_B_PICTURES) || ref_l1 < 1 || + avctx->max_b_frames < 1 || prediction_pre_only) { +if (ctx->p_to_gpb) + av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " + "(supported references: %d / %d).\n", + ref_l0, ref_l1); +else +av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames " + "(supported references: %d / %d).\n", ref_l0, ref_l1); +ctx->gop_size = avctx->gop_size; +ctx->p_per_i = INT_MAX; +ctx->b_per_p = 0; +} else { + if (ctx->p_to_gpb) + av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " + "(supported references: %d / %d).\n", + ref_l0, ref_l1); + else + av_log(avctx, AV_LOG_VERBOSE, "Using intra, P- and B-frames " + "(supported references: %d / %d).\n", ref_l0, ref_l1); +ctx->gop_size = avctx->gop_size; +ctx->p_per_i = INT_MAX; +ctx->b_per_p = avctx->max_b_frames; +if (flags & FLAG_B_PICTURE_REFERENCES) { +ctx->max_b_depth = FFMIN(ctx->desired_b_depth, + av_log2(ctx->b_per_p) + 1); +} else { +ctx->max_b_depth = 1; +} +} + +if (flags & FLAG_NON_IDR_KEY_PICTURES) { +ctx->closed_gop = !!(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP); +ctx->gop_per_idr = ctx->idr_interval + 1; +} else { +ctx->closed_gop = 1; +ctx->gop_per_idr = 1; +} + +return 0; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { HWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 7e20f57b9c..07936bf9bb 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -119,6 +119,14 @@ typedef struct HWBaseEncodeContext { // Hardware-specific hooks. const struct HWEncodePictureOperation *op; +// Global options. + +// Number of I frames between IDR frames. +int idr_interval; + +// Desired B frame reference depth. +int desired_b_depth; + // The hardware device context. AVBufferRef*device_ref; AVHWDeviceContext *device; @@ -197,11 +205,22 @@ typedef struct HWBaseEncodeContext { int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); +int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, + int flags, int prediction_pre_only); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); #define HW_BASE_ENCODE_COMMON_OPTIONS \ +{ "idr_interval", \ + "Distance (in I-frames) between key frames", \ + OFFSET(common.base.idr_interval), AV_OPT_TYPE_INT, \ + { .i64 = 0 }, 0, INT_MAX, FLAGS }, \ +{ "b_depth", \ + "Maximum B-frame reference depth", \ + OFFSET(common.base.desired_b_depth), AV_OPT_TYPE_INT, \ + { .i64 = 1 }, 1, INT_MAX, FLAGS }, \ { "async_depth", "Maximum processing parallelism. " \ "Increase this to improve single channel performance.", \ OFFSET(common.base.async_depth), AV_OPT_TYPE_INT, \ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index c3ab0fc192..4db64b686b 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1638,7 +1638,7 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) VAStatus vas; VAConfigAttrib attr = { VAConfigAttribEncMaxRefFrames }; uint32_t ref_l0, ref_l1; -int prediction_pre_only; +int prediction_pre_only, err; vas = vaGetConfigAttributes(ctx->hwctx->display,
[FFmpeg-devel] [PATCH v10 08/13] avcodec/vaapi_encode: extract set_output_property to base layer
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 40 + libavcodec/hw_base_encode.h | 3 +++ libavcodec/vaapi_encode.c | 44 ++--- 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index dfe20c4e67..df820c2f83 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -491,6 +491,46 @@ fail: return err; } +int ff_hw_base_encode_set_output_property(AVCodecContext *avctx, + HWBaseEncodePicture *pic, + AVPacket *pkt, int flag_no_delay) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; + +if (pic->type == PICTURE_TYPE_IDR) +pkt->flags |= AV_PKT_FLAG_KEY; + +pkt->pts = pic->pts; +pkt->duration = pic->duration; + +// for no-delay encoders this is handled in generic codec +if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY && +avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { +pkt->opaque = pic->opaque; +pkt->opaque_ref = pic->opaque_ref; +pic->opaque_ref = NULL; +} + +if (flag_no_delay) { +pkt->dts = pkt->pts; +return 0; +} + +if (ctx->output_delay == 0) { +pkt->dts = pkt->pts; +} else if (pic->encode_order < ctx->decode_delay) { +if (ctx->ts_ring[pic->encode_order] < INT64_MIN + ctx->dts_pts_diff) +pkt->dts = INT64_MIN; +else +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 + ctx->async_depth)]; +} + +return 0; +} + int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) { HWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 07936bf9bb..d363819329 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -203,6 +203,9 @@ typedef struct HWBaseEncodeContext { AVPacket*tail_pkt; } HWBaseEncodeContext; +int ff_hw_base_encode_set_output_property(AVCodecContext *avctx, HWBaseEncodePicture *pic, + AVPacket *pkt, int flag_no_delay); + int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 4db64b686b..6ab1b633ed 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -660,47 +660,6 @@ fail_at_end: return err; } -static int vaapi_encode_set_output_property(AVCodecContext *avctx, -HWBaseEncodePicture *pic, -AVPacket *pkt) -{ -HWBaseEncodeContext *base_ctx = avctx->priv_data; -VAAPIEncodeContext *ctx = avctx->priv_data; - -if (pic->type == PICTURE_TYPE_IDR) -pkt->flags |= AV_PKT_FLAG_KEY; - -pkt->pts = pic->pts; -pkt->duration = pic->duration; - -// for no-delay encoders this is handled in generic codec -if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY && -avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { -pkt->opaque = pic->opaque; -pkt->opaque_ref = pic->opaque_ref; -pic->opaque_ref = NULL; -} - -if (ctx->codec->flags & FLAG_TIMESTAMP_NO_DELAY) { -pkt->dts = pkt->pts; -return 0; -} - -if (base_ctx->output_delay == 0) { -pkt->dts = pkt->pts; -} else if (pic->encode_order < base_ctx->decode_delay) { -if (base_ctx->ts_ring[pic->encode_order] < INT64_MIN + base_ctx->dts_pts_diff) -pkt->dts = INT64_MIN; -else -pkt->dts = base_ctx->ts_ring[pic->encode_order] - base_ctx->dts_pts_diff; -} else { -pkt->dts = base_ctx->ts_ring[(pic->encode_order - base_ctx->decode_delay) % - (3 * base_ctx->output_delay + base_ctx->async_depth)]; -} - -return 0; -} - static int vaapi_encode_get_coded_buffer_size(AVCodecContext *avctx, VABufferID buf_id) { VAAPIEncodeContext *ctx = avctx->priv_data; @@ -852,7 +811,8 @@ static int vaapi_encode_output(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n", base_pic->display_order, base_pic->encode_order); -vaapi_encode_set_output_property(avctx, (HWBaseEncodePicture*)pic, pkt_ptr); +ff_hw_base_encode_set_output_property(avctx, (HWBaseEncodePicture*)base_pic, pkt_ptr, + ctx->codec->flags & FLAG_TIMESTAMP_NO_DELAY); end: ff_refstruct_unref(&pic->output_buffer_ref); -- 2.41.0.windows.1 _
[FFmpeg-devel] [PATCH v10 05/13] avcodec/vaapi_encode: move the dpb logic from VAAPI to base layer
From: Tong Wu Move receive_packet function to base. This requires adding *alloc, *issue, *output, *free as hardware callbacks. HWBaseEncodePicture is introduced as the base layer structure. The related parameters in VAAPIEncodeContext are also extracted to HWBaseEncodeContext. Then DPB management logic can be fully extracted to base layer as-is. Signed-off-by: Tong Wu --- libavcodec/Makefile | 2 +- libavcodec/hw_base_encode.c | 597 libavcodec/hw_base_encode.h | 124 + libavcodec/vaapi_encode.c | 793 +--- libavcodec/vaapi_encode.h | 102 +--- libavcodec/vaapi_encode_av1.c | 35 +- libavcodec/vaapi_encode_h264.c | 84 ++-- libavcodec/vaapi_encode_h265.c | 53 ++- libavcodec/vaapi_encode_mjpeg.c | 13 +- libavcodec/vaapi_encode_mpeg2.c | 33 +- libavcodec/vaapi_encode_vp8.c | 18 +- libavcodec/vaapi_encode_vp9.c | 24 +- 12 files changed, 988 insertions(+), 890 deletions(-) create mode 100644 libavcodec/hw_base_encode.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2443d2c6fd..998f6b7e12 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -165,7 +165,7 @@ OBJS-$(CONFIG_STARTCODE) += startcode.o OBJS-$(CONFIG_TEXTUREDSP) += texturedsp.o OBJS-$(CONFIG_TEXTUREDSPENC) += texturedspenc.o OBJS-$(CONFIG_TPELDSP) += tpeldsp.o -OBJS-$(CONFIG_VAAPI_ENCODE)+= vaapi_encode.o +OBJS-$(CONFIG_VAAPI_ENCODE)+= vaapi_encode.o hw_base_encode.o OBJS-$(CONFIG_AV1_AMF_ENCODER) += amfenc_av1.o OBJS-$(CONFIG_VC1DSP) += vc1dsp.o OBJS-$(CONFIG_VIDEODSP)+= videodsp.o diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c new file mode 100644 index 00..ec7178d2dc --- /dev/null +++ b/libavcodec/hw_base_encode.c @@ -0,0 +1,597 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" + +#include "encode.h" +#include "avcodec.h" +#include "hw_base_encode.h" + +static void hw_base_encode_add_ref(AVCodecContext *avctx, + HWBaseEncodePicture *pic, + HWBaseEncodePicture *target, + int is_ref, int in_dpb, int prev) +{ +int refs = 0; + +if (is_ref) { +av_assert0(pic != target); +av_assert0(pic->nb_refs[0] < MAX_PICTURE_REFERENCES && + pic->nb_refs[1] < MAX_PICTURE_REFERENCES); +if (target->display_order < pic->display_order) +pic->refs[0][pic->nb_refs[0]++] = target; +else +pic->refs[1][pic->nb_refs[1]++] = target; +++refs; +} + +if (in_dpb) { +av_assert0(pic->nb_dpb_pics < MAX_DPB_SIZE); +pic->dpb[pic->nb_dpb_pics++] = target; +++refs; +} + +if (prev) { +av_assert0(!pic->prev); +pic->prev = target; +++refs; +} + +target->ref_count[0] += refs; +target->ref_count[1] += refs; +} + +static void hw_base_encode_remove_refs(AVCodecContext *avctx, + HWBaseEncodePicture *pic, + int level) +{ +int i; + +if (pic->ref_removed[level]) +return; + +for (i = 0; i < pic->nb_refs[0]; i++) { +av_assert0(pic->refs[0][i]); +--pic->refs[0][i]->ref_count[level]; +av_assert0(pic->refs[0][i]->ref_count[level] >= 0); +} + +for (i = 0; i < pic->nb_refs[1]; i++) { +av_assert0(pic->refs[1][i]); +--pic->refs[1][i]->ref_count[level]; +av_assert0(pic->refs[1][i]->ref_count[level] >= 0); +} + +for (i = 0; i < pic->nb_dpb_pics; i++) { +av_assert0(pic->dpb[i]); +--pic->dpb[i]->ref_count[level]; +av_assert0(pic->dpb[i]->ref_count[level] >= 0); +} + +av_assert0(pic->prev || pic->type == PICTURE_TYPE_IDR); +if (pic->prev) { +--pic->prev->ref_count[level]; +av_assert0(pic->prev->ref_count[level] >= 0); +} + +pic->ref_removed[l
[FFmpeg-devel] [PATCH v10 06/13] avcodec/vaapi_encode: extract the init and close function to base layer
From: Tong Wu Related parameters such as device context, frame context are also moved to base layer. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 49 ++ libavcodec/hw_base_encode.h | 17 +++ libavcodec/vaapi_encode.c | 90 +++-- libavcodec/vaapi_encode.h | 10 libavcodec/vaapi_encode_av1.c | 2 +- libavcodec/vaapi_encode_h264.c | 2 +- libavcodec/vaapi_encode_h265.c | 2 +- libavcodec/vaapi_encode_mjpeg.c | 6 ++- 8 files changed, 102 insertions(+), 76 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index ec7178d2dc..f2b6ef4a3a 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -595,3 +595,52 @@ end: return 0; } + +int ff_hw_base_encode_init(AVCodecContext *avctx) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; + +ctx->frame = av_frame_alloc(); +if (!ctx->frame) +return AVERROR(ENOMEM); + +if (!avctx->hw_frames_ctx) { +av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is " + "required to associate the encoding device.\n"); +return AVERROR(EINVAL); +} + +ctx->input_frames_ref = av_buffer_ref(avctx->hw_frames_ctx); +if (!ctx->input_frames_ref) +return AVERROR(ENOMEM); + +ctx->input_frames = (AVHWFramesContext *)ctx->input_frames_ref->data; + +ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref); +if (!ctx->device_ref) +return AVERROR(ENOMEM); + +ctx->device = (AVHWDeviceContext *)ctx->device_ref->data; + +ctx->tail_pkt = av_packet_alloc(); +if (!ctx->tail_pkt) +return AVERROR(ENOMEM); + +return 0; +} + +int ff_hw_base_encode_close(AVCodecContext *avctx) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; + +av_fifo_freep2(&ctx->encode_fifo); + +av_frame_free(&ctx->frame); +av_packet_free(&ctx->tail_pkt); + +av_buffer_unref(&ctx->device_ref); +av_buffer_unref(&ctx->input_frames_ref); +av_buffer_unref(&ctx->recon_frames_ref); + +return 0; +} diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 2667ae61cd..7e20f57b9c 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -19,6 +19,7 @@ #ifndef AVCODEC_HW_BASE_ENCODE_H #define AVCODEC_HW_BASE_ENCODE_H +#include "libavutil/hwcontext.h" #include "libavutil/fifo.h" #define MAX_DPB_SIZE 16 @@ -118,6 +119,18 @@ typedef struct HWBaseEncodeContext { // Hardware-specific hooks. const struct HWEncodePictureOperation *op; +// The hardware device context. +AVBufferRef*device_ref; +AVHWDeviceContext *device; + +// The hardware frame context containing the input frames. +AVBufferRef*input_frames_ref; +AVHWFramesContext *input_frames; + +// The hardware frame context containing the reconstructed frames. +AVBufferRef*recon_frames_ref; +AVHWFramesContext *recon_frames; + // Current encoding window, in display (input) order. HWBaseEncodePicture *pic_start, *pic_end; // The next picture to use as the previous reference picture in @@ -184,6 +197,10 @@ typedef struct HWBaseEncodeContext { int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); +int ff_hw_base_encode_init(AVCodecContext *avctx); + +int ff_hw_base_encode_close(AVCodecContext *avctx); + #define HW_BASE_ENCODE_COMMON_OPTIONS \ { "async_depth", "Maximum processing parallelism. " \ "Increase this to improve single channel performance.", \ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index c4bb93c520..c3ab0fc192 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -314,7 +314,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Input surface is %#x.\n", pic->input_surface); -err = av_hwframe_get_buffer(ctx->recon_frames_ref, base_pic->recon_image, 0); +err = av_hwframe_get_buffer(base_ctx->recon_frames_ref, base_pic->recon_image, 0); if (err < 0) { err = AVERROR(ENOMEM); goto fail; @@ -996,9 +996,10 @@ static const VAEntrypoint vaapi_encode_entrypoints_low_power[] = { static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx) { -VAAPIEncodeContext *ctx = avctx->priv_data; -VAProfile*va_profiles= NULL; -VAEntrypoint *va_entrypoints = NULL; +HWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; +VAProfile *va_profiles= NULL; +VAEntrypoint *va_entrypoints = NULL; VAStatus vas; const VAEntrypoint *usable_entrypoints; const VAAPIEncodeProfile *profile; @@ -1021,10 +1022,10 @@ static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx) usable_entrypoints = vaapi_encode_entrypoints_normal; } -desc = av_pix_fmt_desc_get(ctx->input_frames->sw_format); +
[FFmpeg-devel] [PATCH v10 09/13] avcodec/vaapi_encode: extract a get_recon_format function to base layer
From: Tong Wu Surface size and block size parameters are also moved to base layer. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 58 +++ libavcodec/hw_base_encode.h | 12 + libavcodec/vaapi_encode.c | 81 - libavcodec/vaapi_encode.h | 10 libavcodec/vaapi_encode_av1.c | 10 ++-- libavcodec/vaapi_encode_h264.c | 11 +++-- libavcodec/vaapi_encode_h265.c | 25 +- libavcodec/vaapi_encode_mjpeg.c | 5 +- libavcodec/vaapi_encode_vp9.c | 6 +-- 9 files changed, 118 insertions(+), 100 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index df820c2f83..42c40cb48f 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -690,6 +690,64 @@ int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32 return 0; } +int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; +AVHWFramesConstraints *constraints = NULL; +enum AVPixelFormat recon_format; +int err, i; + +constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref, + hwconfig); +if (!constraints) { +err = AVERROR(ENOMEM); +goto fail; +} + +// Probably we can use the input surface format as the surface format +// of the reconstructed frames. If not, we just pick the first (only?) +// format in the valid list and hope that it all works. +recon_format = AV_PIX_FMT_NONE; +if (constraints->valid_sw_formats) { +for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { +if (ctx->input_frames->sw_format == +constraints->valid_sw_formats[i]) { +recon_format = ctx->input_frames->sw_format; +break; +} +} +if (recon_format == AV_PIX_FMT_NONE) { +// No match. Just use the first in the supported list and +// hope for the best. +recon_format = constraints->valid_sw_formats[0]; +} +} else { +// No idea what to use; copy input format. +recon_format = ctx->input_frames->sw_format; +} +av_log(avctx, AV_LOG_DEBUG, "Using %s as format of " + "reconstructed frames.\n", av_get_pix_fmt_name(recon_format)); + +if (ctx->surface_width < constraints->min_width || +ctx->surface_height < constraints->min_height || +ctx->surface_width > constraints->max_width || +ctx->surface_height > constraints->max_height) { +av_log(avctx, AV_LOG_ERROR, "Hardware does not support encoding at " + "size %dx%d (constraints: width %d-%d height %d-%d).\n", + ctx->surface_width, ctx->surface_height, + constraints->min_width, constraints->max_width, + constraints->min_height, constraints->max_height); +err = AVERROR(EINVAL); +goto fail; +} + +*fmt = recon_format; +err = 0; +fail: +av_hwframe_constraints_free(&constraints); +return err; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { HWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index d363819329..7d40da039c 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -127,6 +127,16 @@ typedef struct HWBaseEncodeContext { // Desired B frame reference depth. int desired_b_depth; +// The required size of surfaces. This is probably the input +// size (AVCodecContext.width|height) aligned up to whatever +// block size is required by the codec. +int surface_width; +int surface_height; + +// The block size for slice calculations. +int slice_block_width; +int slice_block_height; + // The hardware device context. AVBufferRef*device_ref; AVHWDeviceContext *device; @@ -211,6 +221,8 @@ int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, int flags, int prediction_pre_only); +int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 6ab1b633ed..98b8c82da3 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1777,6 +1777,7 @@ static av_cold int vaapi_encode_init_tile_slice_structure(AVCodecContext *avctx, static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) { +HWBaseEncodeContext *base_ctx = avctx->pr
[FFmpeg-devel] [PATCH v10 10/13] avcodec/vaapi_encode: extract a free funtion to base layer
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 11 +++ libavcodec/hw_base_encode.h | 2 ++ libavcodec/vaapi_encode.c | 6 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 42c40cb48f..f743d119cd 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -748,6 +748,17 @@ fail: return err; } +int ff_hw_base_encode_free(AVCodecContext *avctx, HWBaseEncodePicture *pic) +{ +av_frame_free(&pic->input_image); +av_frame_free(&pic->recon_image); + +av_buffer_unref(&pic->opaque_ref); +av_freep(&pic->priv_data); + +return 0; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { HWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 7d40da039c..76a39e2d97 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -223,6 +223,8 @@ int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32 int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt); +int ff_hw_base_encode_free(AVCodecContext *avctx, HWBaseEncodePicture *pic); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 98b8c82da3..e89d6e01af 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -878,17 +878,13 @@ static int vaapi_encode_free(AVCodecContext *avctx, av_freep(&pic->slices[i].codec_slice_params); } -av_frame_free(&base_pic->input_image); -av_frame_free(&base_pic->recon_image); - -av_buffer_unref(&base_pic->opaque_ref); +ff_hw_base_encode_free(avctx, base_pic); av_freep(&pic->param_buffers); av_freep(&pic->slices); // Output buffer should already be destroyed. av_assert0(pic->output_buffer == VA_INVALID_ID); -av_freep(&base_pic->priv_data); av_freep(&pic->codec_picture_params); av_freep(&pic->roi); -- 2.41.0.windows.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 v10 11/13] avutil/hwcontext_d3d12va: add Flags for resource creation
From: Tong Wu Flags field is added to support diffferent resource creation. Signed-off-by: Tong Wu --- doc/APIchanges| 3 +++ libavutil/hwcontext_d3d12va.c | 2 +- libavutil/hwcontext_d3d12va.h | 8 libavutil/version.h | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 269fd36559..808ba02f2d 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2024-03-07 API changes, most recent first: +2024-01-xx - xx - lavu 59.20.100 - hwcontext_d3d12va.h + Add AVD3D12VAFramesContext.flags + 2024-05-xx - xx - lavu 59.19.100 - hwcontext_qsv.h Add AVQSVFramesContext.info diff --git a/libavutil/hwcontext_d3d12va.c b/libavutil/hwcontext_d3d12va.c index cfc016315d..6507cf69c1 100644 --- a/libavutil/hwcontext_d3d12va.c +++ b/libavutil/hwcontext_d3d12va.c @@ -247,7 +247,7 @@ static AVBufferRef *d3d12va_pool_alloc(void *opaque, size_t size) .Format = hwctx->format, .SampleDesc = {.Count = 1, .Quality = 0 }, .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, -.Flags= D3D12_RESOURCE_FLAG_NONE, +.Flags= hwctx->flags, }; frame = av_mallocz(sizeof(AVD3D12VAFrame)); diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h index ff06e6f2ef..212a6a6146 100644 --- a/libavutil/hwcontext_d3d12va.h +++ b/libavutil/hwcontext_d3d12va.h @@ -129,6 +129,14 @@ typedef struct AVD3D12VAFramesContext { * If unset, will be automatically set. */ DXGI_FORMAT format; + +/** + * Options for working with resources. + * If unset, this will be D3D12_RESOURCE_FLAG_NONE. + * + * @see https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_resource_flags + */ +D3D12_RESOURCE_FLAGS flags; } AVD3D12VAFramesContext; #endif /* AVUTIL_HWCONTEXT_D3D12VA_H */ diff --git a/libavutil/version.h b/libavutil/version.h index 3221c4c592..9c7146c228 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 59 -#define LIBAVUTIL_VERSION_MINOR 19 +#define LIBAVUTIL_VERSION_MINOR 20 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ -- 2.41.0.windows.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 v10 12/13] avcodec: add D3D12VA hardware HEVC encoder
From: Tong Wu This implementation is based on D3D12 Video Encoding Spec: https://microsoft.github.io/DirectX-Specs/d3d/D3D12VideoEncoding.html Sample command line for transcoding: ffmpeg.exe -hwaccel d3d12va -hwaccel_output_format d3d12 -i input.mp4 -c:v hevc_d3d12va output.mp4 Signed-off-by: Tong Wu --- configure|6 + libavcodec/Makefile |5 +- libavcodec/allcodecs.c |1 + libavcodec/d3d12va_encode.c | 1558 ++ libavcodec/d3d12va_encode.h | 334 +++ libavcodec/d3d12va_encode_hevc.c | 1007 +++ 6 files changed, 2910 insertions(+), 1 deletion(-) create mode 100644 libavcodec/d3d12va_encode.c create mode 100644 libavcodec/d3d12va_encode.h create mode 100644 libavcodec/d3d12va_encode_hevc.c diff --git a/configure b/configure index b16722d83d..127d68e60c 100755 --- a/configure +++ b/configure @@ -2551,6 +2551,7 @@ CONFIG_EXTRA=" cbs_mpeg2 cbs_vp8 cbs_vp9 +d3d12va_encode deflate_wrapper dirac_parse dnn @@ -3287,6 +3288,7 @@ wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel" # hardware-accelerated codecs +d3d12va_encode_deps="d3d12va ID3D12VideoEncoder d3d12_encoder_feature" mediafoundation_deps="mftransform_h MFCreateAlignedMemoryBuffer" omx_deps="libdl pthreads" omx_rpi_select="omx" @@ -3354,6 +3356,7 @@ h264_v4l2m2m_encoder_deps="v4l2_m2m h264_v4l2_m2m" hevc_amf_encoder_deps="amf" hevc_cuvid_decoder_deps="cuvid" hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf" +hevc_d3d12va_encoder_select="cbs_h265 d3d12va_encode" hevc_mediacodec_decoder_deps="mediacodec" hevc_mediacodec_decoder_select="hevc_mp4toannexb_bsf hevc_parser" hevc_mediacodec_encoder_deps="mediacodec" @@ -6725,6 +6728,9 @@ check_type "windows.h d3d11.h" "ID3D11VideoDecoder" check_type "windows.h d3d11.h" "ID3D11VideoContext" check_type "windows.h d3d12.h" "ID3D12Device" check_type "windows.h d3d12video.h" "ID3D12VideoDecoder" +check_type "windows.h d3d12video.h" "ID3D12VideoEncoder" +test_code cc "windows.h d3d12video.h" "D3D12_FEATURE_VIDEO feature = D3D12_FEATURE_VIDEO_ENCODER_CODEC" && \ +test_code cc "windows.h d3d12video.h" "D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOURCE_REQUIREMENTS req" && enable d3d12_encoder_feature check_type "windows.h" "DPI_AWARENESS_CONTEXT" -D_WIN32_WINNT=0x0A00 check_type "d3d9.h dxva2api.h" DXVA2_ConfigPictureDecode -D_WIN32_WINNT=0x0602 check_func_headers mfapi.h MFCreateAlignedMemoryBuffer -lmfplat diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 998f6b7e12..6c4500ce6d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -86,6 +86,7 @@ OBJS-$(CONFIG_CBS_JPEG)+= cbs_jpeg.o OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o OBJS-$(CONFIG_CBS_VP8) += cbs_vp8.o vp8data.o OBJS-$(CONFIG_CBS_VP9) += cbs_vp9.o +OBJS-$(CONFIG_D3D12VA_ENCODE) += d3d12va_encode.o hw_base_encode.o OBJS-$(CONFIG_DEFLATE_WRAPPER) += zlib_wrapper.o OBJS-$(CONFIG_DOVI_RPUDEC) += dovi_rpu.o dovi_rpudec.o OBJS-$(CONFIG_DOVI_RPUENC) += dovi_rpu.o dovi_rpuenc.o @@ -436,6 +437,8 @@ OBJS-$(CONFIG_HEVC_DECODER)+= hevcdec.o hevc_mvs.o \ h274.o aom_film_grain.o OBJS-$(CONFIG_HEVC_AMF_ENCODER)+= amfenc_hevc.o OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o +OBJS-$(CONFIG_HEVC_D3D12VA_ENCODER)+= d3d12va_encode_hevc.o h265_profile_level.o \ + h2645data.o OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_HEVC_MEDIACODEC_ENCODER) += mediacodecenc.o OBJS-$(CONFIG_HEVC_MF_ENCODER) += mfenc.o mf_utils.o @@ -1265,7 +1268,7 @@ SKIPHEADERS+= %_tablegen.h \ SKIPHEADERS-$(CONFIG_AMF) += amfenc.h SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h -SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h +SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h d3d12va_encode.h SKIPHEADERS-$(CONFIG_DXVA2)+= dxva2.h dxva2_internal.h SKIPHEADERS-$(CONFIG_JNI) += ffjni.h SKIPHEADERS-$(CONFIG_LCMS2)+= fflcms2.h diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index b102a8069e..463ffbbd08 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -848,6 +848,7 @@ extern const FFCodec ff_h264_vaapi_encoder; extern const FFCodec ff_h264_videotoolbox_encoder; extern const FFCodec ff_hevc_amf_encoder; extern const FFCodec ff_hevc_cuvid_decoder; +extern const FFCodec ff_hevc_d3d12va_encoder; extern const FFCodec ff_hevc_mediacodec_decoder; extern const FFCodec ff_hevc_mediacodec_encoder; extern const FFCodec ff_hevc_mf_encoder; diff --git a/libavcodec/d3d12va_encode.c b/libavcodec/d3d12va_encode.c new file mode 100644 index 00..a20e6cc961 --- /
[FFmpeg-devel] [PATCH v10 13/13] Changelog: add D3D12VA HEVC encoder changelog
From: Tong Wu Signed-off-by: Tong Wu --- Changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 12770e4296..c5d57b3813 100644 --- a/Changelog +++ b/Changelog @@ -11,7 +11,7 @@ version : - vf_scale2ref deprecated - qsv_params option added for QSV encoders - VVC decoder compatible with DVB test content - +- D3D12VA HEVC encoder version 7.0: - DXV DXT1 encoder -- 2.41.0.windows.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 v11 01/14] avcodec/vaapi_encode: introduce a base layer for vaapi encode
From: Tong Wu Since VAAPI and future D3D12VA implementation may share some common parameters, a base layer encode context is introduced as vaapi context's base. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 56 + libavcodec/vaapi_encode.h | 39 +- 2 files changed, 63 insertions(+), 32 deletions(-) create mode 100644 libavcodec/hw_base_encode.h diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h new file mode 100644 index 00..ffcb6bcbb2 --- /dev/null +++ b/libavcodec/hw_base_encode.h @@ -0,0 +1,56 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_HW_BASE_ENCODE_H +#define AVCODEC_HW_BASE_ENCODE_H + +#define MAX_DPB_SIZE 16 +#define MAX_PICTURE_REFERENCES 2 +#define MAX_REORDER_DELAY 16 +#define MAX_ASYNC_DEPTH 64 +#define MAX_REFERENCE_LIST_NUM 2 + +enum { +PICTURE_TYPE_IDR = 0, +PICTURE_TYPE_I = 1, +PICTURE_TYPE_P = 2, +PICTURE_TYPE_B = 3, +}; + +enum { +// Codec supports controlling the subdivision of pictures into slices. +FLAG_SLICE_CONTROL = 1 << 0, +// Codec only supports constant quality (no rate control). +FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, +// Codec is intra-only. +FLAG_INTRA_ONLY= 1 << 2, +// Codec supports B-pictures. +FLAG_B_PICTURES= 1 << 3, +// Codec supports referencing B-pictures. +FLAG_B_PICTURE_REFERENCES = 1 << 4, +// Codec supports non-IDR key pictures (that is, key pictures do +// not necessarily empty the DPB). +FLAG_NON_IDR_KEY_PICTURES = 1 << 5, +}; + +typedef struct FFHWBaseEncodeContext { +const AVClass *class; +} FFHWBaseEncodeContext; + +#endif /* AVCODEC_HW_BASE_ENCODE_H */ + diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index 0eed9691ca..cae7af8725 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -33,34 +33,27 @@ #include "avcodec.h" #include "hwconfig.h" +#include "hw_base_encode.h" struct VAAPIEncodeType; struct VAAPIEncodePicture; +// Codec output packet without timestamp delay, which means the +// output packet has same PTS and DTS. +#define FLAG_TIMESTAMP_NO_DELAY 1 << 6 + enum { MAX_CONFIG_ATTRIBUTES = 4, MAX_GLOBAL_PARAMS = 4, -MAX_DPB_SIZE = 16, -MAX_PICTURE_REFERENCES = 2, -MAX_REORDER_DELAY = 16, MAX_PARAM_BUFFER_SIZE = 1024, // A.4.1: table A.6 allows at most 22 tile rows for any level. 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, -MAX_REFERENCE_LIST_NUM = 2, }; extern const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[]; -enum { -PICTURE_TYPE_IDR = 0, -PICTURE_TYPE_I = 1, -PICTURE_TYPE_P = 2, -PICTURE_TYPE_B = 3, -}; - typedef struct VAAPIEncodeSlice { int index; int row_start; @@ -193,7 +186,8 @@ typedef struct VAAPIEncodeRCMode { } VAAPIEncodeRCMode; typedef struct VAAPIEncodeContext { -const AVClass *class; +// Base context. +FFHWBaseEncodeContext base; // Codec-specific hooks. const struct VAAPIEncodeType *codec; @@ -397,25 +391,6 @@ typedef struct VAAPIEncodeContext { AVPacket*tail_pkt; } VAAPIEncodeContext; -enum { -// Codec supports controlling the subdivision of pictures into slices. -FLAG_SLICE_CONTROL = 1 << 0, -// Codec only supports constant quality (no rate control). -FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, -// Codec is intra-only. -FLAG_INTRA_ONLY= 1 << 2, -// Codec supports B-pictures. -FLAG_B_PICTURES= 1 << 3, -// Codec supports referencing B-pictures. -FLAG_B_PICTURE_REFERENCES = 1 << 4, -// Codec supports non-IDR key pictures (that is, key pictures do -// not necessarily empty the DPB). -FLAG_NON_IDR_KEY_PICTURES = 1 << 5, -// Codec output packet without timestamp delay, which means the -// output packet has same PTS and DTS. -FLAG_TIMESTAMP_NO_DELAY= 1 << 6, -}; - typedef struct VAAPIEncodeType { // List of supported profiles and corr
[FFmpeg-devel] [PATCH v11 02/14] avcodec/hw_base_encode: add FF_HW_ prefix for two enums
From: Tong Wu PICTURE_TYPE_* and FLAG_* are added FF_HW_ prefix after being moved to base layer. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 20 ++--- libavcodec/vaapi_encode.c | 50 - libavcodec/vaapi_encode_av1.c | 12 libavcodec/vaapi_encode_h264.c | 50 - libavcodec/vaapi_encode_h265.c | 44 ++--- libavcodec/vaapi_encode_mjpeg.c | 6 ++-- libavcodec/vaapi_encode_mpeg2.c | 30 ++-- libavcodec/vaapi_encode_vp8.c | 10 +++ libavcodec/vaapi_encode_vp9.c | 16 +-- 9 files changed, 119 insertions(+), 119 deletions(-) diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index ffcb6bcbb2..f3c9f32977 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -26,26 +26,26 @@ #define MAX_REFERENCE_LIST_NUM 2 enum { -PICTURE_TYPE_IDR = 0, -PICTURE_TYPE_I = 1, -PICTURE_TYPE_P = 2, -PICTURE_TYPE_B = 3, +FF_HW_PICTURE_TYPE_IDR = 0, +FF_HW_PICTURE_TYPE_I = 1, +FF_HW_PICTURE_TYPE_P = 2, +FF_HW_PICTURE_TYPE_B = 3, }; enum { // Codec supports controlling the subdivision of pictures into slices. -FLAG_SLICE_CONTROL = 1 << 0, +FF_HW_FLAG_SLICE_CONTROL = 1 << 0, // Codec only supports constant quality (no rate control). -FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, +FF_HW_FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, // Codec is intra-only. -FLAG_INTRA_ONLY= 1 << 2, +FF_HW_FLAG_INTRA_ONLY= 1 << 2, // Codec supports B-pictures. -FLAG_B_PICTURES= 1 << 3, +FF_HW_FLAG_B_PICTURES= 1 << 3, // Codec supports referencing B-pictures. -FLAG_B_PICTURE_REFERENCES = 1 << 4, +FF_HW_FLAG_B_PICTURE_REFERENCES = 1 << 4, // Codec supports non-IDR key pictures (that is, key pictures do // not necessarily empty the DPB). -FLAG_NON_IDR_KEY_PICTURES = 1 << 5, +FF_HW_FLAG_NON_IDR_KEY_PICTURES = 1 << 5, }; typedef struct FFHWBaseEncodeContext { diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index f54b2579ec..3c3d6a37c7 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -345,7 +345,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, pic->nb_param_buffers = 0; -if (pic->type == PICTURE_TYPE_IDR && ctx->codec->init_sequence_params) { +if (pic->type == FF_HW_PICTURE_TYPE_IDR && ctx->codec->init_sequence_params) { err = vaapi_encode_make_param_buffer(avctx, pic, VAEncSequenceParameterBufferType, ctx->codec_sequence_params, @@ -354,7 +354,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, goto fail; } -if (pic->type == PICTURE_TYPE_IDR) { +if (pic->type == FF_HW_PICTURE_TYPE_IDR) { for (i = 0; i < ctx->nb_global_params; i++) { err = vaapi_encode_make_misc_param_buffer(avctx, pic, ctx->global_params_type[i], @@ -391,7 +391,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, } #endif -if (pic->type == PICTURE_TYPE_IDR) { +if (pic->type == FF_HW_PICTURE_TYPE_IDR) { if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE && ctx->codec->write_sequence_header) { bit_len = 8 * sizeof(data); @@ -671,7 +671,7 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, { VAAPIEncodeContext *ctx = avctx->priv_data; -if (pic->type == PICTURE_TYPE_IDR) +if (pic->type == FF_HW_PICTURE_TYPE_IDR) pkt->flags |= AV_PKT_FLAG_KEY; pkt->pts = pic->pts; @@ -996,7 +996,7 @@ static void vaapi_encode_remove_refs(AVCodecContext *avctx, av_assert0(pic->dpb[i]->ref_count[level] >= 0); } -av_assert0(pic->prev || pic->type == PICTURE_TYPE_IDR); +av_assert0(pic->prev || pic->type == FF_HW_PICTURE_TYPE_IDR); if (pic->prev) { --pic->prev->ref_count[level]; av_assert0(pic->prev->ref_count[level] >= 0); @@ -1025,7 +1025,7 @@ static void vaapi_encode_set_b_pictures(AVCodecContext *avctx, for (pic = start->next; pic; pic = pic->next) { if (pic == end) break; -pic->type= PICTURE_TYPE_B; +pic->type= FF_HW_PICTURE_TYPE_B; pic->b_depth = current_depth; vaapi_encode_add_ref(avctx, pic, start, 1, 1, 0); @@ -1045,7 +1045,7 @@ static void vaapi_encode_set_b_pictures(AVCodecContext *avctx, ++len; for (pic = start->next, i = 1; 2 * i < len; pic = pic->next, i++); -pic->type= PICTURE_TYPE_B; +pic->type= FF_HW_PICTURE_TYPE_B; pic->b_depth = current_depth; pic->is_reference = 1; @@ -1078,7 +1078,7 @@ static void vaapi_enco
[FFmpeg-devel] [PATCH v11 03/14] avcodec/vaapi_encode: add async_depth to common options
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 10 +- libavcodec/vaapi_encode.c | 13 - libavcodec/vaapi_encode.h | 7 --- libavcodec/vaapi_encode_av1.c | 1 + libavcodec/vaapi_encode_h264.c | 1 + libavcodec/vaapi_encode_h265.c | 1 + libavcodec/vaapi_encode_mjpeg.c | 1 + libavcodec/vaapi_encode_mpeg2.c | 1 + libavcodec/vaapi_encode_vp8.c | 1 + libavcodec/vaapi_encode_vp9.c | 1 + 10 files changed, 24 insertions(+), 13 deletions(-) diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index f3c9f32977..c14c174102 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -50,7 +50,15 @@ enum { typedef struct FFHWBaseEncodeContext { const AVClass *class; + +// Max number of frame buffered in encoder. +int async_depth; } FFHWBaseEncodeContext; -#endif /* AVCODEC_HW_BASE_ENCODE_H */ +#define HW_BASE_ENCODE_COMMON_OPTIONS \ +{ "async_depth", "Maximum processing parallelism. " \ + "Increase this to improve single channel performance.", \ + OFFSET(common.base.async_depth), AV_OPT_TYPE_INT, \ + { .i64 = 2 }, 1, MAX_ASYNC_DEPTH, FLAGS } +#endif /* AVCODEC_HW_BASE_ENCODE_H */ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 3c3d6a37c7..77f539dc6d 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -669,7 +669,8 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, VAAPIEncodePicture *pic, AVPacket *pkt) { -VAAPIEncodeContext *ctx = avctx->priv_data; +FFHWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; if (pic->type == FF_HW_PICTURE_TYPE_IDR) pkt->flags |= AV_PKT_FLAG_KEY; @@ -699,7 +700,7 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, 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 + ctx->async_depth)]; +(3 * ctx->output_delay + base_ctx->async_depth)]; } return 0; @@ -1320,6 +1321,7 @@ static int vaapi_encode_check_frame(AVCodecContext *avctx, static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) { +FFHWBaseEncodeContext *base_ctx = avctx->priv_data; VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic; int err; @@ -1365,7 +1367,7 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) ctx->dts_pts_diff = pic->pts - ctx->first_pts; if (ctx->output_delay > 0) ctx->ts_ring[ctx->input_order % -(3 * ctx->output_delay + ctx->async_depth)] = pic->pts; +(3 * ctx->output_delay + base_ctx->async_depth)] = pic->pts; pic->display_order = ctx->input_order; ++ctx->input_order; @@ -2773,7 +2775,8 @@ static av_cold int vaapi_encode_create_recon_frames(AVCodecContext *avctx) av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) { -VAAPIEncodeContext *ctx = avctx->priv_data; +FFHWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; AVVAAPIFramesContext *recon_hwctx = NULL; VAStatus vas; int err; @@ -2966,7 +2969,7 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) vas = vaSyncBuffer(ctx->hwctx->display, VA_INVALID_ID, 0); if (vas != VA_STATUS_ERROR_UNIMPLEMENTED) { ctx->has_sync_buffer_func = 1; -ctx->encode_fifo = av_fifo_alloc2(ctx->async_depth, +ctx->encode_fifo = av_fifo_alloc2(base_ctx->async_depth, sizeof(VAAPIEncodePicture *), 0); if (!ctx->encode_fifo) diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index cae7af8725..9fdb945b18 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -374,8 +374,6 @@ typedef struct VAAPIEncodeContext { int has_sync_buffer_func; // Store buffered pic AVFifo *encode_fifo; -// Max number of frame buffered in encoder. -int async_depth; /** Head data for current output pkt, used only for AV1. */ //void *header_data; @@ -491,11 +489,6 @@ int ff_vaapi_encode_close(AVCodecContext *avctx); "Maximum B-frame reference depth", \ OFFSET(common.desired_b_depth), AV_OPT_TYPE_INT, \ { .i64 = 1 }, 1, INT_MAX, FLAGS }, \ -{ "async_depth", "Maximum processing parallelism. " \ - "Increase this to improve single channel performance. This option " \ - "doesn't work if driver doesn't implement vaSyncBuffer function.", \ - OFFSET(co
[FFmpeg-devel] [PATCH v11 04/14] avcodec/vaapi_encode: add picture type name to base
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 6 ++ libavcodec/vaapi_encode.c | 4 +--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index c14c174102..858450afa8 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -25,6 +25,12 @@ #define MAX_ASYNC_DEPTH 64 #define MAX_REFERENCE_LIST_NUM 2 +static inline const char *ff_hw_base_encode_get_pictype_name(const int type) +{ +const char * const picture_type_name[] = { "IDR", "I", "P", "B" }; +return picture_type_name[type]; +} + enum { FF_HW_PICTURE_TYPE_IDR = 0, FF_HW_PICTURE_TYPE_I = 1, diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 77f539dc6d..54bdd73902 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -38,8 +38,6 @@ const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[] = { NULL, }; -static const char * const picture_type_name[] = { "IDR", "I", "P", "B" }; - static int vaapi_encode_make_packed_header(AVCodecContext *avctx, VAAPIEncodePicture *pic, int type, char *data, size_t bit_len) @@ -277,7 +275,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Issuing encode for pic %"PRId64"/%"PRId64" " "as type %s.\n", pic->display_order, pic->encode_order, - picture_type_name[pic->type]); + ff_hw_base_encode_get_pictype_name(pic->type)); if (pic->nb_refs[0] == 0 && pic->nb_refs[1] == 0) { av_log(avctx, AV_LOG_DEBUG, "No reference pictures.\n"); } else { -- 2.41.0.windows.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 v11 05/14] avcodec/vaapi_encode: move pic->input_surface initialization to encode_alloc
From: Tong Wu When allocating the VAAPIEncodePicture, pic->input_surface can be initialized right in the place. This movement simplifies the send_frame logic and is the preparation for moving vaapi_encode_send_frame to the base layer. Signed-off-by: Tong Wu --- libavcodec/vaapi_encode.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 54bdd73902..194422b36d 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -878,7 +878,8 @@ static int vaapi_encode_discard(AVCodecContext *avctx, return 0; } -static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx) +static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx, + const AVFrame *frame) { VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic; @@ -895,7 +896,7 @@ static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx) } } -pic->input_surface = VA_INVALID_ID; +pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; pic->recon_surface = VA_INVALID_ID; pic->output_buffer = VA_INVALID_ID; @@ -1332,7 +1333,7 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) if (err < 0) return err; -pic = vaapi_encode_alloc(avctx); +pic = vaapi_encode_alloc(avctx, frame); if (!pic) return AVERROR(ENOMEM); @@ -1345,7 +1346,6 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) if (ctx->input_order == 0 || frame->pict_type == AV_PICTURE_TYPE_I) pic->force_idr = 1; -pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; pic->pts = frame->pts; pic->duration = frame->duration; -- 2.41.0.windows.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 v11 08/14] avcodec/vaapi_encode: extract gop configuration and two options to base layer
From: Tong Wu idr_interval and desired_b_depth are moved to HW_BASE_ENCODE_COMMON_OPTIONS. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 54 + libavcodec/hw_base_encode.h | 19 + libavcodec/vaapi_encode.c | 52 +++ libavcodec/vaapi_encode.h | 16 --- 4 files changed, 77 insertions(+), 64 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index c4789380b6..56dc015e2e 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -593,6 +593,60 @@ end: return 0; } +int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, + int flags, int prediction_pre_only) +{ +FFHWBaseEncodeContext *ctx = avctx->priv_data; + +if (flags & FF_HW_FLAG_INTRA_ONLY || avctx->gop_size <= 1) { +av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n"); +ctx->gop_size = 1; +} else if (ref_l0 < 1) { +av_log(avctx, AV_LOG_ERROR, "Driver does not support any " + "reference frames.\n"); +return AVERROR(EINVAL); +} else if (!(flags & FF_HW_FLAG_B_PICTURES) || ref_l1 < 1 || + avctx->max_b_frames < 1 || prediction_pre_only) { +if (ctx->p_to_gpb) + av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " + "(supported references: %d / %d).\n", + ref_l0, ref_l1); +else +av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames " + "(supported references: %d / %d).\n", ref_l0, ref_l1); +ctx->gop_size = avctx->gop_size; +ctx->p_per_i = INT_MAX; +ctx->b_per_p = 0; +} else { + if (ctx->p_to_gpb) + av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " + "(supported references: %d / %d).\n", + ref_l0, ref_l1); + else + av_log(avctx, AV_LOG_VERBOSE, "Using intra, P- and B-frames " + "(supported references: %d / %d).\n", ref_l0, ref_l1); +ctx->gop_size = avctx->gop_size; +ctx->p_per_i = INT_MAX; +ctx->b_per_p = avctx->max_b_frames; +if (flags & FF_HW_FLAG_B_PICTURE_REFERENCES) { +ctx->max_b_depth = FFMIN(ctx->desired_b_depth, + av_log2(ctx->b_per_p) + 1); +} else { +ctx->max_b_depth = 1; +} +} + +if (flags & FF_HW_FLAG_NON_IDR_KEY_PICTURES) { +ctx->closed_gop = !!(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP); +ctx->gop_per_idr = ctx->idr_interval + 1; +} else { +ctx->closed_gop = 1; +ctx->gop_per_idr = 1; +} + +return 0; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { FFHWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index a062009860..c7e535d35d 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -120,6 +120,14 @@ typedef struct FFHWBaseEncodeContext { // Hardware-specific hooks. const struct FFHWEncodePictureOperation *op; +// Global options. + +// Number of I frames between IDR frames. +int idr_interval; + +// Desired B frame reference depth. +int desired_b_depth; + // The hardware device context. AVBufferRef*device_ref; AVHWDeviceContext *device; @@ -198,11 +206,22 @@ typedef struct FFHWBaseEncodeContext { int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); +int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, + int flags, int prediction_pre_only); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); #define HW_BASE_ENCODE_COMMON_OPTIONS \ +{ "idr_interval", \ + "Distance (in I-frames) between key frames", \ + OFFSET(common.base.idr_interval), AV_OPT_TYPE_INT, \ + { .i64 = 0 }, 0, INT_MAX, FLAGS }, \ +{ "b_depth", \ + "Maximum B-frame reference depth", \ + OFFSET(common.base.desired_b_depth), AV_OPT_TYPE_INT, \ + { .i64 = 1 }, 1, INT_MAX, FLAGS }, \ { "async_depth", "Maximum processing parallelism. " \ "Increase this to improve single channel performance.", \ OFFSET(common.base.async_depth), AV_OPT_TYPE_INT, \ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 1b3bab2c14..c29493e2c8 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1638,7 +1638,7 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) VAStatus vas; VAConfigAttrib attr = { VAConfigAttribEncMaxRefFrames }; uint32_t ref_l0, ref_l1; -int prediction_pre_only; +int prediction_pre_only, err; vas = vaGetConfigAttributes(ctx->hwctx-
[FFmpeg-devel] [PATCH v11 06/14] avcodec/vaapi_encode: move the dpb logic from VAAPI to base layer
From: Tong Wu Move receive_packet function to base. This requires adding *alloc, *issue, *output, *free as hardware callbacks. HWBaseEncodePicture is introduced as the base layer structure. The related parameters in VAAPIEncodeContext are also extracted to HWBaseEncodeContext. Then DPB management logic can be fully extracted to base layer as-is. Signed-off-by: Tong Wu --- libavcodec/Makefile | 2 +- libavcodec/hw_base_encode.c | 594 libavcodec/hw_base_encode.h | 124 + libavcodec/vaapi_encode.c | 793 +--- libavcodec/vaapi_encode.h | 102 +--- libavcodec/vaapi_encode_av1.c | 35 +- libavcodec/vaapi_encode_h264.c | 84 ++-- libavcodec/vaapi_encode_h265.c | 53 ++- libavcodec/vaapi_encode_mjpeg.c | 13 +- libavcodec/vaapi_encode_mpeg2.c | 33 +- libavcodec/vaapi_encode_vp8.c | 18 +- libavcodec/vaapi_encode_vp9.c | 24 +- 12 files changed, 985 insertions(+), 890 deletions(-) create mode 100644 libavcodec/hw_base_encode.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2443d2c6fd..998f6b7e12 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -165,7 +165,7 @@ OBJS-$(CONFIG_STARTCODE) += startcode.o OBJS-$(CONFIG_TEXTUREDSP) += texturedsp.o OBJS-$(CONFIG_TEXTUREDSPENC) += texturedspenc.o OBJS-$(CONFIG_TPELDSP) += tpeldsp.o -OBJS-$(CONFIG_VAAPI_ENCODE)+= vaapi_encode.o +OBJS-$(CONFIG_VAAPI_ENCODE)+= vaapi_encode.o hw_base_encode.o OBJS-$(CONFIG_AV1_AMF_ENCODER) += amfenc_av1.o OBJS-$(CONFIG_VC1DSP) += vc1dsp.o OBJS-$(CONFIG_VIDEODSP)+= videodsp.o diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c new file mode 100644 index 00..16afaa37be --- /dev/null +++ b/libavcodec/hw_base_encode.c @@ -0,0 +1,594 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" + +#include "encode.h" +#include "avcodec.h" +#include "hw_base_encode.h" + +static void hw_base_encode_add_ref(FFHWBaseEncodePicture *pic, + FFHWBaseEncodePicture *target, + int is_ref, int in_dpb, int prev) +{ +int refs = 0; + +if (is_ref) { +av_assert0(pic != target); +av_assert0(pic->nb_refs[0] < MAX_PICTURE_REFERENCES && + pic->nb_refs[1] < MAX_PICTURE_REFERENCES); +if (target->display_order < pic->display_order) +pic->refs[0][pic->nb_refs[0]++] = target; +else +pic->refs[1][pic->nb_refs[1]++] = target; +++refs; +} + +if (in_dpb) { +av_assert0(pic->nb_dpb_pics < MAX_DPB_SIZE); +pic->dpb[pic->nb_dpb_pics++] = target; +++refs; +} + +if (prev) { +av_assert0(!pic->prev); +pic->prev = target; +++refs; +} + +target->ref_count[0] += refs; +target->ref_count[1] += refs; +} + +static void hw_base_encode_remove_refs(FFHWBaseEncodePicture *pic, int level) +{ +int i; + +if (pic->ref_removed[level]) +return; + +for (i = 0; i < pic->nb_refs[0]; i++) { +av_assert0(pic->refs[0][i]); +--pic->refs[0][i]->ref_count[level]; +av_assert0(pic->refs[0][i]->ref_count[level] >= 0); +} + +for (i = 0; i < pic->nb_refs[1]; i++) { +av_assert0(pic->refs[1][i]); +--pic->refs[1][i]->ref_count[level]; +av_assert0(pic->refs[1][i]->ref_count[level] >= 0); +} + +for (i = 0; i < pic->nb_dpb_pics; i++) { +av_assert0(pic->dpb[i]); +--pic->dpb[i]->ref_count[level]; +av_assert0(pic->dpb[i]->ref_count[level] >= 0); +} + +av_assert0(pic->prev || pic->type == FF_HW_PICTURE_TYPE_IDR); +if (pic->prev) { +--pic->prev->ref_count[level]; +av_assert0(pic->prev->ref_count[level] >= 0); +} + +pic->ref_removed[level] = 1; +} + +static void hw_base_encode_set_b_pictures(AVCodecContext *avctx, + FFHWBaseEncodePicture *st
[FFmpeg-devel] [PATCH v11 09/14] avcodec/vaapi_encode: extract set_output_property to base layer
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 40 + libavcodec/hw_base_encode.h | 3 +++ libavcodec/vaapi_encode.c | 44 ++--- 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 56dc015e2e..25fcfdbb5e 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -488,6 +488,46 @@ fail: return err; } +int ff_hw_base_encode_set_output_property(AVCodecContext *avctx, + FFHWBaseEncodePicture *pic, + AVPacket *pkt, int flag_no_delay) +{ +FFHWBaseEncodeContext *ctx = avctx->priv_data; + +if (pic->type == FF_HW_PICTURE_TYPE_IDR) +pkt->flags |= AV_PKT_FLAG_KEY; + +pkt->pts = pic->pts; +pkt->duration = pic->duration; + +// for no-delay encoders this is handled in generic codec +if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY && +avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { +pkt->opaque = pic->opaque; +pkt->opaque_ref = pic->opaque_ref; +pic->opaque_ref = NULL; +} + +if (flag_no_delay) { +pkt->dts = pkt->pts; +return 0; +} + +if (ctx->output_delay == 0) { +pkt->dts = pkt->pts; +} else if (pic->encode_order < ctx->decode_delay) { +if (ctx->ts_ring[pic->encode_order] < INT64_MIN + ctx->dts_pts_diff) +pkt->dts = INT64_MIN; +else +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 + ctx->async_depth)]; +} + +return 0; +} + int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) { FFHWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index c7e535d35d..f097d826a7 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -204,6 +204,9 @@ typedef struct FFHWBaseEncodeContext { AVPacket*tail_pkt; } FFHWBaseEncodeContext; +int ff_hw_base_encode_set_output_property(AVCodecContext *avctx, FFHWBaseEncodePicture *pic, + AVPacket *pkt, int flag_no_delay); + int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index c29493e2c8..4193f3838f 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -660,47 +660,6 @@ fail_at_end: return err; } -static int vaapi_encode_set_output_property(AVCodecContext *avctx, -FFHWBaseEncodePicture *pic, -AVPacket *pkt) -{ -FFHWBaseEncodeContext *base_ctx = avctx->priv_data; -VAAPIEncodeContext *ctx = avctx->priv_data; - -if (pic->type == FF_HW_PICTURE_TYPE_IDR) -pkt->flags |= AV_PKT_FLAG_KEY; - -pkt->pts = pic->pts; -pkt->duration = pic->duration; - -// for no-delay encoders this is handled in generic codec -if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY && -avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { -pkt->opaque = pic->opaque; -pkt->opaque_ref = pic->opaque_ref; -pic->opaque_ref = NULL; -} - -if (ctx->codec->flags & FLAG_TIMESTAMP_NO_DELAY) { -pkt->dts = pkt->pts; -return 0; -} - -if (base_ctx->output_delay == 0) { -pkt->dts = pkt->pts; -} else if (pic->encode_order < base_ctx->decode_delay) { -if (base_ctx->ts_ring[pic->encode_order] < INT64_MIN + base_ctx->dts_pts_diff) -pkt->dts = INT64_MIN; -else -pkt->dts = base_ctx->ts_ring[pic->encode_order] - base_ctx->dts_pts_diff; -} else { -pkt->dts = base_ctx->ts_ring[(pic->encode_order - base_ctx->decode_delay) % - (3 * base_ctx->output_delay + base_ctx->async_depth)]; -} - -return 0; -} - static int vaapi_encode_get_coded_buffer_size(AVCodecContext *avctx, VABufferID buf_id) { VAAPIEncodeContext *ctx = avctx->priv_data; @@ -852,7 +811,8 @@ static int vaapi_encode_output(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n", base_pic->display_order, base_pic->encode_order); -vaapi_encode_set_output_property(avctx, (FFHWBaseEncodePicture*)pic, pkt_ptr); +ff_hw_base_encode_set_output_property(avctx, (FFHWBaseEncodePicture*)base_pic, pkt_ptr, + ctx->codec->flags & FLAG_TIMESTAMP_NO_DELAY); end: ff_refstruct_unref(&pic->output_buffer_ref); -- 2.41.
[FFmpeg-devel] [PATCH v11 10/14] avcodec/vaapi_encode: extract a get_recon_format function to base layer
From: Tong Wu Surface size and block size parameters are also moved to base layer. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 58 +++ libavcodec/hw_base_encode.h | 12 + libavcodec/vaapi_encode.c | 81 - libavcodec/vaapi_encode.h | 10 libavcodec/vaapi_encode_av1.c | 10 ++-- libavcodec/vaapi_encode_h264.c | 11 +++-- libavcodec/vaapi_encode_h265.c | 25 +- libavcodec/vaapi_encode_mjpeg.c | 5 +- libavcodec/vaapi_encode_vp9.c | 6 +-- 9 files changed, 118 insertions(+), 100 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 25fcfdbb5e..31046bd73e 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -687,6 +687,64 @@ int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32 return 0; } +int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt) +{ +FFHWBaseEncodeContext *ctx = avctx->priv_data; +AVHWFramesConstraints *constraints = NULL; +enum AVPixelFormat recon_format; +int err, i; + +constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref, + hwconfig); +if (!constraints) { +err = AVERROR(ENOMEM); +goto fail; +} + +// Probably we can use the input surface format as the surface format +// of the reconstructed frames. If not, we just pick the first (only?) +// format in the valid list and hope that it all works. +recon_format = AV_PIX_FMT_NONE; +if (constraints->valid_sw_formats) { +for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { +if (ctx->input_frames->sw_format == +constraints->valid_sw_formats[i]) { +recon_format = ctx->input_frames->sw_format; +break; +} +} +if (recon_format == AV_PIX_FMT_NONE) { +// No match. Just use the first in the supported list and +// hope for the best. +recon_format = constraints->valid_sw_formats[0]; +} +} else { +// No idea what to use; copy input format. +recon_format = ctx->input_frames->sw_format; +} +av_log(avctx, AV_LOG_DEBUG, "Using %s as format of " + "reconstructed frames.\n", av_get_pix_fmt_name(recon_format)); + +if (ctx->surface_width < constraints->min_width || +ctx->surface_height < constraints->min_height || +ctx->surface_width > constraints->max_width || +ctx->surface_height > constraints->max_height) { +av_log(avctx, AV_LOG_ERROR, "Hardware does not support encoding at " + "size %dx%d (constraints: width %d-%d height %d-%d).\n", + ctx->surface_width, ctx->surface_height, + constraints->min_width, constraints->max_width, + constraints->min_height, constraints->max_height); +err = AVERROR(EINVAL); +goto fail; +} + +*fmt = recon_format; +err = 0; +fail: +av_hwframe_constraints_free(&constraints); +return err; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { FFHWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index f097d826a7..f5414e2c28 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -128,6 +128,16 @@ typedef struct FFHWBaseEncodeContext { // Desired B frame reference depth. int desired_b_depth; +// The required size of surfaces. This is probably the input +// size (AVCodecContext.width|height) aligned up to whatever +// block size is required by the codec. +int surface_width; +int surface_height; + +// The block size for slice calculations. +int slice_block_width; +int slice_block_height; + // The hardware device context. AVBufferRef*device_ref; AVHWDeviceContext *device; @@ -212,6 +222,8 @@ int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, int flags, int prediction_pre_only); +int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 4193f3838f..d96f146b28 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1777,6 +1777,7 @@ static av_cold int vaapi_encode_init_tile_slice_structure(AVCodecContext *avctx, static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) { +FFHWBaseEncodeContext *base_ctx = a
[FFmpeg-devel] [PATCH v11 12/14] avutil/hwcontext_d3d12va: add Flags for resource creation
From: Tong Wu Flags field is added to support diffferent resource creation. Signed-off-by: Tong Wu --- doc/APIchanges| 3 +++ libavutil/hwcontext_d3d12va.c | 2 +- libavutil/hwcontext_d3d12va.h | 8 libavutil/version.h | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 60f056b863..0c3d0221e8 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2024-03-07 API changes, most recent first: +2024-01-xx - xx - lavu 59.21.100 - hwcontext_d3d12va.h + Add AVD3D12VAFramesContext.flags + 2024-05-23 - xx - lavu 59.20.100 - channel_layout.h Add av_channel_layout_ambisonic_order(). diff --git a/libavutil/hwcontext_d3d12va.c b/libavutil/hwcontext_d3d12va.c index cfc016315d..6507cf69c1 100644 --- a/libavutil/hwcontext_d3d12va.c +++ b/libavutil/hwcontext_d3d12va.c @@ -247,7 +247,7 @@ static AVBufferRef *d3d12va_pool_alloc(void *opaque, size_t size) .Format = hwctx->format, .SampleDesc = {.Count = 1, .Quality = 0 }, .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, -.Flags= D3D12_RESOURCE_FLAG_NONE, +.Flags= hwctx->flags, }; frame = av_mallocz(sizeof(AVD3D12VAFrame)); diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h index ff06e6f2ef..212a6a6146 100644 --- a/libavutil/hwcontext_d3d12va.h +++ b/libavutil/hwcontext_d3d12va.h @@ -129,6 +129,14 @@ typedef struct AVD3D12VAFramesContext { * If unset, will be automatically set. */ DXGI_FORMAT format; + +/** + * Options for working with resources. + * If unset, this will be D3D12_RESOURCE_FLAG_NONE. + * + * @see https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_resource_flags + */ +D3D12_RESOURCE_FLAGS flags; } AVD3D12VAFramesContext; #endif /* AVUTIL_HWCONTEXT_D3D12VA_H */ diff --git a/libavutil/version.h b/libavutil/version.h index 9c7146c228..9d08d56884 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 59 -#define LIBAVUTIL_VERSION_MINOR 20 +#define LIBAVUTIL_VERSION_MINOR 21 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ -- 2.41.0.windows.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 v11 11/14] avcodec/vaapi_encode: extract a free funtion to base layer
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 11 +++ libavcodec/hw_base_encode.h | 2 ++ libavcodec/vaapi_encode.c | 6 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 31046bd73e..92f69bb78c 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -745,6 +745,17 @@ fail: return err; } +int ff_hw_base_encode_free(FFHWBaseEncodePicture *pic) +{ +av_frame_free(&pic->input_image); +av_frame_free(&pic->recon_image); + +av_buffer_unref(&pic->opaque_ref); +av_freep(&pic->priv_data); + +return 0; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { FFHWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index f5414e2c28..15ef3d7ac6 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -224,6 +224,8 @@ int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32 int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt); +int ff_hw_base_encode_free(FFHWBaseEncodePicture *pic); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index d96f146b28..b35a23e852 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -878,17 +878,13 @@ static int vaapi_encode_free(AVCodecContext *avctx, av_freep(&pic->slices[i].codec_slice_params); } -av_frame_free(&base_pic->input_image); -av_frame_free(&base_pic->recon_image); - -av_buffer_unref(&base_pic->opaque_ref); +ff_hw_base_encode_free(base_pic); av_freep(&pic->param_buffers); av_freep(&pic->slices); // Output buffer should already be destroyed. av_assert0(pic->output_buffer == VA_INVALID_ID); -av_freep(&base_pic->priv_data); av_freep(&pic->codec_picture_params); av_freep(&pic->roi); -- 2.41.0.windows.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 v11 07/14] avcodec/vaapi_encode: extract the init and close function to base layer
From: Tong Wu Related parameters such as device context, frame context are also moved to base layer. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 49 ++ libavcodec/hw_base_encode.h | 17 +++ libavcodec/vaapi_encode.c | 90 +++-- libavcodec/vaapi_encode.h | 10 libavcodec/vaapi_encode_av1.c | 2 +- libavcodec/vaapi_encode_h264.c | 2 +- libavcodec/vaapi_encode_h265.c | 2 +- libavcodec/vaapi_encode_mjpeg.c | 6 ++- 8 files changed, 102 insertions(+), 76 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 16afaa37be..c4789380b6 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -592,3 +592,52 @@ end: return 0; } + +int ff_hw_base_encode_init(AVCodecContext *avctx) +{ +FFHWBaseEncodeContext *ctx = avctx->priv_data; + +ctx->frame = av_frame_alloc(); +if (!ctx->frame) +return AVERROR(ENOMEM); + +if (!avctx->hw_frames_ctx) { +av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is " + "required to associate the encoding device.\n"); +return AVERROR(EINVAL); +} + +ctx->input_frames_ref = av_buffer_ref(avctx->hw_frames_ctx); +if (!ctx->input_frames_ref) +return AVERROR(ENOMEM); + +ctx->input_frames = (AVHWFramesContext *)ctx->input_frames_ref->data; + +ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref); +if (!ctx->device_ref) +return AVERROR(ENOMEM); + +ctx->device = (AVHWDeviceContext *)ctx->device_ref->data; + +ctx->tail_pkt = av_packet_alloc(); +if (!ctx->tail_pkt) +return AVERROR(ENOMEM); + +return 0; +} + +int ff_hw_base_encode_close(AVCodecContext *avctx) +{ +FFHWBaseEncodeContext *ctx = avctx->priv_data; + +av_fifo_freep2(&ctx->encode_fifo); + +av_frame_free(&ctx->frame); +av_packet_free(&ctx->tail_pkt); + +av_buffer_unref(&ctx->device_ref); +av_buffer_unref(&ctx->input_frames_ref); +av_buffer_unref(&ctx->recon_frames_ref); + +return 0; +} diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 81e6c87036..a062009860 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -19,6 +19,7 @@ #ifndef AVCODEC_HW_BASE_ENCODE_H #define AVCODEC_HW_BASE_ENCODE_H +#include "libavutil/hwcontext.h" #include "libavutil/fifo.h" #define MAX_DPB_SIZE 16 @@ -119,6 +120,18 @@ typedef struct FFHWBaseEncodeContext { // Hardware-specific hooks. const struct FFHWEncodePictureOperation *op; +// The hardware device context. +AVBufferRef*device_ref; +AVHWDeviceContext *device; + +// The hardware frame context containing the input frames. +AVBufferRef*input_frames_ref; +AVHWFramesContext *input_frames; + +// The hardware frame context containing the reconstructed frames. +AVBufferRef*recon_frames_ref; +AVHWFramesContext *recon_frames; + // Current encoding window, in display (input) order. FFHWBaseEncodePicture *pic_start, *pic_end; // The next picture to use as the previous reference picture in @@ -185,6 +198,10 @@ typedef struct FFHWBaseEncodeContext { int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); +int ff_hw_base_encode_init(AVCodecContext *avctx); + +int ff_hw_base_encode_close(AVCodecContext *avctx); + #define HW_BASE_ENCODE_COMMON_OPTIONS \ { "async_depth", "Maximum processing parallelism. " \ "Increase this to improve single channel performance.", \ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 1055fca0b1..1b3bab2c14 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -314,7 +314,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Input surface is %#x.\n", pic->input_surface); -err = av_hwframe_get_buffer(ctx->recon_frames_ref, base_pic->recon_image, 0); +err = av_hwframe_get_buffer(base_ctx->recon_frames_ref, base_pic->recon_image, 0); if (err < 0) { err = AVERROR(ENOMEM); goto fail; @@ -996,9 +996,10 @@ static const VAEntrypoint vaapi_encode_entrypoints_low_power[] = { static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx) { -VAAPIEncodeContext *ctx = avctx->priv_data; -VAProfile*va_profiles= NULL; -VAEntrypoint *va_entrypoints = NULL; +FFHWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; +VAProfile *va_profiles= NULL; +VAEntrypoint*va_entrypoints = NULL; VAStatus vas; const VAEntrypoint *usable_entrypoints; const VAAPIEncodeProfile *profile; @@ -1021,10 +1022,10 @@ static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx) usable_entrypoints = vaapi_encode_entrypoints_normal; } -desc = av_pix_fmt_desc_get(ctx->input_frame
[FFmpeg-devel] [PATCH v11 14/14] Changelog: add D3D12VA HEVC encoder changelog
From: Tong Wu Signed-off-by: Tong Wu --- Changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 12770e4296..c5d57b3813 100644 --- a/Changelog +++ b/Changelog @@ -11,7 +11,7 @@ version : - vf_scale2ref deprecated - qsv_params option added for QSV encoders - VVC decoder compatible with DVB test content - +- D3D12VA HEVC encoder version 7.0: - DXV DXT1 encoder -- 2.41.0.windows.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 v11 13/14] avcodec: add D3D12VA hardware HEVC encoder
From: Tong Wu This implementation is based on D3D12 Video Encoding Spec: https://microsoft.github.io/DirectX-Specs/d3d/D3D12VideoEncoding.html Sample command line for transcoding: ffmpeg.exe -hwaccel d3d12va -hwaccel_output_format d3d12 -i input.mp4 -c:v hevc_d3d12va output.mp4 Signed-off-by: Tong Wu --- configure|6 + libavcodec/Makefile |5 +- libavcodec/allcodecs.c |1 + libavcodec/d3d12va_encode.c | 1558 ++ libavcodec/d3d12va_encode.h | 334 +++ libavcodec/d3d12va_encode_hevc.c | 1007 +++ 6 files changed, 2910 insertions(+), 1 deletion(-) create mode 100644 libavcodec/d3d12va_encode.c create mode 100644 libavcodec/d3d12va_encode.h create mode 100644 libavcodec/d3d12va_encode_hevc.c diff --git a/configure b/configure index b16722d83d..127d68e60c 100755 --- a/configure +++ b/configure @@ -2551,6 +2551,7 @@ CONFIG_EXTRA=" cbs_mpeg2 cbs_vp8 cbs_vp9 +d3d12va_encode deflate_wrapper dirac_parse dnn @@ -3287,6 +3288,7 @@ wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel" # hardware-accelerated codecs +d3d12va_encode_deps="d3d12va ID3D12VideoEncoder d3d12_encoder_feature" mediafoundation_deps="mftransform_h MFCreateAlignedMemoryBuffer" omx_deps="libdl pthreads" omx_rpi_select="omx" @@ -3354,6 +3356,7 @@ h264_v4l2m2m_encoder_deps="v4l2_m2m h264_v4l2_m2m" hevc_amf_encoder_deps="amf" hevc_cuvid_decoder_deps="cuvid" hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf" +hevc_d3d12va_encoder_select="cbs_h265 d3d12va_encode" hevc_mediacodec_decoder_deps="mediacodec" hevc_mediacodec_decoder_select="hevc_mp4toannexb_bsf hevc_parser" hevc_mediacodec_encoder_deps="mediacodec" @@ -6725,6 +6728,9 @@ check_type "windows.h d3d11.h" "ID3D11VideoDecoder" check_type "windows.h d3d11.h" "ID3D11VideoContext" check_type "windows.h d3d12.h" "ID3D12Device" check_type "windows.h d3d12video.h" "ID3D12VideoDecoder" +check_type "windows.h d3d12video.h" "ID3D12VideoEncoder" +test_code cc "windows.h d3d12video.h" "D3D12_FEATURE_VIDEO feature = D3D12_FEATURE_VIDEO_ENCODER_CODEC" && \ +test_code cc "windows.h d3d12video.h" "D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOURCE_REQUIREMENTS req" && enable d3d12_encoder_feature check_type "windows.h" "DPI_AWARENESS_CONTEXT" -D_WIN32_WINNT=0x0A00 check_type "d3d9.h dxva2api.h" DXVA2_ConfigPictureDecode -D_WIN32_WINNT=0x0602 check_func_headers mfapi.h MFCreateAlignedMemoryBuffer -lmfplat diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 998f6b7e12..6c4500ce6d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -86,6 +86,7 @@ OBJS-$(CONFIG_CBS_JPEG)+= cbs_jpeg.o OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o OBJS-$(CONFIG_CBS_VP8) += cbs_vp8.o vp8data.o OBJS-$(CONFIG_CBS_VP9) += cbs_vp9.o +OBJS-$(CONFIG_D3D12VA_ENCODE) += d3d12va_encode.o hw_base_encode.o OBJS-$(CONFIG_DEFLATE_WRAPPER) += zlib_wrapper.o OBJS-$(CONFIG_DOVI_RPUDEC) += dovi_rpu.o dovi_rpudec.o OBJS-$(CONFIG_DOVI_RPUENC) += dovi_rpu.o dovi_rpuenc.o @@ -436,6 +437,8 @@ OBJS-$(CONFIG_HEVC_DECODER)+= hevcdec.o hevc_mvs.o \ h274.o aom_film_grain.o OBJS-$(CONFIG_HEVC_AMF_ENCODER)+= amfenc_hevc.o OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o +OBJS-$(CONFIG_HEVC_D3D12VA_ENCODER)+= d3d12va_encode_hevc.o h265_profile_level.o \ + h2645data.o OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_HEVC_MEDIACODEC_ENCODER) += mediacodecenc.o OBJS-$(CONFIG_HEVC_MF_ENCODER) += mfenc.o mf_utils.o @@ -1265,7 +1268,7 @@ SKIPHEADERS+= %_tablegen.h \ SKIPHEADERS-$(CONFIG_AMF) += amfenc.h SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h -SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h +SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h d3d12va_encode.h SKIPHEADERS-$(CONFIG_DXVA2)+= dxva2.h dxva2_internal.h SKIPHEADERS-$(CONFIG_JNI) += ffjni.h SKIPHEADERS-$(CONFIG_LCMS2)+= fflcms2.h diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index b102a8069e..463ffbbd08 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -848,6 +848,7 @@ extern const FFCodec ff_h264_vaapi_encoder; extern const FFCodec ff_h264_videotoolbox_encoder; extern const FFCodec ff_hevc_amf_encoder; extern const FFCodec ff_hevc_cuvid_decoder; +extern const FFCodec ff_hevc_d3d12va_encoder; extern const FFCodec ff_hevc_mediacodec_decoder; extern const FFCodec ff_hevc_mediacodec_encoder; extern const FFCodec ff_hevc_mf_encoder; diff --git a/libavcodec/d3d12va_encode.c b/libavcodec/d3d12va_encode.c new file mode 100644 index 00..739f90ecb7 --- /
[FFmpeg-devel] [PATCH v12 01/15] avcodec/vaapi_encode: introduce a base layer for vaapi encode
From: Tong Wu Since VAAPI and future D3D12VA implementation may share some common parameters, a base layer encode context is introduced as vaapi context's base. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 56 + libavcodec/vaapi_encode.h | 39 +- 2 files changed, 63 insertions(+), 32 deletions(-) create mode 100644 libavcodec/hw_base_encode.h diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h new file mode 100644 index 00..ffcb6bcbb2 --- /dev/null +++ b/libavcodec/hw_base_encode.h @@ -0,0 +1,56 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_HW_BASE_ENCODE_H +#define AVCODEC_HW_BASE_ENCODE_H + +#define MAX_DPB_SIZE 16 +#define MAX_PICTURE_REFERENCES 2 +#define MAX_REORDER_DELAY 16 +#define MAX_ASYNC_DEPTH 64 +#define MAX_REFERENCE_LIST_NUM 2 + +enum { +PICTURE_TYPE_IDR = 0, +PICTURE_TYPE_I = 1, +PICTURE_TYPE_P = 2, +PICTURE_TYPE_B = 3, +}; + +enum { +// Codec supports controlling the subdivision of pictures into slices. +FLAG_SLICE_CONTROL = 1 << 0, +// Codec only supports constant quality (no rate control). +FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, +// Codec is intra-only. +FLAG_INTRA_ONLY= 1 << 2, +// Codec supports B-pictures. +FLAG_B_PICTURES= 1 << 3, +// Codec supports referencing B-pictures. +FLAG_B_PICTURE_REFERENCES = 1 << 4, +// Codec supports non-IDR key pictures (that is, key pictures do +// not necessarily empty the DPB). +FLAG_NON_IDR_KEY_PICTURES = 1 << 5, +}; + +typedef struct FFHWBaseEncodeContext { +const AVClass *class; +} FFHWBaseEncodeContext; + +#endif /* AVCODEC_HW_BASE_ENCODE_H */ + diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index 0eed9691ca..cae7af8725 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -33,34 +33,27 @@ #include "avcodec.h" #include "hwconfig.h" +#include "hw_base_encode.h" struct VAAPIEncodeType; struct VAAPIEncodePicture; +// Codec output packet without timestamp delay, which means the +// output packet has same PTS and DTS. +#define FLAG_TIMESTAMP_NO_DELAY 1 << 6 + enum { MAX_CONFIG_ATTRIBUTES = 4, MAX_GLOBAL_PARAMS = 4, -MAX_DPB_SIZE = 16, -MAX_PICTURE_REFERENCES = 2, -MAX_REORDER_DELAY = 16, MAX_PARAM_BUFFER_SIZE = 1024, // A.4.1: table A.6 allows at most 22 tile rows for any level. 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, -MAX_REFERENCE_LIST_NUM = 2, }; extern const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[]; -enum { -PICTURE_TYPE_IDR = 0, -PICTURE_TYPE_I = 1, -PICTURE_TYPE_P = 2, -PICTURE_TYPE_B = 3, -}; - typedef struct VAAPIEncodeSlice { int index; int row_start; @@ -193,7 +186,8 @@ typedef struct VAAPIEncodeRCMode { } VAAPIEncodeRCMode; typedef struct VAAPIEncodeContext { -const AVClass *class; +// Base context. +FFHWBaseEncodeContext base; // Codec-specific hooks. const struct VAAPIEncodeType *codec; @@ -397,25 +391,6 @@ typedef struct VAAPIEncodeContext { AVPacket*tail_pkt; } VAAPIEncodeContext; -enum { -// Codec supports controlling the subdivision of pictures into slices. -FLAG_SLICE_CONTROL = 1 << 0, -// Codec only supports constant quality (no rate control). -FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, -// Codec is intra-only. -FLAG_INTRA_ONLY= 1 << 2, -// Codec supports B-pictures. -FLAG_B_PICTURES= 1 << 3, -// Codec supports referencing B-pictures. -FLAG_B_PICTURE_REFERENCES = 1 << 4, -// Codec supports non-IDR key pictures (that is, key pictures do -// not necessarily empty the DPB). -FLAG_NON_IDR_KEY_PICTURES = 1 << 5, -// Codec output packet without timestamp delay, which means the -// output packet has same PTS and DTS. -FLAG_TIMESTAMP_NO_DELAY= 1 << 6, -}; - typedef struct VAAPIEncodeType { // List of supported profiles and corr
[FFmpeg-devel] [PATCH v12 02/15] avcodec/hw_base_encode: add FF_HW_ prefix for two enums
From: Tong Wu PICTURE_TYPE_* and FLAG_* are added FF_HW_ prefix after being moved to base layer. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 20 ++--- libavcodec/vaapi_encode.c | 50 - libavcodec/vaapi_encode_av1.c | 12 libavcodec/vaapi_encode_h264.c | 50 - libavcodec/vaapi_encode_h265.c | 44 ++--- libavcodec/vaapi_encode_mjpeg.c | 6 ++-- libavcodec/vaapi_encode_mpeg2.c | 30 ++-- libavcodec/vaapi_encode_vp8.c | 10 +++ libavcodec/vaapi_encode_vp9.c | 16 +-- 9 files changed, 119 insertions(+), 119 deletions(-) diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index ffcb6bcbb2..f3c9f32977 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -26,26 +26,26 @@ #define MAX_REFERENCE_LIST_NUM 2 enum { -PICTURE_TYPE_IDR = 0, -PICTURE_TYPE_I = 1, -PICTURE_TYPE_P = 2, -PICTURE_TYPE_B = 3, +FF_HW_PICTURE_TYPE_IDR = 0, +FF_HW_PICTURE_TYPE_I = 1, +FF_HW_PICTURE_TYPE_P = 2, +FF_HW_PICTURE_TYPE_B = 3, }; enum { // Codec supports controlling the subdivision of pictures into slices. -FLAG_SLICE_CONTROL = 1 << 0, +FF_HW_FLAG_SLICE_CONTROL = 1 << 0, // Codec only supports constant quality (no rate control). -FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, +FF_HW_FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, // Codec is intra-only. -FLAG_INTRA_ONLY= 1 << 2, +FF_HW_FLAG_INTRA_ONLY= 1 << 2, // Codec supports B-pictures. -FLAG_B_PICTURES= 1 << 3, +FF_HW_FLAG_B_PICTURES= 1 << 3, // Codec supports referencing B-pictures. -FLAG_B_PICTURE_REFERENCES = 1 << 4, +FF_HW_FLAG_B_PICTURE_REFERENCES = 1 << 4, // Codec supports non-IDR key pictures (that is, key pictures do // not necessarily empty the DPB). -FLAG_NON_IDR_KEY_PICTURES = 1 << 5, +FF_HW_FLAG_NON_IDR_KEY_PICTURES = 1 << 5, }; typedef struct FFHWBaseEncodeContext { diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index f54b2579ec..3c3d6a37c7 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -345,7 +345,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, pic->nb_param_buffers = 0; -if (pic->type == PICTURE_TYPE_IDR && ctx->codec->init_sequence_params) { +if (pic->type == FF_HW_PICTURE_TYPE_IDR && ctx->codec->init_sequence_params) { err = vaapi_encode_make_param_buffer(avctx, pic, VAEncSequenceParameterBufferType, ctx->codec_sequence_params, @@ -354,7 +354,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, goto fail; } -if (pic->type == PICTURE_TYPE_IDR) { +if (pic->type == FF_HW_PICTURE_TYPE_IDR) { for (i = 0; i < ctx->nb_global_params; i++) { err = vaapi_encode_make_misc_param_buffer(avctx, pic, ctx->global_params_type[i], @@ -391,7 +391,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, } #endif -if (pic->type == PICTURE_TYPE_IDR) { +if (pic->type == FF_HW_PICTURE_TYPE_IDR) { if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE && ctx->codec->write_sequence_header) { bit_len = 8 * sizeof(data); @@ -671,7 +671,7 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, { VAAPIEncodeContext *ctx = avctx->priv_data; -if (pic->type == PICTURE_TYPE_IDR) +if (pic->type == FF_HW_PICTURE_TYPE_IDR) pkt->flags |= AV_PKT_FLAG_KEY; pkt->pts = pic->pts; @@ -996,7 +996,7 @@ static void vaapi_encode_remove_refs(AVCodecContext *avctx, av_assert0(pic->dpb[i]->ref_count[level] >= 0); } -av_assert0(pic->prev || pic->type == PICTURE_TYPE_IDR); +av_assert0(pic->prev || pic->type == FF_HW_PICTURE_TYPE_IDR); if (pic->prev) { --pic->prev->ref_count[level]; av_assert0(pic->prev->ref_count[level] >= 0); @@ -1025,7 +1025,7 @@ static void vaapi_encode_set_b_pictures(AVCodecContext *avctx, for (pic = start->next; pic; pic = pic->next) { if (pic == end) break; -pic->type= PICTURE_TYPE_B; +pic->type= FF_HW_PICTURE_TYPE_B; pic->b_depth = current_depth; vaapi_encode_add_ref(avctx, pic, start, 1, 1, 0); @@ -1045,7 +1045,7 @@ static void vaapi_encode_set_b_pictures(AVCodecContext *avctx, ++len; for (pic = start->next, i = 1; 2 * i < len; pic = pic->next, i++); -pic->type= PICTURE_TYPE_B; +pic->type= FF_HW_PICTURE_TYPE_B; pic->b_depth = current_depth; pic->is_reference = 1; @@ -1078,7 +1078,7 @@ static void vaapi_enco
[FFmpeg-devel] [PATCH v12 03/15] avcodec/vaapi_encode: add async_depth to common options
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 10 +- libavcodec/vaapi_encode.c | 13 - libavcodec/vaapi_encode.h | 7 --- libavcodec/vaapi_encode_av1.c | 1 + libavcodec/vaapi_encode_h264.c | 1 + libavcodec/vaapi_encode_h265.c | 1 + libavcodec/vaapi_encode_mjpeg.c | 1 + libavcodec/vaapi_encode_mpeg2.c | 1 + libavcodec/vaapi_encode_vp8.c | 1 + libavcodec/vaapi_encode_vp9.c | 1 + 10 files changed, 24 insertions(+), 13 deletions(-) diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index f3c9f32977..c14c174102 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -50,7 +50,15 @@ enum { typedef struct FFHWBaseEncodeContext { const AVClass *class; + +// Max number of frame buffered in encoder. +int async_depth; } FFHWBaseEncodeContext; -#endif /* AVCODEC_HW_BASE_ENCODE_H */ +#define HW_BASE_ENCODE_COMMON_OPTIONS \ +{ "async_depth", "Maximum processing parallelism. " \ + "Increase this to improve single channel performance.", \ + OFFSET(common.base.async_depth), AV_OPT_TYPE_INT, \ + { .i64 = 2 }, 1, MAX_ASYNC_DEPTH, FLAGS } +#endif /* AVCODEC_HW_BASE_ENCODE_H */ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 3c3d6a37c7..77f539dc6d 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -669,7 +669,8 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, VAAPIEncodePicture *pic, AVPacket *pkt) { -VAAPIEncodeContext *ctx = avctx->priv_data; +FFHWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; if (pic->type == FF_HW_PICTURE_TYPE_IDR) pkt->flags |= AV_PKT_FLAG_KEY; @@ -699,7 +700,7 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, 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 + ctx->async_depth)]; +(3 * ctx->output_delay + base_ctx->async_depth)]; } return 0; @@ -1320,6 +1321,7 @@ static int vaapi_encode_check_frame(AVCodecContext *avctx, static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) { +FFHWBaseEncodeContext *base_ctx = avctx->priv_data; VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic; int err; @@ -1365,7 +1367,7 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) ctx->dts_pts_diff = pic->pts - ctx->first_pts; if (ctx->output_delay > 0) ctx->ts_ring[ctx->input_order % -(3 * ctx->output_delay + ctx->async_depth)] = pic->pts; +(3 * ctx->output_delay + base_ctx->async_depth)] = pic->pts; pic->display_order = ctx->input_order; ++ctx->input_order; @@ -2773,7 +2775,8 @@ static av_cold int vaapi_encode_create_recon_frames(AVCodecContext *avctx) av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) { -VAAPIEncodeContext *ctx = avctx->priv_data; +FFHWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; AVVAAPIFramesContext *recon_hwctx = NULL; VAStatus vas; int err; @@ -2966,7 +2969,7 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) vas = vaSyncBuffer(ctx->hwctx->display, VA_INVALID_ID, 0); if (vas != VA_STATUS_ERROR_UNIMPLEMENTED) { ctx->has_sync_buffer_func = 1; -ctx->encode_fifo = av_fifo_alloc2(ctx->async_depth, +ctx->encode_fifo = av_fifo_alloc2(base_ctx->async_depth, sizeof(VAAPIEncodePicture *), 0); if (!ctx->encode_fifo) diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index cae7af8725..9fdb945b18 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -374,8 +374,6 @@ typedef struct VAAPIEncodeContext { int has_sync_buffer_func; // Store buffered pic AVFifo *encode_fifo; -// Max number of frame buffered in encoder. -int async_depth; /** Head data for current output pkt, used only for AV1. */ //void *header_data; @@ -491,11 +489,6 @@ int ff_vaapi_encode_close(AVCodecContext *avctx); "Maximum B-frame reference depth", \ OFFSET(common.desired_b_depth), AV_OPT_TYPE_INT, \ { .i64 = 1 }, 1, INT_MAX, FLAGS }, \ -{ "async_depth", "Maximum processing parallelism. " \ - "Increase this to improve single channel performance. This option " \ - "doesn't work if driver doesn't implement vaSyncBuffer function.", \ - OFFSET(co
[FFmpeg-devel] [PATCH v12 04/15] avcodec/vaapi_encode: add picture type name to base
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 6 ++ libavcodec/vaapi_encode.c | 4 +--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index c14c174102..858450afa8 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -25,6 +25,12 @@ #define MAX_ASYNC_DEPTH 64 #define MAX_REFERENCE_LIST_NUM 2 +static inline const char *ff_hw_base_encode_get_pictype_name(const int type) +{ +const char * const picture_type_name[] = { "IDR", "I", "P", "B" }; +return picture_type_name[type]; +} + enum { FF_HW_PICTURE_TYPE_IDR = 0, FF_HW_PICTURE_TYPE_I = 1, diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 77f539dc6d..54bdd73902 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -38,8 +38,6 @@ const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[] = { NULL, }; -static const char * const picture_type_name[] = { "IDR", "I", "P", "B" }; - static int vaapi_encode_make_packed_header(AVCodecContext *avctx, VAAPIEncodePicture *pic, int type, char *data, size_t bit_len) @@ -277,7 +275,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Issuing encode for pic %"PRId64"/%"PRId64" " "as type %s.\n", pic->display_order, pic->encode_order, - picture_type_name[pic->type]); + ff_hw_base_encode_get_pictype_name(pic->type)); if (pic->nb_refs[0] == 0 && pic->nb_refs[1] == 0) { av_log(avctx, AV_LOG_DEBUG, "No reference pictures.\n"); } else { -- 2.41.0.windows.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 v12 05/15] avcodec/vaapi_encode: move pic->input_surface initialization to encode_alloc
From: Tong Wu When allocating the VAAPIEncodePicture, pic->input_surface can be initialized right in the place. This movement simplifies the send_frame logic and is the preparation for moving vaapi_encode_send_frame to the base layer. Signed-off-by: Tong Wu --- libavcodec/vaapi_encode.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 54bdd73902..194422b36d 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -878,7 +878,8 @@ static int vaapi_encode_discard(AVCodecContext *avctx, return 0; } -static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx) +static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx, + const AVFrame *frame) { VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic; @@ -895,7 +896,7 @@ static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx) } } -pic->input_surface = VA_INVALID_ID; +pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; pic->recon_surface = VA_INVALID_ID; pic->output_buffer = VA_INVALID_ID; @@ -1332,7 +1333,7 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) if (err < 0) return err; -pic = vaapi_encode_alloc(avctx); +pic = vaapi_encode_alloc(avctx, frame); if (!pic) return AVERROR(ENOMEM); @@ -1345,7 +1346,6 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) if (ctx->input_order == 0 || frame->pict_type == AV_PICTURE_TYPE_I) pic->force_idr = 1; -pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; pic->pts = frame->pts; pic->duration = frame->duration; -- 2.41.0.windows.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 v12 08/15] avcodec/vaapi_encode: extract gop configuration and two options to base layer
From: Tong Wu idr_interval and desired_b_depth are moved to HW_BASE_ENCODE_COMMON_OPTIONS. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 54 + libavcodec/hw_base_encode.h | 19 + libavcodec/vaapi_encode.c | 52 +++ libavcodec/vaapi_encode.h | 16 --- 4 files changed, 77 insertions(+), 64 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index c4789380b6..56dc015e2e 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -593,6 +593,60 @@ end: return 0; } +int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, + int flags, int prediction_pre_only) +{ +FFHWBaseEncodeContext *ctx = avctx->priv_data; + +if (flags & FF_HW_FLAG_INTRA_ONLY || avctx->gop_size <= 1) { +av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n"); +ctx->gop_size = 1; +} else if (ref_l0 < 1) { +av_log(avctx, AV_LOG_ERROR, "Driver does not support any " + "reference frames.\n"); +return AVERROR(EINVAL); +} else if (!(flags & FF_HW_FLAG_B_PICTURES) || ref_l1 < 1 || + avctx->max_b_frames < 1 || prediction_pre_only) { +if (ctx->p_to_gpb) + av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " + "(supported references: %d / %d).\n", + ref_l0, ref_l1); +else +av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames " + "(supported references: %d / %d).\n", ref_l0, ref_l1); +ctx->gop_size = avctx->gop_size; +ctx->p_per_i = INT_MAX; +ctx->b_per_p = 0; +} else { + if (ctx->p_to_gpb) + av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " + "(supported references: %d / %d).\n", + ref_l0, ref_l1); + else + av_log(avctx, AV_LOG_VERBOSE, "Using intra, P- and B-frames " + "(supported references: %d / %d).\n", ref_l0, ref_l1); +ctx->gop_size = avctx->gop_size; +ctx->p_per_i = INT_MAX; +ctx->b_per_p = avctx->max_b_frames; +if (flags & FF_HW_FLAG_B_PICTURE_REFERENCES) { +ctx->max_b_depth = FFMIN(ctx->desired_b_depth, + av_log2(ctx->b_per_p) + 1); +} else { +ctx->max_b_depth = 1; +} +} + +if (flags & FF_HW_FLAG_NON_IDR_KEY_PICTURES) { +ctx->closed_gop = !!(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP); +ctx->gop_per_idr = ctx->idr_interval + 1; +} else { +ctx->closed_gop = 1; +ctx->gop_per_idr = 1; +} + +return 0; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { FFHWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index a062009860..c7e535d35d 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -120,6 +120,14 @@ typedef struct FFHWBaseEncodeContext { // Hardware-specific hooks. const struct FFHWEncodePictureOperation *op; +// Global options. + +// Number of I frames between IDR frames. +int idr_interval; + +// Desired B frame reference depth. +int desired_b_depth; + // The hardware device context. AVBufferRef*device_ref; AVHWDeviceContext *device; @@ -198,11 +206,22 @@ typedef struct FFHWBaseEncodeContext { int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); +int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, + int flags, int prediction_pre_only); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); #define HW_BASE_ENCODE_COMMON_OPTIONS \ +{ "idr_interval", \ + "Distance (in I-frames) between key frames", \ + OFFSET(common.base.idr_interval), AV_OPT_TYPE_INT, \ + { .i64 = 0 }, 0, INT_MAX, FLAGS }, \ +{ "b_depth", \ + "Maximum B-frame reference depth", \ + OFFSET(common.base.desired_b_depth), AV_OPT_TYPE_INT, \ + { .i64 = 1 }, 1, INT_MAX, FLAGS }, \ { "async_depth", "Maximum processing parallelism. " \ "Increase this to improve single channel performance.", \ OFFSET(common.base.async_depth), AV_OPT_TYPE_INT, \ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 1b3bab2c14..c29493e2c8 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1638,7 +1638,7 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) VAStatus vas; VAConfigAttrib attr = { VAConfigAttribEncMaxRefFrames }; uint32_t ref_l0, ref_l1; -int prediction_pre_only; +int prediction_pre_only, err; vas = vaGetConfigAttributes(ctx->hwctx-
[FFmpeg-devel] [PATCH v12 06/15] avcodec/vaapi_encode: move the dpb logic from VAAPI to base layer
From: Tong Wu Move receive_packet function to base. This requires adding *alloc, *issue, *output, *free as hardware callbacks. HWBaseEncodePicture is introduced as the base layer structure. The related parameters in VAAPIEncodeContext are also extracted to HWBaseEncodeContext. Then DPB management logic can be fully extracted to base layer as-is. Signed-off-by: Tong Wu --- libavcodec/Makefile | 2 +- libavcodec/hw_base_encode.c | 594 libavcodec/hw_base_encode.h | 124 + libavcodec/vaapi_encode.c | 793 +--- libavcodec/vaapi_encode.h | 102 +--- libavcodec/vaapi_encode_av1.c | 35 +- libavcodec/vaapi_encode_h264.c | 84 ++-- libavcodec/vaapi_encode_h265.c | 53 ++- libavcodec/vaapi_encode_mjpeg.c | 13 +- libavcodec/vaapi_encode_mpeg2.c | 33 +- libavcodec/vaapi_encode_vp8.c | 18 +- libavcodec/vaapi_encode_vp9.c | 24 +- 12 files changed, 985 insertions(+), 890 deletions(-) create mode 100644 libavcodec/hw_base_encode.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2443d2c6fd..998f6b7e12 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -165,7 +165,7 @@ OBJS-$(CONFIG_STARTCODE) += startcode.o OBJS-$(CONFIG_TEXTUREDSP) += texturedsp.o OBJS-$(CONFIG_TEXTUREDSPENC) += texturedspenc.o OBJS-$(CONFIG_TPELDSP) += tpeldsp.o -OBJS-$(CONFIG_VAAPI_ENCODE)+= vaapi_encode.o +OBJS-$(CONFIG_VAAPI_ENCODE)+= vaapi_encode.o hw_base_encode.o OBJS-$(CONFIG_AV1_AMF_ENCODER) += amfenc_av1.o OBJS-$(CONFIG_VC1DSP) += vc1dsp.o OBJS-$(CONFIG_VIDEODSP)+= videodsp.o diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c new file mode 100644 index 00..16afaa37be --- /dev/null +++ b/libavcodec/hw_base_encode.c @@ -0,0 +1,594 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" + +#include "encode.h" +#include "avcodec.h" +#include "hw_base_encode.h" + +static void hw_base_encode_add_ref(FFHWBaseEncodePicture *pic, + FFHWBaseEncodePicture *target, + int is_ref, int in_dpb, int prev) +{ +int refs = 0; + +if (is_ref) { +av_assert0(pic != target); +av_assert0(pic->nb_refs[0] < MAX_PICTURE_REFERENCES && + pic->nb_refs[1] < MAX_PICTURE_REFERENCES); +if (target->display_order < pic->display_order) +pic->refs[0][pic->nb_refs[0]++] = target; +else +pic->refs[1][pic->nb_refs[1]++] = target; +++refs; +} + +if (in_dpb) { +av_assert0(pic->nb_dpb_pics < MAX_DPB_SIZE); +pic->dpb[pic->nb_dpb_pics++] = target; +++refs; +} + +if (prev) { +av_assert0(!pic->prev); +pic->prev = target; +++refs; +} + +target->ref_count[0] += refs; +target->ref_count[1] += refs; +} + +static void hw_base_encode_remove_refs(FFHWBaseEncodePicture *pic, int level) +{ +int i; + +if (pic->ref_removed[level]) +return; + +for (i = 0; i < pic->nb_refs[0]; i++) { +av_assert0(pic->refs[0][i]); +--pic->refs[0][i]->ref_count[level]; +av_assert0(pic->refs[0][i]->ref_count[level] >= 0); +} + +for (i = 0; i < pic->nb_refs[1]; i++) { +av_assert0(pic->refs[1][i]); +--pic->refs[1][i]->ref_count[level]; +av_assert0(pic->refs[1][i]->ref_count[level] >= 0); +} + +for (i = 0; i < pic->nb_dpb_pics; i++) { +av_assert0(pic->dpb[i]); +--pic->dpb[i]->ref_count[level]; +av_assert0(pic->dpb[i]->ref_count[level] >= 0); +} + +av_assert0(pic->prev || pic->type == FF_HW_PICTURE_TYPE_IDR); +if (pic->prev) { +--pic->prev->ref_count[level]; +av_assert0(pic->prev->ref_count[level] >= 0); +} + +pic->ref_removed[level] = 1; +} + +static void hw_base_encode_set_b_pictures(AVCodecContext *avctx, + FFHWBaseEncodePicture *st
[FFmpeg-devel] [PATCH v12 09/15] avcodec/vaapi_encode: extract set_output_property to base layer
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 40 + libavcodec/hw_base_encode.h | 3 +++ libavcodec/vaapi_encode.c | 44 ++--- 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 56dc015e2e..25fcfdbb5e 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -488,6 +488,46 @@ fail: return err; } +int ff_hw_base_encode_set_output_property(AVCodecContext *avctx, + FFHWBaseEncodePicture *pic, + AVPacket *pkt, int flag_no_delay) +{ +FFHWBaseEncodeContext *ctx = avctx->priv_data; + +if (pic->type == FF_HW_PICTURE_TYPE_IDR) +pkt->flags |= AV_PKT_FLAG_KEY; + +pkt->pts = pic->pts; +pkt->duration = pic->duration; + +// for no-delay encoders this is handled in generic codec +if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY && +avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { +pkt->opaque = pic->opaque; +pkt->opaque_ref = pic->opaque_ref; +pic->opaque_ref = NULL; +} + +if (flag_no_delay) { +pkt->dts = pkt->pts; +return 0; +} + +if (ctx->output_delay == 0) { +pkt->dts = pkt->pts; +} else if (pic->encode_order < ctx->decode_delay) { +if (ctx->ts_ring[pic->encode_order] < INT64_MIN + ctx->dts_pts_diff) +pkt->dts = INT64_MIN; +else +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 + ctx->async_depth)]; +} + +return 0; +} + int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) { FFHWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index c7e535d35d..f097d826a7 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -204,6 +204,9 @@ typedef struct FFHWBaseEncodeContext { AVPacket*tail_pkt; } FFHWBaseEncodeContext; +int ff_hw_base_encode_set_output_property(AVCodecContext *avctx, FFHWBaseEncodePicture *pic, + AVPacket *pkt, int flag_no_delay); + int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index c29493e2c8..4193f3838f 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -660,47 +660,6 @@ fail_at_end: return err; } -static int vaapi_encode_set_output_property(AVCodecContext *avctx, -FFHWBaseEncodePicture *pic, -AVPacket *pkt) -{ -FFHWBaseEncodeContext *base_ctx = avctx->priv_data; -VAAPIEncodeContext *ctx = avctx->priv_data; - -if (pic->type == FF_HW_PICTURE_TYPE_IDR) -pkt->flags |= AV_PKT_FLAG_KEY; - -pkt->pts = pic->pts; -pkt->duration = pic->duration; - -// for no-delay encoders this is handled in generic codec -if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY && -avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { -pkt->opaque = pic->opaque; -pkt->opaque_ref = pic->opaque_ref; -pic->opaque_ref = NULL; -} - -if (ctx->codec->flags & FLAG_TIMESTAMP_NO_DELAY) { -pkt->dts = pkt->pts; -return 0; -} - -if (base_ctx->output_delay == 0) { -pkt->dts = pkt->pts; -} else if (pic->encode_order < base_ctx->decode_delay) { -if (base_ctx->ts_ring[pic->encode_order] < INT64_MIN + base_ctx->dts_pts_diff) -pkt->dts = INT64_MIN; -else -pkt->dts = base_ctx->ts_ring[pic->encode_order] - base_ctx->dts_pts_diff; -} else { -pkt->dts = base_ctx->ts_ring[(pic->encode_order - base_ctx->decode_delay) % - (3 * base_ctx->output_delay + base_ctx->async_depth)]; -} - -return 0; -} - static int vaapi_encode_get_coded_buffer_size(AVCodecContext *avctx, VABufferID buf_id) { VAAPIEncodeContext *ctx = avctx->priv_data; @@ -852,7 +811,8 @@ static int vaapi_encode_output(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n", base_pic->display_order, base_pic->encode_order); -vaapi_encode_set_output_property(avctx, (FFHWBaseEncodePicture*)pic, pkt_ptr); +ff_hw_base_encode_set_output_property(avctx, (FFHWBaseEncodePicture*)base_pic, pkt_ptr, + ctx->codec->flags & FLAG_TIMESTAMP_NO_DELAY); end: ff_refstruct_unref(&pic->output_buffer_ref); -- 2.41.
[FFmpeg-devel] [PATCH v12 10/15] avcodec/vaapi_encode: extract a get_recon_format function to base layer
From: Tong Wu Surface size and block size parameters are also moved to base layer. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 58 +++ libavcodec/hw_base_encode.h | 12 + libavcodec/vaapi_encode.c | 81 - libavcodec/vaapi_encode.h | 10 libavcodec/vaapi_encode_av1.c | 10 ++-- libavcodec/vaapi_encode_h264.c | 11 +++-- libavcodec/vaapi_encode_h265.c | 25 +- libavcodec/vaapi_encode_mjpeg.c | 5 +- libavcodec/vaapi_encode_vp9.c | 6 +-- 9 files changed, 118 insertions(+), 100 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 25fcfdbb5e..31046bd73e 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -687,6 +687,64 @@ int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32 return 0; } +int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt) +{ +FFHWBaseEncodeContext *ctx = avctx->priv_data; +AVHWFramesConstraints *constraints = NULL; +enum AVPixelFormat recon_format; +int err, i; + +constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref, + hwconfig); +if (!constraints) { +err = AVERROR(ENOMEM); +goto fail; +} + +// Probably we can use the input surface format as the surface format +// of the reconstructed frames. If not, we just pick the first (only?) +// format in the valid list and hope that it all works. +recon_format = AV_PIX_FMT_NONE; +if (constraints->valid_sw_formats) { +for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { +if (ctx->input_frames->sw_format == +constraints->valid_sw_formats[i]) { +recon_format = ctx->input_frames->sw_format; +break; +} +} +if (recon_format == AV_PIX_FMT_NONE) { +// No match. Just use the first in the supported list and +// hope for the best. +recon_format = constraints->valid_sw_formats[0]; +} +} else { +// No idea what to use; copy input format. +recon_format = ctx->input_frames->sw_format; +} +av_log(avctx, AV_LOG_DEBUG, "Using %s as format of " + "reconstructed frames.\n", av_get_pix_fmt_name(recon_format)); + +if (ctx->surface_width < constraints->min_width || +ctx->surface_height < constraints->min_height || +ctx->surface_width > constraints->max_width || +ctx->surface_height > constraints->max_height) { +av_log(avctx, AV_LOG_ERROR, "Hardware does not support encoding at " + "size %dx%d (constraints: width %d-%d height %d-%d).\n", + ctx->surface_width, ctx->surface_height, + constraints->min_width, constraints->max_width, + constraints->min_height, constraints->max_height); +err = AVERROR(EINVAL); +goto fail; +} + +*fmt = recon_format; +err = 0; +fail: +av_hwframe_constraints_free(&constraints); +return err; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { FFHWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index f097d826a7..f5414e2c28 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -128,6 +128,16 @@ typedef struct FFHWBaseEncodeContext { // Desired B frame reference depth. int desired_b_depth; +// The required size of surfaces. This is probably the input +// size (AVCodecContext.width|height) aligned up to whatever +// block size is required by the codec. +int surface_width; +int surface_height; + +// The block size for slice calculations. +int slice_block_width; +int slice_block_height; + // The hardware device context. AVBufferRef*device_ref; AVHWDeviceContext *device; @@ -212,6 +222,8 @@ int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, int flags, int prediction_pre_only); +int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 4193f3838f..d96f146b28 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1777,6 +1777,7 @@ static av_cold int vaapi_encode_init_tile_slice_structure(AVCodecContext *avctx, static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) { +FFHWBaseEncodeContext *base_ctx = a
[FFmpeg-devel] [PATCH v12 11/15] avcodec/vaapi_encode: extract a free funtion to base layer
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 11 +++ libavcodec/hw_base_encode.h | 2 ++ libavcodec/vaapi_encode.c | 6 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 31046bd73e..92f69bb78c 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -745,6 +745,17 @@ fail: return err; } +int ff_hw_base_encode_free(FFHWBaseEncodePicture *pic) +{ +av_frame_free(&pic->input_image); +av_frame_free(&pic->recon_image); + +av_buffer_unref(&pic->opaque_ref); +av_freep(&pic->priv_data); + +return 0; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { FFHWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index f5414e2c28..15ef3d7ac6 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -224,6 +224,8 @@ int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32 int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt); +int ff_hw_base_encode_free(FFHWBaseEncodePicture *pic); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index d96f146b28..b35a23e852 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -878,17 +878,13 @@ static int vaapi_encode_free(AVCodecContext *avctx, av_freep(&pic->slices[i].codec_slice_params); } -av_frame_free(&base_pic->input_image); -av_frame_free(&base_pic->recon_image); - -av_buffer_unref(&base_pic->opaque_ref); +ff_hw_base_encode_free(base_pic); av_freep(&pic->param_buffers); av_freep(&pic->slices); // Output buffer should already be destroyed. av_assert0(pic->output_buffer == VA_INVALID_ID); -av_freep(&base_pic->priv_data); av_freep(&pic->codec_picture_params); av_freep(&pic->roi); -- 2.41.0.windows.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 v12 12/15] avutil/hwcontext_d3d12va: add Flags for resource creation
From: Tong Wu Flags field is added to support diffferent resource creation. Signed-off-by: Tong Wu --- doc/APIchanges| 3 +++ libavutil/hwcontext_d3d12va.c | 2 +- libavutil/hwcontext_d3d12va.h | 8 libavutil/version.h | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 60f056b863..0c3d0221e8 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2024-03-07 API changes, most recent first: +2024-01-xx - xx - lavu 59.21.100 - hwcontext_d3d12va.h + Add AVD3D12VAFramesContext.flags + 2024-05-23 - xx - lavu 59.20.100 - channel_layout.h Add av_channel_layout_ambisonic_order(). diff --git a/libavutil/hwcontext_d3d12va.c b/libavutil/hwcontext_d3d12va.c index cfc016315d..6507cf69c1 100644 --- a/libavutil/hwcontext_d3d12va.c +++ b/libavutil/hwcontext_d3d12va.c @@ -247,7 +247,7 @@ static AVBufferRef *d3d12va_pool_alloc(void *opaque, size_t size) .Format = hwctx->format, .SampleDesc = {.Count = 1, .Quality = 0 }, .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, -.Flags= D3D12_RESOURCE_FLAG_NONE, +.Flags= hwctx->flags, }; frame = av_mallocz(sizeof(AVD3D12VAFrame)); diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h index ff06e6f2ef..212a6a6146 100644 --- a/libavutil/hwcontext_d3d12va.h +++ b/libavutil/hwcontext_d3d12va.h @@ -129,6 +129,14 @@ typedef struct AVD3D12VAFramesContext { * If unset, will be automatically set. */ DXGI_FORMAT format; + +/** + * Options for working with resources. + * If unset, this will be D3D12_RESOURCE_FLAG_NONE. + * + * @see https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_resource_flags + */ +D3D12_RESOURCE_FLAGS flags; } AVD3D12VAFramesContext; #endif /* AVUTIL_HWCONTEXT_D3D12VA_H */ diff --git a/libavutil/version.h b/libavutil/version.h index 9c7146c228..9d08d56884 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 59 -#define LIBAVUTIL_VERSION_MINOR 20 +#define LIBAVUTIL_VERSION_MINOR 21 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ -- 2.41.0.windows.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 v12 13/15] avcodec: add D3D12VA hardware HEVC encoder
From: Tong Wu This implementation is based on D3D12 Video Encoding Spec: https://microsoft.github.io/DirectX-Specs/d3d/D3D12VideoEncoding.html Sample command line for transcoding: ffmpeg.exe -hwaccel d3d12va -hwaccel_output_format d3d12 -i input.mp4 -c:v hevc_d3d12va output.mp4 Signed-off-by: Tong Wu --- configure|6 + libavcodec/Makefile |5 +- libavcodec/allcodecs.c |1 + libavcodec/d3d12va_encode.c | 1558 ++ libavcodec/d3d12va_encode.h | 334 +++ libavcodec/d3d12va_encode_hevc.c | 1007 +++ 6 files changed, 2910 insertions(+), 1 deletion(-) create mode 100644 libavcodec/d3d12va_encode.c create mode 100644 libavcodec/d3d12va_encode.h create mode 100644 libavcodec/d3d12va_encode_hevc.c diff --git a/configure b/configure index b16722d83d..127d68e60c 100755 --- a/configure +++ b/configure @@ -2551,6 +2551,7 @@ CONFIG_EXTRA=" cbs_mpeg2 cbs_vp8 cbs_vp9 +d3d12va_encode deflate_wrapper dirac_parse dnn @@ -3287,6 +3288,7 @@ wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel" # hardware-accelerated codecs +d3d12va_encode_deps="d3d12va ID3D12VideoEncoder d3d12_encoder_feature" mediafoundation_deps="mftransform_h MFCreateAlignedMemoryBuffer" omx_deps="libdl pthreads" omx_rpi_select="omx" @@ -3354,6 +3356,7 @@ h264_v4l2m2m_encoder_deps="v4l2_m2m h264_v4l2_m2m" hevc_amf_encoder_deps="amf" hevc_cuvid_decoder_deps="cuvid" hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf" +hevc_d3d12va_encoder_select="cbs_h265 d3d12va_encode" hevc_mediacodec_decoder_deps="mediacodec" hevc_mediacodec_decoder_select="hevc_mp4toannexb_bsf hevc_parser" hevc_mediacodec_encoder_deps="mediacodec" @@ -6725,6 +6728,9 @@ check_type "windows.h d3d11.h" "ID3D11VideoDecoder" check_type "windows.h d3d11.h" "ID3D11VideoContext" check_type "windows.h d3d12.h" "ID3D12Device" check_type "windows.h d3d12video.h" "ID3D12VideoDecoder" +check_type "windows.h d3d12video.h" "ID3D12VideoEncoder" +test_code cc "windows.h d3d12video.h" "D3D12_FEATURE_VIDEO feature = D3D12_FEATURE_VIDEO_ENCODER_CODEC" && \ +test_code cc "windows.h d3d12video.h" "D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOURCE_REQUIREMENTS req" && enable d3d12_encoder_feature check_type "windows.h" "DPI_AWARENESS_CONTEXT" -D_WIN32_WINNT=0x0A00 check_type "d3d9.h dxva2api.h" DXVA2_ConfigPictureDecode -D_WIN32_WINNT=0x0602 check_func_headers mfapi.h MFCreateAlignedMemoryBuffer -lmfplat diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 998f6b7e12..6c4500ce6d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -86,6 +86,7 @@ OBJS-$(CONFIG_CBS_JPEG)+= cbs_jpeg.o OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o OBJS-$(CONFIG_CBS_VP8) += cbs_vp8.o vp8data.o OBJS-$(CONFIG_CBS_VP9) += cbs_vp9.o +OBJS-$(CONFIG_D3D12VA_ENCODE) += d3d12va_encode.o hw_base_encode.o OBJS-$(CONFIG_DEFLATE_WRAPPER) += zlib_wrapper.o OBJS-$(CONFIG_DOVI_RPUDEC) += dovi_rpu.o dovi_rpudec.o OBJS-$(CONFIG_DOVI_RPUENC) += dovi_rpu.o dovi_rpuenc.o @@ -436,6 +437,8 @@ OBJS-$(CONFIG_HEVC_DECODER)+= hevcdec.o hevc_mvs.o \ h274.o aom_film_grain.o OBJS-$(CONFIG_HEVC_AMF_ENCODER)+= amfenc_hevc.o OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o +OBJS-$(CONFIG_HEVC_D3D12VA_ENCODER)+= d3d12va_encode_hevc.o h265_profile_level.o \ + h2645data.o OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_HEVC_MEDIACODEC_ENCODER) += mediacodecenc.o OBJS-$(CONFIG_HEVC_MF_ENCODER) += mfenc.o mf_utils.o @@ -1265,7 +1268,7 @@ SKIPHEADERS+= %_tablegen.h \ SKIPHEADERS-$(CONFIG_AMF) += amfenc.h SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h -SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h +SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h d3d12va_encode.h SKIPHEADERS-$(CONFIG_DXVA2)+= dxva2.h dxva2_internal.h SKIPHEADERS-$(CONFIG_JNI) += ffjni.h SKIPHEADERS-$(CONFIG_LCMS2)+= fflcms2.h diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index b102a8069e..463ffbbd08 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -848,6 +848,7 @@ extern const FFCodec ff_h264_vaapi_encoder; extern const FFCodec ff_h264_videotoolbox_encoder; extern const FFCodec ff_hevc_amf_encoder; extern const FFCodec ff_hevc_cuvid_decoder; +extern const FFCodec ff_hevc_d3d12va_encoder; extern const FFCodec ff_hevc_mediacodec_decoder; extern const FFCodec ff_hevc_mediacodec_encoder; extern const FFCodec ff_hevc_mf_encoder; diff --git a/libavcodec/d3d12va_encode.c b/libavcodec/d3d12va_encode.c new file mode 100644 index 00..0fbf8eb07c --- /
[FFmpeg-devel] [PATCH v12 07/15] avcodec/vaapi_encode: extract the init and close function to base layer
From: Tong Wu Related parameters such as device context, frame context are also moved to base layer. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 49 ++ libavcodec/hw_base_encode.h | 17 +++ libavcodec/vaapi_encode.c | 90 +++-- libavcodec/vaapi_encode.h | 10 libavcodec/vaapi_encode_av1.c | 2 +- libavcodec/vaapi_encode_h264.c | 2 +- libavcodec/vaapi_encode_h265.c | 2 +- libavcodec/vaapi_encode_mjpeg.c | 6 ++- 8 files changed, 102 insertions(+), 76 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 16afaa37be..c4789380b6 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -592,3 +592,52 @@ end: return 0; } + +int ff_hw_base_encode_init(AVCodecContext *avctx) +{ +FFHWBaseEncodeContext *ctx = avctx->priv_data; + +ctx->frame = av_frame_alloc(); +if (!ctx->frame) +return AVERROR(ENOMEM); + +if (!avctx->hw_frames_ctx) { +av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is " + "required to associate the encoding device.\n"); +return AVERROR(EINVAL); +} + +ctx->input_frames_ref = av_buffer_ref(avctx->hw_frames_ctx); +if (!ctx->input_frames_ref) +return AVERROR(ENOMEM); + +ctx->input_frames = (AVHWFramesContext *)ctx->input_frames_ref->data; + +ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref); +if (!ctx->device_ref) +return AVERROR(ENOMEM); + +ctx->device = (AVHWDeviceContext *)ctx->device_ref->data; + +ctx->tail_pkt = av_packet_alloc(); +if (!ctx->tail_pkt) +return AVERROR(ENOMEM); + +return 0; +} + +int ff_hw_base_encode_close(AVCodecContext *avctx) +{ +FFHWBaseEncodeContext *ctx = avctx->priv_data; + +av_fifo_freep2(&ctx->encode_fifo); + +av_frame_free(&ctx->frame); +av_packet_free(&ctx->tail_pkt); + +av_buffer_unref(&ctx->device_ref); +av_buffer_unref(&ctx->input_frames_ref); +av_buffer_unref(&ctx->recon_frames_ref); + +return 0; +} diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 81e6c87036..a062009860 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -19,6 +19,7 @@ #ifndef AVCODEC_HW_BASE_ENCODE_H #define AVCODEC_HW_BASE_ENCODE_H +#include "libavutil/hwcontext.h" #include "libavutil/fifo.h" #define MAX_DPB_SIZE 16 @@ -119,6 +120,18 @@ typedef struct FFHWBaseEncodeContext { // Hardware-specific hooks. const struct FFHWEncodePictureOperation *op; +// The hardware device context. +AVBufferRef*device_ref; +AVHWDeviceContext *device; + +// The hardware frame context containing the input frames. +AVBufferRef*input_frames_ref; +AVHWFramesContext *input_frames; + +// The hardware frame context containing the reconstructed frames. +AVBufferRef*recon_frames_ref; +AVHWFramesContext *recon_frames; + // Current encoding window, in display (input) order. FFHWBaseEncodePicture *pic_start, *pic_end; // The next picture to use as the previous reference picture in @@ -185,6 +198,10 @@ typedef struct FFHWBaseEncodeContext { int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); +int ff_hw_base_encode_init(AVCodecContext *avctx); + +int ff_hw_base_encode_close(AVCodecContext *avctx); + #define HW_BASE_ENCODE_COMMON_OPTIONS \ { "async_depth", "Maximum processing parallelism. " \ "Increase this to improve single channel performance.", \ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 1055fca0b1..1b3bab2c14 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -314,7 +314,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Input surface is %#x.\n", pic->input_surface); -err = av_hwframe_get_buffer(ctx->recon_frames_ref, base_pic->recon_image, 0); +err = av_hwframe_get_buffer(base_ctx->recon_frames_ref, base_pic->recon_image, 0); if (err < 0) { err = AVERROR(ENOMEM); goto fail; @@ -996,9 +996,10 @@ static const VAEntrypoint vaapi_encode_entrypoints_low_power[] = { static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx) { -VAAPIEncodeContext *ctx = avctx->priv_data; -VAProfile*va_profiles= NULL; -VAEntrypoint *va_entrypoints = NULL; +FFHWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; +VAProfile *va_profiles= NULL; +VAEntrypoint*va_entrypoints = NULL; VAStatus vas; const VAEntrypoint *usable_entrypoints; const VAAPIEncodeProfile *profile; @@ -1021,10 +1022,10 @@ static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx) usable_entrypoints = vaapi_encode_entrypoints_normal; } -desc = av_pix_fmt_desc_get(ctx->input_frame
[FFmpeg-devel] [PATCH v12 14/15] Changelog: add D3D12VA HEVC encoder changelog
From: Tong Wu Signed-off-by: Tong Wu --- Changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 12770e4296..c5d57b3813 100644 --- a/Changelog +++ b/Changelog @@ -11,7 +11,7 @@ version : - vf_scale2ref deprecated - qsv_params option added for QSV encoders - VVC decoder compatible with DVB test content - +- D3D12VA HEVC encoder version 7.0: - DXV DXT1 encoder -- 2.41.0.windows.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 v12 15/15] avcodec/hw_base_encode: add avctx pointer for FFHWBaseEncodeContext
From: Tong Wu An avctx pointer is added to FFHWBaseEncodeContext. This is to make FFHWBaseEncodeContext a standalone component for ff_hw_base_* functions. This patch also removes some unnecessary AVCodecContext arguments. Signed-off-by: Tong Wu --- libavcodec/d3d12va_encode.c | 6 +++--- libavcodec/hw_base_encode.c | 31 +-- libavcodec/hw_base_encode.h | 8 +--- libavcodec/vaapi_encode.c | 6 +++--- 4 files changed, 24 insertions(+), 27 deletions(-) diff --git a/libavcodec/d3d12va_encode.c b/libavcodec/d3d12va_encode.c index 0fbf8eb07c..6d3a53c6ca 100644 --- a/libavcodec/d3d12va_encode.c +++ b/libavcodec/d3d12va_encode.c @@ -1351,7 +1351,7 @@ static int d3d12va_encode_create_recon_frames(AVCodecContext *avctx) enum AVPixelFormat recon_format; int err; -err = ff_hw_base_get_recon_format(avctx, NULL, &recon_format); +err = ff_hw_base_get_recon_format(base_ctx, NULL, &recon_format); if (err < 0) return err; @@ -1398,7 +1398,7 @@ int ff_d3d12va_encode_init(AVCodecContext *avctx) int err; HRESULT hr; -err = ff_hw_base_encode_init(avctx); +err = ff_hw_base_encode_init(avctx, base_ctx); if (err < 0) goto fail; @@ -1552,7 +1552,7 @@ int ff_d3d12va_encode_close(AVCodecContext *avctx) D3D12_OBJECT_RELEASE(ctx->video_device3); D3D12_OBJECT_RELEASE(ctx->device3); -ff_hw_base_encode_close(avctx); +ff_hw_base_encode_close(base_ctx); return 0; } diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 92f69bb78c..88efdf672c 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -94,14 +94,13 @@ static void hw_base_encode_remove_refs(FFHWBaseEncodePicture *pic, int level) pic->ref_removed[level] = 1; } -static void hw_base_encode_set_b_pictures(AVCodecContext *avctx, +static void hw_base_encode_set_b_pictures(FFHWBaseEncodeContext *ctx, FFHWBaseEncodePicture *start, FFHWBaseEncodePicture *end, FFHWBaseEncodePicture *prev, int current_depth, FFHWBaseEncodePicture **last) { -FFHWBaseEncodeContext *ctx = avctx->priv_data; FFHWBaseEncodePicture *pic, *next, *ref; int i, len; @@ -148,20 +147,19 @@ static void hw_base_encode_set_b_pictures(AVCodecContext *avctx, hw_base_encode_add_ref(pic, ref, 0, 1, 0); if (i > 1) -hw_base_encode_set_b_pictures(avctx, start, pic, pic, +hw_base_encode_set_b_pictures(ctx, start, pic, pic, current_depth + 1, &next); else next = pic; -hw_base_encode_set_b_pictures(avctx, pic, end, next, +hw_base_encode_set_b_pictures(ctx, pic, end, next, current_depth + 1, last); } } -static void hw_base_encode_add_next_prev(AVCodecContext *avctx, +static void hw_base_encode_add_next_prev(FFHWBaseEncodeContext *ctx, FFHWBaseEncodePicture *pic) { -FFHWBaseEncodeContext *ctx = avctx->priv_data; int i; if (!pic) @@ -333,12 +331,12 @@ static int hw_base_encode_pick_next(AVCodecContext *avctx, } if (b_counter > 0) { -hw_base_encode_set_b_pictures(avctx, start, pic, pic, 1, +hw_base_encode_set_b_pictures(ctx, start, pic, pic, 1, &prev); } else { prev = pic; } -hw_base_encode_add_next_prev(avctx, prev); +hw_base_encode_add_next_prev(ctx, prev); return 0; } @@ -687,9 +685,9 @@ int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32 return 0; } -int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt) +int ff_hw_base_get_recon_format(FFHWBaseEncodeContext *ctx, const void *hwconfig, +enum AVPixelFormat *fmt) { -FFHWBaseEncodeContext *ctx = avctx->priv_data; AVHWFramesConstraints *constraints = NULL; enum AVPixelFormat recon_format; int err, i; @@ -722,14 +720,14 @@ int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enu // No idea what to use; copy input format. recon_format = ctx->input_frames->sw_format; } -av_log(avctx, AV_LOG_DEBUG, "Using %s as format of " +av_log(ctx->avctx, AV_LOG_DEBUG, "Using %s as format of " "reconstructed frames.\n", av_get_pix_fmt_name(recon_format)); if (ctx->surface_width < constraints->min_width || ctx->surface_height < constraints->min_height || ctx->surface_width > constraints->max_width || ctx->surface_height > constraints->max_height) { -av_log(avctx, AV_LOG_ERROR, "Hardware does not support
[FFmpeg-devel] [PATCH v13 01/15] avcodec/vaapi_encode: introduce a base layer for vaapi encode
From: Tong Wu Since VAAPI and future D3D12VA implementation may share some common parameters, a base layer encode context is introduced as vaapi context's base. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 56 + libavcodec/vaapi_encode.h | 39 +- 2 files changed, 63 insertions(+), 32 deletions(-) create mode 100644 libavcodec/hw_base_encode.h diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h new file mode 100644 index 00..ffcb6bcbb2 --- /dev/null +++ b/libavcodec/hw_base_encode.h @@ -0,0 +1,56 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_HW_BASE_ENCODE_H +#define AVCODEC_HW_BASE_ENCODE_H + +#define MAX_DPB_SIZE 16 +#define MAX_PICTURE_REFERENCES 2 +#define MAX_REORDER_DELAY 16 +#define MAX_ASYNC_DEPTH 64 +#define MAX_REFERENCE_LIST_NUM 2 + +enum { +PICTURE_TYPE_IDR = 0, +PICTURE_TYPE_I = 1, +PICTURE_TYPE_P = 2, +PICTURE_TYPE_B = 3, +}; + +enum { +// Codec supports controlling the subdivision of pictures into slices. +FLAG_SLICE_CONTROL = 1 << 0, +// Codec only supports constant quality (no rate control). +FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, +// Codec is intra-only. +FLAG_INTRA_ONLY= 1 << 2, +// Codec supports B-pictures. +FLAG_B_PICTURES= 1 << 3, +// Codec supports referencing B-pictures. +FLAG_B_PICTURE_REFERENCES = 1 << 4, +// Codec supports non-IDR key pictures (that is, key pictures do +// not necessarily empty the DPB). +FLAG_NON_IDR_KEY_PICTURES = 1 << 5, +}; + +typedef struct FFHWBaseEncodeContext { +const AVClass *class; +} FFHWBaseEncodeContext; + +#endif /* AVCODEC_HW_BASE_ENCODE_H */ + diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index 0eed9691ca..cae7af8725 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -33,34 +33,27 @@ #include "avcodec.h" #include "hwconfig.h" +#include "hw_base_encode.h" struct VAAPIEncodeType; struct VAAPIEncodePicture; +// Codec output packet without timestamp delay, which means the +// output packet has same PTS and DTS. +#define FLAG_TIMESTAMP_NO_DELAY 1 << 6 + enum { MAX_CONFIG_ATTRIBUTES = 4, MAX_GLOBAL_PARAMS = 4, -MAX_DPB_SIZE = 16, -MAX_PICTURE_REFERENCES = 2, -MAX_REORDER_DELAY = 16, MAX_PARAM_BUFFER_SIZE = 1024, // A.4.1: table A.6 allows at most 22 tile rows for any level. 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, -MAX_REFERENCE_LIST_NUM = 2, }; extern const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[]; -enum { -PICTURE_TYPE_IDR = 0, -PICTURE_TYPE_I = 1, -PICTURE_TYPE_P = 2, -PICTURE_TYPE_B = 3, -}; - typedef struct VAAPIEncodeSlice { int index; int row_start; @@ -193,7 +186,8 @@ typedef struct VAAPIEncodeRCMode { } VAAPIEncodeRCMode; typedef struct VAAPIEncodeContext { -const AVClass *class; +// Base context. +FFHWBaseEncodeContext base; // Codec-specific hooks. const struct VAAPIEncodeType *codec; @@ -397,25 +391,6 @@ typedef struct VAAPIEncodeContext { AVPacket*tail_pkt; } VAAPIEncodeContext; -enum { -// Codec supports controlling the subdivision of pictures into slices. -FLAG_SLICE_CONTROL = 1 << 0, -// Codec only supports constant quality (no rate control). -FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, -// Codec is intra-only. -FLAG_INTRA_ONLY= 1 << 2, -// Codec supports B-pictures. -FLAG_B_PICTURES= 1 << 3, -// Codec supports referencing B-pictures. -FLAG_B_PICTURE_REFERENCES = 1 << 4, -// Codec supports non-IDR key pictures (that is, key pictures do -// not necessarily empty the DPB). -FLAG_NON_IDR_KEY_PICTURES = 1 << 5, -// Codec output packet without timestamp delay, which means the -// output packet has same PTS and DTS. -FLAG_TIMESTAMP_NO_DELAY= 1 << 6, -}; - typedef struct VAAPIEncodeType { // List of supported profiles and corr
[FFmpeg-devel] [PATCH v13 02/15] avcodec/hw_base_encode: add FF_HW_ prefix for two enums
From: Tong Wu PICTURE_TYPE_* and FLAG_* are added FF_HW_ prefix after being moved to base layer. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 20 ++--- libavcodec/vaapi_encode.c | 50 - libavcodec/vaapi_encode_av1.c | 12 libavcodec/vaapi_encode_h264.c | 50 - libavcodec/vaapi_encode_h265.c | 44 ++--- libavcodec/vaapi_encode_mjpeg.c | 6 ++-- libavcodec/vaapi_encode_mpeg2.c | 30 ++-- libavcodec/vaapi_encode_vp8.c | 10 +++ libavcodec/vaapi_encode_vp9.c | 16 +-- 9 files changed, 119 insertions(+), 119 deletions(-) diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index ffcb6bcbb2..f3c9f32977 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -26,26 +26,26 @@ #define MAX_REFERENCE_LIST_NUM 2 enum { -PICTURE_TYPE_IDR = 0, -PICTURE_TYPE_I = 1, -PICTURE_TYPE_P = 2, -PICTURE_TYPE_B = 3, +FF_HW_PICTURE_TYPE_IDR = 0, +FF_HW_PICTURE_TYPE_I = 1, +FF_HW_PICTURE_TYPE_P = 2, +FF_HW_PICTURE_TYPE_B = 3, }; enum { // Codec supports controlling the subdivision of pictures into slices. -FLAG_SLICE_CONTROL = 1 << 0, +FF_HW_FLAG_SLICE_CONTROL = 1 << 0, // Codec only supports constant quality (no rate control). -FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, +FF_HW_FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, // Codec is intra-only. -FLAG_INTRA_ONLY= 1 << 2, +FF_HW_FLAG_INTRA_ONLY= 1 << 2, // Codec supports B-pictures. -FLAG_B_PICTURES= 1 << 3, +FF_HW_FLAG_B_PICTURES= 1 << 3, // Codec supports referencing B-pictures. -FLAG_B_PICTURE_REFERENCES = 1 << 4, +FF_HW_FLAG_B_PICTURE_REFERENCES = 1 << 4, // Codec supports non-IDR key pictures (that is, key pictures do // not necessarily empty the DPB). -FLAG_NON_IDR_KEY_PICTURES = 1 << 5, +FF_HW_FLAG_NON_IDR_KEY_PICTURES = 1 << 5, }; typedef struct FFHWBaseEncodeContext { diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index f54b2579ec..3c3d6a37c7 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -345,7 +345,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, pic->nb_param_buffers = 0; -if (pic->type == PICTURE_TYPE_IDR && ctx->codec->init_sequence_params) { +if (pic->type == FF_HW_PICTURE_TYPE_IDR && ctx->codec->init_sequence_params) { err = vaapi_encode_make_param_buffer(avctx, pic, VAEncSequenceParameterBufferType, ctx->codec_sequence_params, @@ -354,7 +354,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, goto fail; } -if (pic->type == PICTURE_TYPE_IDR) { +if (pic->type == FF_HW_PICTURE_TYPE_IDR) { for (i = 0; i < ctx->nb_global_params; i++) { err = vaapi_encode_make_misc_param_buffer(avctx, pic, ctx->global_params_type[i], @@ -391,7 +391,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, } #endif -if (pic->type == PICTURE_TYPE_IDR) { +if (pic->type == FF_HW_PICTURE_TYPE_IDR) { if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE && ctx->codec->write_sequence_header) { bit_len = 8 * sizeof(data); @@ -671,7 +671,7 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, { VAAPIEncodeContext *ctx = avctx->priv_data; -if (pic->type == PICTURE_TYPE_IDR) +if (pic->type == FF_HW_PICTURE_TYPE_IDR) pkt->flags |= AV_PKT_FLAG_KEY; pkt->pts = pic->pts; @@ -996,7 +996,7 @@ static void vaapi_encode_remove_refs(AVCodecContext *avctx, av_assert0(pic->dpb[i]->ref_count[level] >= 0); } -av_assert0(pic->prev || pic->type == PICTURE_TYPE_IDR); +av_assert0(pic->prev || pic->type == FF_HW_PICTURE_TYPE_IDR); if (pic->prev) { --pic->prev->ref_count[level]; av_assert0(pic->prev->ref_count[level] >= 0); @@ -1025,7 +1025,7 @@ static void vaapi_encode_set_b_pictures(AVCodecContext *avctx, for (pic = start->next; pic; pic = pic->next) { if (pic == end) break; -pic->type= PICTURE_TYPE_B; +pic->type= FF_HW_PICTURE_TYPE_B; pic->b_depth = current_depth; vaapi_encode_add_ref(avctx, pic, start, 1, 1, 0); @@ -1045,7 +1045,7 @@ static void vaapi_encode_set_b_pictures(AVCodecContext *avctx, ++len; for (pic = start->next, i = 1; 2 * i < len; pic = pic->next, i++); -pic->type= PICTURE_TYPE_B; +pic->type= FF_HW_PICTURE_TYPE_B; pic->b_depth = current_depth; pic->is_reference = 1; @@ -1078,7 +1078,7 @@ static void vaapi_enco
[FFmpeg-devel] [PATCH v13 03/15] avcodec/vaapi_encode: add async_depth to common options
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 10 +- libavcodec/vaapi_encode.c | 13 - libavcodec/vaapi_encode.h | 7 --- libavcodec/vaapi_encode_av1.c | 1 + libavcodec/vaapi_encode_h264.c | 1 + libavcodec/vaapi_encode_h265.c | 1 + libavcodec/vaapi_encode_mjpeg.c | 1 + libavcodec/vaapi_encode_mpeg2.c | 1 + libavcodec/vaapi_encode_vp8.c | 1 + libavcodec/vaapi_encode_vp9.c | 1 + 10 files changed, 24 insertions(+), 13 deletions(-) diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index f3c9f32977..c14c174102 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -50,7 +50,15 @@ enum { typedef struct FFHWBaseEncodeContext { const AVClass *class; + +// Max number of frame buffered in encoder. +int async_depth; } FFHWBaseEncodeContext; -#endif /* AVCODEC_HW_BASE_ENCODE_H */ +#define HW_BASE_ENCODE_COMMON_OPTIONS \ +{ "async_depth", "Maximum processing parallelism. " \ + "Increase this to improve single channel performance.", \ + OFFSET(common.base.async_depth), AV_OPT_TYPE_INT, \ + { .i64 = 2 }, 1, MAX_ASYNC_DEPTH, FLAGS } +#endif /* AVCODEC_HW_BASE_ENCODE_H */ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 3c3d6a37c7..77f539dc6d 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -669,7 +669,8 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, VAAPIEncodePicture *pic, AVPacket *pkt) { -VAAPIEncodeContext *ctx = avctx->priv_data; +FFHWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; if (pic->type == FF_HW_PICTURE_TYPE_IDR) pkt->flags |= AV_PKT_FLAG_KEY; @@ -699,7 +700,7 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, 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 + ctx->async_depth)]; +(3 * ctx->output_delay + base_ctx->async_depth)]; } return 0; @@ -1320,6 +1321,7 @@ static int vaapi_encode_check_frame(AVCodecContext *avctx, static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) { +FFHWBaseEncodeContext *base_ctx = avctx->priv_data; VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic; int err; @@ -1365,7 +1367,7 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) ctx->dts_pts_diff = pic->pts - ctx->first_pts; if (ctx->output_delay > 0) ctx->ts_ring[ctx->input_order % -(3 * ctx->output_delay + ctx->async_depth)] = pic->pts; +(3 * ctx->output_delay + base_ctx->async_depth)] = pic->pts; pic->display_order = ctx->input_order; ++ctx->input_order; @@ -2773,7 +2775,8 @@ static av_cold int vaapi_encode_create_recon_frames(AVCodecContext *avctx) av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) { -VAAPIEncodeContext *ctx = avctx->priv_data; +FFHWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; AVVAAPIFramesContext *recon_hwctx = NULL; VAStatus vas; int err; @@ -2966,7 +2969,7 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) vas = vaSyncBuffer(ctx->hwctx->display, VA_INVALID_ID, 0); if (vas != VA_STATUS_ERROR_UNIMPLEMENTED) { ctx->has_sync_buffer_func = 1; -ctx->encode_fifo = av_fifo_alloc2(ctx->async_depth, +ctx->encode_fifo = av_fifo_alloc2(base_ctx->async_depth, sizeof(VAAPIEncodePicture *), 0); if (!ctx->encode_fifo) diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index cae7af8725..9fdb945b18 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -374,8 +374,6 @@ typedef struct VAAPIEncodeContext { int has_sync_buffer_func; // Store buffered pic AVFifo *encode_fifo; -// Max number of frame buffered in encoder. -int async_depth; /** Head data for current output pkt, used only for AV1. */ //void *header_data; @@ -491,11 +489,6 @@ int ff_vaapi_encode_close(AVCodecContext *avctx); "Maximum B-frame reference depth", \ OFFSET(common.desired_b_depth), AV_OPT_TYPE_INT, \ { .i64 = 1 }, 1, INT_MAX, FLAGS }, \ -{ "async_depth", "Maximum processing parallelism. " \ - "Increase this to improve single channel performance. This option " \ - "doesn't work if driver doesn't implement vaSyncBuffer function.", \ - OFFSET(co
[FFmpeg-devel] [PATCH v13 04/15] avcodec/vaapi_encode: add picture type name to base
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 6 ++ libavcodec/vaapi_encode.c | 4 +--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index c14c174102..858450afa8 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -25,6 +25,12 @@ #define MAX_ASYNC_DEPTH 64 #define MAX_REFERENCE_LIST_NUM 2 +static inline const char *ff_hw_base_encode_get_pictype_name(const int type) +{ +const char * const picture_type_name[] = { "IDR", "I", "P", "B" }; +return picture_type_name[type]; +} + enum { FF_HW_PICTURE_TYPE_IDR = 0, FF_HW_PICTURE_TYPE_I = 1, diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 77f539dc6d..54bdd73902 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -38,8 +38,6 @@ const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[] = { NULL, }; -static const char * const picture_type_name[] = { "IDR", "I", "P", "B" }; - static int vaapi_encode_make_packed_header(AVCodecContext *avctx, VAAPIEncodePicture *pic, int type, char *data, size_t bit_len) @@ -277,7 +275,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Issuing encode for pic %"PRId64"/%"PRId64" " "as type %s.\n", pic->display_order, pic->encode_order, - picture_type_name[pic->type]); + ff_hw_base_encode_get_pictype_name(pic->type)); if (pic->nb_refs[0] == 0 && pic->nb_refs[1] == 0) { av_log(avctx, AV_LOG_DEBUG, "No reference pictures.\n"); } else { -- 2.41.0.windows.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 v13 05/15] avcodec/vaapi_encode: move pic->input_surface initialization to encode_alloc
From: Tong Wu When allocating the VAAPIEncodePicture, pic->input_surface can be initialized right in the place. This movement simplifies the send_frame logic and is the preparation for moving vaapi_encode_send_frame to the base layer. Signed-off-by: Tong Wu --- libavcodec/vaapi_encode.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 54bdd73902..194422b36d 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -878,7 +878,8 @@ static int vaapi_encode_discard(AVCodecContext *avctx, return 0; } -static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx) +static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx, + const AVFrame *frame) { VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic; @@ -895,7 +896,7 @@ static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx) } } -pic->input_surface = VA_INVALID_ID; +pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; pic->recon_surface = VA_INVALID_ID; pic->output_buffer = VA_INVALID_ID; @@ -1332,7 +1333,7 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) if (err < 0) return err; -pic = vaapi_encode_alloc(avctx); +pic = vaapi_encode_alloc(avctx, frame); if (!pic) return AVERROR(ENOMEM); @@ -1345,7 +1346,6 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) if (ctx->input_order == 0 || frame->pict_type == AV_PICTURE_TYPE_I) pic->force_idr = 1; -pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; pic->pts = frame->pts; pic->duration = frame->duration; -- 2.41.0.windows.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 v13 06/15] avcodec/vaapi_encode: move the dpb logic from VAAPI to base layer
From: Tong Wu Move receive_packet function to base. This requires adding *alloc, *issue, *output, *free as hardware callbacks. HWBaseEncodePicture is introduced as the base layer structure. The related parameters in VAAPIEncodeContext are also extracted to HWBaseEncodeContext. Then DPB management logic can be fully extracted to base layer as-is. Signed-off-by: Tong Wu --- libavcodec/Makefile | 2 +- libavcodec/hw_base_encode.c | 594 libavcodec/hw_base_encode.h | 124 + libavcodec/vaapi_encode.c | 793 +--- libavcodec/vaapi_encode.h | 102 +--- libavcodec/vaapi_encode_av1.c | 35 +- libavcodec/vaapi_encode_h264.c | 84 ++-- libavcodec/vaapi_encode_h265.c | 53 ++- libavcodec/vaapi_encode_mjpeg.c | 13 +- libavcodec/vaapi_encode_mpeg2.c | 33 +- libavcodec/vaapi_encode_vp8.c | 18 +- libavcodec/vaapi_encode_vp9.c | 24 +- 12 files changed, 985 insertions(+), 890 deletions(-) create mode 100644 libavcodec/hw_base_encode.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2443d2c6fd..998f6b7e12 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -165,7 +165,7 @@ OBJS-$(CONFIG_STARTCODE) += startcode.o OBJS-$(CONFIG_TEXTUREDSP) += texturedsp.o OBJS-$(CONFIG_TEXTUREDSPENC) += texturedspenc.o OBJS-$(CONFIG_TPELDSP) += tpeldsp.o -OBJS-$(CONFIG_VAAPI_ENCODE)+= vaapi_encode.o +OBJS-$(CONFIG_VAAPI_ENCODE)+= vaapi_encode.o hw_base_encode.o OBJS-$(CONFIG_AV1_AMF_ENCODER) += amfenc_av1.o OBJS-$(CONFIG_VC1DSP) += vc1dsp.o OBJS-$(CONFIG_VIDEODSP)+= videodsp.o diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c new file mode 100644 index 00..16afaa37be --- /dev/null +++ b/libavcodec/hw_base_encode.c @@ -0,0 +1,594 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" + +#include "encode.h" +#include "avcodec.h" +#include "hw_base_encode.h" + +static void hw_base_encode_add_ref(FFHWBaseEncodePicture *pic, + FFHWBaseEncodePicture *target, + int is_ref, int in_dpb, int prev) +{ +int refs = 0; + +if (is_ref) { +av_assert0(pic != target); +av_assert0(pic->nb_refs[0] < MAX_PICTURE_REFERENCES && + pic->nb_refs[1] < MAX_PICTURE_REFERENCES); +if (target->display_order < pic->display_order) +pic->refs[0][pic->nb_refs[0]++] = target; +else +pic->refs[1][pic->nb_refs[1]++] = target; +++refs; +} + +if (in_dpb) { +av_assert0(pic->nb_dpb_pics < MAX_DPB_SIZE); +pic->dpb[pic->nb_dpb_pics++] = target; +++refs; +} + +if (prev) { +av_assert0(!pic->prev); +pic->prev = target; +++refs; +} + +target->ref_count[0] += refs; +target->ref_count[1] += refs; +} + +static void hw_base_encode_remove_refs(FFHWBaseEncodePicture *pic, int level) +{ +int i; + +if (pic->ref_removed[level]) +return; + +for (i = 0; i < pic->nb_refs[0]; i++) { +av_assert0(pic->refs[0][i]); +--pic->refs[0][i]->ref_count[level]; +av_assert0(pic->refs[0][i]->ref_count[level] >= 0); +} + +for (i = 0; i < pic->nb_refs[1]; i++) { +av_assert0(pic->refs[1][i]); +--pic->refs[1][i]->ref_count[level]; +av_assert0(pic->refs[1][i]->ref_count[level] >= 0); +} + +for (i = 0; i < pic->nb_dpb_pics; i++) { +av_assert0(pic->dpb[i]); +--pic->dpb[i]->ref_count[level]; +av_assert0(pic->dpb[i]->ref_count[level] >= 0); +} + +av_assert0(pic->prev || pic->type == FF_HW_PICTURE_TYPE_IDR); +if (pic->prev) { +--pic->prev->ref_count[level]; +av_assert0(pic->prev->ref_count[level] >= 0); +} + +pic->ref_removed[level] = 1; +} + +static void hw_base_encode_set_b_pictures(AVCodecContext *avctx, + FFHWBaseEncodePicture *st
[FFmpeg-devel] [PATCH v13 09/15] avcodec/vaapi_encode: extract set_output_property to base layer
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 40 + libavcodec/hw_base_encode.h | 3 +++ libavcodec/vaapi_encode.c | 44 ++--- 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 56dc015e2e..25fcfdbb5e 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -488,6 +488,46 @@ fail: return err; } +int ff_hw_base_encode_set_output_property(AVCodecContext *avctx, + FFHWBaseEncodePicture *pic, + AVPacket *pkt, int flag_no_delay) +{ +FFHWBaseEncodeContext *ctx = avctx->priv_data; + +if (pic->type == FF_HW_PICTURE_TYPE_IDR) +pkt->flags |= AV_PKT_FLAG_KEY; + +pkt->pts = pic->pts; +pkt->duration = pic->duration; + +// for no-delay encoders this is handled in generic codec +if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY && +avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { +pkt->opaque = pic->opaque; +pkt->opaque_ref = pic->opaque_ref; +pic->opaque_ref = NULL; +} + +if (flag_no_delay) { +pkt->dts = pkt->pts; +return 0; +} + +if (ctx->output_delay == 0) { +pkt->dts = pkt->pts; +} else if (pic->encode_order < ctx->decode_delay) { +if (ctx->ts_ring[pic->encode_order] < INT64_MIN + ctx->dts_pts_diff) +pkt->dts = INT64_MIN; +else +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 + ctx->async_depth)]; +} + +return 0; +} + int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) { FFHWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index c7e535d35d..f097d826a7 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -204,6 +204,9 @@ typedef struct FFHWBaseEncodeContext { AVPacket*tail_pkt; } FFHWBaseEncodeContext; +int ff_hw_base_encode_set_output_property(AVCodecContext *avctx, FFHWBaseEncodePicture *pic, + AVPacket *pkt, int flag_no_delay); + int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index c29493e2c8..4193f3838f 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -660,47 +660,6 @@ fail_at_end: return err; } -static int vaapi_encode_set_output_property(AVCodecContext *avctx, -FFHWBaseEncodePicture *pic, -AVPacket *pkt) -{ -FFHWBaseEncodeContext *base_ctx = avctx->priv_data; -VAAPIEncodeContext *ctx = avctx->priv_data; - -if (pic->type == FF_HW_PICTURE_TYPE_IDR) -pkt->flags |= AV_PKT_FLAG_KEY; - -pkt->pts = pic->pts; -pkt->duration = pic->duration; - -// for no-delay encoders this is handled in generic codec -if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY && -avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { -pkt->opaque = pic->opaque; -pkt->opaque_ref = pic->opaque_ref; -pic->opaque_ref = NULL; -} - -if (ctx->codec->flags & FLAG_TIMESTAMP_NO_DELAY) { -pkt->dts = pkt->pts; -return 0; -} - -if (base_ctx->output_delay == 0) { -pkt->dts = pkt->pts; -} else if (pic->encode_order < base_ctx->decode_delay) { -if (base_ctx->ts_ring[pic->encode_order] < INT64_MIN + base_ctx->dts_pts_diff) -pkt->dts = INT64_MIN; -else -pkt->dts = base_ctx->ts_ring[pic->encode_order] - base_ctx->dts_pts_diff; -} else { -pkt->dts = base_ctx->ts_ring[(pic->encode_order - base_ctx->decode_delay) % - (3 * base_ctx->output_delay + base_ctx->async_depth)]; -} - -return 0; -} - static int vaapi_encode_get_coded_buffer_size(AVCodecContext *avctx, VABufferID buf_id) { VAAPIEncodeContext *ctx = avctx->priv_data; @@ -852,7 +811,8 @@ static int vaapi_encode_output(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n", base_pic->display_order, base_pic->encode_order); -vaapi_encode_set_output_property(avctx, (FFHWBaseEncodePicture*)pic, pkt_ptr); +ff_hw_base_encode_set_output_property(avctx, (FFHWBaseEncodePicture*)base_pic, pkt_ptr, + ctx->codec->flags & FLAG_TIMESTAMP_NO_DELAY); end: ff_refstruct_unref(&pic->output_buffer_ref); -- 2.41.
[FFmpeg-devel] [PATCH v13 07/15] avcodec/vaapi_encode: extract the init and close function to base layer
From: Tong Wu Related parameters such as device context, frame context are also moved to base layer. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 49 ++ libavcodec/hw_base_encode.h | 17 +++ libavcodec/vaapi_encode.c | 90 +++-- libavcodec/vaapi_encode.h | 10 libavcodec/vaapi_encode_av1.c | 2 +- libavcodec/vaapi_encode_h264.c | 2 +- libavcodec/vaapi_encode_h265.c | 2 +- libavcodec/vaapi_encode_mjpeg.c | 6 ++- 8 files changed, 102 insertions(+), 76 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 16afaa37be..c4789380b6 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -592,3 +592,52 @@ end: return 0; } + +int ff_hw_base_encode_init(AVCodecContext *avctx) +{ +FFHWBaseEncodeContext *ctx = avctx->priv_data; + +ctx->frame = av_frame_alloc(); +if (!ctx->frame) +return AVERROR(ENOMEM); + +if (!avctx->hw_frames_ctx) { +av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is " + "required to associate the encoding device.\n"); +return AVERROR(EINVAL); +} + +ctx->input_frames_ref = av_buffer_ref(avctx->hw_frames_ctx); +if (!ctx->input_frames_ref) +return AVERROR(ENOMEM); + +ctx->input_frames = (AVHWFramesContext *)ctx->input_frames_ref->data; + +ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref); +if (!ctx->device_ref) +return AVERROR(ENOMEM); + +ctx->device = (AVHWDeviceContext *)ctx->device_ref->data; + +ctx->tail_pkt = av_packet_alloc(); +if (!ctx->tail_pkt) +return AVERROR(ENOMEM); + +return 0; +} + +int ff_hw_base_encode_close(AVCodecContext *avctx) +{ +FFHWBaseEncodeContext *ctx = avctx->priv_data; + +av_fifo_freep2(&ctx->encode_fifo); + +av_frame_free(&ctx->frame); +av_packet_free(&ctx->tail_pkt); + +av_buffer_unref(&ctx->device_ref); +av_buffer_unref(&ctx->input_frames_ref); +av_buffer_unref(&ctx->recon_frames_ref); + +return 0; +} diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 81e6c87036..a062009860 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -19,6 +19,7 @@ #ifndef AVCODEC_HW_BASE_ENCODE_H #define AVCODEC_HW_BASE_ENCODE_H +#include "libavutil/hwcontext.h" #include "libavutil/fifo.h" #define MAX_DPB_SIZE 16 @@ -119,6 +120,18 @@ typedef struct FFHWBaseEncodeContext { // Hardware-specific hooks. const struct FFHWEncodePictureOperation *op; +// The hardware device context. +AVBufferRef*device_ref; +AVHWDeviceContext *device; + +// The hardware frame context containing the input frames. +AVBufferRef*input_frames_ref; +AVHWFramesContext *input_frames; + +// The hardware frame context containing the reconstructed frames. +AVBufferRef*recon_frames_ref; +AVHWFramesContext *recon_frames; + // Current encoding window, in display (input) order. FFHWBaseEncodePicture *pic_start, *pic_end; // The next picture to use as the previous reference picture in @@ -185,6 +198,10 @@ typedef struct FFHWBaseEncodeContext { int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); +int ff_hw_base_encode_init(AVCodecContext *avctx); + +int ff_hw_base_encode_close(AVCodecContext *avctx); + #define HW_BASE_ENCODE_COMMON_OPTIONS \ { "async_depth", "Maximum processing parallelism. " \ "Increase this to improve single channel performance.", \ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 1055fca0b1..1b3bab2c14 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -314,7 +314,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Input surface is %#x.\n", pic->input_surface); -err = av_hwframe_get_buffer(ctx->recon_frames_ref, base_pic->recon_image, 0); +err = av_hwframe_get_buffer(base_ctx->recon_frames_ref, base_pic->recon_image, 0); if (err < 0) { err = AVERROR(ENOMEM); goto fail; @@ -996,9 +996,10 @@ static const VAEntrypoint vaapi_encode_entrypoints_low_power[] = { static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx) { -VAAPIEncodeContext *ctx = avctx->priv_data; -VAProfile*va_profiles= NULL; -VAEntrypoint *va_entrypoints = NULL; +FFHWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; +VAProfile *va_profiles= NULL; +VAEntrypoint*va_entrypoints = NULL; VAStatus vas; const VAEntrypoint *usable_entrypoints; const VAAPIEncodeProfile *profile; @@ -1021,10 +1022,10 @@ static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx) usable_entrypoints = vaapi_encode_entrypoints_normal; } -desc = av_pix_fmt_desc_get(ctx->input_frame
[FFmpeg-devel] [PATCH v13 10/15] avcodec/vaapi_encode: extract a get_recon_format function to base layer
From: Tong Wu Surface size and block size parameters are also moved to base layer. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 58 +++ libavcodec/hw_base_encode.h | 12 + libavcodec/vaapi_encode.c | 81 - libavcodec/vaapi_encode.h | 10 libavcodec/vaapi_encode_av1.c | 10 ++-- libavcodec/vaapi_encode_h264.c | 11 +++-- libavcodec/vaapi_encode_h265.c | 25 +- libavcodec/vaapi_encode_mjpeg.c | 5 +- libavcodec/vaapi_encode_vp9.c | 6 +-- 9 files changed, 118 insertions(+), 100 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 25fcfdbb5e..31046bd73e 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -687,6 +687,64 @@ int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32 return 0; } +int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt) +{ +FFHWBaseEncodeContext *ctx = avctx->priv_data; +AVHWFramesConstraints *constraints = NULL; +enum AVPixelFormat recon_format; +int err, i; + +constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref, + hwconfig); +if (!constraints) { +err = AVERROR(ENOMEM); +goto fail; +} + +// Probably we can use the input surface format as the surface format +// of the reconstructed frames. If not, we just pick the first (only?) +// format in the valid list and hope that it all works. +recon_format = AV_PIX_FMT_NONE; +if (constraints->valid_sw_formats) { +for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { +if (ctx->input_frames->sw_format == +constraints->valid_sw_formats[i]) { +recon_format = ctx->input_frames->sw_format; +break; +} +} +if (recon_format == AV_PIX_FMT_NONE) { +// No match. Just use the first in the supported list and +// hope for the best. +recon_format = constraints->valid_sw_formats[0]; +} +} else { +// No idea what to use; copy input format. +recon_format = ctx->input_frames->sw_format; +} +av_log(avctx, AV_LOG_DEBUG, "Using %s as format of " + "reconstructed frames.\n", av_get_pix_fmt_name(recon_format)); + +if (ctx->surface_width < constraints->min_width || +ctx->surface_height < constraints->min_height || +ctx->surface_width > constraints->max_width || +ctx->surface_height > constraints->max_height) { +av_log(avctx, AV_LOG_ERROR, "Hardware does not support encoding at " + "size %dx%d (constraints: width %d-%d height %d-%d).\n", + ctx->surface_width, ctx->surface_height, + constraints->min_width, constraints->max_width, + constraints->min_height, constraints->max_height); +err = AVERROR(EINVAL); +goto fail; +} + +*fmt = recon_format; +err = 0; +fail: +av_hwframe_constraints_free(&constraints); +return err; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { FFHWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index f097d826a7..f5414e2c28 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -128,6 +128,16 @@ typedef struct FFHWBaseEncodeContext { // Desired B frame reference depth. int desired_b_depth; +// The required size of surfaces. This is probably the input +// size (AVCodecContext.width|height) aligned up to whatever +// block size is required by the codec. +int surface_width; +int surface_height; + +// The block size for slice calculations. +int slice_block_width; +int slice_block_height; + // The hardware device context. AVBufferRef*device_ref; AVHWDeviceContext *device; @@ -212,6 +222,8 @@ int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, int flags, int prediction_pre_only); +int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 4193f3838f..d96f146b28 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1777,6 +1777,7 @@ static av_cold int vaapi_encode_init_tile_slice_structure(AVCodecContext *avctx, static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) { +FFHWBaseEncodeContext *base_ctx = a
[FFmpeg-devel] [PATCH v13 11/15] avcodec/vaapi_encode: extract a free funtion to base layer
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 11 +++ libavcodec/hw_base_encode.h | 2 ++ libavcodec/vaapi_encode.c | 6 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 31046bd73e..92f69bb78c 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -745,6 +745,17 @@ fail: return err; } +int ff_hw_base_encode_free(FFHWBaseEncodePicture *pic) +{ +av_frame_free(&pic->input_image); +av_frame_free(&pic->recon_image); + +av_buffer_unref(&pic->opaque_ref); +av_freep(&pic->priv_data); + +return 0; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { FFHWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index f5414e2c28..15ef3d7ac6 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -224,6 +224,8 @@ int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32 int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt); +int ff_hw_base_encode_free(FFHWBaseEncodePicture *pic); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index d96f146b28..b35a23e852 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -878,17 +878,13 @@ static int vaapi_encode_free(AVCodecContext *avctx, av_freep(&pic->slices[i].codec_slice_params); } -av_frame_free(&base_pic->input_image); -av_frame_free(&base_pic->recon_image); - -av_buffer_unref(&base_pic->opaque_ref); +ff_hw_base_encode_free(base_pic); av_freep(&pic->param_buffers); av_freep(&pic->slices); // Output buffer should already be destroyed. av_assert0(pic->output_buffer == VA_INVALID_ID); -av_freep(&base_pic->priv_data); av_freep(&pic->codec_picture_params); av_freep(&pic->roi); -- 2.41.0.windows.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 v13 08/15] avcodec/vaapi_encode: extract gop configuration and two options to base layer
From: Tong Wu idr_interval and desired_b_depth are moved to HW_BASE_ENCODE_COMMON_OPTIONS. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 54 + libavcodec/hw_base_encode.h | 19 + libavcodec/vaapi_encode.c | 52 +++ libavcodec/vaapi_encode.h | 16 --- 4 files changed, 77 insertions(+), 64 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index c4789380b6..56dc015e2e 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -593,6 +593,60 @@ end: return 0; } +int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, + int flags, int prediction_pre_only) +{ +FFHWBaseEncodeContext *ctx = avctx->priv_data; + +if (flags & FF_HW_FLAG_INTRA_ONLY || avctx->gop_size <= 1) { +av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n"); +ctx->gop_size = 1; +} else if (ref_l0 < 1) { +av_log(avctx, AV_LOG_ERROR, "Driver does not support any " + "reference frames.\n"); +return AVERROR(EINVAL); +} else if (!(flags & FF_HW_FLAG_B_PICTURES) || ref_l1 < 1 || + avctx->max_b_frames < 1 || prediction_pre_only) { +if (ctx->p_to_gpb) + av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " + "(supported references: %d / %d).\n", + ref_l0, ref_l1); +else +av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames " + "(supported references: %d / %d).\n", ref_l0, ref_l1); +ctx->gop_size = avctx->gop_size; +ctx->p_per_i = INT_MAX; +ctx->b_per_p = 0; +} else { + if (ctx->p_to_gpb) + av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " + "(supported references: %d / %d).\n", + ref_l0, ref_l1); + else + av_log(avctx, AV_LOG_VERBOSE, "Using intra, P- and B-frames " + "(supported references: %d / %d).\n", ref_l0, ref_l1); +ctx->gop_size = avctx->gop_size; +ctx->p_per_i = INT_MAX; +ctx->b_per_p = avctx->max_b_frames; +if (flags & FF_HW_FLAG_B_PICTURE_REFERENCES) { +ctx->max_b_depth = FFMIN(ctx->desired_b_depth, + av_log2(ctx->b_per_p) + 1); +} else { +ctx->max_b_depth = 1; +} +} + +if (flags & FF_HW_FLAG_NON_IDR_KEY_PICTURES) { +ctx->closed_gop = !!(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP); +ctx->gop_per_idr = ctx->idr_interval + 1; +} else { +ctx->closed_gop = 1; +ctx->gop_per_idr = 1; +} + +return 0; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { FFHWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index a062009860..c7e535d35d 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -120,6 +120,14 @@ typedef struct FFHWBaseEncodeContext { // Hardware-specific hooks. const struct FFHWEncodePictureOperation *op; +// Global options. + +// Number of I frames between IDR frames. +int idr_interval; + +// Desired B frame reference depth. +int desired_b_depth; + // The hardware device context. AVBufferRef*device_ref; AVHWDeviceContext *device; @@ -198,11 +206,22 @@ typedef struct FFHWBaseEncodeContext { int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); +int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, + int flags, int prediction_pre_only); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); #define HW_BASE_ENCODE_COMMON_OPTIONS \ +{ "idr_interval", \ + "Distance (in I-frames) between key frames", \ + OFFSET(common.base.idr_interval), AV_OPT_TYPE_INT, \ + { .i64 = 0 }, 0, INT_MAX, FLAGS }, \ +{ "b_depth", \ + "Maximum B-frame reference depth", \ + OFFSET(common.base.desired_b_depth), AV_OPT_TYPE_INT, \ + { .i64 = 1 }, 1, INT_MAX, FLAGS }, \ { "async_depth", "Maximum processing parallelism. " \ "Increase this to improve single channel performance.", \ OFFSET(common.base.async_depth), AV_OPT_TYPE_INT, \ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 1b3bab2c14..c29493e2c8 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1638,7 +1638,7 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) VAStatus vas; VAConfigAttrib attr = { VAConfigAttribEncMaxRefFrames }; uint32_t ref_l0, ref_l1; -int prediction_pre_only; +int prediction_pre_only, err; vas = vaGetConfigAttributes(ctx->hwctx-
[FFmpeg-devel] [PATCH v13 12/15] avutil/hwcontext_d3d12va: add Flags for resource creation
From: Tong Wu Flags field is added to support diffferent resource creation. Signed-off-by: Tong Wu --- doc/APIchanges| 3 +++ libavutil/hwcontext_d3d12va.c | 2 +- libavutil/hwcontext_d3d12va.h | 8 libavutil/version.h | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index e36a01336c..b54be3b0b0 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2024-03-07 API changes, most recent first: +2024-01-xx - xx - lavu 59.22.100 - hwcontext_d3d12va.h + Add AVD3D12VAFramesContext.flags + 2024-06-02 - xx - lavu 59.21.100 - channel_layout.h Add AV_CHAN_SIDE_SURROUND_RIGHT and AV_CH_SIDE_SURROUND_LEFT. Add AV_CHAN_SIDE_SURROUND_RIGHT and AV_CH_SIDE_SURROUND_RIGHT. diff --git a/libavutil/hwcontext_d3d12va.c b/libavutil/hwcontext_d3d12va.c index cfc016315d..6507cf69c1 100644 --- a/libavutil/hwcontext_d3d12va.c +++ b/libavutil/hwcontext_d3d12va.c @@ -247,7 +247,7 @@ static AVBufferRef *d3d12va_pool_alloc(void *opaque, size_t size) .Format = hwctx->format, .SampleDesc = {.Count = 1, .Quality = 0 }, .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, -.Flags= D3D12_RESOURCE_FLAG_NONE, +.Flags= hwctx->flags, }; frame = av_mallocz(sizeof(AVD3D12VAFrame)); diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h index ff06e6f2ef..212a6a6146 100644 --- a/libavutil/hwcontext_d3d12va.h +++ b/libavutil/hwcontext_d3d12va.h @@ -129,6 +129,14 @@ typedef struct AVD3D12VAFramesContext { * If unset, will be automatically set. */ DXGI_FORMAT format; + +/** + * Options for working with resources. + * If unset, this will be D3D12_RESOURCE_FLAG_NONE. + * + * @see https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_resource_flags + */ +D3D12_RESOURCE_FLAGS flags; } AVD3D12VAFramesContext; #endif /* AVUTIL_HWCONTEXT_D3D12VA_H */ diff --git a/libavutil/version.h b/libavutil/version.h index 9d08d56884..bd4c5a2ab3 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 59 -#define LIBAVUTIL_VERSION_MINOR 21 +#define LIBAVUTIL_VERSION_MINOR 22 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ -- 2.41.0.windows.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 v13 13/15] avcodec: add D3D12VA hardware HEVC encoder
From: Tong Wu This implementation is based on D3D12 Video Encoding Spec: https://microsoft.github.io/DirectX-Specs/d3d/D3D12VideoEncoding.html Sample command line for transcoding: ffmpeg.exe -hwaccel d3d12va -hwaccel_output_format d3d12 -i input.mp4 -c:v hevc_d3d12va output.mp4 Signed-off-by: Tong Wu --- configure|6 + libavcodec/Makefile |5 +- libavcodec/allcodecs.c |1 + libavcodec/d3d12va_encode.c | 1558 ++ libavcodec/d3d12va_encode.h | 334 +++ libavcodec/d3d12va_encode_hevc.c | 1007 +++ 6 files changed, 2910 insertions(+), 1 deletion(-) create mode 100644 libavcodec/d3d12va_encode.c create mode 100644 libavcodec/d3d12va_encode.h create mode 100644 libavcodec/d3d12va_encode_hevc.c diff --git a/configure b/configure index 6c5b8aab9a..a5e1c3fae4 100755 --- a/configure +++ b/configure @@ -2551,6 +2551,7 @@ CONFIG_EXTRA=" cbs_mpeg2 cbs_vp8 cbs_vp9 +d3d12va_encode deflate_wrapper dirac_parse dnn @@ -3287,6 +3288,7 @@ wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel" # hardware-accelerated codecs +d3d12va_encode_deps="d3d12va ID3D12VideoEncoder d3d12_encoder_feature" mediafoundation_deps="mftransform_h MFCreateAlignedMemoryBuffer" omx_deps="libdl pthreads" omx_rpi_select="omx" @@ -3354,6 +3356,7 @@ h264_v4l2m2m_encoder_deps="v4l2_m2m h264_v4l2_m2m" hevc_amf_encoder_deps="amf" hevc_cuvid_decoder_deps="cuvid" hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf" +hevc_d3d12va_encoder_select="cbs_h265 d3d12va_encode" hevc_mediacodec_decoder_deps="mediacodec" hevc_mediacodec_decoder_select="hevc_mp4toannexb_bsf hevc_parser" hevc_mediacodec_encoder_deps="mediacodec" @@ -6725,6 +6728,9 @@ check_type "windows.h d3d11.h" "ID3D11VideoDecoder" check_type "windows.h d3d11.h" "ID3D11VideoContext" check_type "windows.h d3d12.h" "ID3D12Device" check_type "windows.h d3d12video.h" "ID3D12VideoDecoder" +check_type "windows.h d3d12video.h" "ID3D12VideoEncoder" +test_code cc "windows.h d3d12video.h" "D3D12_FEATURE_VIDEO feature = D3D12_FEATURE_VIDEO_ENCODER_CODEC" && \ +test_code cc "windows.h d3d12video.h" "D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOURCE_REQUIREMENTS req" && enable d3d12_encoder_feature check_type "windows.h" "DPI_AWARENESS_CONTEXT" -D_WIN32_WINNT=0x0A00 check_type "d3d9.h dxva2api.h" DXVA2_ConfigPictureDecode -D_WIN32_WINNT=0x0602 check_func_headers mfapi.h MFCreateAlignedMemoryBuffer -lmfplat diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 998f6b7e12..6c4500ce6d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -86,6 +86,7 @@ OBJS-$(CONFIG_CBS_JPEG)+= cbs_jpeg.o OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o OBJS-$(CONFIG_CBS_VP8) += cbs_vp8.o vp8data.o OBJS-$(CONFIG_CBS_VP9) += cbs_vp9.o +OBJS-$(CONFIG_D3D12VA_ENCODE) += d3d12va_encode.o hw_base_encode.o OBJS-$(CONFIG_DEFLATE_WRAPPER) += zlib_wrapper.o OBJS-$(CONFIG_DOVI_RPUDEC) += dovi_rpu.o dovi_rpudec.o OBJS-$(CONFIG_DOVI_RPUENC) += dovi_rpu.o dovi_rpuenc.o @@ -436,6 +437,8 @@ OBJS-$(CONFIG_HEVC_DECODER)+= hevcdec.o hevc_mvs.o \ h274.o aom_film_grain.o OBJS-$(CONFIG_HEVC_AMF_ENCODER)+= amfenc_hevc.o OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o +OBJS-$(CONFIG_HEVC_D3D12VA_ENCODER)+= d3d12va_encode_hevc.o h265_profile_level.o \ + h2645data.o OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_HEVC_MEDIACODEC_ENCODER) += mediacodecenc.o OBJS-$(CONFIG_HEVC_MF_ENCODER) += mfenc.o mf_utils.o @@ -1265,7 +1268,7 @@ SKIPHEADERS+= %_tablegen.h \ SKIPHEADERS-$(CONFIG_AMF) += amfenc.h SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h -SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h +SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h d3d12va_encode.h SKIPHEADERS-$(CONFIG_DXVA2)+= dxva2.h dxva2_internal.h SKIPHEADERS-$(CONFIG_JNI) += ffjni.h SKIPHEADERS-$(CONFIG_LCMS2)+= fflcms2.h diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index b102a8069e..463ffbbd08 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -848,6 +848,7 @@ extern const FFCodec ff_h264_vaapi_encoder; extern const FFCodec ff_h264_videotoolbox_encoder; extern const FFCodec ff_hevc_amf_encoder; extern const FFCodec ff_hevc_cuvid_decoder; +extern const FFCodec ff_hevc_d3d12va_encoder; extern const FFCodec ff_hevc_mediacodec_decoder; extern const FFCodec ff_hevc_mediacodec_encoder; extern const FFCodec ff_hevc_mf_encoder; diff --git a/libavcodec/d3d12va_encode.c b/libavcodec/d3d12va_encode.c new file mode 100644 index 00..0fbf8eb07c --- /
[FFmpeg-devel] [PATCH v13 14/15] Changelog: add D3D12VA HEVC encoder changelog
From: Tong Wu Signed-off-by: Tong Wu --- Changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 03d6b29ad8..ff1efcfea6 100644 --- a/Changelog +++ b/Changelog @@ -12,7 +12,7 @@ version : - qsv_params option added for QSV encoders - VVC decoder compatible with DVB test content - xHE-AAC decoder - +- D3D12VA HEVC encoder version 7.0: - DXV DXT1 encoder -- 2.41.0.windows.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 v13 15/15] avcodec/hw_base_encode: avoid getting FFHWBaseEncodeContext from avctx
From: Tong Wu This patch is to make FFHWBaseEncodeContext a standalone component and avoid getting FFHWBaseEncodeContext from avctx->priv_data. This patch also removes some unnecessary AVCodecContext arguments. For receive_packet call, a small wrapper is introduced. Signed-off-by: Tong Wu --- libavcodec/d3d12va_encode.c | 17 +--- libavcodec/d3d12va_encode.h | 2 + libavcodec/d3d12va_encode_hevc.c | 2 +- libavcodec/hw_base_encode.c | 71 ++-- libavcodec/hw_base_encode.h | 17 libavcodec/vaapi_encode.c| 16 --- libavcodec/vaapi_encode.h| 2 + libavcodec/vaapi_encode_av1.c| 2 +- libavcodec/vaapi_encode_h264.c | 2 +- libavcodec/vaapi_encode_h265.c | 2 +- libavcodec/vaapi_encode_mjpeg.c | 2 +- libavcodec/vaapi_encode_mpeg2.c | 2 +- libavcodec/vaapi_encode_vp8.c| 2 +- libavcodec/vaapi_encode_vp9.c| 2 +- 14 files changed, 76 insertions(+), 65 deletions(-) diff --git a/libavcodec/d3d12va_encode.c b/libavcodec/d3d12va_encode.c index 0fbf8eb07c..9f7a42911e 100644 --- a/libavcodec/d3d12va_encode.c +++ b/libavcodec/d3d12va_encode.c @@ -676,6 +676,7 @@ end: static int d3d12va_encode_output(AVCodecContext *avctx, const FFHWBaseEncodePicture *base_pic, AVPacket *pkt) { +FFHWBaseEncodeContext *base_ctx = avctx->priv_data; D3D12VAEncodePicture *pic = (D3D12VAEncodePicture *)base_pic; AVPacket *pkt_ptr = pkt; int err; @@ -691,7 +692,8 @@ static int d3d12va_encode_output(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n", base_pic->display_order, base_pic->encode_order); -ff_hw_base_encode_set_output_property(avctx, (FFHWBaseEncodePicture *)base_pic, pkt_ptr, 0); +ff_hw_base_encode_set_output_property(base_ctx, avctx, (FFHWBaseEncodePicture *)base_pic, + pkt_ptr, 0); return 0; } @@ -1119,7 +1121,7 @@ static int d3d12va_encode_init_gop_structure(AVCodecContext *avctx) "replacing them with B-frames.\n"); } -err = ff_hw_base_init_gop_structure(avctx, ref_l0, ref_l1, ctx->codec->flags, 0); +err = ff_hw_base_init_gop_structure(base_ctx, avctx, ref_l0, ref_l1, ctx->codec->flags, 0); if (err < 0) return err; @@ -1351,7 +1353,7 @@ static int d3d12va_encode_create_recon_frames(AVCodecContext *avctx) enum AVPixelFormat recon_format; int err; -err = ff_hw_base_get_recon_format(avctx, NULL, &recon_format); +err = ff_hw_base_get_recon_format(base_ctx, NULL, &recon_format); if (err < 0) return err; @@ -1390,6 +1392,11 @@ static const FFHWEncodePictureOperation d3d12va_type = { .free = &d3d12va_encode_free, }; +int ff_d3d12va_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) +{ +return ff_hw_base_encode_receive_packet(avctx->priv_data, avctx, pkt); +} + int ff_d3d12va_encode_init(AVCodecContext *avctx) { FFHWBaseEncodeContext *base_ctx = avctx->priv_data; @@ -1398,7 +1405,7 @@ int ff_d3d12va_encode_init(AVCodecContext *avctx) int err; HRESULT hr; -err = ff_hw_base_encode_init(avctx); +err = ff_hw_base_encode_init(avctx, base_ctx); if (err < 0) goto fail; @@ -1552,7 +1559,7 @@ int ff_d3d12va_encode_close(AVCodecContext *avctx) D3D12_OBJECT_RELEASE(ctx->video_device3); D3D12_OBJECT_RELEASE(ctx->device3); -ff_hw_base_encode_close(avctx); +ff_hw_base_encode_close(base_ctx); return 0; } diff --git a/libavcodec/d3d12va_encode.h b/libavcodec/d3d12va_encode.h index f355261f66..1a0abc5bd0 100644 --- a/libavcodec/d3d12va_encode.h +++ b/libavcodec/d3d12va_encode.h @@ -313,6 +313,8 @@ typedef struct D3D12VAEncodeType { char *data, size_t *data_len); } D3D12VAEncodeType; +int ff_d3d12va_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); + int ff_d3d12va_encode_init(AVCodecContext *avctx); int ff_d3d12va_encode_close(AVCodecContext *avctx); diff --git a/libavcodec/d3d12va_encode_hevc.c b/libavcodec/d3d12va_encode_hevc.c index 24823b3c56..4a12ddd0dc 100644 --- a/libavcodec/d3d12va_encode_hevc.c +++ b/libavcodec/d3d12va_encode_hevc.c @@ -990,7 +990,7 @@ const FFCodec ff_hevc_d3d12va_encoder = { .p.id = AV_CODEC_ID_HEVC, .priv_data_size = sizeof(D3D12VAEncodeHEVCContext), .init = &d3d12va_encode_hevc_init, -FF_CODEC_RECEIVE_PACKET_CB(&ff_hw_base_encode_receive_packet), +FF_CODEC_RECEIVE_PACKET_CB(&ff_d3d12va_encode_receive_packet), .close = &d3d12va_encode_hevc_close, .p.priv_class = &d3d12va_encode_hevc_class, .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 92f69bb78c..ecb4be6aa4 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -94,14 +94,13
[FFmpeg-devel] [PATCH] lavc/vaapi_encode: correct the timestamp when input_order = decode_delay
From: Tong Wu Fixed the command line: ffmpeg -hwaccel vaapi -pix_fmt nv12 -s:v widthxheight -i input.yuv -vf "hwupload" -c:v hevc_vaapi -bf 10 -b_depth 3 -vframes 3 -f null - Signed-off-by: Tong Wu --- libavcodec/vaapi_encode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index f54b2579ec..3c627b5ca8 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1383,7 +1383,7 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) // Fix timestamps if we hit end-of-stream before the initial decode // delay has elapsed. -if (ctx->input_order < ctx->decode_delay) +if (ctx->input_order <= ctx->decode_delay) ctx->dts_pts_diff = ctx->pic_end->pts - ctx->first_pts; } -- 2.41.0.windows.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] avcodec/hevc_ps: fix the problem of memcmp losing effectiveness
From: Tong Wu HEVCHdrParams* receives a pointer which points to a dynamically allocated memory block. It causes the memcmp always returning 1. Add a function to do the comparision. A condition is also added to avoid malloc(0). Signed-off-by: Tong Wu --- libavcodec/hevc_ps.c | 20 libavcodec/hevc_ps.h | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index cbef3ef4cd..8b3a27a17c 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -449,6 +449,16 @@ static void uninit_vps(FFRefStructOpaque opaque, void *obj) av_freep(&vps->hdr); } +static int compare_vps(const HEVCVPS *vps1, const HEVCVPS *vps2) +{ +if ((!vps1->hdr && !vps2->hdr) || +(vps1->hdr && vps2->hdr && !memcmp(vps1->hdr, vps2->hdr, sizeof(*vps1->hdr { +return !memcmp(vps1, vps2, offsetof(HEVCVPS, hdr)); +} + +return 0; +} + int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, HEVCParamSets *ps) { @@ -545,9 +555,11 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, goto err; } -vps->hdr = av_calloc(vps->vps_num_hrd_parameters, sizeof(*vps->hdr)); -if (!vps->hdr) -goto err; +if (vps->vps_num_hrd_parameters) { +vps->hdr = av_calloc(vps->vps_num_hrd_parameters, sizeof(*vps->hdr)); +if (!vps->hdr) +goto err; +} for (i = 0; i < vps->vps_num_hrd_parameters; i++) { int common_inf_present = 1; @@ -569,7 +581,7 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, } if (ps->vps_list[vps_id] && -!memcmp(ps->vps_list[vps_id], vps, sizeof(*vps))) { +compare_vps(ps->vps_list[vps_id], vps)) { ff_refstruct_unref(&vps); } else { remove_vps(ps, vps_id); diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index cc75aeb8d3..8edac2508d 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -153,7 +153,6 @@ typedef struct PTL { typedef struct HEVCVPS { unsigned int vps_id; -HEVCHdrParams *hdr; uint8_t vps_temporal_id_nesting_flag; int vps_max_layers; @@ -175,6 +174,7 @@ typedef struct HEVCVPS { uint8_t data[4096]; int data_size; +HEVCHdrParams *hdr; } HEVCVPS; typedef struct ScalingList { -- 2.41.0.windows.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] avcodec/hevc_ps: fix the problem of memcmp losing effectiveness
From: Tong Wu HEVCHdrParams* receives a pointer which points to a dynamically allocated memory block. It causes the memcmp always returning 1. Add a function to do the comparision. A condition is also added to avoid malloc(0). Signed-off-by: Tong Wu --- libavcodec/hevc_ps.c | 20 libavcodec/hevc_ps.h | 4 +++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index cbef3ef4cd..8b3a27a17c 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -449,6 +449,16 @@ static void uninit_vps(FFRefStructOpaque opaque, void *obj) av_freep(&vps->hdr); } +static int compare_vps(const HEVCVPS *vps1, const HEVCVPS *vps2) +{ +if ((!vps1->hdr && !vps2->hdr) || +(vps1->hdr && vps2->hdr && !memcmp(vps1->hdr, vps2->hdr, sizeof(*vps1->hdr { +return !memcmp(vps1, vps2, offsetof(HEVCVPS, hdr)); +} + +return 0; +} + int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, HEVCParamSets *ps) { @@ -545,9 +555,11 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, goto err; } -vps->hdr = av_calloc(vps->vps_num_hrd_parameters, sizeof(*vps->hdr)); -if (!vps->hdr) -goto err; +if (vps->vps_num_hrd_parameters) { +vps->hdr = av_calloc(vps->vps_num_hrd_parameters, sizeof(*vps->hdr)); +if (!vps->hdr) +goto err; +} for (i = 0; i < vps->vps_num_hrd_parameters; i++) { int common_inf_present = 1; @@ -569,7 +581,7 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, } if (ps->vps_list[vps_id] && -!memcmp(ps->vps_list[vps_id], vps, sizeof(*vps))) { +compare_vps(ps->vps_list[vps_id], vps)) { ff_refstruct_unref(&vps); } else { remove_vps(ps, vps_id); diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index cc75aeb8d3..0d8eaf2b3e 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -153,7 +153,6 @@ typedef struct PTL { typedef struct HEVCVPS { unsigned int vps_id; -HEVCHdrParams *hdr; uint8_t vps_temporal_id_nesting_flag; int vps_max_layers; @@ -175,6 +174,9 @@ typedef struct HEVCVPS { uint8_t data[4096]; int data_size; +/* Put this at the end of the structure to make it easier to calculate the + * size before this pointer, which is used for memcmp */ +HEVCHdrParams *hdr; } HEVCVPS; typedef struct ScalingList { -- 2.41.0.windows.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] avcodec/hevc_ps: fix the problem of memcmp losing effectiveness
From: Tong Wu HEVCHdrParams* receives a pointer which points to a dynamically allocated memory block. It causes the memcmp always returning 1. Add a function to do the comparision. A condition is also added to avoid malloc(0). Signed-off-by: Tong Wu --- libavcodec/hevc_ps.c | 22 ++ libavcodec/hevc_ps.h | 4 +++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index cbef3ef4cd..d3c589ec24 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -449,6 +449,18 @@ static void uninit_vps(FFRefStructOpaque opaque, void *obj) av_freep(&vps->hdr); } +static int compare_vps(const HEVCVPS *vps1, const HEVCVPS *vps2) +{ +if (!vps1->hdr && !vps2->hdr && !memcmp(vps1, vps2, offsetof(HEVCVPS, hdr))) +return 1; + +if (vps1->hdr && vps2->hdr && !memcmp(vps1, vps2, offsetof(HEVCVPS, hdr)) && +!memcmp(vps1->hdr, vps2->hdr, vps1->vps_num_hrd_parameters * sizeof(*vps1->hdr))) +return 1; + +return 0; +} + int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, HEVCParamSets *ps) { @@ -545,9 +557,11 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, goto err; } -vps->hdr = av_calloc(vps->vps_num_hrd_parameters, sizeof(*vps->hdr)); -if (!vps->hdr) -goto err; +if (vps->vps_num_hrd_parameters) { +vps->hdr = av_calloc(vps->vps_num_hrd_parameters, sizeof(*vps->hdr)); +if (!vps->hdr) +goto err; +} for (i = 0; i < vps->vps_num_hrd_parameters; i++) { int common_inf_present = 1; @@ -569,7 +583,7 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, } if (ps->vps_list[vps_id] && -!memcmp(ps->vps_list[vps_id], vps, sizeof(*vps))) { +compare_vps(ps->vps_list[vps_id], vps)) { ff_refstruct_unref(&vps); } else { remove_vps(ps, vps_id); diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index cc75aeb8d3..0d8eaf2b3e 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -153,7 +153,6 @@ typedef struct PTL { typedef struct HEVCVPS { unsigned int vps_id; -HEVCHdrParams *hdr; uint8_t vps_temporal_id_nesting_flag; int vps_max_layers; @@ -175,6 +174,9 @@ typedef struct HEVCVPS { uint8_t data[4096]; int data_size; +/* Put this at the end of the structure to make it easier to calculate the + * size before this pointer, which is used for memcmp */ +HEVCHdrParams *hdr; } HEVCVPS; typedef struct ScalingList { -- 2.41.0.windows.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] avcodec/hevc_ps: fix the problem of memcmp losing effectiveness
From: Tong Wu HEVCHdrParams* receives a pointer which points to a dynamically allocated memory block. It causes the memcmp always returning 1. Add a function to do the comparision. A condition is also added to avoid malloc(0). Reviewed-by: James Almer Signed-off-by: Tong Wu --- libavcodec/hevc_ps.c | 19 +++ libavcodec/hevc_ps.h | 4 +++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index cbef3ef4cd..6475d86d7d 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -449,6 +449,15 @@ static void uninit_vps(FFRefStructOpaque opaque, void *obj) av_freep(&vps->hdr); } +static int compare_vps(const HEVCVPS *vps1, const HEVCVPS *vps2) +{ +if (!memcmp(vps1, vps2, offsetof(HEVCVPS, hdr))) +return !vps1->vps_num_hrd_parameters || + !memcmp(vps1->hdr, vps2->hdr, vps1->vps_num_hrd_parameters * sizeof(*vps1->hdr)); + +return 0; +} + int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, HEVCParamSets *ps) { @@ -545,9 +554,11 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, goto err; } -vps->hdr = av_calloc(vps->vps_num_hrd_parameters, sizeof(*vps->hdr)); -if (!vps->hdr) -goto err; +if (vps->vps_num_hrd_parameters) { +vps->hdr = av_calloc(vps->vps_num_hrd_parameters, sizeof(*vps->hdr)); +if (!vps->hdr) +goto err; +} for (i = 0; i < vps->vps_num_hrd_parameters; i++) { int common_inf_present = 1; @@ -569,7 +580,7 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, } if (ps->vps_list[vps_id] && -!memcmp(ps->vps_list[vps_id], vps, sizeof(*vps))) { +compare_vps(ps->vps_list[vps_id], vps)) { ff_refstruct_unref(&vps); } else { remove_vps(ps, vps_id); diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h index cc75aeb8d3..0d8eaf2b3e 100644 --- a/libavcodec/hevc_ps.h +++ b/libavcodec/hevc_ps.h @@ -153,7 +153,6 @@ typedef struct PTL { typedef struct HEVCVPS { unsigned int vps_id; -HEVCHdrParams *hdr; uint8_t vps_temporal_id_nesting_flag; int vps_max_layers; @@ -175,6 +174,9 @@ typedef struct HEVCVPS { uint8_t data[4096]; int data_size; +/* Put this at the end of the structure to make it easier to calculate the + * size before this pointer, which is used for memcmp */ +HEVCHdrParams *hdr; } HEVCVPS; typedef struct ScalingList { -- 2.41.0.windows.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 v8 01/15] avcodec/vaapi_encode: introduce a base layer for vaapi encode
From: Tong Wu Since VAAPI and future D3D12VA implementation may share some common parameters, a base layer encode context is introduced as vaapi context's base. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 52 + libavcodec/vaapi_encode.h | 36 - 2 files changed, 57 insertions(+), 31 deletions(-) create mode 100644 libavcodec/hw_base_encode.h diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h new file mode 100644 index 00..3d1974bba3 --- /dev/null +++ b/libavcodec/hw_base_encode.h @@ -0,0 +1,52 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_HW_BASE_ENCODE_H +#define AVCODEC_HW_BASE_ENCODE_H + +#define MAX_DPB_SIZE 16 +#define MAX_PICTURE_REFERENCES 2 +#define MAX_REORDER_DELAY 16 +#define MAX_ASYNC_DEPTH 64 +#define MAX_REFERENCE_LIST_NUM 2 + +enum { +PICTURE_TYPE_IDR = 0, +PICTURE_TYPE_I = 1, +PICTURE_TYPE_P = 2, +PICTURE_TYPE_B = 3, +}; + +enum { +// Codec supports controlling the subdivision of pictures into slices. +FLAG_SLICE_CONTROL = 1 << 0, +// Codec only supports constant quality (no rate control). +FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, +// Codec is intra-only. +FLAG_INTRA_ONLY= 1 << 2, +// Codec supports B-pictures. +FLAG_B_PICTURES= 1 << 3, +// Codec supports referencing B-pictures. +FLAG_B_PICTURE_REFERENCES = 1 << 4, +// Codec supports non-IDR key pictures (that is, key pictures do +// not necessarily empty the DPB). +FLAG_NON_IDR_KEY_PICTURES = 1 << 5, +}; + +#endif /* AVCODEC_HW_BASE_ENCODE_H */ + diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index 0eed9691ca..5e18f374a7 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -33,34 +33,27 @@ #include "avcodec.h" #include "hwconfig.h" +#include "hw_base_encode.h" struct VAAPIEncodeType; struct VAAPIEncodePicture; +// Codec output packet without timestamp delay, which means the +// output packet has same PTS and DTS. +#define FLAG_TIMESTAMP_NO_DELAY 1 << 6 + enum { MAX_CONFIG_ATTRIBUTES = 4, MAX_GLOBAL_PARAMS = 4, -MAX_DPB_SIZE = 16, -MAX_PICTURE_REFERENCES = 2, -MAX_REORDER_DELAY = 16, MAX_PARAM_BUFFER_SIZE = 1024, // A.4.1: table A.6 allows at most 22 tile rows for any level. 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, -MAX_REFERENCE_LIST_NUM = 2, }; extern const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[]; -enum { -PICTURE_TYPE_IDR = 0, -PICTURE_TYPE_I = 1, -PICTURE_TYPE_P = 2, -PICTURE_TYPE_B = 3, -}; - typedef struct VAAPIEncodeSlice { int index; int row_start; @@ -397,25 +390,6 @@ typedef struct VAAPIEncodeContext { AVPacket*tail_pkt; } VAAPIEncodeContext; -enum { -// Codec supports controlling the subdivision of pictures into slices. -FLAG_SLICE_CONTROL = 1 << 0, -// Codec only supports constant quality (no rate control). -FLAG_CONSTANT_QUALITY_ONLY = 1 << 1, -// Codec is intra-only. -FLAG_INTRA_ONLY= 1 << 2, -// Codec supports B-pictures. -FLAG_B_PICTURES= 1 << 3, -// Codec supports referencing B-pictures. -FLAG_B_PICTURE_REFERENCES = 1 << 4, -// Codec supports non-IDR key pictures (that is, key pictures do -// not necessarily empty the DPB). -FLAG_NON_IDR_KEY_PICTURES = 1 << 5, -// Codec output packet without timestamp delay, which means the -// output packet has same PTS and DTS. -FLAG_TIMESTAMP_NO_DELAY= 1 << 6, -}; - typedef struct VAAPIEncodeType { // List of supported profiles and corresponding VAAPI profiles. // (Must end with AV_PROFILE_UNKNOWN.) -- 2.41.0.windows.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 v8 02/15] avcodec/vaapi_encode: add async_depth to common options
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 14 +- libavcodec/vaapi_encode.c | 13 - libavcodec/vaapi_encode.h | 10 ++ libavcodec/vaapi_encode_av1.c | 1 + libavcodec/vaapi_encode_h264.c | 1 + libavcodec/vaapi_encode_h265.c | 1 + libavcodec/vaapi_encode_mjpeg.c | 1 + libavcodec/vaapi_encode_mpeg2.c | 1 + libavcodec/vaapi_encode_vp8.c | 1 + libavcodec/vaapi_encode_vp9.c | 1 + 10 files changed, 30 insertions(+), 14 deletions(-) diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 3d1974bba3..5272f2836d 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -48,5 +48,17 @@ enum { FLAG_NON_IDR_KEY_PICTURES = 1 << 5, }; -#endif /* AVCODEC_HW_BASE_ENCODE_H */ +typedef struct HWBaseEncodeContext { +const AVClass *class; + +// Max number of frame buffered in encoder. +int async_depth; +} HWBaseEncodeContext; +#define HW_BASE_ENCODE_COMMON_OPTIONS \ +{ "async_depth", "Maximum processing parallelism. " \ + "Increase this to improve single channel performance.", \ + OFFSET(common.base.async_depth), AV_OPT_TYPE_INT, \ + { .i64 = 2 }, 1, MAX_ASYNC_DEPTH, FLAGS } + +#endif /* AVCODEC_HW_BASE_ENCODE_H */ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index f54b2579ec..9373512417 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -669,7 +669,8 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, VAAPIEncodePicture *pic, AVPacket *pkt) { -VAAPIEncodeContext *ctx = avctx->priv_data; +HWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; if (pic->type == PICTURE_TYPE_IDR) pkt->flags |= AV_PKT_FLAG_KEY; @@ -699,7 +700,7 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, 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 + ctx->async_depth)]; +(3 * ctx->output_delay + base_ctx->async_depth)]; } return 0; @@ -1320,6 +1321,7 @@ static int vaapi_encode_check_frame(AVCodecContext *avctx, static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) { +HWBaseEncodeContext *base_ctx = avctx->priv_data; VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic; int err; @@ -1365,7 +1367,7 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) ctx->dts_pts_diff = pic->pts - ctx->first_pts; if (ctx->output_delay > 0) ctx->ts_ring[ctx->input_order % -(3 * ctx->output_delay + ctx->async_depth)] = pic->pts; +(3 * ctx->output_delay + base_ctx->async_depth)] = pic->pts; pic->display_order = ctx->input_order; ++ctx->input_order; @@ -2773,7 +2775,8 @@ static av_cold int vaapi_encode_create_recon_frames(AVCodecContext *avctx) av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) { -VAAPIEncodeContext *ctx = avctx->priv_data; +HWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; AVVAAPIFramesContext *recon_hwctx = NULL; VAStatus vas; int err; @@ -2966,7 +2969,7 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) vas = vaSyncBuffer(ctx->hwctx->display, VA_INVALID_ID, 0); if (vas != VA_STATUS_ERROR_UNIMPLEMENTED) { ctx->has_sync_buffer_func = 1; -ctx->encode_fifo = av_fifo_alloc2(ctx->async_depth, +ctx->encode_fifo = av_fifo_alloc2(base_ctx->async_depth, sizeof(VAAPIEncodePicture *), 0); if (!ctx->encode_fifo) diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index 5e18f374a7..02410c72ec 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -186,7 +186,8 @@ typedef struct VAAPIEncodeRCMode { } VAAPIEncodeRCMode; typedef struct VAAPIEncodeContext { -const AVClass *class; +// Base context. +HWBaseEncodeContext base; // Codec-specific hooks. const struct VAAPIEncodeType *codec; @@ -373,8 +374,6 @@ typedef struct VAAPIEncodeContext { int has_sync_buffer_func; // Store buffered pic AVFifo *encode_fifo; -// Max number of frame buffered in encoder. -int async_depth; /** Head data for current output pkt, used only for AV1. */ //void *header_data; @@ -490,11 +489,6 @@ int ff_vaapi_encode_close(AVCodecContext *avctx); "Maximum B-frame reference depth", \ OFFSET(common.desire
[FFmpeg-devel] [PATCH v8 03/15] avcodec/vaapi_encode: add picture type name to base
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 5 + libavcodec/vaapi_encode.c | 4 +--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 5272f2836d..a578db8c06 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -25,6 +25,11 @@ #define MAX_ASYNC_DEPTH 64 #define MAX_REFERENCE_LIST_NUM 2 +static inline const char *ff_hw_base_encode_get_pictype_name(const int type) { +const char * const picture_type_name[] = { "IDR", "I", "P", "B" }; +return picture_type_name[type]; +} + enum { PICTURE_TYPE_IDR = 0, PICTURE_TYPE_I = 1, diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 9373512417..2d22e4bd85 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -38,8 +38,6 @@ const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[] = { NULL, }; -static const char * const picture_type_name[] = { "IDR", "I", "P", "B" }; - static int vaapi_encode_make_packed_header(AVCodecContext *avctx, VAAPIEncodePicture *pic, int type, char *data, size_t bit_len) @@ -277,7 +275,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Issuing encode for pic %"PRId64"/%"PRId64" " "as type %s.\n", pic->display_order, pic->encode_order, - picture_type_name[pic->type]); + ff_hw_base_encode_get_pictype_name(pic->type)); if (pic->nb_refs[0] == 0 && pic->nb_refs[1] == 0) { av_log(avctx, AV_LOG_DEBUG, "No reference pictures.\n"); } else { -- 2.41.0.windows.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 v8 04/15] avcodec/vaapi_encode: move pic->input_surface initialization to encode_alloc
From: Tong Wu When allocating the VAAPIEncodePicture, pic->input_surface can be initialized right in the place. This movement simplifies the send_frame logic and is the preparation for moving vaapi_encode_send_frame to the base layer. Signed-off-by: Tong Wu --- libavcodec/vaapi_encode.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 2d22e4bd85..227cccae64 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -878,7 +878,8 @@ static int vaapi_encode_discard(AVCodecContext *avctx, return 0; } -static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx) +static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx, + const AVFrame *frame) { VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic; @@ -895,7 +896,7 @@ static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx) } } -pic->input_surface = VA_INVALID_ID; +pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; pic->recon_surface = VA_INVALID_ID; pic->output_buffer = VA_INVALID_ID; @@ -1332,7 +1333,7 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) if (err < 0) return err; -pic = vaapi_encode_alloc(avctx); +pic = vaapi_encode_alloc(avctx, frame); if (!pic) return AVERROR(ENOMEM); @@ -1345,7 +1346,6 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) if (ctx->input_order == 0 || frame->pict_type == AV_PICTURE_TYPE_I) pic->force_idr = 1; -pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; pic->pts = frame->pts; pic->duration = frame->duration; -- 2.41.0.windows.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 v8 05/15] avcodec/vaapi_encode: move the dpb logic from VAAPI to base layer
From: Tong Wu Move receive_packet function to base. This requires adding *alloc, *issue, *output, *free as hardware callbacks. HWBaseEncodePicture is introduced as the base layer structure. The related parameters in VAAPIEncodeContext are also extracted to HWBaseEncodeContext. Then DPB management logic can be fully extracted to base layer as-is. Signed-off-by: Tong Wu --- libavcodec/Makefile | 2 +- libavcodec/hw_base_encode.c | 600 libavcodec/hw_base_encode.h | 123 + libavcodec/vaapi_encode.c | 793 +--- libavcodec/vaapi_encode.h | 102 +--- libavcodec/vaapi_encode_av1.c | 51 +- libavcodec/vaapi_encode_h264.c | 176 +++ libavcodec/vaapi_encode_h265.c | 121 ++--- libavcodec/vaapi_encode_mjpeg.c | 7 +- libavcodec/vaapi_encode_mpeg2.c | 47 +- libavcodec/vaapi_encode_vp8.c | 18 +- libavcodec/vaapi_encode_vp9.c | 54 +-- 12 files changed, 1097 insertions(+), 997 deletions(-) create mode 100644 libavcodec/hw_base_encode.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 7f6de4470e..a2174dcb2f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -162,7 +162,7 @@ OBJS-$(CONFIG_STARTCODE) += startcode.o OBJS-$(CONFIG_TEXTUREDSP) += texturedsp.o OBJS-$(CONFIG_TEXTUREDSPENC) += texturedspenc.o OBJS-$(CONFIG_TPELDSP) += tpeldsp.o -OBJS-$(CONFIG_VAAPI_ENCODE)+= vaapi_encode.o +OBJS-$(CONFIG_VAAPI_ENCODE)+= vaapi_encode.o hw_base_encode.o OBJS-$(CONFIG_AV1_AMF_ENCODER) += amfenc_av1.o OBJS-$(CONFIG_VC1DSP) += vc1dsp.o OBJS-$(CONFIG_VIDEODSP)+= videodsp.o diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c new file mode 100644 index 00..1d9a255f69 --- /dev/null +++ b/libavcodec/hw_base_encode.c @@ -0,0 +1,600 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" + +#include "encode.h" +#include "avcodec.h" +#include "hw_base_encode.h" + +static void hw_base_encode_add_ref(AVCodecContext *avctx, + HWBaseEncodePicture *pic, + HWBaseEncodePicture *target, + int is_ref, int in_dpb, int prev) +{ +int refs = 0; + +if (is_ref) { +av_assert0(pic != target); +av_assert0(pic->nb_refs[0] < MAX_PICTURE_REFERENCES && + pic->nb_refs[1] < MAX_PICTURE_REFERENCES); +if (target->display_order < pic->display_order) +pic->refs[0][pic->nb_refs[0]++] = target; +else +pic->refs[1][pic->nb_refs[1]++] = target; +++refs; +} + +if (in_dpb) { +av_assert0(pic->nb_dpb_pics < MAX_DPB_SIZE); +pic->dpb[pic->nb_dpb_pics++] = target; +++refs; +} + +if (prev) { +av_assert0(!pic->prev); +pic->prev = target; +++refs; +} + +target->ref_count[0] += refs; +target->ref_count[1] += refs; +} + +static void hw_base_encode_remove_refs(AVCodecContext *avctx, + HWBaseEncodePicture *pic, + int level) +{ +int i; + +if (pic->ref_removed[level]) +return; + +for (i = 0; i < pic->nb_refs[0]; i++) { +av_assert0(pic->refs[0][i]); +--pic->refs[0][i]->ref_count[level]; +av_assert0(pic->refs[0][i]->ref_count[level] >= 0); +} + +for (i = 0; i < pic->nb_refs[1]; i++) { +av_assert0(pic->refs[1][i]); +--pic->refs[1][i]->ref_count[level]; +av_assert0(pic->refs[1][i]->ref_count[level] >= 0); +} + +for (i = 0; i < pic->nb_dpb_pics; i++) { +av_assert0(pic->dpb[i]); +--pic->dpb[i]->ref_count[level]; +av_assert0(pic->dpb[i]->ref_count[level] >= 0); +} + +av_assert0(pic->prev || pic->type == PICTURE_TYPE_IDR); +if (pic->prev) { +--pic->prev->ref_count[level]; +av_assert0(pic->prev->ref_count[level] >= 0); +} + +pic->ref_re
[FFmpeg-devel] [PATCH v8 06/15] avcodec/vaapi_encode: extract the init function to base layer
From: Tong Wu Related parameters are also moved to base layer. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 33 libavcodec/hw_base_encode.h | 11 ++ libavcodec/vaapi_encode.c | 68 ++--- libavcodec/vaapi_encode.h | 6 --- libavcodec/vaapi_encode_av1.c | 2 +- libavcodec/vaapi_encode_h264.c | 2 +- libavcodec/vaapi_encode_h265.c | 2 +- libavcodec/vaapi_encode_mjpeg.c | 6 ++- 8 files changed, 72 insertions(+), 58 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 1d9a255f69..14f3ecfc94 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -598,3 +598,36 @@ end: return 0; } + +int ff_hw_base_encode_init(AVCodecContext *avctx) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; + +ctx->frame = av_frame_alloc(); +if (!ctx->frame) +return AVERROR(ENOMEM); + +if (!avctx->hw_frames_ctx) { +av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is " + "required to associate the encoding device.\n"); +return AVERROR(EINVAL); +} + +ctx->input_frames_ref = av_buffer_ref(avctx->hw_frames_ctx); +if (!ctx->input_frames_ref) +return AVERROR(ENOMEM); + +ctx->input_frames = (AVHWFramesContext *)ctx->input_frames_ref->data; + +ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref); +if (!ctx->device_ref) +return AVERROR(ENOMEM); + +ctx->device = (AVHWDeviceContext *)ctx->device_ref->data; + +ctx->tail_pkt = av_packet_alloc(); +if (!ctx->tail_pkt) +return AVERROR(ENOMEM); + +return 0; +} diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index b5b676b9a8..f7e385e840 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -19,6 +19,7 @@ #ifndef AVCODEC_HW_BASE_ENCODE_H #define AVCODEC_HW_BASE_ENCODE_H +#include "libavutil/hwcontext.h" #include "libavutil/fifo.h" #define MAX_DPB_SIZE 16 @@ -117,6 +118,14 @@ typedef struct HWBaseEncodeContext { // Hardware-specific hooks. const struct HWEncodePictureOperation *op; +// The hardware device context. +AVBufferRef*device_ref; +AVHWDeviceContext *device; + +// The hardware frame context containing the input frames. +AVBufferRef*input_frames_ref; +AVHWFramesContext *input_frames; + // Current encoding window, in display (input) order. HWBaseEncodePicture *pic_start, *pic_end; // The next picture to use as the previous reference picture in @@ -183,6 +192,8 @@ typedef struct HWBaseEncodeContext { int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); +int ff_hw_base_encode_init(AVCodecContext *avctx); + #define HW_BASE_ENCODE_COMMON_OPTIONS \ { "async_depth", "Maximum processing parallelism. " \ "Increase this to improve single channel performance.", \ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 18966596e1..c7488ad150 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -996,9 +996,10 @@ static const VAEntrypoint vaapi_encode_entrypoints_low_power[] = { static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx) { -VAAPIEncodeContext *ctx = avctx->priv_data; -VAProfile*va_profiles= NULL; -VAEntrypoint *va_entrypoints = NULL; +HWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; +VAProfile *va_profiles= NULL; +VAEntrypoint *va_entrypoints = NULL; VAStatus vas; const VAEntrypoint *usable_entrypoints; const VAAPIEncodeProfile *profile; @@ -1021,10 +1022,10 @@ static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx) usable_entrypoints = vaapi_encode_entrypoints_normal; } -desc = av_pix_fmt_desc_get(ctx->input_frames->sw_format); +desc = av_pix_fmt_desc_get(base_ctx->input_frames->sw_format); if (!desc) { av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%d).\n", - ctx->input_frames->sw_format); + base_ctx->input_frames->sw_format); return AVERROR(EINVAL); } depth = desc->comp[0].depth; @@ -2131,20 +2132,21 @@ static int vaapi_encode_alloc_output_buffer(FFRefStructOpaque opaque, void *obj) static av_cold int vaapi_encode_create_recon_frames(AVCodecContext *avctx) { -VAAPIEncodeContext *ctx = avctx->priv_data; +HWBaseEncodeContext *base_ctx = avctx->priv_data; +VAAPIEncodeContext *ctx = avctx->priv_data; AVVAAPIHWConfig *hwconfig = NULL; AVHWFramesConstraints *constraints = NULL; enum AVPixelFormat recon_format; int err, i; -hwconfig = av_hwdevice_hwconfig_alloc(ctx->device_ref); +hwconfig = av_hwdevice_hwconfig_alloc(base_ctx->device_ref); if (!hwconfig) { err = AVERROR(ENOMEM); goto fail; } hw
[FFmpeg-devel] [PATCH v8 09/15] avcodec/vaapi_encode: extract a close function for base layer
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 16 libavcodec/hw_base_encode.h | 2 ++ libavcodec/vaapi_encode.c | 8 +--- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 6e450f9dca..fa954d984d 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -685,3 +685,19 @@ int ff_hw_base_encode_init(AVCodecContext *avctx) return 0; } + +int ff_hw_base_encode_close(AVCodecContext *avctx) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; + +av_fifo_freep2(&ctx->encode_fifo); + +av_frame_free(&ctx->frame); +av_packet_free(&ctx->tail_pkt); + +av_buffer_unref(&ctx->device_ref); +av_buffer_unref(&ctx->input_frames_ref); +av_buffer_unref(&ctx->recon_frames_ref); + +return 0; +} diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 3eea3ef998..d822175fcf 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -209,6 +209,8 @@ int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32 int ff_hw_base_encode_init(AVCodecContext *avctx); +int ff_hw_base_encode_close(AVCodecContext *avctx); + #define HW_BASE_ENCODE_COMMON_OPTIONS \ { "idr_interval", \ "Distance (in I-frames) between key frames", \ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 8640a888b7..41d0d0f2bc 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -2397,16 +2397,10 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx) ctx->va_config = VA_INVALID_ID; } -av_frame_free(&base_ctx->frame); -av_packet_free(&base_ctx->tail_pkt); - av_freep(&ctx->codec_sequence_params); av_freep(&ctx->codec_picture_params); -av_fifo_freep2(&base_ctx->encode_fifo); -av_buffer_unref(&base_ctx->recon_frames_ref); -av_buffer_unref(&base_ctx->input_frames_ref); -av_buffer_unref(&base_ctx->device_ref); +ff_hw_base_encode_close(avctx); return 0; } -- 2.41.0.windows.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 v8 07/15] avcodec/vaapi_encode: extract gop configuration and two options to base layer
From: Tong Wu idr_interval and desired_b_depth are moved to HW_BASE_ENCODE_COMMON_OPTIONS. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 54 + libavcodec/hw_base_encode.h | 19 + libavcodec/vaapi_encode.c | 52 +++ libavcodec/vaapi_encode.h | 16 --- 4 files changed, 77 insertions(+), 64 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 14f3ecfc94..6e450f9dca 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -599,6 +599,60 @@ end: return 0; } +int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, + int flags, int prediction_pre_only) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; + +if (flags & FLAG_INTRA_ONLY || avctx->gop_size <= 1) { +av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n"); +ctx->gop_size = 1; +} else if (ref_l0 < 1) { +av_log(avctx, AV_LOG_ERROR, "Driver does not support any " + "reference frames.\n"); +return AVERROR(EINVAL); +} else if (!(flags & FLAG_B_PICTURES) || ref_l1 < 1 || + avctx->max_b_frames < 1 || prediction_pre_only) { +if (ctx->p_to_gpb) + av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " + "(supported references: %d / %d).\n", + ref_l0, ref_l1); +else +av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames " + "(supported references: %d / %d).\n", ref_l0, ref_l1); +ctx->gop_size = avctx->gop_size; +ctx->p_per_i = INT_MAX; +ctx->b_per_p = 0; +} else { + if (ctx->p_to_gpb) + av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " + "(supported references: %d / %d).\n", + ref_l0, ref_l1); + else + av_log(avctx, AV_LOG_VERBOSE, "Using intra, P- and B-frames " + "(supported references: %d / %d).\n", ref_l0, ref_l1); +ctx->gop_size = avctx->gop_size; +ctx->p_per_i = INT_MAX; +ctx->b_per_p = avctx->max_b_frames; +if (flags & FLAG_B_PICTURE_REFERENCES) { +ctx->max_b_depth = FFMIN(ctx->desired_b_depth, + av_log2(ctx->b_per_p) + 1); +} else { +ctx->max_b_depth = 1; +} +} + +if (flags & FLAG_NON_IDR_KEY_PICTURES) { +ctx->closed_gop = !!(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP); +ctx->gop_per_idr = ctx->idr_interval + 1; +} else { +ctx->closed_gop = 1; +ctx->gop_per_idr = 1; +} + +return 0; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { HWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index f7e385e840..1f6d7882bc 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -118,6 +118,14 @@ typedef struct HWBaseEncodeContext { // Hardware-specific hooks. const struct HWEncodePictureOperation *op; +// Global options. + +// Number of I frames between IDR frames. +int idr_interval; + +// Desired B frame reference depth. +int desired_b_depth; + // The hardware device context. AVBufferRef*device_ref; AVHWDeviceContext *device; @@ -192,9 +200,20 @@ typedef struct HWBaseEncodeContext { int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); +int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, + int flags, int prediction_pre_only); + int ff_hw_base_encode_init(AVCodecContext *avctx); #define HW_BASE_ENCODE_COMMON_OPTIONS \ +{ "idr_interval", \ + "Distance (in I-frames) between key frames", \ + OFFSET(common.base.idr_interval), AV_OPT_TYPE_INT, \ + { .i64 = 0 }, 0, INT_MAX, FLAGS }, \ +{ "b_depth", \ + "Maximum B-frame reference depth", \ + OFFSET(common.base.desired_b_depth), AV_OPT_TYPE_INT, \ + { .i64 = 1 }, 1, INT_MAX, FLAGS }, \ { "async_depth", "Maximum processing parallelism. " \ "Increase this to improve single channel performance.", \ OFFSET(common.base.async_depth), AV_OPT_TYPE_INT, \ diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index c7488ad150..993b2640a9 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1638,7 +1638,7 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) VAStatus vas; VAConfigAttrib attr = { VAConfigAttribEncMaxRefFrames }; uint32_t ref_l0, ref_l1; -int prediction_pre_only; +int prediction_pre_only, err; vas = vaGetConfigAttributes(ctx->hwctx->display, ctx->va_profile, @@ -1702,53 +1702,9 @@ static
[FFmpeg-devel] [PATCH v8 10/15] avcodec/vaapi_encode: extract set_output_property to base layer
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 40 + libavcodec/hw_base_encode.h | 3 +++ libavcodec/vaapi_encode.c | 44 ++--- 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index fa954d984d..a4223d90f0 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -491,6 +491,46 @@ fail: return err; } +int ff_hw_base_encode_set_output_property(AVCodecContext *avctx, + HWBaseEncodePicture *pic, + AVPacket *pkt, int flag_no_delay) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; + +if (pic->type == PICTURE_TYPE_IDR) +pkt->flags |= AV_PKT_FLAG_KEY; + +pkt->pts = pic->pts; +pkt->duration = pic->duration; + +// for no-delay encoders this is handled in generic codec +if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY && +avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { +pkt->opaque = pic->opaque; +pkt->opaque_ref = pic->opaque_ref; +pic->opaque_ref = NULL; +} + +if (flag_no_delay) { +pkt->dts = pkt->pts; +return 0; +} + +if (ctx->output_delay == 0) { +pkt->dts = pkt->pts; +} else if (pic->encode_order < ctx->decode_delay) { +if (ctx->ts_ring[pic->encode_order] < INT64_MIN + ctx->dts_pts_diff) +pkt->dts = INT64_MIN; +else +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 + ctx->async_depth)]; +} + +return 0; +} + int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) { HWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index d822175fcf..d717f955d8 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -202,6 +202,9 @@ typedef struct HWBaseEncodeContext { AVPacket*tail_pkt; } HWBaseEncodeContext; +int ff_hw_base_encode_set_output_property(AVCodecContext *avctx, HWBaseEncodePicture *pic, + AVPacket *pkt, int flag_no_delay); + int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 41d0d0f2bc..ec4cde3c37 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -660,47 +660,6 @@ fail_at_end: return err; } -static int vaapi_encode_set_output_property(AVCodecContext *avctx, -HWBaseEncodePicture *pic, -AVPacket *pkt) -{ -HWBaseEncodeContext *base_ctx = avctx->priv_data; -VAAPIEncodeContext *ctx = avctx->priv_data; - -if (pic->type == PICTURE_TYPE_IDR) -pkt->flags |= AV_PKT_FLAG_KEY; - -pkt->pts = pic->pts; -pkt->duration = pic->duration; - -// for no-delay encoders this is handled in generic codec -if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY && -avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { -pkt->opaque = pic->opaque; -pkt->opaque_ref = pic->opaque_ref; -pic->opaque_ref = NULL; -} - -if (ctx->codec->flags & FLAG_TIMESTAMP_NO_DELAY) { -pkt->dts = pkt->pts; -return 0; -} - -if (base_ctx->output_delay == 0) { -pkt->dts = pkt->pts; -} else if (pic->encode_order < base_ctx->decode_delay) { -if (base_ctx->ts_ring[pic->encode_order] < INT64_MIN + base_ctx->dts_pts_diff) -pkt->dts = INT64_MIN; -else -pkt->dts = base_ctx->ts_ring[pic->encode_order] - base_ctx->dts_pts_diff; -} else { -pkt->dts = base_ctx->ts_ring[(pic->encode_order - base_ctx->decode_delay) % - (3 * base_ctx->output_delay + base_ctx->async_depth)]; -} - -return 0; -} - static int vaapi_encode_get_coded_buffer_size(AVCodecContext *avctx, VABufferID buf_id) { VAAPIEncodeContext *ctx = avctx->priv_data; @@ -852,7 +811,8 @@ static int vaapi_encode_output(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n", base_pic->display_order, base_pic->encode_order); -vaapi_encode_set_output_property(avctx, (HWBaseEncodePicture*)pic, pkt_ptr); +ff_hw_base_encode_set_output_property(avctx, (HWBaseEncodePicture*)base_pic, pkt_ptr, + ctx->codec->flags & FLAG_TIMESTAMP_NO_DELAY); end: ff_refstruct_unref(&pic->output_buffer_ref); -- 2.41.0.windows.1 _
[FFmpeg-devel] [PATCH v8 11/15] avcodec/vaapi_encode: extract a get_recon_format function to base layer
From: Tong Wu Surface size and block size parameters are also moved to base layer. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 58 +++ libavcodec/hw_base_encode.h | 12 + libavcodec/vaapi_encode.c | 81 - libavcodec/vaapi_encode.h | 10 libavcodec/vaapi_encode_av1.c | 10 ++-- libavcodec/vaapi_encode_h264.c | 11 +++-- libavcodec/vaapi_encode_h265.c | 25 +- libavcodec/vaapi_encode_mjpeg.c | 5 +- libavcodec/vaapi_encode_vp9.c | 6 +-- 9 files changed, 118 insertions(+), 100 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index a4223d90f0..af85bb99aa 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -693,6 +693,64 @@ int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32 return 0; } +int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; +AVHWFramesConstraints *constraints = NULL; +enum AVPixelFormat recon_format; +int err, i; + +constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref, + hwconfig); +if (!constraints) { +err = AVERROR(ENOMEM); +goto fail; +} + +// Probably we can use the input surface format as the surface format +// of the reconstructed frames. If not, we just pick the first (only?) +// format in the valid list and hope that it all works. +recon_format = AV_PIX_FMT_NONE; +if (constraints->valid_sw_formats) { +for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { +if (ctx->input_frames->sw_format == +constraints->valid_sw_formats[i]) { +recon_format = ctx->input_frames->sw_format; +break; +} +} +if (recon_format == AV_PIX_FMT_NONE) { +// No match. Just use the first in the supported list and +// hope for the best. +recon_format = constraints->valid_sw_formats[0]; +} +} else { +// No idea what to use; copy input format. +recon_format = ctx->input_frames->sw_format; +} +av_log(avctx, AV_LOG_DEBUG, "Using %s as format of " + "reconstructed frames.\n", av_get_pix_fmt_name(recon_format)); + +if (ctx->surface_width < constraints->min_width || +ctx->surface_height < constraints->min_height || +ctx->surface_width > constraints->max_width || +ctx->surface_height > constraints->max_height) { +av_log(avctx, AV_LOG_ERROR, "Hardware does not support encoding at " + "size %dx%d (constraints: width %d-%d height %d-%d).\n", + ctx->surface_width, ctx->surface_height, + constraints->min_width, constraints->max_width, + constraints->min_height, constraints->max_height); +err = AVERROR(EINVAL); +goto fail; +} + +*fmt = recon_format; +err = 0; +fail: +av_hwframe_constraints_free(&constraints); +return err; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { HWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index d717f955d8..7686cf9501 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -126,6 +126,16 @@ typedef struct HWBaseEncodeContext { // Desired B frame reference depth. int desired_b_depth; +// The required size of surfaces. This is probably the input +// size (AVCodecContext.width|height) aligned up to whatever +// block size is required by the codec. +int surface_width; +int surface_height; + +// The block size for slice calculations. +int slice_block_width; +int slice_block_height; + // The hardware device context. AVBufferRef*device_ref; AVHWDeviceContext *device; @@ -210,6 +220,8 @@ int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, int flags, int prediction_pre_only); +int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index ec4cde3c37..ee4cf42baf 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1777,6 +1777,7 @@ static av_cold int vaapi_encode_init_tile_slice_structure(AVCodecContext *avctx, static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) { +HWBaseEncodeContext *base_ctx = avctx->pr
[FFmpeg-devel] [PATCH v8 08/15] avcodec/vaapi_encode: move two reconstructed frames parameters to base layer
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.h | 4 libavcodec/vaapi_encode.c | 22 +++--- libavcodec/vaapi_encode.h | 4 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 1f6d7882bc..3eea3ef998 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -134,6 +134,10 @@ typedef struct HWBaseEncodeContext { AVBufferRef*input_frames_ref; AVHWFramesContext *input_frames; +// The hardware frame context containing the reconstructed frames. +AVBufferRef*recon_frames_ref; +AVHWFramesContext *recon_frames; + // Current encoding window, in display (input) order. HWBaseEncodePicture *pic_start, *pic_end; // The next picture to use as the previous reference picture in diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 993b2640a9..8640a888b7 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -314,7 +314,7 @@ static int vaapi_encode_issue(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Input surface is %#x.\n", pic->input_surface); -err = av_hwframe_get_buffer(ctx->recon_frames_ref, base_pic->recon_image, 0); +err = av_hwframe_get_buffer(base_ctx->recon_frames_ref, base_pic->recon_image, 0); if (err < 0) { err = AVERROR(ENOMEM); goto fail; @@ -2149,19 +2149,19 @@ static av_cold int vaapi_encode_create_recon_frames(AVCodecContext *avctx) av_freep(&hwconfig); av_hwframe_constraints_free(&constraints); -ctx->recon_frames_ref = av_hwframe_ctx_alloc(base_ctx->device_ref); -if (!ctx->recon_frames_ref) { +base_ctx->recon_frames_ref = av_hwframe_ctx_alloc(base_ctx->device_ref); +if (!base_ctx->recon_frames_ref) { err = AVERROR(ENOMEM); goto fail; } -ctx->recon_frames = (AVHWFramesContext*)ctx->recon_frames_ref->data; +base_ctx->recon_frames = (AVHWFramesContext*)base_ctx->recon_frames_ref->data; -ctx->recon_frames->format= AV_PIX_FMT_VAAPI; -ctx->recon_frames->sw_format = recon_format; -ctx->recon_frames->width = ctx->surface_width; -ctx->recon_frames->height= ctx->surface_height; +base_ctx->recon_frames->format= AV_PIX_FMT_VAAPI; +base_ctx->recon_frames->sw_format = recon_format; +base_ctx->recon_frames->width = ctx->surface_width; +base_ctx->recon_frames->height= ctx->surface_height; -err = av_hwframe_ctx_init(ctx->recon_frames_ref); +err = av_hwframe_ctx_init(base_ctx->recon_frames_ref); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to initialise reconstructed " "frame context: %d.\n", err); @@ -2269,7 +2269,7 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) if (err < 0) goto fail; -recon_hwctx = ctx->recon_frames->hwctx; +recon_hwctx = base_ctx->recon_frames->hwctx; vas = vaCreateContext(ctx->hwctx->display, ctx->va_config, ctx->surface_width, ctx->surface_height, VA_PROGRESSIVE, @@ -2404,7 +2404,7 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx) av_freep(&ctx->codec_picture_params); av_fifo_freep2(&base_ctx->encode_fifo); -av_buffer_unref(&ctx->recon_frames_ref); +av_buffer_unref(&base_ctx->recon_frames_ref); av_buffer_unref(&base_ctx->input_frames_ref); av_buffer_unref(&base_ctx->device_ref); diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index 0d3d8e2ed0..76fb645d71 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -213,10 +213,6 @@ typedef struct VAAPIEncodeContext { AVVAAPIDeviceContext *hwctx; -// The hardware frame context containing the reconstructed frames. -AVBufferRef*recon_frames_ref; -AVHWFramesContext *recon_frames; - // Pool of (reusable) bitstream output buffers. struct FFRefStructPool *output_buffer_pool; -- 2.41.0.windows.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 v8 12/15] avcodec/vaapi_encode: extract a free funtion to base layer
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 11 +++ libavcodec/hw_base_encode.h | 2 ++ libavcodec/vaapi_encode.c | 6 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index af85bb99aa..812668f3f2 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -751,6 +751,17 @@ fail: return err; } +int ff_hw_base_encode_free(AVCodecContext *avctx, HWBaseEncodePicture *pic) +{ +av_frame_free(&pic->input_image); +av_frame_free(&pic->recon_image); + +av_buffer_unref(&pic->opaque_ref); +av_freep(&pic->priv_data); + +return 0; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { HWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 7686cf9501..d566980efc 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -222,6 +222,8 @@ int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32 int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt); +int ff_hw_base_encode_free(AVCodecContext *avctx, HWBaseEncodePicture *pic); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index ee4cf42baf..08792c07c5 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -878,17 +878,13 @@ static int vaapi_encode_free(AVCodecContext *avctx, av_freep(&pic->slices[i].codec_slice_params); } -av_frame_free(&base_pic->input_image); -av_frame_free(&base_pic->recon_image); - -av_buffer_unref(&base_pic->opaque_ref); +ff_hw_base_encode_free(avctx, base_pic); av_freep(&pic->param_buffers); av_freep(&pic->slices); // Output buffer should already be destroyed. av_assert0(pic->output_buffer == VA_INVALID_ID); -av_freep(&base_pic->priv_data); av_freep(&pic->codec_picture_params); av_freep(&pic->roi); -- 2.41.0.windows.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 v8 13/15] avutil/hwcontext_d3d12va: add Flags for resource creation
From: Tong Wu Flags field is added to support diffferent resource creation. Signed-off-by: Tong Wu --- doc/APIchanges| 3 +++ libavutil/hwcontext_d3d12va.c | 2 +- libavutil/hwcontext_d3d12va.h | 8 libavutil/version.h | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 63e7a47126..ebf645dda8 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2024-03-07 API changes, most recent first: +2024-01-xx - xx - lavu 59.16.100 - hwcontext_d3d12va.h + Add AVD3D12VAFramesContext.flags + 2024-04-11 - xx - lavc 61.5.102 - avcodec.h AVCodecContext.decoded_side_data may now be set by libavcodec after calling avcodec_open2(). diff --git a/libavutil/hwcontext_d3d12va.c b/libavutil/hwcontext_d3d12va.c index cfc016315d..6507cf69c1 100644 --- a/libavutil/hwcontext_d3d12va.c +++ b/libavutil/hwcontext_d3d12va.c @@ -247,7 +247,7 @@ static AVBufferRef *d3d12va_pool_alloc(void *opaque, size_t size) .Format = hwctx->format, .SampleDesc = {.Count = 1, .Quality = 0 }, .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, -.Flags= D3D12_RESOURCE_FLAG_NONE, +.Flags= hwctx->flags, }; frame = av_mallocz(sizeof(AVD3D12VAFrame)); diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h index ff06e6f2ef..608dbac97f 100644 --- a/libavutil/hwcontext_d3d12va.h +++ b/libavutil/hwcontext_d3d12va.h @@ -129,6 +129,14 @@ typedef struct AVD3D12VAFramesContext { * If unset, will be automatically set. */ DXGI_FORMAT format; + +/** + * This field is used to specify options for working with resources. + * If unset, this will be D3D12_RESOURCE_FLAG_NONE. + * + * @see: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_resource_flags. + */ +D3D12_RESOURCE_FLAGS flags; } AVD3D12VAFramesContext; #endif /* AVUTIL_HWCONTEXT_D3D12VA_H */ diff --git a/libavutil/version.h b/libavutil/version.h index 1f2bddc022..ea289c406f 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 59 -#define LIBAVUTIL_VERSION_MINOR 15 +#define LIBAVUTIL_VERSION_MINOR 16 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ -- 2.41.0.windows.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 v8 15/15] Changelog: add D3D12VA HEVC encoder changelog
From: Tong Wu Signed-off-by: Tong Wu --- Changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog b/Changelog index 8db14f02b4..573e356a96 100644 --- a/Changelog +++ b/Changelog @@ -7,7 +7,7 @@ version : - ffmpeg CLI filtergraph chaining - LC3/LC3plus demuxer and muxer - pad_vaapi, drawbox_vaapi filters - +- D3D12VA HEVC encoder version 7.0: - DXV DXT1 encoder -- 2.41.0.windows.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 v8 14/15] avcodec: add D3D12VA hardware HEVC encoder
From: Tong Wu This implementation is based on D3D12 Video Encoding Spec: https://microsoft.github.io/DirectX-Specs/d3d/D3D12VideoEncoding.html Sample command line for transcoding: ffmpeg.exe -hwaccel d3d12va -hwaccel_output_format d3d12 -i input.mp4 -c:v hevc_d3d12va output.mp4 Signed-off-by: Tong Wu --- configure|6 + libavcodec/Makefile |4 +- libavcodec/allcodecs.c |1 + libavcodec/d3d12va_encode.c | 1558 ++ libavcodec/d3d12va_encode.h | 339 +++ libavcodec/d3d12va_encode_hevc.c | 1007 +++ 6 files changed, 2914 insertions(+), 1 deletion(-) create mode 100644 libavcodec/d3d12va_encode.c create mode 100644 libavcodec/d3d12va_encode.h create mode 100644 libavcodec/d3d12va_encode_hevc.c diff --git a/configure b/configure index 18eeca89f2..f11b256c80 100755 --- a/configure +++ b/configure @@ -2547,6 +2547,7 @@ CONFIG_EXTRA=" cbs_mpeg2 cbs_vp8 cbs_vp9 +d3d12va_encode deflate_wrapper dirac_parse dnn @@ -3274,6 +3275,7 @@ wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel" # hardware-accelerated codecs +d3d12va_encode_deps="d3d12va ID3D12VideoEncoder d3d12_encoder_feature" mediafoundation_deps="mftransform_h MFCreateAlignedMemoryBuffer" omx_deps="libdl pthreads" omx_rpi_select="omx" @@ -3340,6 +3342,7 @@ h264_v4l2m2m_encoder_deps="v4l2_m2m h264_v4l2_m2m" hevc_amf_encoder_deps="amf" hevc_cuvid_decoder_deps="cuvid" hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf" +hevc_d3d12va_encoder_select="cbs_h265 d3d12va_encode" hevc_mediacodec_decoder_deps="mediacodec" hevc_mediacodec_decoder_select="hevc_mp4toannexb_bsf hevc_parser" hevc_mediacodec_encoder_deps="mediacodec" @@ -6697,6 +6700,9 @@ check_type "windows.h d3d11.h" "ID3D11VideoDecoder" check_type "windows.h d3d11.h" "ID3D11VideoContext" check_type "windows.h d3d12.h" "ID3D12Device" check_type "windows.h d3d12video.h" "ID3D12VideoDecoder" +check_type "windows.h d3d12video.h" "ID3D12VideoEncoder" +test_code cc "windows.h d3d12video.h" "D3D12_FEATURE_VIDEO feature = D3D12_FEATURE_VIDEO_ENCODER_CODEC" && \ +test_code cc "windows.h d3d12video.h" "D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOURCE_REQUIREMENTS req" && enable d3d12_encoder_feature check_type "windows.h" "DPI_AWARENESS_CONTEXT" -D_WIN32_WINNT=0x0A00 check_type "d3d9.h dxva2api.h" DXVA2_ConfigPictureDecode -D_WIN32_WINNT=0x0602 check_func_headers mfapi.h MFCreateAlignedMemoryBuffer -lmfplat diff --git a/libavcodec/Makefile b/libavcodec/Makefile index a2174dcb2f..ed1fa62f92 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -84,6 +84,7 @@ OBJS-$(CONFIG_CBS_JPEG)+= cbs_jpeg.o OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o OBJS-$(CONFIG_CBS_VP8) += cbs_vp8.o vp8data.o OBJS-$(CONFIG_CBS_VP9) += cbs_vp9.o +OBJS-$(CONFIG_D3D12VA_ENCODE) += d3d12va_encode.o hw_base_encode.o OBJS-$(CONFIG_DEFLATE_WRAPPER) += zlib_wrapper.o OBJS-$(CONFIG_DOVI_RPU)+= dovi_rpu.o OBJS-$(CONFIG_ERROR_RESILIENCE)+= error_resilience.o @@ -435,6 +436,7 @@ OBJS-$(CONFIG_HEVC_DECODER)+= hevcdec.o hevc_mvs.o \ h274.o aom_film_grain.o OBJS-$(CONFIG_HEVC_AMF_ENCODER)+= amfenc_hevc.o OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o +OBJS-$(CONFIG_HEVC_D3D12VA_ENCODER)+= d3d12va_encode_hevc.o OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_HEVC_MEDIACODEC_ENCODER) += mediacodecenc.o OBJS-$(CONFIG_HEVC_MF_ENCODER) += mfenc.o mf_utils.o @@ -1264,7 +1266,7 @@ SKIPHEADERS+= %_tablegen.h \ SKIPHEADERS-$(CONFIG_AMF) += amfenc.h SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h -SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h +SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h d3d12va_encode.h SKIPHEADERS-$(CONFIG_DXVA2)+= dxva2.h dxva2_internal.h SKIPHEADERS-$(CONFIG_JNI) += ffjni.h SKIPHEADERS-$(CONFIG_LCMS2)+= fflcms2.h diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index f4705651fb..de08eb722b 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -857,6 +857,7 @@ extern const FFCodec ff_h264_vaapi_encoder; extern const FFCodec ff_h264_videotoolbox_encoder; extern const FFCodec ff_hevc_amf_encoder; extern const FFCodec ff_hevc_cuvid_decoder; +extern const FFCodec ff_hevc_d3d12va_encoder; extern const FFCodec ff_hevc_mediacodec_decoder; extern const FFCodec ff_hevc_mediacodec_encoder; extern const FFCodec ff_hevc_mf_encoder; diff --git a/libavcodec/d3d12va_encode.c b/libavcodec/d3d12va_encode.c new file mode 100644 index 00..1ef9c7a16f --- /dev/null +++ b/libavcodec/d3d12va_encode.c @@ -0,0 +1,1558 @@ +/* + * Direct3D 12 HW acceleration v
[FFmpeg-devel] [PATCH v5 1/9] avcodec/vaapi_encode: move pic->input_surface initialization to encode_alloc
From: Tong Wu When allocating the VAAPIEncodePicture, pic->input_surface can be initialized right in the place. This movement simplifies the send_frame logic and is the preparation for moving vaapi_encode_send_frame to the base layer. Signed-off-by: Tong Wu --- libavcodec/vaapi_encode.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 86f4110cd2..38d855fbd4 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -878,7 +878,8 @@ static int vaapi_encode_discard(AVCodecContext *avctx, return 0; } -static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx) +static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx, + const AVFrame *frame) { VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic; @@ -895,7 +896,7 @@ static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx) } } -pic->input_surface = VA_INVALID_ID; +pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; pic->recon_surface = VA_INVALID_ID; pic->output_buffer = VA_INVALID_ID; @@ -1332,7 +1333,7 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) if (err < 0) return err; -pic = vaapi_encode_alloc(avctx); +pic = vaapi_encode_alloc(avctx, frame); if (!pic) return AVERROR(ENOMEM); @@ -1345,7 +1346,6 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) if (ctx->input_order == 0 || frame->pict_type == AV_PICTURE_TYPE_I) pic->force_idr = 1; -pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3]; pic->pts = frame->pts; pic->duration = frame->duration; -- 2.41.0.windows.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/9] avcodec/vaapi_encode: extract set_output_property to base layer
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 40 + libavcodec/hw_base_encode.h | 3 +++ libavcodec/vaapi_encode.c | 44 ++--- 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index 62adda2fc3..f0e4ef9655 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -385,6 +385,46 @@ static int hw_base_encode_clear_old(AVCodecContext *avctx) return 0; } +int ff_hw_base_encode_set_output_property(AVCodecContext *avctx, + HWBaseEncodePicture *pic, + AVPacket *pkt, int flag_no_delay) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; + +if (pic->type == PICTURE_TYPE_IDR) +pkt->flags |= AV_PKT_FLAG_KEY; + +pkt->pts = pic->pts; +pkt->duration = pic->duration; + +// for no-delay encoders this is handled in generic codec +if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY && +avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { +pkt->opaque = pic->opaque; +pkt->opaque_ref = pic->opaque_ref; +pic->opaque_ref = NULL; +} + +if (flag_no_delay) { +pkt->dts = pkt->pts; +return 0; +} + +if (ctx->output_delay == 0) { +pkt->dts = pkt->pts; +} else if (pic->encode_order < ctx->decode_delay) { +if (ctx->ts_ring[pic->encode_order] < INT64_MIN + ctx->dts_pts_diff) +pkt->dts = INT64_MIN; +else +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 + ctx->async_depth)]; +} + +return 0; +} + static int hw_base_encode_check_frame(AVCodecContext *avctx, const AVFrame *frame) { diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 70982c97b2..b836b22e6b 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -237,6 +237,9 @@ typedef struct HWBaseEncodeContext { AVPacket*tail_pkt; } HWBaseEncodeContext; +int ff_hw_base_encode_set_output_property(AVCodecContext *avctx, HWBaseEncodePicture *pic, + AVPacket *pkt, int flag_no_delay); + int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); int ff_hw_base_encode_init(AVCodecContext *avctx); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index e2f968c36d..2d839a1202 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -668,47 +668,6 @@ fail_at_end: return err; } -static int vaapi_encode_set_output_property(AVCodecContext *avctx, -HWBaseEncodePicture *pic, -AVPacket *pkt) -{ -HWBaseEncodeContext *base_ctx = avctx->priv_data; -VAAPIEncodeContext *ctx = avctx->priv_data; - -if (pic->type == PICTURE_TYPE_IDR) -pkt->flags |= AV_PKT_FLAG_KEY; - -pkt->pts = pic->pts; -pkt->duration = pic->duration; - -// for no-delay encoders this is handled in generic codec -if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY && -avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { -pkt->opaque = pic->opaque; -pkt->opaque_ref = pic->opaque_ref; -pic->opaque_ref = NULL; -} - -if (ctx->codec->flags & FLAG_TIMESTAMP_NO_DELAY) { -pkt->dts = pkt->pts; -return 0; -} - -if (base_ctx->output_delay == 0) { -pkt->dts = pkt->pts; -} else if (pic->encode_order < base_ctx->decode_delay) { -if (base_ctx->ts_ring[pic->encode_order] < INT64_MIN + base_ctx->dts_pts_diff) -pkt->dts = INT64_MIN; -else -pkt->dts = base_ctx->ts_ring[pic->encode_order] - base_ctx->dts_pts_diff; -} else { -pkt->dts = base_ctx->ts_ring[(pic->encode_order - base_ctx->decode_delay) % - (3 * base_ctx->output_delay + base_ctx->async_depth)]; -} - -return 0; -} - static int vaapi_encode_get_coded_buffer_size(AVCodecContext *avctx, VABufferID buf_id) { VAAPIEncodeContext *ctx = avctx->priv_data; @@ -860,7 +819,8 @@ static int vaapi_encode_output(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n", base_pic->display_order, base_pic->encode_order); -vaapi_encode_set_output_property(avctx, base_pic, pkt_ptr); +ff_hw_base_encode_set_output_property(avctx, base_pic, pkt_ptr, + ctx->codec->flags & FLAG_TIMESTAMP_NO_DELAY); end: ff_refstruct_unref(&pic->output_buffer_ref); -- 2.41.0.windows.1 ___ ffmpeg-devel
[FFmpeg-devel] [PATCH v5 4/9] avcodec/vaapi_encode: extract rc parameter configuration to base layer
From: Tong Wu VAAPI and D3D12VA can share rate control configuration codes. Hence, it can be moved to base layer for simplification. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c| 151 libavcodec/hw_base_encode.h| 34 ++ libavcodec/vaapi_encode.c | 210 ++--- libavcodec/vaapi_encode.h | 14 +-- libavcodec/vaapi_encode_av1.c | 2 +- libavcodec/vaapi_encode_h264.c | 2 +- libavcodec/vaapi_encode_vp9.c | 2 +- 7 files changed, 227 insertions(+), 188 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index f0e4ef9655..c20c47bf55 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -631,6 +631,157 @@ end: return 0; } +int ff_hw_base_rc_mode_configure(AVCodecContext *avctx, const HWBaseEncodeRCMode *rc_mode, + int default_quality, HWBaseEncodeRCConfigure *rc_conf) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; + +if (!rc_mode || !rc_conf) +return -1; + +if (rc_mode->bitrate) { +if (avctx->bit_rate <= 0) { +av_log(avctx, AV_LOG_ERROR, "Bitrate must be set for %s " + "RC mode.\n", rc_mode->name); +return AVERROR(EINVAL); +} + +if (rc_mode->mode == RC_MODE_AVBR) { +// For maximum confusion AVBR is hacked into the existing API +// by overloading some of the fields with completely different +// meanings. + +// Target percentage does not apply in AVBR mode. +rc_conf->rc_bits_per_second = avctx->bit_rate; + +// Accuracy tolerance range for meeting the specified target +// bitrate. It's very unclear how this is actually intended +// to work - since we do want to get the specified bitrate, +// set the accuracy to 100% for now. +rc_conf->rc_target_percentage = 100; + +// Convergence period in frames. The GOP size reflects the +// user's intended block size for cutting, so reusing that +// as the convergence period seems a reasonable default. +rc_conf->rc_window_size = avctx->gop_size > 0 ? avctx->gop_size : 60; + +} else if (rc_mode->maxrate) { +if (avctx->rc_max_rate > 0) { +if (avctx->rc_max_rate < avctx->bit_rate) { +av_log(avctx, AV_LOG_ERROR, "Invalid bitrate settings: " + "bitrate (%"PRId64") must not be greater than " + "maxrate (%"PRId64").\n", avctx->bit_rate, + avctx->rc_max_rate); +return AVERROR(EINVAL); +} +rc_conf->rc_bits_per_second = avctx->rc_max_rate; +rc_conf->rc_target_percentage = (avctx->bit_rate * 100) / + avctx->rc_max_rate; +} else { +// We only have a target bitrate, but this mode requires +// that a maximum rate be supplied as well. Since the +// user does not want this to be a constraint, arbitrarily +// pick a maximum rate of double the target rate. +rc_conf->rc_bits_per_second = 2 * avctx->bit_rate; +rc_conf->rc_target_percentage = 50; +} +} else { +if (avctx->rc_max_rate > avctx->bit_rate) { +av_log(avctx, AV_LOG_WARNING, "Max bitrate is ignored " + "in %s RC mode.\n", rc_mode->name); +} +rc_conf->rc_bits_per_second = avctx->bit_rate; +rc_conf->rc_target_percentage = 100; +} +} else { +rc_conf->rc_bits_per_second = 0; +rc_conf->rc_target_percentage = 100; +} + +if (rc_mode->quality) { +if (ctx->explicit_qp) { +rc_conf->rc_quality = ctx->explicit_qp; +} else if (avctx->global_quality > 0) { +rc_conf->rc_quality = avctx->global_quality; +} else { +rc_conf->rc_quality = default_quality; +av_log(avctx, AV_LOG_WARNING, "No quality level set; " + "using default (%d).\n", rc_conf->rc_quality); +} +} else { +rc_conf->rc_quality = 0; +} + +if (rc_mode->hrd) { +if (avctx->rc_buffer_size) +rc_conf->hrd_buffer_size = avctx->rc_buffer_size; +else if (avctx->rc_max_rate > 0) +rc_conf->hrd_buffer_size = avctx->rc_max_rate; +else +rc_conf->hrd_buffer_size = avctx->bit_rate; +if (avctx->rc_initial_buffer_occupancy) { +if (avctx->rc_initial_buffer_occupancy > rc_conf->hrd_buffer_size) { +av_log(avctx, AV_LOG_ERROR, "Invalid RC buffer settings: " + "must have initial buffer size (%d) <= " + "buffer size (%"
[FFmpeg-devel] [PATCH v5 5/9] avcodec/vaapi_encode: extract gop configuration to base layer
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 54 + libavcodec/hw_base_encode.h | 3 +++ libavcodec/vaapi_encode.c | 52 +++ 3 files changed, 61 insertions(+), 48 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index c20c47bf55..bb9fe70239 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -782,6 +782,60 @@ int ff_hw_base_rc_mode_configure(AVCodecContext *avctx, const HWBaseEncodeRCMode return 0; } +int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, + int flags, int prediction_pre_only) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; + +if (flags & FLAG_INTRA_ONLY || avctx->gop_size <= 1) { +av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n"); +ctx->gop_size = 1; +} else if (ref_l0 < 1) { +av_log(avctx, AV_LOG_ERROR, "Driver does not support any " + "reference frames.\n"); +return AVERROR(EINVAL); +} else if (!(flags & FLAG_B_PICTURES) || ref_l1 < 1 || + avctx->max_b_frames < 1 || prediction_pre_only) { +if (ctx->p_to_gpb) + av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " + "(supported references: %d / %d).\n", + ref_l0, ref_l1); +else +av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames " + "(supported references: %d / %d).\n", ref_l0, ref_l1); +ctx->gop_size = avctx->gop_size; +ctx->p_per_i = INT_MAX; +ctx->b_per_p = 0; +} else { + if (ctx->p_to_gpb) + av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " + "(supported references: %d / %d).\n", + ref_l0, ref_l1); + else + av_log(avctx, AV_LOG_VERBOSE, "Using intra, P- and B-frames " + "(supported references: %d / %d).\n", ref_l0, ref_l1); +ctx->gop_size = avctx->gop_size; +ctx->p_per_i = INT_MAX; +ctx->b_per_p = avctx->max_b_frames; +if (flags & FLAG_B_PICTURE_REFERENCES) { +ctx->max_b_depth = FFMIN(ctx->desired_b_depth, + av_log2(ctx->b_per_p) + 1); +} else { +ctx->max_b_depth = 1; +} +} + +if (flags & FLAG_NON_IDR_KEY_PICTURES) { +ctx->closed_gop = !!(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP); +ctx->gop_per_idr = ctx->idr_interval + 1; +} else { +ctx->closed_gop = 1; +ctx->gop_per_idr = 1; +} + +return 0; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { HWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index 4072b514d3..ca72b7e118 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -276,6 +276,9 @@ int ff_hw_base_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt); int ff_hw_base_rc_mode_configure(AVCodecContext *avctx, const HWBaseEncodeRCMode *rc_mode, int default_quality, HWBaseEncodeRCConfigure *rc_conf); +int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, + int flags, int prediction_pre_only); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 30e5deac08..0bce3ce105 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1443,7 +1443,7 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) VAStatus vas; VAConfigAttrib attr = { VAConfigAttribEncMaxRefFrames }; uint32_t ref_l0, ref_l1; -int prediction_pre_only; +int prediction_pre_only, err; vas = vaGetConfigAttributes(ctx->hwctx->display, ctx->va_profile, @@ -1507,53 +1507,9 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) } #endif -if (ctx->codec->flags & FLAG_INTRA_ONLY || -avctx->gop_size <= 1) { -av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n"); -base_ctx->gop_size = 1; -} else if (ref_l0 < 1) { -av_log(avctx, AV_LOG_ERROR, "Driver does not support any " - "reference frames.\n"); -return AVERROR(EINVAL); -} else if (!(ctx->codec->flags & FLAG_B_PICTURES) || - ref_l1 < 1 || avctx->max_b_frames < 1 || - prediction_pre_only) { -if (base_ctx->p_to_gpb) - av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " - "(supported references: %d / %d).\n", - ref_l0, ref_l1); -else -av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames
[FFmpeg-devel] [PATCH v5 6/9] avcodec/vaapi_encode: extract a get_recon_format function to base layer
From: Tong Wu Get constraints and set recon frame format can be shared with other HW encoder such as D3D12. Extract this part as a new function to base layer. Signed-off-by: Tong Wu --- libavcodec/hw_base_encode.c | 58 + libavcodec/hw_base_encode.h | 2 ++ libavcodec/vaapi_encode.c | 51 ++-- 3 files changed, 63 insertions(+), 48 deletions(-) diff --git a/libavcodec/hw_base_encode.c b/libavcodec/hw_base_encode.c index bb9fe70239..7497e0397e 100644 --- a/libavcodec/hw_base_encode.c +++ b/libavcodec/hw_base_encode.c @@ -836,6 +836,64 @@ int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32 return 0; } +int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt) +{ +HWBaseEncodeContext *ctx = avctx->priv_data; +AVHWFramesConstraints *constraints = NULL; +enum AVPixelFormat recon_format; +int err, i; + +constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref, + hwconfig); +if (!constraints) { +err = AVERROR(ENOMEM); +goto fail; +} + +// Probably we can use the input surface format as the surface format +// of the reconstructed frames. If not, we just pick the first (only?) +// format in the valid list and hope that it all works. +recon_format = AV_PIX_FMT_NONE; +if (constraints->valid_sw_formats) { +for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { +if (ctx->input_frames->sw_format == +constraints->valid_sw_formats[i]) { +recon_format = ctx->input_frames->sw_format; +break; +} +} +if (recon_format == AV_PIX_FMT_NONE) { +// No match. Just use the first in the supported list and +// hope for the best. +recon_format = constraints->valid_sw_formats[0]; +} +} else { +// No idea what to use; copy input format. +recon_format = ctx->input_frames->sw_format; +} +av_log(avctx, AV_LOG_DEBUG, "Using %s as format of " + "reconstructed frames.\n", av_get_pix_fmt_name(recon_format)); + +if (ctx->surface_width < constraints->min_width || +ctx->surface_height < constraints->min_height || +ctx->surface_width > constraints->max_width || +ctx->surface_height > constraints->max_height) { +av_log(avctx, AV_LOG_ERROR, "Hardware does not support encoding at " + "size %dx%d (constraints: width %d-%d height %d-%d).\n", + ctx->surface_width, ctx->surface_height, + constraints->min_width, constraints->max_width, + constraints->min_height, constraints->max_height); +err = AVERROR(EINVAL); +goto fail; +} + +*fmt = recon_format; +err = 0; +fail: +av_hwframe_constraints_free(&constraints); +return err; +} + int ff_hw_base_encode_init(AVCodecContext *avctx) { HWBaseEncodeContext *ctx = avctx->priv_data; diff --git a/libavcodec/hw_base_encode.h b/libavcodec/hw_base_encode.h index ca72b7e118..e0133d65f0 100644 --- a/libavcodec/hw_base_encode.h +++ b/libavcodec/hw_base_encode.h @@ -279,6 +279,8 @@ int ff_hw_base_rc_mode_configure(AVCodecContext *avctx, const HWBaseEncodeRCMode int ff_hw_base_init_gop_structure(AVCodecContext *avctx, uint32_t ref_l0, uint32_t ref_l1, int flags, int prediction_pre_only); +int ff_hw_base_get_recon_format(AVCodecContext *avctx, const void *hwconfig, enum AVPixelFormat *fmt); + int ff_hw_base_encode_init(AVCodecContext *avctx); int ff_hw_base_encode_close(AVCodecContext *avctx); diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 0bce3ce105..84a81559e1 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -1898,9 +1898,8 @@ static av_cold int vaapi_encode_create_recon_frames(AVCodecContext *avctx) HWBaseEncodeContext *base_ctx = avctx->priv_data; VAAPIEncodeContext *ctx = avctx->priv_data; AVVAAPIHWConfig *hwconfig = NULL; -AVHWFramesConstraints *constraints = NULL; enum AVPixelFormat recon_format; -int err, i; +int err; hwconfig = av_hwdevice_hwconfig_alloc(base_ctx->device_ref); if (!hwconfig) { @@ -1909,52 +1908,9 @@ static av_cold int vaapi_encode_create_recon_frames(AVCodecContext *avctx) } hwconfig->config_id = ctx->va_config; -constraints = av_hwdevice_get_hwframe_constraints(base_ctx->device_ref, - hwconfig); -if (!constraints) { -err = AVERROR(ENOMEM); -goto fail; -} - -// Probably we can use the input surface format as the surface format -// of the reconstructed frames. If not, we just pick the first (only?) -// format in the valid list and hope that it all w
[FFmpeg-devel] [PATCH v5 9/9] Changelog: add D3D12VA HEVC encoder changelog
From: Tong Wu Signed-off-by: Tong Wu --- Changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog b/Changelog index c5fb21d198..6923c451c5 100644 --- a/Changelog +++ b/Changelog @@ -24,6 +24,7 @@ version : - ffmpeg CLI options may now be used as -/opt , which is equivalent to -opt > - showinfo bitstream filter +- D3D12VA HEVC encoder version 6.1: - libaribcaption decoder -- 2.41.0.windows.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 7/9] avutil/hwcontext_d3d12va: add Flags for resource creation
From: Tong Wu Flags field is added to support diffferent resource creation. Signed-off-by: Tong Wu --- doc/APIchanges| 3 +++ libavutil/hwcontext_d3d12va.c | 2 +- libavutil/hwcontext_d3d12va.h | 8 libavutil/version.h | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 4e94132cf0..e1ed7334db 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2023-02-09 API changes, most recent first: +2024-01-xx - xx - lavu 58.40.100 - hwcontext_d3d12va.h + Add AVD3D12VAFramesContext.flags + 2024-02-16 - xx - lavu 58.39.100 - pixfmt.h Add AV_VIDEO_MAX_PLANES diff --git a/libavutil/hwcontext_d3d12va.c b/libavutil/hwcontext_d3d12va.c index 3acd5ac43a..b9984a4151 100644 --- a/libavutil/hwcontext_d3d12va.c +++ b/libavutil/hwcontext_d3d12va.c @@ -237,7 +237,7 @@ static AVBufferRef *d3d12va_pool_alloc(void *opaque, size_t size) .Format = hwctx->format, .SampleDesc = {.Count = 1, .Quality = 0 }, .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, -.Flags= D3D12_RESOURCE_FLAG_NONE, +.Flags= hwctx->flags, }; frame = av_mallocz(sizeof(AVD3D12VAFrame)); diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h index ff06e6f2ef..608dbac97f 100644 --- a/libavutil/hwcontext_d3d12va.h +++ b/libavutil/hwcontext_d3d12va.h @@ -129,6 +129,14 @@ typedef struct AVD3D12VAFramesContext { * If unset, will be automatically set. */ DXGI_FORMAT format; + +/** + * This field is used to specify options for working with resources. + * If unset, this will be D3D12_RESOURCE_FLAG_NONE. + * + * @see: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_resource_flags. + */ +D3D12_RESOURCE_FLAGS flags; } AVD3D12VAFramesContext; #endif /* AVUTIL_HWCONTEXT_D3D12VA_H */ diff --git a/libavutil/version.h b/libavutil/version.h index 9f45af93df..3fbc292a68 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 58 -#define LIBAVUTIL_VERSION_MINOR 39 +#define LIBAVUTIL_VERSION_MINOR 40 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ -- 2.41.0.windows.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 8/9] avcodec: add D3D12VA hardware HEVC encoder
From: Tong Wu This implementation is based on D3D12 Video Encoding Spec: https://microsoft.github.io/DirectX-Specs/d3d/D3D12VideoEncoding.html Sample command line for transcoding: ffmpeg.exe -hwaccel d3d12va -hwaccel_output_format d3d12 -i input.mp4 -c:v hevc_d3d12va output.mp4 Signed-off-by: Tong Wu --- configure|6 + libavcodec/Makefile |4 +- libavcodec/allcodecs.c |1 + libavcodec/d3d12va_encode.c | 1443 ++ libavcodec/d3d12va_encode.h | 275 ++ libavcodec/d3d12va_encode_hevc.c | 1013 + libavcodec/hw_base_encode.h |2 +- 7 files changed, 2742 insertions(+), 2 deletions(-) create mode 100644 libavcodec/d3d12va_encode.c create mode 100644 libavcodec/d3d12va_encode.h create mode 100644 libavcodec/d3d12va_encode_hevc.c diff --git a/configure b/configure index f72533b7d2..682576aa91 100755 --- a/configure +++ b/configure @@ -2564,6 +2564,7 @@ CONFIG_EXTRA=" tpeldsp vaapi_1 vaapi_encode +d3d12va_encode vc1dsp videodsp vp3dsp @@ -3208,6 +3209,7 @@ wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel" wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel" # hardware-accelerated codecs +d3d12va_encode_deps="d3d12va ID3D12VideoEncoder d3d12_encoder_feature" mediafoundation_deps="mftransform_h MFCreateAlignedMemoryBuffer" omx_deps="libdl pthreads" omx_rpi_select="omx" @@ -3275,6 +3277,7 @@ h264_v4l2m2m_encoder_deps="v4l2_m2m h264_v4l2_m2m" hevc_amf_encoder_deps="amf" hevc_cuvid_decoder_deps="cuvid" hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf" +hevc_d3d12va_encoder_select="atsc_a53 cbs_h265 d3d12va_encode" hevc_mediacodec_decoder_deps="mediacodec" hevc_mediacodec_decoder_select="hevc_mp4toannexb_bsf hevc_parser" hevc_mediacodec_encoder_deps="mediacodec" @@ -6617,6 +6620,9 @@ check_type "windows.h d3d11.h" "ID3D11VideoDecoder" check_type "windows.h d3d11.h" "ID3D11VideoContext" check_type "windows.h d3d12.h" "ID3D12Device" check_type "windows.h d3d12video.h" "ID3D12VideoDecoder" +check_type "windows.h d3d12video.h" "ID3D12VideoEncoder" +test_code cc "windows.h d3d12video.h" "D3D12_FEATURE_VIDEO feature = D3D12_FEATURE_VIDEO_ENCODER_CODEC" && \ +test_code cc "windows.h d3d12video.h" "D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOURCE_REQUIREMENTS req" && enable d3d12_encoder_feature check_type "windows.h" "DPI_AWARENESS_CONTEXT" -D_WIN32_WINNT=0x0A00 check_type "d3d9.h dxva2api.h" DXVA2_ConfigPictureDecode -D_WIN32_WINNT=0x0602 check_func_headers mfapi.h MFCreateAlignedMemoryBuffer -lmfplat diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 23946f6ea3..50590b34f4 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -86,6 +86,7 @@ OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o OBJS-$(CONFIG_CBS_VP8) += cbs_vp8.o vp8data.o OBJS-$(CONFIG_CBS_VP9) += cbs_vp9.o OBJS-$(CONFIG_CRYSTALHD) += crystalhd.o +OBJS-$(CONFIG_D3D12VA_ENCODE) += d3d12va_encode.o hw_base_encode.o OBJS-$(CONFIG_DEFLATE_WRAPPER) += zlib_wrapper.o OBJS-$(CONFIG_DOVI_RPU)+= dovi_rpu.o OBJS-$(CONFIG_ERROR_RESILIENCE)+= error_resilience.o @@ -437,6 +438,7 @@ OBJS-$(CONFIG_HEVC_DECODER)+= hevcdec.o hevc_mvs.o \ h274.o OBJS-$(CONFIG_HEVC_AMF_ENCODER)+= amfenc_hevc.o OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o +OBJS-$(CONFIG_HEVC_D3D12VA_ENCODER)+= d3d12va_encode_hevc.o OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_HEVC_MEDIACODEC_ENCODER) += mediacodecenc.o OBJS-$(CONFIG_HEVC_MF_ENCODER) += mfenc.o mf_utils.o @@ -1267,7 +1269,7 @@ SKIPHEADERS+= %_tablegen.h \ SKIPHEADERS-$(CONFIG_AMF) += amfenc.h SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h -SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h +SKIPHEADERS-$(CONFIG_D3D12VA) += d3d12va_decode.h d3d12va_encode.h SKIPHEADERS-$(CONFIG_DXVA2)+= dxva2.h dxva2_internal.h SKIPHEADERS-$(CONFIG_JNI) += ffjni.h SKIPHEADERS-$(CONFIG_LCMS2)+= fflcms2.h diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index ef8c3a6d7d..9a34974141 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -865,6 +865,7 @@ extern const FFCodec ff_h264_vaapi_encoder; extern const FFCodec ff_h264_videotoolbox_encoder; extern const FFCodec ff_hevc_amf_encoder; extern const FFCodec ff_hevc_cuvid_decoder; +extern const FFCodec ff_hevc_d3d12va_encoder; extern const FFCodec ff_hevc_mediacodec_decoder; extern const FFCodec ff_hevc_mediacodec_encoder; extern const FFCodec ff_hevc_mf_encoder; diff --git a/libavcodec/d3d12va_encode.c b/libavcodec/d3d12va_encode.c new file mode 100644 index 00..24898dbcb1 --- /dev/null +++ b/libavcodec/d3d12va_encode.c @@ -0,0 +1,1443 @@ +/*
[FFmpeg-devel] [PATCH] avcodec/vaapi_encode: remove a duplicate av_freep
From: Tong Wu Signed-off-by: Tong Wu --- libavcodec/vaapi_encode.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 86f4110cd2..808b79c0c7 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -914,7 +914,6 @@ static int vaapi_encode_free(AVCodecContext *avctx, for (i = 0; i < pic->nb_slices; i++) av_freep(&pic->slices[i].codec_slice_params); } -av_freep(&pic->codec_picture_params); av_frame_free(&pic->input_image); av_frame_free(&pic->recon_image); -- 2.41.0.windows.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/2] avcodec/vaapi_encode_h264: use is_reference to fill reference_pic_flag
From: Tong Wu This codec supports FLAG_B_PICTURE_REFERENCES. We need to correctly fill the reference_pic_flag with is_reference variable instead of 0 for B frames. Signed-off-by: Tong Wu --- libavcodec/vaapi_encode_h264.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 37df9103ae..4a738215c1 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -759,7 +759,7 @@ static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx, vpic->frame_num = hpic->frame_num; vpic->pic_fields.bits.idr_pic_flag = (pic->type == PICTURE_TYPE_IDR); -vpic->pic_fields.bits.reference_pic_flag = (pic->type != PICTURE_TYPE_B); +vpic->pic_fields.bits.reference_pic_flag = pic->is_reference; return 0; } -- 2.41.0.windows.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".