gallium: Parse packed HEVC SPS encode header for crop parameters

The crop / conformance window parameters are set by ffmpeg but they only
seem to be made available in packed headers. This commit copies the H265
header parsing code from st/omx (planning in the future to move this
code to a common place to be shared by the different state trackers) in
order to grab the crop parameters

Signed-off-by: Thong Thai <thong.thai@amd.com>
Reviewed-by: Leo Liu <leo.liu@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4184>
This commit is contained in:
Thong Thai 2020-03-12 10:06:52 -04:00 committed by Marge Bot
parent 0a3f92bcc6
commit 245f619411
5 changed files with 190 additions and 2 deletions

View File

@ -157,7 +157,9 @@ vlVaGetConfigAttributes(VADriverContextP ctx, VAProfile profile, VAEntrypoint en
value = VA_RC_CQP | VA_RC_CBR | VA_RC_VBR;
break;
case VAConfigAttribEncPackedHeaders:
value = 0;
value = VA_ENC_PACKED_HEADER_NONE;
if (u_reduce_video_profile(ProfileToPipe(profile)) == PIPE_VIDEO_FORMAT_HEVC)
value |= VA_ENC_PACKED_HEADER_SEQUENCE;
break;
case VAConfigAttribEncMaxRefFrames:
value = 1;

View File

@ -466,6 +466,48 @@ handleVAEncSliceParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaB
return status;
}
static VAStatus
handleVAEncPackedHeaderParameterBufferType(vlVaContext *context, vlVaBuffer *buf)
{
VAStatus status = VA_STATUS_SUCCESS;
switch (u_reduce_video_profile(context->templat.profile)) {
case PIPE_VIDEO_FORMAT_HEVC:
break;
default:
return VA_STATUS_ERROR_UNIMPLEMENTED;
}
VAEncPackedHeaderParameterBuffer *param = (VAEncPackedHeaderParameterBuffer *)buf->data;
if (param->type == VAEncPackedHeaderSequence)
context->packed_header_type = param->type;
else
status = VA_STATUS_ERROR_UNIMPLEMENTED;
return status;
}
static VAStatus
handleVAEncPackedHeaderDataBufferType(vlVaContext *context, vlVaBuffer *buf)
{
VAStatus status = VA_STATUS_SUCCESS;
if (context->packed_header_type != VAEncPackedHeaderSequence)
return VA_STATUS_ERROR_UNIMPLEMENTED;
switch (u_reduce_video_profile(context->templat.profile)) {
case PIPE_VIDEO_FORMAT_HEVC:
status = vlVaHandleVAEncPackedHeaderDataBufferTypeHEVC(context, buf);
break;
default:
break;
}
return status;
}
VAStatus
vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buffers, int num_buffers)
{
@ -536,6 +578,13 @@ vlVaRenderPicture(VADriverContextP ctx, VAContextID context_id, VABufferID *buff
vlVaHandleHuffmanTableBufferType(context, buf);
break;
case VAEncPackedHeaderParameterBufferType:
handleVAEncPackedHeaderParameterBufferType(context, buf);
break;
case VAEncPackedHeaderDataBufferType:
handleVAEncPackedHeaderDataBufferType(context, buf);
break;
default:
break;
}

View File

@ -29,6 +29,15 @@
#include "util/u_video.h"
#include "va_private.h"
#include "vl/vl_vlc.h"
#include "vl/vl_rbsp.h"
enum HEVCNALUnitType {
HEVC_NAL_VPS = 32,
HEVC_NAL_SPS = 33,
HEVC_NAL_PPS = 34,
};
VAStatus
vlVaHandleVAEncPictureParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf)
{
@ -188,6 +197,128 @@ vlVaHandleVAEncMiscParameterTypeFrameRateHEVC(vlVaContext *context, VAEncMiscPar
return VA_STATUS_SUCCESS;
}
static void profile_tier(struct vl_rbsp *rbsp)
{
vl_rbsp_u(rbsp, 2); /* general_profile_space */
vl_rbsp_u(rbsp, 1); /* general_tier_flag */
vl_rbsp_u(rbsp, 5); /* general_profile_idc */
/* general_profile_compatibility_flag */
for(int i = 0; i < 32; ++i)
vl_rbsp_u(rbsp, 1);
vl_rbsp_u(rbsp, 1); /* general_progressive_source_flag */
vl_rbsp_u(rbsp, 1); /* general_interlaced_source_flag */
vl_rbsp_u(rbsp, 1); /* general_non_packed_constraint_flag */
vl_rbsp_u(rbsp, 1); /* general_frame_only_constraint_flag */
/* general_reserved_zero_44bits */
vl_rbsp_u(rbsp, 16);
vl_rbsp_u(rbsp, 16);
vl_rbsp_u(rbsp, 12);
}
static unsigned profile_tier_level(struct vl_rbsp *rbsp,
int max_sublayers_minus1)
{
bool sub_layer_profile_present_flag[6];
bool sub_layer_level_present_flag[6];
unsigned level_idc;
int i;
profile_tier(rbsp);
level_idc = vl_rbsp_u(rbsp, 8); /* general_level_idc */
for (i = 0; i < max_sublayers_minus1; ++i) {
sub_layer_profile_present_flag[i] = vl_rbsp_u(rbsp, 1);
sub_layer_level_present_flag[i] = vl_rbsp_u(rbsp, 1);
}
if (max_sublayers_minus1 > 0)
for (i = max_sublayers_minus1; i < 8; ++i)
vl_rbsp_u(rbsp, 2); /* reserved_zero_2bits */
for (i = 0; i < max_sublayers_minus1; ++i) {
if (sub_layer_profile_present_flag[i])
profile_tier(rbsp);
if (sub_layer_level_present_flag[i])
vl_rbsp_u(rbsp, 8); /* sub_layer_level_idc */
}
return level_idc;
}
static void parseEncSpsParamsH265(vlVaContext *context, struct vl_rbsp *rbsp)
{
int sps_max_sub_layers_minus1;
vl_rbsp_u(rbsp, 4); /* sps_video_parameter_set_id */
sps_max_sub_layers_minus1 = vl_rbsp_u(rbsp, 3);
vl_rbsp_u(rbsp, 1); /* sps_temporal_id_nesting_flag */
/* level_idc */
profile_tier_level(rbsp, sps_max_sub_layers_minus1);
vl_rbsp_ue(rbsp); /* id */
context->desc.h265enc.seq.chroma_format_idc = vl_rbsp_ue(rbsp);
if (context->desc.h265enc.seq.chroma_format_idc == 3)
vl_rbsp_u(rbsp, 1); /* separate_colour_plane_flag */
context->desc.h265enc.seq.pic_width_in_luma_samples = vl_rbsp_ue(rbsp);
context->desc.h265enc.seq.pic_height_in_luma_samples = vl_rbsp_ue(rbsp);
/* conformance_window_flag - used for cropping */
context->desc.h265enc.seq.conformance_window_flag = vl_rbsp_u(rbsp, 1);
if (context->desc.h265enc.seq.conformance_window_flag) {
context->desc.h265enc.seq.conf_win_left_offset = vl_rbsp_ue(rbsp);
context->desc.h265enc.seq.conf_win_right_offset = vl_rbsp_ue(rbsp);
context->desc.h265enc.seq.conf_win_top_offset = vl_rbsp_ue(rbsp);
context->desc.h265enc.seq.conf_win_bottom_offset = vl_rbsp_ue(rbsp);
}
}
VAStatus
vlVaHandleVAEncPackedHeaderDataBufferTypeHEVC(vlVaContext *context, vlVaBuffer *buf)
{
struct vl_vlc vlc = {0};
vl_vlc_init(&vlc, 1, (const void * const*)&buf->data, &buf->size);
while (vl_vlc_bits_left(&vlc) > 0) {
/* search the first 64 bytes for a startcode */
for (int i = 0; i < 64 && vl_vlc_bits_left(&vlc) >= 24; ++i) {
if (vl_vlc_peekbits(&vlc, 24) == 0x000001)
break;
vl_vlc_eatbits(&vlc, 8);
vl_vlc_fillbits(&vlc);
}
vl_vlc_eatbits(&vlc, 24); /* eat the startcode */
if (vl_vlc_valid_bits(&vlc) < 15)
vl_vlc_fillbits(&vlc);
vl_vlc_eatbits(&vlc, 1);
unsigned nal_unit_type = vl_vlc_get_uimsbf(&vlc, 6);
vl_vlc_eatbits(&vlc, 6);
vl_vlc_eatbits(&vlc, 3);
struct vl_rbsp rbsp;
vl_rbsp_init(&rbsp, &vlc, ~0);
switch(nal_unit_type) {
case HEVC_NAL_SPS:
parseEncSpsParamsH265(context, &rbsp);
break;
case HEVC_NAL_VPS:
case HEVC_NAL_PPS:
default:
break;
}
}
return VA_STATUS_SUCCESS;
}
void getEncParamPresetH265(vlVaContext *context)
{
//rate control

View File

@ -308,6 +308,7 @@ typedef struct {
int gop_coeff;
bool needs_begin_frame;
void *blit_cs;
int packed_header_type;
} vlVaContext;
typedef struct {
@ -459,5 +460,5 @@ VAStatus vlVaHandleVAEncSliceParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContex
VAStatus vlVaHandleVAEncSequenceParameterBufferTypeHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf);
VAStatus vlVaHandleVAEncMiscParameterTypeRateControlHEVC(vlVaContext *context, VAEncMiscParameterBuffer *buf);
VAStatus vlVaHandleVAEncMiscParameterTypeFrameRateHEVC(vlVaContext *context, VAEncMiscParameterBuffer *buf);
VAStatus vlVaHandleVAEncPackedHeaderDataBufferTypeHEVC(vlVaContext *context, vlVaBuffer *buf);
#endif //VA_PRIVATE_H

View File

@ -457,6 +457,11 @@ struct pipe_h265_enc_seq_param
uint8_t log2_diff_max_min_transform_block_size;
uint8_t max_transform_hierarchy_depth_inter;
uint8_t max_transform_hierarchy_depth_intra;
uint8_t conformance_window_flag;
uint16_t conf_win_left_offset;
uint16_t conf_win_right_offset;
uint16_t conf_win_top_offset;
uint16_t conf_win_bottom_offset;
};
struct pipe_h265_enc_pic_param