From d3a203c969077993faa5b6dda97e9e7cea55eddc Mon Sep 17 00:00:00 2001 From: Feng Jiang Date: Thu, 29 Sep 2022 11:38:20 +0800 Subject: [PATCH] virgl/video: Add support for H.264 encoding Implement encoding framework and support H.264 encoding. Signed-off-by: Feng Jiang Signed-off-by: Ming Xie Signed-off-by: Liming Sun Reviewed-by: Gert Wollny Reviewed-by: Boyuan Zhang Part-of: --- src/gallium/drivers/virgl/virgl_encode.c | 13 ++ src/gallium/drivers/virgl/virgl_encode.h | 5 + src/gallium/drivers/virgl/virgl_video.c | 268 +++++++++++++++++++++-- src/gallium/drivers/virgl/virgl_video.h | 3 + src/virtio/virtio-gpu/virgl_protocol.h | 16 +- src/virtio/virtio-gpu/virgl_video_hw.h | 136 ++++++++++++ 6 files changed, 423 insertions(+), 18 deletions(-) diff --git a/src/gallium/drivers/virgl/virgl_encode.c b/src/gallium/drivers/virgl/virgl_encode.c index 364f92b5911..7e7e10b6e53 100644 --- a/src/gallium/drivers/virgl/virgl_encode.c +++ b/src/gallium/drivers/virgl/virgl_encode.c @@ -1706,6 +1706,19 @@ void virgl_encode_decode_bitstream(struct virgl_context *ctx, virgl_encoder_write_dword(ctx->cbuf, cdc->bs_size); } +void virgl_encode_encode_bitstream(struct virgl_context *ctx, + struct virgl_video_codec *cdc, + struct virgl_video_buffer *buf, + struct virgl_resource *tgt) +{ + virgl_encoder_write_cmd_dword(ctx, VIRGL_CMD0(VIRGL_CCMD_ENCODE_BITSTREAM, 0, 5)); + virgl_encoder_write_dword(ctx->cbuf, cdc->handle); + virgl_encoder_write_dword(ctx->cbuf, buf->handle); + virgl_encoder_write_res(ctx, tgt); + virgl_encoder_write_res(ctx, virgl_resource(cdc->desc_buffers[cdc->cur_buffer])); + virgl_encoder_write_res(ctx, virgl_resource(cdc->feed_buffers[cdc->cur_buffer])); +} + void virgl_encode_end_frame(struct virgl_context *ctx, struct virgl_video_codec *cdc, struct virgl_video_buffer *buf) diff --git a/src/gallium/drivers/virgl/virgl_encode.h b/src/gallium/drivers/virgl/virgl_encode.h index 90fe8d1ffe5..bcb0ad60c42 100644 --- a/src/gallium/drivers/virgl/virgl_encode.h +++ b/src/gallium/drivers/virgl/virgl_encode.h @@ -340,6 +340,11 @@ void virgl_encode_decode_bitstream(struct virgl_context *ctx, struct virgl_video_buffer *buf, void *desc, uint32_t desc_size); +void virgl_encode_encode_bitstream(struct virgl_context *ctx, + struct virgl_video_codec *cdc, + struct virgl_video_buffer *buf, + struct virgl_resource *tgt); + void virgl_encode_end_frame(struct virgl_context *ctx, struct virgl_video_codec *cdc, struct virgl_video_buffer *buf); diff --git a/src/gallium/drivers/virgl/virgl_video.c b/src/gallium/drivers/virgl/virgl_video.c index b1b5750a7cd..128ddf33e5f 100644 --- a/src/gallium/drivers/virgl/virgl_video.c +++ b/src/gallium/drivers/virgl/virgl_video.c @@ -21,6 +21,50 @@ * USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/** + * @file + * Virgl video driver implementation. + * + * The virgl video driver acts as the frontend, and the virglrenderer acts as + * the backend. Currently, the backend is implemented via VA-API, but it is + * not limited to this. + * + * The relationship between vaSurface and video buffer objects: + * + * GUEST (Mesa) | HOST (Virglrenderer) + * | + * +------------+ | +------------+ + * | vaSurface | | | vaSurface | <------+ + * +------------+ | +------------+ | + * | | | + * +---------------------------+ | +-------------------------+ | + * | virgl_video_buffer | | | vrend_video_buffer | | + * | +-----------------------+ | | | +-------------------+ | | + * | | vl_video_buffer | | | | | vrend_resource(s) | | | + * | | +-------------------+ | |<--+-->| +-------------------+ | | + * | | | virgl_resource(s) | | | | | +--------------------+ | | + * | | +-------------------+ | | | | | virgl_video_buffer |-+--+ + * | +-----------------------+ | | | +--------------------+ | + * +---------------------------+ | +-------------------------+ + * + * The relationship between vaContext and video codec objects: + * + * GUEST (Mesa) | HOST (Virglrenderer) + * | + * +------------+ | +------------+ + * | vaContext | | | vaContext | <-------+ + * +------------+ | +------------+ | + * | | | + * +------------------------+ | +--------------------------+ | + * | virgl_video_codec | <--+--> | vrend_video_codec | | + * +------------------------+ | | +--------------------+ | | + * | | | virgl_video_codec | -+--+ + * | | +--------------------+ | + * | +--------------------------+ + * + * @author Feng Jiang + */ + #include #include @@ -149,6 +193,112 @@ static int fill_h264_picture_desc(const struct pipe_picture_desc *desc, return 0; } +static int fill_h264_enc_picture_desc(const struct pipe_picture_desc *desc, + union virgl_picture_desc *vdsc) +{ + unsigned i; + struct virgl_h264_enc_picture_desc *vh264 = &vdsc->h264_enc; + struct pipe_h264_enc_picture_desc *h264 = (struct pipe_h264_enc_picture_desc *)desc; + + fill_base_picture_desc(desc, &vh264->base); + + /* seq param */ + ITEM_SET(vh264, h264, seq.enc_constraint_set_flags); + ITEM_SET(vh264, h264, seq.enc_frame_cropping_flag); + ITEM_SET(vh264, h264, seq.enc_frame_crop_left_offset); + ITEM_SET(vh264, h264, seq.enc_frame_crop_right_offset); + ITEM_SET(vh264, h264, seq.enc_frame_crop_top_offset); + ITEM_SET(vh264, h264, seq.enc_frame_crop_bottom_offset); + ITEM_SET(vh264, h264, seq.pic_order_cnt_type); + ITEM_SET(vh264, h264, seq.num_temporal_layers); + ITEM_SET(vh264, h264, seq.vui_parameters_present_flag); + ITEM_SET(vh264, h264, seq.vui_flags.aspect_ratio_info_present_flag); + ITEM_SET(vh264, h264, seq.vui_flags.timing_info_present_flag); + ITEM_SET(vh264, h264, seq.aspect_ratio_idc); + ITEM_SET(vh264, h264, seq.sar_width); + ITEM_SET(vh264, h264, seq.sar_height); + ITEM_SET(vh264, h264, seq.num_units_in_tick); + ITEM_SET(vh264, h264, seq.time_scale); + + /* rate_ctrl */ + for (i = 0; i < 4; i++) { + ITEM_SET(vh264, h264, rate_ctrl[i].rate_ctrl_method); + ITEM_SET(vh264, h264, rate_ctrl[i].target_bitrate); + ITEM_SET(vh264, h264, rate_ctrl[i].peak_bitrate); + ITEM_SET(vh264, h264, rate_ctrl[i].frame_rate_num); + ITEM_SET(vh264, h264, rate_ctrl[i].frame_rate_den); + ITEM_SET(vh264, h264, rate_ctrl[i].vbv_buffer_size); + ITEM_SET(vh264, h264, rate_ctrl[i].vbv_buf_lv); + ITEM_SET(vh264, h264, rate_ctrl[i].target_bits_picture); + ITEM_SET(vh264, h264, rate_ctrl[i].peak_bits_picture_integer); + ITEM_SET(vh264, h264, rate_ctrl[i].peak_bits_picture_fraction); + ITEM_SET(vh264, h264, rate_ctrl[i].fill_data_enable); + ITEM_SET(vh264, h264, rate_ctrl[i].skip_frame_enable); + ITEM_SET(vh264, h264, rate_ctrl[i].enforce_hrd); + ITEM_SET(vh264, h264, rate_ctrl[i].max_au_size); + ITEM_SET(vh264, h264, rate_ctrl[i].max_qp); + ITEM_SET(vh264, h264, rate_ctrl[i].min_qp); + } + + /* motion_est */ + ITEM_SET(vh264, h264, motion_est.motion_est_quarter_pixel); + ITEM_SET(vh264, h264, motion_est.enc_disable_sub_mode); + ITEM_SET(vh264, h264, motion_est.lsmvert); + ITEM_SET(vh264, h264, motion_est.enc_en_ime_overw_dis_subm); + ITEM_SET(vh264, h264, motion_est.enc_ime_overw_dis_subm_no); + ITEM_SET(vh264, h264, motion_est.enc_ime2_search_range_x); + ITEM_SET(vh264, h264, motion_est.enc_ime2_search_range_y); + + /* pic_ctrl */ + ITEM_SET(vh264, h264, pic_ctrl.enc_cabac_enable); + ITEM_SET(vh264, h264, pic_ctrl.enc_cabac_init_idc); + + ITEM_SET(vh264, h264, intra_idr_period); + + ITEM_SET(vh264, h264, quant_i_frames); + ITEM_SET(vh264, h264, quant_p_frames); + ITEM_SET(vh264, h264, quant_b_frames); + + ITEM_SET(vh264, h264, picture_type); + ITEM_SET(vh264, h264, frame_num); + ITEM_SET(vh264, h264, frame_num_cnt); + ITEM_SET(vh264, h264, p_remain); + ITEM_SET(vh264, h264, i_remain); + ITEM_SET(vh264, h264, idr_pic_id); + ITEM_SET(vh264, h264, gop_cnt); + ITEM_SET(vh264, h264, pic_order_cnt); + ITEM_SET(vh264, h264, num_ref_idx_l0_active_minus1); + ITEM_SET(vh264, h264, num_ref_idx_l1_active_minus1); + + for (i = 0; i < 32; i++) { + ITEM_SET(vh264, h264, ref_idx_l0_list[i]); + ITEM_SET(vh264, h264, ref_idx_l1_list[i]); + ITEM_SET(vh264, h264, l0_is_long_term[i]); + ITEM_SET(vh264, h264, l1_is_long_term[i]); + } + + ITEM_SET(vh264, h264, gop_size); + + ITEM_SET(vh264, h264, quality_modes.level); + ITEM_SET(vh264, h264, quality_modes.preset_mode); + ITEM_SET(vh264, h264, quality_modes.pre_encode_mode); + ITEM_SET(vh264, h264, quality_modes.vbaq_mode); + + ITEM_SET(vh264, h264, not_referenced); + ITEM_SET(vh264, h264, is_ltr); + ITEM_SET(vh264, h264, ltr_index); + ITEM_SET(vh264, h264, enable_vui); + + ITEM_SET(vh264, h264, num_slice_descriptors); + for (i = 0; i < vh264->num_slice_descriptors; i++) { + ITEM_SET(vh264, h264, slices_descriptors[i].macroblock_address); + ITEM_SET(vh264, h264, slices_descriptors[i].num_macroblocks); + ITEM_SET(vh264, h264, slices_descriptors[i].slice_type); + } + + return 0; +} + static int fill_h265_picture_desc(const struct pipe_picture_desc *desc, union virgl_picture_desc *vdsc) { @@ -312,6 +462,17 @@ static int fill_picture_desc(const struct pipe_picture_desc *desc, } } +static int fill_enc_picture_desc(const struct pipe_picture_desc *desc, + union virgl_picture_desc *vdsc) +{ + switch (u_reduce_video_profile(desc->profile)) { + case PIPE_VIDEO_FORMAT_MPEG4_AVC: + return fill_h264_enc_picture_desc(desc, vdsc); + default: + return -1; + } +} + static void virgl_video_begin_frame(struct pipe_video_codec *codec, struct pipe_video_buffer *target, struct pipe_picture_desc *picture) @@ -319,6 +480,9 @@ static void virgl_video_begin_frame(struct pipe_video_codec *codec, struct virgl_video_codec *vcdc = virgl_video_codec(codec); struct virgl_video_buffer *vbuf = virgl_video_buffer(target); + if (codec->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) + fill_enc_picture_desc(picture, &vcdc->desc); + virgl_encode_begin_frame(vcdc->vctx, vcdc, vbuf); } @@ -390,6 +554,51 @@ static void virgl_video_decode_bitstream(struct pipe_video_codec *codec, virgl_encode_decode_bitstream(vctx, vcdc, vbuf, &vdsc, sizeof(vdsc)); } +static void virgl_video_encode_bitstream(struct pipe_video_codec *codec, + struct pipe_video_buffer *source, + struct pipe_resource *target, + void **feedback) +{ + struct virgl_video_codec *vcdc = virgl_video_codec(codec); + struct virgl_context *vctx = vcdc->vctx; + struct virgl_screen *vs = virgl_screen(vctx->base.screen); + struct virgl_resource *vres; + struct virgl_video_encode_feedback *fb; + struct pipe_transfer *xfer = NULL; + void *ptr; + + /* Transfer picture desc */ + vres = virgl_resource(vcdc->desc_buffers[vcdc->cur_buffer]); + vs->vws->resource_wait(vs->vws, vres->hw_res); + ptr = pipe_buffer_map(&vctx->base, vcdc->desc_buffers[vcdc->cur_buffer], + PIPE_MAP_WRITE, &xfer); + if (!ptr) + return; + memcpy(ptr, &vcdc->desc, sizeof(vcdc->desc)); + pipe_buffer_unmap(&vctx->base, xfer); + + /* Init feedback */ + vres = virgl_resource(vcdc->feed_buffers[vcdc->cur_buffer]); + vs->vws->resource_wait(vs->vws, vres->hw_res); + fb = pipe_buffer_map(&vctx->base, vcdc->feed_buffers[vcdc->cur_buffer], + PIPE_MAP_WRITE, &xfer); + if (!fb) + return; + fb->stat = VIRGL_VIDEO_ENCODE_STAT_NOT_STARTED; + fb->coded_size = 0; + pipe_buffer_unmap(&vctx->base, xfer); + *feedback = vres; + + /* + * These objects do not need to be transferred manually: + * source - corresponds to VASurface in VA-API + * target - corresponds to VACodedBuffer in VA-API + */ + + virgl_encode_encode_bitstream(vctx, vcdc, virgl_video_buffer(source), + virgl_resource(target)); +} + static void virgl_video_end_frame(struct pipe_video_codec *codec, struct pipe_video_buffer *target, struct pipe_picture_desc *picture) @@ -406,16 +615,43 @@ static void virgl_video_end_frame(struct pipe_video_codec *codec, static void virgl_video_flush(struct pipe_video_codec *codec) { - (void)codec; + struct pipe_context *ctx = codec->context; + struct pipe_fence_handle *fence = NULL; + + ctx->flush(ctx, &fence, 0); + if (fence) { + ctx->screen->fence_finish(ctx->screen, NULL, fence, PIPE_TIMEOUT_INFINITE); + ctx->screen->fence_reference(ctx->screen, &fence, NULL); + } } static void virgl_video_get_feedback(struct pipe_video_codec *codec, void *feedback, unsigned *size) { - (void)codec; - (void)feedback; - (void)size; + struct virgl_video_codec *vcdc = virgl_video_codec(codec); + struct virgl_context *vctx = vcdc->vctx; + struct virgl_screen *vs = virgl_screen(vctx->base.screen); + struct virgl_resource *vres = feedback; + struct virgl_video_encode_feedback *fb; + struct pipe_transfer *xfer; + + if (!feedback || !size) + return; + + vs->vws->resource_wait(vs->vws, vres->hw_res); + fb = pipe_buffer_map(&vctx->base, &vres->b, PIPE_MAP_READ, &xfer); + if (!fb) + return; + if (fb->stat == VIRGL_VIDEO_ENCODE_STAT_SUCCESS) { + *size = fb->coded_size; + } else { + *size = 0; + if (virgl_debug & VIRGL_DEBUG_VIDEO) { + debug_printf("unexpected encode feedback: %u\n", fb->stat); + } + } + pipe_buffer_unmap(&vctx->base, xfer); } static void virgl_video_destroy_codec(struct pipe_video_codec *codec) @@ -425,7 +661,11 @@ static void virgl_video_destroy_codec(struct pipe_video_codec *codec) struct virgl_context *vctx = virgl_context(vcdc->base.context); for (i = 0; i < VIRGL_VIDEO_CODEC_BUF_NUM; i++) { - pipe_resource_reference(&vcdc->bs_buffers[i], NULL); + if (codec->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) { + pipe_resource_reference(&vcdc->bs_buffers[i], NULL); + } else { + pipe_resource_reference(&vcdc->feed_buffers[i], NULL); + } pipe_resource_reference(&vcdc->desc_buffers[i], NULL); } @@ -451,11 +691,6 @@ virgl_video_create_codec(struct pipe_context *ctx, templ->chroma_format, templ->width, templ->height, templ->max_references, templ->expect_chunked_decode); - /* encode: not supported now */ - if (templ->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) - return NULL; - - /* decode: */ switch (u_reduce_video_profile(templ->profile)) { case PIPE_VIDEO_FORMAT_MPEG4: /* fall through */ case PIPE_VIDEO_FORMAT_MPEG4_AVC: @@ -480,6 +715,7 @@ virgl_video_create_codec(struct pipe_context *ctx, vcdc->base.begin_frame = virgl_video_begin_frame; vcdc->base.decode_macroblock = virgl_video_decode_macroblock; vcdc->base.decode_bitstream = virgl_video_decode_bitstream; + vcdc->base.encode_bitstream = virgl_video_encode_bitstream; vcdc->base.end_frame = virgl_video_end_frame; vcdc->base.flush = virgl_video_flush; vcdc->base.get_feedback = virgl_video_get_feedback; @@ -487,9 +723,15 @@ virgl_video_create_codec(struct pipe_context *ctx, vcdc->bs_size = 0; vcdc->cur_buffer = 0; for (i = 0; i < VIRGL_VIDEO_CODEC_BUF_NUM; i++) { - vcdc->bs_buffers[i] = pipe_buffer_create(ctx->screen, - PIPE_BIND_CUSTOM, PIPE_USAGE_STAGING, - BS_BUF_DEFAULT_SIZE(width, height)); + if (templ->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) { + vcdc->bs_buffers[i] = pipe_buffer_create(ctx->screen, + PIPE_BIND_CUSTOM, PIPE_USAGE_STAGING, + BS_BUF_DEFAULT_SIZE(width, height)); + } else { + vcdc->feed_buffers[i] = pipe_buffer_create(ctx->screen, + PIPE_BIND_CUSTOM, PIPE_USAGE_STAGING, + sizeof(struct virgl_video_encode_feedback)); + } vcdc->desc_buffers[i] = pipe_buffer_create(ctx->screen, PIPE_BIND_CUSTOM, PIPE_USAGE_STAGING, diff --git a/src/gallium/drivers/virgl/virgl_video.h b/src/gallium/drivers/virgl/virgl_video.h index 7b4a3fd5cf2..3ebcb0448b0 100644 --- a/src/gallium/drivers/virgl/virgl_video.h +++ b/src/gallium/drivers/virgl/virgl_video.h @@ -39,6 +39,7 @@ #include "virgl_context.h" #include "vl/vl_video_buffer.h" #include "pipe/p_video_codec.h" +#include "virtio-gpu/virgl_video_hw.h" #define VIRGL_VIDEO_CODEC_BUF_NUM 10 @@ -47,11 +48,13 @@ struct virgl_video_codec { uint32_t handle; struct virgl_context *vctx; + union virgl_picture_desc desc; uint32_t bs_size; /* size of data in bs_buffer */ uint32_t cur_buffer; /* index of current bs/desc buffer */ struct pipe_resource *bs_buffers[VIRGL_VIDEO_CODEC_BUF_NUM]; struct pipe_resource *desc_buffers[VIRGL_VIDEO_CODEC_BUF_NUM]; + struct pipe_resource *feed_buffers[VIRGL_VIDEO_CODEC_BUF_NUM]; }; struct virgl_video_buffer { diff --git a/src/virtio/virtio-gpu/virgl_protocol.h b/src/virtio/virtio-gpu/virgl_protocol.h index be65a2f9847..05010777f19 100644 --- a/src/virtio/virtio-gpu/virgl_protocol.h +++ b/src/virtio/virtio-gpu/virgl_protocol.h @@ -720,7 +720,7 @@ enum vrend_tweak_type { #define VIRGL_CREATE_VIDEO_CODEC_MAX_REF 8 /* VIRGL_CCMD_DESTROY_VIDEO_CODEC */ -#define VIRGL_DESTROY_VIDEO_CODEC_SIZE 1 +#define VIRGL_DESTROY_VIDEO_CODEC_MIN_SIZE 1 #define VIRGL_DESTROY_VIDEO_CODEC_HANDLE 1 /* VIRGL_CCMD_CREATE_VIDEO_BUFFER */ @@ -732,18 +732,18 @@ enum vrend_tweak_type { #define VIRGL_CREATE_VIDEO_BUFFER_RES_BASE 5 /* VIRGL_CCMD_DESTROY_VIDEO_BUFFER */ -#define VIRGL_DESTROY_VIDEO_BUFFER_SIZE 1 +#define VIRGL_DESTROY_VIDEO_BUFFER_MIN_SIZE 1 #define VIRGL_DESTROY_VIDEO_BUFFER_HANDLE 1 /* VIRGL_CCMD_BEGIN_FRAME */ -#define VIRGL_BEGIN_FRAME_SIZE 2 +#define VIRGL_BEGIN_FRAME_MIN_SIZE 2 #define VIRGL_BEGIN_FRAME_CDC_HANDLE 1 #define VIRGL_BEGIN_FRAME_TGT_HANDLE 2 /* VIRGL_CCMD_DECODE_MACROBLOCK */ /* VIRGL_CCMD_DECODE_BITSTREAM */ -#define VIRGL_DECODE_BS_SIZE 5 +#define VIRGL_DECODE_BS_MIN_SIZE 5 #define VIRGL_DECODE_BS_CDC_HANDLE 1 #define VIRGL_DECODE_BS_TGT_HANDLE 2 #define VIRGL_DECODE_BS_DSC_HANDLE 3 @@ -751,9 +751,15 @@ enum vrend_tweak_type { #define VIRGL_DECODE_BS_BUF_SIZE 5 /* VIRGL_CCMD_ENCODE_BITSTREAM */ +#define VIRGL_ENCODE_BS_MIN_SIZE 5 +#define VIRGL_ENCODE_BS_CDC_HANDLE 1 +#define VIRGL_ENCODE_BS_SRC_HANDLE 2 +#define VIRGL_ENCODE_BS_DEST_HANDLE 3 +#define VIRGL_ENCODE_BS_DESC_HANDLE 4 +#define VIRGL_ENCODE_BS_FEED_HANDLE 5 /* VIRGL_CCMD_END_FRAME */ -#define VIRGL_END_FRAME_SIZE 2 +#define VIRGL_END_FRAME_MIN_SIZE 2 #define VIRGL_END_FRAME_CDC_HANDLE 1 #define VIRGL_END_FRAME_TGT_HANDLE 2 diff --git a/src/virtio/virtio-gpu/virgl_video_hw.h b/src/virtio/virtio-gpu/virgl_video_hw.h index e74478957d0..18ea1306509 100644 --- a/src/virtio/virtio-gpu/virgl_video_hw.h +++ b/src/virtio/virtio-gpu/virgl_video_hw.h @@ -51,6 +51,13 @@ struct virgl_base_picture_desc { }; +struct virgl_enc_quality_modes { + uint32_t level; + uint32_t preset_mode; + uint32_t pre_encode_mode; + uint32_t vbaq_mode; +}; + /* H.264 sequence parameter set */ struct virgl_h264_sps { uint8_t level_idc; @@ -140,6 +147,120 @@ struct virgl_h264_picture_desc { uint8_t reserved[2]; }; +struct virgl_h264_enc_seq_param +{ + uint32_t enc_constraint_set_flags; + uint32_t enc_frame_cropping_flag; + uint32_t enc_frame_crop_left_offset; + uint32_t enc_frame_crop_right_offset; + uint32_t enc_frame_crop_top_offset; + uint32_t enc_frame_crop_bottom_offset; + uint32_t pic_order_cnt_type; + uint32_t num_temporal_layers; + uint32_t vui_parameters_present_flag; + struct { + uint32_t aspect_ratio_info_present_flag: 1; + uint32_t timing_info_present_flag: 1; + uint32_t reserved:30; + } vui_flags; + uint32_t aspect_ratio_idc; + uint32_t sar_width; + uint32_t sar_height; + uint32_t num_units_in_tick; + uint32_t time_scale; +}; + +struct virgl_h264_enc_rate_control +{ + uint32_t target_bitrate; + uint32_t peak_bitrate; + uint32_t frame_rate_num; + uint32_t frame_rate_den; + uint32_t vbv_buffer_size; + uint32_t vbv_buf_lv; + uint32_t target_bits_picture; + uint32_t peak_bits_picture_integer; + uint32_t peak_bits_picture_fraction; + uint32_t fill_data_enable; + uint32_t skip_frame_enable; + uint32_t enforce_hrd; + uint32_t max_au_size; + uint32_t max_qp; + uint32_t min_qp; + + uint8_t rate_ctrl_method; /* see enum pipe_h2645_enc_rate_control_method */ + uint8_t reserved[3]; +}; + +struct virgl_h264_enc_motion_estimation +{ + uint32_t motion_est_quarter_pixel; + uint32_t enc_disable_sub_mode; + uint32_t lsmvert; + uint32_t enc_en_ime_overw_dis_subm; + uint32_t enc_ime_overw_dis_subm_no; + uint32_t enc_ime2_search_range_x; + uint32_t enc_ime2_search_range_y; +}; + +struct virgl_h264_enc_pic_control +{ + uint32_t enc_cabac_enable; + uint32_t enc_cabac_init_idc; +}; + +struct virgl_h264_slice_descriptor +{ + uint32_t macroblock_address; + uint32_t num_macroblocks; + + uint8_t slice_type; /* see enum pipe_h264_slice_type */ + uint8_t reserved[3]; +}; + +struct virgl_h264_enc_picture_desc +{ + struct virgl_base_picture_desc base; + + struct virgl_h264_enc_seq_param seq; + struct virgl_h264_enc_rate_control rate_ctrl[4]; + struct virgl_h264_enc_motion_estimation motion_est; + struct virgl_h264_enc_pic_control pic_ctrl; + + uint32_t intra_idr_period; + + uint32_t quant_i_frames; + uint32_t quant_p_frames; + uint32_t quant_b_frames; + + uint32_t frame_num; + uint32_t frame_num_cnt; + uint32_t p_remain; + uint32_t i_remain; + uint32_t idr_pic_id; + uint32_t gop_cnt; + uint32_t pic_order_cnt; + uint32_t num_ref_idx_l0_active_minus1; + uint32_t num_ref_idx_l1_active_minus1; + uint32_t ref_idx_l0_list[32]; + uint8_t l0_is_long_term[32]; + uint32_t ref_idx_l1_list[32]; + uint8_t l1_is_long_term[32]; + uint32_t gop_size; + struct virgl_enc_quality_modes quality_modes; + + uint32_t num_slice_descriptors; + struct virgl_h264_slice_descriptor slices_descriptors[128]; + + uint8_t picture_type; /* see enum pipe_h2645_enc_picture_type */ + uint8_t not_referenced; + uint8_t is_ltr; + uint8_t enable_vui; + + uint32_t ltr_index; +}; + + struct virgl_h265_sps { uint32_t pic_width_in_luma_samples; @@ -305,6 +426,21 @@ union virgl_picture_desc { struct virgl_h264_picture_desc h264; struct virgl_h265_picture_desc h265; struct virgl_mpeg4_picture_desc mpeg4; + struct virgl_h264_enc_picture_desc h264_enc; +}; + +enum virgl_video_encode_stat { + VIRGL_VIDEO_ENCODE_STAT_NOT_STARTED = 0, + VIRGL_VIDEO_ENCODE_STAT_IN_PROGRESS, + VIRGL_VIDEO_ENCODE_STAT_SUCCESS, + VIRGL_VIDEO_ENCODE_STAT_FAILURE, +}; + +struct virgl_video_encode_feedback { + uint8_t stat; /* see enum virgl_video_encode_stat */ + uint8_t reserved[3]; + + uint32_t coded_size; /* size of encoded data in bytes */ }; #endif /* VIRGL_VIDEO_HW_H */