From 454a26662d27edce22bdcdf3f26f4f0f2209ec05 Mon Sep 17 00:00:00 2001 From: David Rosca Date: Wed, 2 Oct 2024 15:31:11 +0200 Subject: [PATCH] frontends/va: Support raw packed headers for AV1 When there is show_existing_frame = 1 frame header, we don't parse it and instead output directly as raw header. Only the frame header that will be used for encoding current frame is parsed and indicated with is_slice. Reviewed-by: Ruijing Dong Part-of: --- src/gallium/frontends/va/context.c | 1 + src/gallium/frontends/va/picture.c | 1 + src/gallium/frontends/va/picture_av1_enc.c | 34 ++++++++++++++++------ src/gallium/frontends/va/va_private.h | 3 +- src/gallium/include/pipe/p_video_state.h | 3 ++ 5 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/gallium/frontends/va/context.c b/src/gallium/frontends/va/context.c index da493977762..40138bdf2d2 100644 --- a/src/gallium/frontends/va/context.c +++ b/src/gallium/frontends/va/context.c @@ -507,6 +507,7 @@ vlVaDestroyContext(VADriverContextP ctx, VAContextID context_id) if (buf && !context->desc.av1enc.dpb[i].id) buf->destroy(buf); } + util_dynarray_fini(&context->desc.av1enc.raw_headers); } } else { if (u_reduce_video_profile(context->decoder->profile) == diff --git a/src/gallium/frontends/va/picture.c b/src/gallium/frontends/va/picture.c index e14bfdedd92..c35e7e427bb 100644 --- a/src/gallium/frontends/va/picture.c +++ b/src/gallium/frontends/va/picture.c @@ -1368,6 +1368,7 @@ vlVaEndPicture(VADriverContextP ctx, VAContextID context_id) switch (u_reduce_video_profile(context->templat.profile)) { case PIPE_VIDEO_FORMAT_AV1: context->desc.av1enc.frame_num++; + vlVaClearRawHeaders(&context->desc.av1enc.raw_headers); break; case PIPE_VIDEO_FORMAT_HEVC: context->desc.h265enc.frame_num++; diff --git a/src/gallium/frontends/va/picture_av1_enc.c b/src/gallium/frontends/va/picture_av1_enc.c index e58bdd8aa68..23f6e5a08c2 100644 --- a/src/gallium/frontends/va/picture_av1_enc.c +++ b/src/gallium/frontends/va/picture_av1_enc.c @@ -675,7 +675,8 @@ static void av1_read_interpolation_filter(vlVaContext *context, struct vl_vlc *v av1_f(vlc, 2); } -static void av1_frame_header(vlVaContext *context, struct vl_vlc *vlc) +static bool av1_frame_header(vlVaContext *context, struct vl_vlc *vlc, + uint32_t extension_flag, uint32_t temporal_id, uint32_t spatial_id) { struct pipe_av1_enc_picture_desc *av1 = &context->desc.av1enc; uint32_t frame_type; @@ -687,10 +688,12 @@ static void av1_frame_header(vlVaContext *context, struct vl_vlc *vlc) id_len = av1->seq.delta_frame_id_length + av1->seq.additional_frame_id_length; all_frames = 255; - av1->show_existing_frame = av1_f(vlc, 1); - /* use the last reference frame to show */ - if (av1->show_existing_frame) - return; + if (av1_f(vlc, 1)) /* show_existing_frame */ + return false; + + av1->obu_extension_flag = extension_flag; + av1->temporal_id = temporal_id; + av1->spatial_id = spatial_id; frame_type = av1_f(vlc, 2); frame_is_intra = (frame_type == FRAME_TYPE_KEY_FRAME || @@ -824,6 +827,8 @@ static void av1_frame_header(vlVaContext *context, struct vl_vlc *vlc) */ av1->uniform_tile_spacing = av1_f(vlc, 1); + + return true; } static void av1_metatype_hdr_cll(vlVaContext *context, struct vl_vlc *vlc) @@ -873,29 +878,40 @@ vlVaHandleVAEncPackedHeaderDataBufferTypeAV1(vlVaContext *context, vlVaBuffer *b if (obu_type != OBU_TYPE_SEQUENCE_HEADER && obu_type != OBU_TYPE_FRAME_HEADER && obu_type != OBU_TYPE_FRAME && - obu_type != OBU_TYPE_META) + obu_type != OBU_TYPE_META) { + vlVaAddRawHeader(&context->desc.av1enc.raw_headers, obu_type, + buf->size, buf->data, false, 0); return VA_STATUS_SUCCESS; + } uint32_t extension_flag = av1_f(&vlc, 1); uint32_t has_size = av1_f(&vlc, 1); av1_f(&vlc, 1); /* obu_reserved_1bit */ + uint32_t temporal_id = 0; + uint32_t spatial_id = 0; + if (extension_flag) { - context->desc.av1enc.temporal_id = av1_f(&vlc, 3); - context->desc.av1enc.spatial_id = av1_f(&vlc, 2); + temporal_id = av1_f(&vlc, 3); + spatial_id = av1_f(&vlc, 2); av1_f(&vlc, 3); /* extension_header_reserved_3bits */ } if (has_size) av1_uleb128(&vlc); + bool is_frame = false; + if (obu_type == OBU_TYPE_SEQUENCE_HEADER) av1_sequence_header(context, &vlc); else if (obu_type == OBU_TYPE_FRAME_HEADER || obu_type == OBU_TYPE_FRAME) - av1_frame_header(context, &vlc); + is_frame = av1_frame_header(context, &vlc, extension_flag, temporal_id, spatial_id); else if (obu_type == OBU_TYPE_META) av1_meta_obu(context, &vlc); + vlVaAddRawHeader(&context->desc.av1enc.raw_headers, obu_type, + buf->size, buf->data, is_frame, 0); + return VA_STATUS_SUCCESS; } diff --git a/src/gallium/frontends/va/va_private.h b/src/gallium/frontends/va/va_private.h index 917c13c6f1a..01d34e014c6 100644 --- a/src/gallium/frontends/va/va_private.h +++ b/src/gallium/frontends/va/va_private.h @@ -97,7 +97,8 @@ VA_ENC_PACKED_HEADER_RAW_DATA) #define ENC_PACKED_HEADERS_AV1 (VA_ENC_PACKED_HEADER_SEQUENCE | \ VA_ENC_PACKED_HEADER_PICTURE | \ - VA_ENC_PACKED_HEADER_MISC) + VA_ENC_PACKED_HEADER_MISC | \ + VA_ENC_PACKED_HEADER_RAW_DATA) static inline enum pipe_video_chroma_format ChromaToPipe(int format) diff --git a/src/gallium/include/pipe/p_video_state.h b/src/gallium/include/pipe/p_video_state.h index 439b27983ee..b836402146a 100644 --- a/src/gallium/include/pipe/p_video_state.h +++ b/src/gallium/include/pipe/p_video_state.h @@ -1334,6 +1334,7 @@ struct pipe_av1_enc_picture_desc struct pipe_av1_enc_seq_param seq; struct pipe_av1_enc_rate_control rc[4]; struct { + uint32_t obu_extension_flag:1; uint32_t enable_frame_obu:1; uint32_t error_resilient_mode:1; uint32_t disable_cdf_update:1; @@ -1469,6 +1470,8 @@ struct pipe_av1_enc_picture_desc uint8_t dpb_ref_frame_idx[PIPE_AV1_REFS_PER_FRAME]; /* index in dpb, PIPE_H2645_LIST_REF_INVALID_ENTRY invalid */ uint8_t ref_list0[PIPE_AV1_REFS_PER_FRAME]; /* index in dpb_ref_frame_idx, PIPE_H2645_LIST_REF_INVALID_ENTRY invalid */ uint8_t ref_list1[PIPE_AV1_REFS_PER_FRAME]; /* index in dpb_ref_frame_idx, PIPE_H2645_LIST_REF_INVALID_ENTRY invalid */ + + struct util_dynarray raw_headers; /* struct pipe_enc_raw_header */ }; struct pipe_h265_sps