[Libva] [PATCH 2/3] Add multi quality levels encoding support for GEN7

lizhong zhong.li at intel.com
Wed Jun 4 22:23:38 PDT 2014


On 06/05/2014 01:14 PM, Xiang, Haihao wrote:
> On Thu, 2014-06-05 at 12:54 +0800, lizhong wrote:
>> On 06/05/2014 12:12 PM, Xiang, Haihao wrote:
>>> On Wed, 2014-06-04 at 21:37 +0800, Zhong Li wrote:
>>>> Two encoding quality levels are support on GEN7.
>>>> Default quality level is set to be 1, which has better quality,
>>>> but higher gpu usage and worse performance.
>>>> The second quality level is set to be 2, which has lower gpu usage and
>>>> better performance,but worse quality.
>>>> Other platforms support for multi-quality-level will be added later.
>>>>
>>>> Signed-off-by: Zhong Li <zhong.li at intel.com>
>>>> ---
>>>>    src/gen6_mfc.c       |  130 ++++++++++++++++++++++++++++++++++++++------------
>>>>    src/gen7_vme.c       |   84 +++++++++++++++++++++++++++-----
>>>>    src/i965_drv_video.c |   12 +++++
>>>>    src/i965_drv_video.h |    7 +++
>>>>    src/i965_encoder.c   |   21 +++++++-
>>>>    5 files changed, 211 insertions(+), 43 deletions(-)
>>>>
>>>> diff --git a/src/gen6_mfc.c b/src/gen6_mfc.c
>>>> index 0a10054..f1cd7ea 100644
>>>> --- a/src/gen6_mfc.c
>>>> +++ b/src/gen6_mfc.c
>>>> @@ -676,8 +676,6 @@ gen6_mfc_stop(VADriverContextP ctx,
>>>>        return VA_STATUS_SUCCESS;
>>>>    }
>>>>    
>>>> -#if __SOFTWARE__
>>>> -
>>>>    static int
>>>>    gen6_mfc_avc_pak_object_intra(VADriverContextP ctx, int x, int y, int end_mb, int qp,unsigned int *msg,
>>>>                                  struct intel_encoder_context *encoder_context,
>>>> @@ -768,6 +766,58 @@ gen6_mfc_avc_pak_object_inter(VADriverContextP ctx, int x, int y, int end_mb, in
>>>>    
>>>>        return len_in_dwords;
>>>>    }
>>>> +
>>>> +static int
>>>> +gen6_mfc_avc_pak_object_inter2(VADriverContextP ctx, int x, int y, int end_mb, int qp,
>>>> +                              unsigned int offset,
>>>> +                              struct intel_encoder_context *encoder_context,
>>>> +                              struct intel_batchbuffer *batch)
>>>> +{
>>>> +    struct gen6_vme_context *vme_context = encoder_context->vme_context;
>>>> +    int len_in_dwords = 11;
>>>> +
>>>> +    if (batch == NULL)
>>>> +        batch = encoder_context->base.batch;
>>>> +
>>>> +    BEGIN_BCS_BATCH(batch, len_in_dwords);
>>>> +
>>>> +    OUT_BCS_BATCH(batch, MFC_AVC_PAK_OBJECT | (len_in_dwords - 2));
>>>> +
>>>> +    OUT_BCS_BATCH(batch, 32);         /* 32 MV*/
>>>> +    OUT_BCS_BATCH(batch, offset);
>>>> +
>>>> +    OUT_BCS_BATCH(batch,
>>>> +                  (1 << 24) |     /* PackedMvNum, Debug*/
>>>> +                  (4 << 20) |     /* 8 MV, SNB don't use it*/
>>>> +                  (1 << 19) |     /* CbpDcY */
>>>> +                  (1 << 18) |     /* CbpDcU */
>>>> +                  (1 << 17) |     /* CbpDcV */
>>>> +                  (0 << 15) |     /* Transform8x8Flag = 0*/
>>>> +                  (0 << 14) |     /* Frame based*/
>>>> +                  (0 << 13) |     /* Inter MB */
>>>> +                  (1 << 8)  |     /* MbType = P_L0_16x16 */
>>>> +                  (0 << 7)  |     /* MBZ for frame */
>>>> +                  (0 << 6)  |     /* MBZ */
>>>> +                  (2 << 4)  |     /* MBZ for inter*/
>>>> +                  (0 << 3)  |     /* MBZ */
>>>> +                  (0 << 2)  |     /* SkipMbFlag */
>>>> +                  (0 << 0));      /* InterMbMode */
>>>> +
>>>> +    OUT_BCS_BATCH(batch, (0xFFFF<<16) | (y << 8) | x);        /* Code Block Pattern for Y*/
>>>> +    OUT_BCS_BATCH(batch, 0x000F000F);                         /* Code Block Pattern */
>>>> +    OUT_BCS_BATCH(batch, (0 << 27) | (end_mb << 26) | qp);    /* Last MB */
>>>> +
>>>> +    /*Stuff for Inter MB*/
>>>> +    OUT_BCS_BATCH(batch, 0x0);
>>>> +    OUT_BCS_BATCH(batch, 0x0);
>>>> +    OUT_BCS_BATCH(batch, 0x0);
>>>> +
>>>> +    OUT_BCS_BATCH(batch, 0xF0020000); /*MaxSizeInWord and TargetSzieInWord*/
>>>> +
>>>> +    ADVANCE_BCS_BATCH(batch);
>>>> +
>>>> +    return len_in_dwords;
>>>> +}
>>>>    
>>>>    static void
>>>>    gen6_mfc_avc_pipeline_slice_programing(VADriverContextP ctx,
>>>> @@ -791,6 +841,7 @@ gen6_mfc_avc_pipeline_slice_programing(VADriverContextP ctx,
>>>>        unsigned int tail_data[] = { 0x0, 0x0 };
>>>>        int slice_type = intel_avc_enc_slice_type_fixup(pSliceParameter->slice_type);
>>>>        int is_intra = slice_type == SLICE_TYPE_I;
>>>> +    int is_low_quality = (encode_state->quality_level == ENCODER_LOW_QUALITY);
>>>>    
>>>>        if (rate_control_mode == VA_RC_CBR) {
>>>>            qp = mfc_context->bit_rate_control_context[slice_type].QpPrimeY;
>>>> @@ -818,36 +869,54 @@ gen6_mfc_avc_pipeline_slice_programing(VADriverContextP ctx,
>>>>        dri_bo_map(vme_context->vme_output.bo , 1);
>>>>        msg = (unsigned int *)vme_context->vme_output.bo->virtual;
>>>>    
>>>> -    if (is_intra) {
>>>> -        msg += pSliceParameter->macroblock_address * INTRA_VME_OUTPUT_IN_DWS;
>>>> -    } else {
>>>> -        msg += pSliceParameter->macroblock_address * INTER_VME_OUTPUT_IN_DWS;
>>>> -        msg += 32; /* the first 32 DWs are MVs */
>>>> -        offset = pSliceParameter->macroblock_address * INTER_VME_OUTPUT_IN_BYTES;
>>>> -    }
>>>> -
>>>> -    for (i = pSliceParameter->macroblock_address;
>>>> -         i < pSliceParameter->macroblock_address + pSliceParameter->num_macroblocks; i++) {
>>>> -        int last_mb = (i == (pSliceParameter->macroblock_address + pSliceParameter->num_macroblocks - 1) );
>>>> -        x = i % width_in_mbs;
>>>> -        y = i / width_in_mbs;
>>>> +    if (is_low_quality) {
>>>> +        for (i = pSliceParameter->macroblock_address;
>>>> +                i < pSliceParameter->macroblock_address + pSliceParameter->num_macroblocks; i++) {
>>>> +            int last_mb = (i == (pSliceParameter->macroblock_address + pSliceParameter->num_macroblocks - 1) );
>>>> +            x = i % width_in_mbs;
>>>> +            y = i / width_in_mbs;
>>>>    
>>>> +            if (is_intra) {
>>>> +                assert(msg);
>>>> +                gen6_mfc_avc_pak_object_intra(ctx, x, y, last_mb, qp, msg, encoder_context, 0, 0, slice_batch);
>>>> +                msg += 4;
>>>> +            } else {
>>>> +                gen6_mfc_avc_pak_object_inter2(ctx, x, y, last_mb, qp, offset, encoder_context, slice_batch);
>>>> +                offset += 64;
>>>> +            }
>>>> +        }
>>>> +    } else {
>>>>            if (is_intra) {
>>>> -            assert(msg);
>>>> -            gen6_mfc_avc_pak_object_intra(ctx, x, y, last_mb, qp, msg, encoder_context, 0, 0, slice_batch);
>>>> -            msg += INTRA_VME_OUTPUT_IN_DWS;
>>>> +            msg += pSliceParameter->macroblock_address * INTRA_VME_OUTPUT_IN_DWS;
>>>>            } else {
>>>> -            if (msg[0] & INTRA_MB_FLAG_MASK) {
>>>> +            msg += pSliceParameter->macroblock_address * INTER_VME_OUTPUT_IN_DWS;
>>>> +            msg += 32; /* the first 32 DWs are MVs */
>>>> +            offset = pSliceParameter->macroblock_address * INTER_VME_OUTPUT_IN_BYTES;
>>>> +        }
>>>> +
>>>> +        for (i = pSliceParameter->macroblock_address;
>>>> +                i < pSliceParameter->macroblock_address + pSliceParameter->num_macroblocks; i++) {
>>>> +            int last_mb = (i == (pSliceParameter->macroblock_address + pSliceParameter->num_macroblocks - 1) );
>>>> +            x = i % width_in_mbs;
>>>> +            y = i / width_in_mbs;
>>>> +
>>>> +            if (is_intra) {
>>>> +                assert(msg);
>>>>                    gen6_mfc_avc_pak_object_intra(ctx, x, y, last_mb, qp, msg, encoder_context, 0, 0, slice_batch);
>>>> +                msg += INTRA_VME_OUTPUT_IN_DWS;
>>>>                } else {
>>>> -                gen6_mfc_avc_pak_object_inter(ctx, x, y, last_mb, qp, msg, offset, encoder_context, 0, 0, slice_type, slice_batch);
>>>> -            }
>>>> +                if (msg[0] & INTRA_MB_FLAG_MASK) {
>>>> +                    gen6_mfc_avc_pak_object_intra(ctx, x, y, last_mb, qp, msg, encoder_context, 0, 0, slice_batch);
>>>> +                } else {
>>>> +                    gen6_mfc_avc_pak_object_inter(ctx, x, y, last_mb, qp, msg, offset, encoder_context, 0, 0, slice_type, slice_batch);
>>>> +                }
>>>>    
>>>> -            msg += INTER_VME_OUTPUT_IN_DWS;
>>>> -            offset += INTER_VME_OUTPUT_IN_BYTES;
>>>> +                msg += INTER_VME_OUTPUT_IN_DWS;
>>>> +                offset += INTER_VME_OUTPUT_IN_BYTES;
>>>> +            }
>>>>            }
>>>>        }
>>>> -
>>>> +
>>>>        dri_bo_unmap(vme_context->vme_output.bo);
>>>>    
>>>>        if ( last_slice ) {
>>>> @@ -896,8 +965,6 @@ gen6_mfc_avc_software_batchbuffer(VADriverContextP ctx,
>>>>        return batch_bo;
>>>>    }
>>>>    
>>>> -#else
>>>> -
>>>>    static void
>>>>    gen6_mfc_batchbuffer_surfaces_input(VADriverContextP ctx,
>>>>                                        struct encode_state *encode_state,
>>>> @@ -1291,9 +1358,6 @@ gen6_mfc_avc_hardware_batchbuffer(VADriverContextP ctx,
>>>>        return mfc_context->mfc_batchbuffer_surface.bo;
>>>>    }
>>>>    
>>>> -#endif
>>>> -
>>>> -
>>>>    static void
>>>>    gen6_mfc_avc_pipeline_programing(VADriverContextP ctx,
>>>>                                     struct encode_state *encode_state,
>>>> @@ -1308,11 +1372,15 @@ gen6_mfc_avc_pipeline_programing(VADriverContextP ctx,
>>>>            return;
>>>>        }
>>>>    
>>>> +    if (encode_state->quality_level == ENCODER_LOW_QUALITY )
>>>> +        slice_batch_bo = gen6_mfc_avc_software_batchbuffer(ctx, encode_state, encoder_context);
>>>> +    else {
>>>>    #if __SOFTWARE__
>>>> -    slice_batch_bo = gen6_mfc_avc_software_batchbuffer(ctx, encode_state, encoder_context);
>>>> +        slice_batch_bo = gen6_mfc_avc_software_batchbuffer(ctx, encode_state, encoder_context);
>>>>    #else
>>>> -    slice_batch_bo = gen6_mfc_avc_hardware_batchbuffer(ctx, encode_state, encoder_context);
>>>> +        slice_batch_bo = gen6_mfc_avc_hardware_batchbuffer(ctx, encode_state, encoder_context);
>>>>    #endif
>>>> +    }
>>>>    
>>>>        // begin programing
>>>>        intel_batchbuffer_start_atomic_bcs(batch, 0x4000);
>>>> diff --git a/src/gen7_vme.c b/src/gen7_vme.c
>>>> index 042fe5d..b45f558 100644
>>>> --- a/src/gen7_vme.c
>>>> +++ b/src/gen7_vme.c
>>>> @@ -63,6 +63,8 @@ enum VIDEO_CODING_TYPE{
>>>>    enum AVC_VME_KERNEL_TYPE{
>>>>        AVC_VME_INTRA_SHADER = 0,
>>>>        AVC_VME_INTER_SHADER,
>>>> +    AVC_VME_OLD_INTRA_SHADER,
>>>> +    AVC_VME_OLD_INTER_SHADER,
>>>>        AVC_VME_BATCHBUFFER,
>>>>        AVC_VME_BINTER_SHADER,
>>>>        AVC_VME_KERNEL_SUM
>>>> @@ -83,6 +85,14 @@ static const uint32_t gen7_vme_inter_frame[][4] = {
>>>>    #include "shaders/vme/inter_frame_ivb.g7b"
>>>>    };
>>>>    
>>>> +static const uint32_t gen7_vme_old_intra_frame[][4] = {
>>>> +#include "shaders/vme_old/intra_frame.g7b"
>>>> +};
>>>> +
>>>> +static const uint32_t gen7_vme_old_inter_frame[][4] = {
>>>> +#include "shaders/vme_old/inter_frame.g7b"
>>>> +};
>>>> +
>>>>    static const uint32_t gen7_vme_batchbuffer[][4] = {
>>>>    #include "shaders/vme/batchbuffer.g7b"
>>>>    };
>>>> @@ -107,6 +117,20 @@ static struct i965_kernel gen7_vme_kernels[] = {
>>>>            NULL
>>>>        },
>>>>        {
>>>> +        "AVC VME Old Intra Frame",
>>>> +        AVC_VME_OLD_INTRA_SHADER,
>>>> +        gen7_vme_old_intra_frame, 			
>>>> +        sizeof(gen7_vme_old_intra_frame),		
>>>> +        NULL
>>>> +    },
>>>> +    {
>>>> +        "AVC VME Old Inter Frame",
>>>> +        AVC_VME_OLD_INTER_SHADER,
>>>> +        gen7_vme_old_inter_frame,
>>>> +        sizeof(gen7_vme_old_inter_frame),
>>>> +        NULL
>>>> +    },
>>>> +    {
>>>>            "AVC VME BATCHBUFFER",
>>>>            AVC_VME_BATCHBUFFER,
>>>>            gen7_vme_batchbuffer,
>>>> @@ -359,6 +383,36 @@ static VAStatus gen7_vme_constant_setup(VADriverContextP ctx,
>>>>        return VA_STATUS_SUCCESS;
>>>>    }
>>>>    
>>>> +static VAStatus
>>>> +gen7_vme_vme_state_setup(VADriverContextP ctx,
>>>> +        struct encode_state *encode_state,
>>>> +        int is_intra,
>>>> +        struct intel_encoder_context *encoder_context)
>>>> +{
>>>> +    struct gen6_vme_context *vme_context = encoder_context->vme_context;
>>>> +    unsigned int *vme_state_message;
>>>> +    int i;
>>>> +
>>>> +    //building VME state message
>>>> +    dri_bo_map(vme_context->vme_state.bo, 1);
>>>> +    assert(vme_context->vme_state.bo->virtual);
>>>> +    vme_state_message = (unsigned int *)vme_context->vme_state.bo->virtual;
>>>> +
>>>> +    vme_state_message[0] = 0x10010101;
>>>> +    vme_state_message[1] = 0x100F0F0F;
>>>> +    vme_state_message[2] = 0x10010101;
>>>> +    vme_state_message[3] = 0x000F0F0F;
>>>> +    for(i = 4; i < 14; i++) {
>>>> +        vme_state_message[i] = 0x00000000;
>>>> +    }	
>>>> +
>>>> +    for(i = 14; i < 32; i++) {
>>>> +        vme_state_message[i] = 0x00000000;
>>>> +    }
>>>> +
>>>> +    dri_bo_unmap( vme_context->vme_state.bo);
>>>> +    return VA_STATUS_SUCCESS;
>>>> +}
>>>>    
>>>>    static VAStatus gen7_vme_avc_state_setup(VADriverContextP ctx,
>>>>                                             struct encode_state *encode_state,
>>>> @@ -598,25 +652,30 @@ static void gen7_vme_pipeline_programing(VADriverContextP ctx,
>>>>        int s;
>>>>        bool allow_hwscore = true;
>>>>        int kernel_shader;
>>>> -
>>>> -    for (s = 0; s < encode_state->num_slice_params_ext; s++) {
>>>> -        pSliceParameter = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[s]->buffer;
>>>> -        if ((pSliceParameter->macroblock_address % width_in_mbs)) {
>>>> -            allow_hwscore = false;
>>>> -            break;
>>>> -	}
>>>> +    unsigned int is_low_quality = (encode_state->quality_level == ENCODER_LOW_QUALITY);
>>>> +
>>>> +    if (is_low_quality)
>>>> +        allow_hwscore = false;
>>>> +    else {
>>>> +        for (s = 0; s < encode_state->num_slice_params_ext; s++) {
>>>> +            pSliceParameter = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[s]->buffer;
>>>> +            if ((pSliceParameter->macroblock_address % width_in_mbs)) {
>>>> +                allow_hwscore = false;
>>>> +                break;
>>>> +            }
>>>> +        }
>>>>        }
>>>>    
>>>>        if ((pSliceParameter->slice_type == SLICE_TYPE_I) ||
>>>>    	(pSliceParameter->slice_type == SLICE_TYPE_I)) {
>>>> -	kernel_shader = AVC_VME_INTRA_SHADER;
>>>> +	kernel_shader = (is_low_quality ? AVC_VME_OLD_INTRA_SHADER : AVC_VME_INTRA_SHADER);
>>>>        } else if ((pSliceParameter->slice_type == SLICE_TYPE_P) ||
>>>>                   (pSliceParameter->slice_type == SLICE_TYPE_SP)) {
>>>> -	kernel_shader = AVC_VME_INTER_SHADER;
>>>> +	kernel_shader = (is_low_quality ? AVC_VME_OLD_INTER_SHADER : AVC_VME_INTER_SHADER);
>>>>        } else {
>>>>    	kernel_shader = AVC_VME_BINTER_SHADER;
>>>>    	if (!allow_hwscore)
>>>> -            kernel_shader = AVC_VME_INTER_SHADER;
>>>> +            kernel_shader = (is_low_quality ? AVC_VME_OLD_INTER_SHADER : AVC_VME_INTER_SHADER);
>>>>        }
>>>>    
>>>>        if (allow_hwscore)
>>>> @@ -668,7 +727,10 @@ static VAStatus gen7_vme_prepare(VADriverContextP ctx,
>>>>        gen7_vme_surface_setup(ctx, encode_state, is_intra, encoder_context);
>>>>        gen7_vme_interface_setup(ctx, encode_state, encoder_context);
>>>>        gen7_vme_constant_setup(ctx, encode_state, encoder_context);
>>>> -    gen7_vme_avc_state_setup(ctx, encode_state, is_intra, encoder_context);
>>>> +    if (encode_state->quality_level == ENCODER_LOW_QUALITY)
>>>> +        gen7_vme_vme_state_setup(ctx, encode_state, is_intra, encoder_context);
>>>> +    else
>>>> +        gen7_vme_avc_state_setup(ctx, encode_state, is_intra, encoder_context);
>>>>    
>>>>        /*Programing media pipeline*/
>>>>        gen7_vme_pipeline_programing(ctx, encode_state, encoder_context);
>>>> diff --git a/src/i965_drv_video.c b/src/i965_drv_video.c
>>>> index fcbab79..6eaf6ca 100755
>>>> --- a/src/i965_drv_video.c
>>>> +++ b/src/i965_drv_video.c
>>>> @@ -621,6 +621,7 @@ i965_GetConfigAttributes(VADriverContextP ctx,
>>>>                             int num_attribs)
>>>>    {
>>>>        VAStatus va_status;
>>>> +    struct i965_driver_data *i965 = i965_driver_data(ctx);
>>>>        int i;
>>>>    
>>>>        va_status = i965_validate_config(ctx, profile, entrypoint);
>>>> @@ -665,6 +666,15 @@ i965_GetConfigAttributes(VADriverContextP ctx,
>>>>    		break;
>>>>    	    }
>>>>    
>>>> +	case VAConfigAttribEncQualityRange:
>>>> +	    if (entrypoint == VAEntrypointEncSlice) {
>>>> +		attrib_list[i].value = 1;
>>>> +                if (profile == VAProfileH264ConstrainedBaseline &&
>>>> +                    IS_GEN7(i965->intel.device_info))
>>> Does the low quality shader support Main Profile ?
>> [Zhong] No, it cann't support B frame, so cann't support Main profile.
>> And it cann't support 8x8 transform(This is high profile feature).
>
> Actually the shader can support B frame with few changes, you can check
> the commit log.
>
[Zhong] Thanks for your remind, I'll check it.
But maybe we can apply these patches, then add more features and reduce 
more limitations later.
>>>> +                    attrib_list[i].value = ENCODER_QUALITY_RANGE;
>>>> +		break;
>>>> +	    }
>>>> +
>>>>            default:
>>>>                /* Do nothing */
>>>>                attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
>>>> @@ -2214,6 +2224,8 @@ i965_BeginPicture(VADriverContextP ctx,
>>>>            obj_context->codec_state.encode.num_slice_params_ext = 0;
>>>>            obj_context->codec_state.encode.current_render_target = render_target;     /*This is input new frame*/
>>>>            obj_context->codec_state.encode.last_packed_header_type = 0;
>>>> +        obj_context->codec_state.encode.quality_level = ENCODER_DEFAULT_QUALITY;
>>>> +
>>>>            memset(obj_context->codec_state.encode.slice_rawdata_index, 0,
>>>>                   sizeof(int) * obj_context->codec_state.encode.slice_num);
>>>>            memset(obj_context->codec_state.encode.slice_rawdata_count, 0,
>>>> diff --git a/src/i965_drv_video.h b/src/i965_drv_video.h
>>>> index 418c277..29aa10b 100644
>>>> --- a/src/i965_drv_video.h
>>>> +++ b/src/i965_drv_video.h
>>>> @@ -65,6 +65,11 @@
>>>>    #define DEFAULT_HUE             0
>>>>    #define DEFAULT_SATURATION      10
>>>>    
>>>> +#define ENCODER_QUALITY_RANGE     2
>>>> +#define ENCODER_DEFAULT_QUALITY   1
>>>> +#define ENCODER_HIGH_QUALITY      ENCODER_DEFAULT_QUALITY
>>>> +#define ENCODER_LOW_QUALITY       2
>>>> +
>>>>    struct i965_surface
>>>>    {
>>>>        struct object_base *base;
>>>> @@ -172,6 +177,8 @@ struct encode_state
>>>>    
>>>>        struct buffer_store *misc_param[16];
>>>>    
>>>> +    unsigned int quality_level;
>>>> +
>>>>        VASurfaceID current_render_target;
>>>>        struct object_surface *input_yuv_object;
>>>>        struct object_surface *reconstructed_object;
>>>> diff --git a/src/i965_encoder.c b/src/i965_encoder.c
>>>> index 14c37bb..bcaa61c 100644
>>>> --- a/src/i965_encoder.c
>>>> +++ b/src/i965_encoder.c
>>>> @@ -124,6 +124,7 @@ intel_encoder_check_yuv_surface(VADriverContextP ctx,
>>>>    
>>>>    static VAStatus
>>>>    intel_encoder_check_avc_parameter(VADriverContextP ctx,
>>>> +                                  VAProfile profile,
>>>>                                      struct encode_state *encode_state,
>>>>                                      struct intel_encoder_context *encoder_context)
>>> This function is used to validate sequence, picture and slice parameters
>>> from user. so it is not suitable to check misc parameter here.
>> [Zhong] This function is used to check parameters before avc encoding.
>> The input of this function is encode_state, not sps/pps/slice parameters.
> Yes, but only for the parameters for the codec.  sps/pps/slice
> parameters are passed down by encode_state.
>
>
>> I don't think there is large gap to check quality level in this function.
>>>>    {
>>>> @@ -151,6 +152,24 @@ intel_encoder_check_avc_parameter(VADriverContextP ctx,
>>>>        if (!obj_buffer || !obj_buffer->buffer_store || !obj_buffer->buffer_store->bo)
>>>>            goto error;
>>>>    
>>>> +    if (encode_state->misc_param[VAEncMiscParameterTypeQualityLevel] &&
>>>> +        encode_state->misc_param[VAEncMiscParameterTypeQualityLevel]->buffer) {
>>>> +        VAEncMiscParameterBuffer* pMiscParam = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeQualityLevel]->buffer;
>>>> +        VAEncMiscParameterBufferQualityLevel* param_quality_level = (VAEncMiscParameterBufferQualityLevel*)pMiscParam->data;
>>>> +        encode_state->quality_level = param_quality_level->quality_level;
>>>> +
>>>> +        if (encode_state->quality_level == 0)
>>>> +            encode_state->quality_level = ENCODER_DEFAULT_QUALITY;
>>>> +        else if (encode_state->quality_level == ENCODER_LOW_QUALITY &&
>>>> +                 (profile != VAProfileH264ConstrainedBaseline ||
>>>> +                  encoder_context->rate_control_mode != VA_RC_CQP)) {
>>>> +            /* low quality level mode only support baseline profile and CQP rate control */
>>>> +            goto error;
>>> This is the limitation for low quality shader on GEN7, it would be
>>> better to move the code to GEN7 related file(s).
>> I am going to add quality level configurable support on gen6 and gen75.
>> As I know, their old version vme shaders  have same limitations.
>>>> +        }
>>>> +        else if (encode_state->quality_level > ENCODER_QUALITY_RANGE)
>>>> +            goto error;
>>>> +   }
>>>> +
>>>>        encode_state->coded_buf_object = obj_buffer;
>>>>    
>>>>        for (i = 0; i < 16; i++) {
>>>> @@ -260,7 +279,7 @@ intel_encoder_sanity_check_input(VADriverContextP ctx,
>>>>        case VAProfileH264High:
>>>>        case VAProfileH264MultiviewHigh:
>>>>        case VAProfileH264StereoHigh:
>>>> -        vaStatus = intel_encoder_check_avc_parameter(ctx, encode_state, encoder_context);
>>>> +        vaStatus = intel_encoder_check_avc_parameter(ctx, profile, encode_state, encoder_context);
>>>>            break;
>>>>    
>>>>        case VAProfileMPEG2Simple:
>>>
>>>
>
>
>



More information about the Libva mailing list