X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Fi965_encoder.c;h=3e28fcb9059fa380074ef9e7f4cb2b134daf00b1;hb=dcae7d3df307f27d0545034768ae54d6153bfcbc;hp=d874322896a81fa0c77ff70cd4e1a7d0cf3ad324;hpb=8b0837394a4224e83ba2e4448cd24307e2db73b9;p=android-x86%2Fhardware-intel-common-vaapi.git diff --git a/src/i965_encoder.c b/src/i965_encoder.c index d874322..3e28fcb 100644 --- a/src/i965_encoder.c +++ b/src/i965_encoder.c @@ -41,6 +41,21 @@ #include "gen6_mfc.h" #include "i965_post_processing.h" +#include "i965_encoder_api.h" +#include "i965_avc_encoder_common.h" + +static struct intel_fraction +reduce_fraction(struct intel_fraction f) +{ + unsigned int a = f.num, b = f.den, c; + while ((c = a % b)) { + a = b; + b = c; + } + return (struct intel_fraction) { + f.num / b, f.den / b + }; +} static VAStatus clear_border(struct object_surface *obj_surface) @@ -48,7 +63,7 @@ clear_border(struct object_surface *obj_surface) int width[3], height[3], hstride[3], vstride[3]; /* in byte */ int planes; unsigned char* p; - int i,j; + int i, j; if (obj_surface->border_cleared) return VA_STATUS_SUCCESS; @@ -59,7 +74,7 @@ clear_border(struct object_surface *obj_surface) height[0] = obj_surface->orig_height; height[1] = obj_surface->orig_height / 2; hstride[0] = hstride[1] = obj_surface->width; - vstride[0]= obj_surface->height; + vstride[0] = obj_surface->height; vstride[1] = obj_surface->height / 2; } else { @@ -105,6 +120,8 @@ intel_encoder_check_yuv_surface(VADriverContextP ctx, struct object_surface *obj_surface; VAStatus status; VARectangle rect; + int format = VA_RT_FORMAT_YUV420; + unsigned int fourcc = VA_FOURCC_NV12; /* releae the temporary surface */ if (encoder_context->is_tmp_id) { @@ -125,7 +142,7 @@ intel_encoder_check_yuv_surface(VADriverContextP ctx, if (obj_surface->fourcc == VA_FOURCC_NV12 || (VAProfileHEVCMain10 == profile && - obj_surface->fourcc == VA_FOURCC_P010)) { + obj_surface->fourcc == VA_FOURCC_P010)) { unsigned int tiling = 0, swizzle = 0; dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle); @@ -137,19 +154,24 @@ intel_encoder_check_yuv_surface(VADriverContextP ctx, } } + if (VAProfileHEVCMain10 == profile) { + format = VA_RT_FORMAT_YUV420_10BPP; + fourcc = VA_FOURCC_P010; + } + rect.x = 0; rect.y = 0; rect.width = obj_surface->orig_width; rect.height = obj_surface->orig_height; - + src_surface.base = (struct object_base *)obj_surface; src_surface.type = I965_SURFACE_TYPE_SURFACE; src_surface.flags = I965_SURFACE_FLAG_FRAME; - + status = i965_CreateSurfaces(ctx, obj_surface->orig_width, obj_surface->orig_height, - VA_RT_FORMAT_YUV420, + format, 1, &encoder_context->input_yuv_surface); ASSERT_RET(status == VA_STATUS_SUCCESS, status); @@ -157,8 +179,8 @@ intel_encoder_check_yuv_surface(VADriverContextP ctx, obj_surface = SURFACE(encoder_context->input_yuv_surface); encode_state->input_yuv_object = obj_surface; assert(obj_surface); - i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420); - + i965_check_alloc_surface_bo(ctx, obj_surface, 1, fourcc, SUBSAMPLE_YUV420); + dst_surface.base = (struct object_base *)obj_surface; dst_surface.type = I965_SURFACE_TYPE_SURFACE; dst_surface.flags = I965_SURFACE_FLAG_FRAME; @@ -178,16 +200,16 @@ intel_encoder_check_yuv_surface(VADriverContextP ctx, static VAStatus intel_encoder_check_jpeg_yuv_surface(VADriverContextP ctx, - VAProfile profile, - struct encode_state *encode_state, - struct intel_encoder_context *encoder_context) + VAProfile profile, + struct encode_state *encode_state, + struct intel_encoder_context *encoder_context) { struct i965_driver_data *i965 = i965_driver_data(ctx); struct i965_surface src_surface, dst_surface; struct object_surface *obj_surface; VAStatus status; VARectangle rect; - int format=0, fourcc=0, subsample=0; + int format = 0, fourcc = 0, subsample = 0; /* releae the temporary surface */ if (encoder_context->is_tmp_id) { @@ -207,9 +229,9 @@ intel_encoder_check_jpeg_yuv_surface(VADriverContextP ctx, dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle); if (tiling == I915_TILING_Y) { - if( (obj_surface->fourcc==VA_FOURCC_NV12) || (obj_surface->fourcc==VA_FOURCC_UYVY) || - (obj_surface->fourcc==VA_FOURCC_YUY2) || (obj_surface->fourcc==VA_FOURCC_Y800) || - (obj_surface->fourcc==VA_FOURCC_RGBA) || (obj_surface->fourcc==VA_FOURCC_444P) ) { + if ((obj_surface->fourcc == VA_FOURCC_NV12) || (obj_surface->fourcc == VA_FOURCC_UYVY) || + (obj_surface->fourcc == VA_FOURCC_YUY2) || (obj_surface->fourcc == VA_FOURCC_Y800) || + (obj_surface->fourcc == VA_FOURCC_RGBA) || (obj_surface->fourcc == VA_FOURCC_444P)) { encoder_context->input_yuv_surface = encode_state->current_render_target; encode_state->input_yuv_object = obj_surface; return VA_STATUS_SUCCESS; @@ -225,43 +247,43 @@ intel_encoder_check_jpeg_yuv_surface(VADriverContextP ctx, src_surface.type = I965_SURFACE_TYPE_SURFACE; src_surface.flags = I965_SURFACE_FLAG_FRAME; - switch( obj_surface->fourcc) { + switch (obj_surface->fourcc) { - case VA_FOURCC_YUY2: - fourcc = VA_FOURCC_YUY2; - format = VA_RT_FORMAT_YUV422; - subsample = SUBSAMPLE_YUV422H; - break; + case VA_FOURCC_YUY2: + fourcc = VA_FOURCC_YUY2; + format = VA_RT_FORMAT_YUV422; + subsample = SUBSAMPLE_YUV422H; + break; - case VA_FOURCC_UYVY: - fourcc = VA_FOURCC_UYVY; - format = VA_RT_FORMAT_YUV422; - subsample = SUBSAMPLE_YUV422H; - break; + case VA_FOURCC_UYVY: + fourcc = VA_FOURCC_UYVY; + format = VA_RT_FORMAT_YUV422; + subsample = SUBSAMPLE_YUV422H; + break; - case VA_FOURCC_Y800: - fourcc = VA_FOURCC_Y800; - format = VA_RT_FORMAT_YUV400; - subsample = SUBSAMPLE_YUV400; - break; + case VA_FOURCC_Y800: + fourcc = VA_FOURCC_Y800; + format = VA_RT_FORMAT_YUV400; + subsample = SUBSAMPLE_YUV400; + break; - case VA_FOURCC_444P: - fourcc = VA_FOURCC_444P; - format = VA_RT_FORMAT_YUV444; - subsample = SUBSAMPLE_YUV444; - break; + case VA_FOURCC_444P: + fourcc = VA_FOURCC_444P; + format = VA_RT_FORMAT_YUV444; + subsample = SUBSAMPLE_YUV444; + break; - case VA_FOURCC_RGBA: - fourcc = VA_FOURCC_RGBA; - format = VA_RT_FORMAT_RGB32; - subsample = SUBSAMPLE_RGBX; - break; + case VA_FOURCC_RGBA: + fourcc = VA_FOURCC_RGBA; + format = VA_RT_FORMAT_RGB32; + subsample = SUBSAMPLE_RGBX; + break; - default: //All other scenarios will have NV12 format - fourcc = VA_FOURCC_NV12; - format = VA_RT_FORMAT_YUV420; - subsample = SUBSAMPLE_YUV420; - break; + default: //All other scenarios will have NV12 format + fourcc = VA_FOURCC_NV12; + format = VA_RT_FORMAT_YUV420; + subsample = SUBSAMPLE_YUV420; + break; } status = i965_CreateSurfaces(ctx, @@ -286,12 +308,12 @@ intel_encoder_check_jpeg_yuv_surface(VADriverContextP ctx, //The Y800 format is expected to be tiled. //Linear Y800 is a corner case and needs code in the i965_image_processing. - if(obj_surface->fourcc != VA_FOURCC_Y800){ + if (obj_surface->fourcc != VA_FOURCC_Y800) { status = i965_image_processing(ctx, - &src_surface, - &rect, - &dst_surface, - &rect); + &src_surface, + &rect, + &dst_surface, + &rect); assert(status == VA_STATUS_SUCCESS); } @@ -303,22 +325,29 @@ intel_encoder_check_jpeg_yuv_surface(VADriverContextP ctx, static VAStatus intel_encoder_check_brc_h264_sequence_parameter(VADriverContextP ctx, struct encode_state *encode_state, - struct intel_encoder_context *encoder_context) + struct intel_encoder_context *encoder_context, + unsigned int *seq_bits_per_second) { VAEncSequenceParameterBufferH264 *seq_param = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer; + struct intel_fraction framerate; unsigned short num_pframes_in_gop, num_bframes_in_gop; - unsigned int bits_per_second, framerate_per_100s; if (!encoder_context->is_new_sequence) return VA_STATUS_SUCCESS; assert(seq_param); - bits_per_second = seq_param->bits_per_second; // for the highest layer - if (!seq_param->num_units_in_tick || !seq_param->time_scale) - framerate_per_100s = 3000; - else - framerate_per_100s = seq_param->time_scale * 100 / (2 * seq_param->num_units_in_tick); // for the highest layer + if (!seq_param->num_units_in_tick || !seq_param->time_scale) { + framerate = (struct intel_fraction) { + 30, 1 + }; + } else { + // for the highest layer + framerate = (struct intel_fraction) { + seq_param->time_scale, 2 * seq_param->num_units_in_tick + }; + } + framerate = reduce_fraction(framerate); encoder_context->brc.num_iframes_in_gop = 1; // Always 1 @@ -326,7 +355,7 @@ intel_encoder_check_brc_h264_sequence_parameter(VADriverContextP ctx, if (seq_param->ip_period == 0) goto error; - encoder_context->brc.gop_size = (unsigned int)(framerate_per_100s / 100.0 + 0.5); // fake + encoder_context->brc.gop_size = (framerate.num + framerate.den - 1) / framerate.den; // fake num_pframes_in_gop = (encoder_context->brc.gop_size + seq_param->ip_period - 1) / seq_param->ip_period - 1; } else if (seq_param->intra_period == 1) { // E.g. IDRIII... @@ -346,12 +375,11 @@ intel_encoder_check_brc_h264_sequence_parameter(VADriverContextP ctx, if (num_pframes_in_gop != encoder_context->brc.num_pframes_in_gop || num_bframes_in_gop != encoder_context->brc.num_bframes_in_gop || - bits_per_second != encoder_context->brc.bits_per_second[encoder_context->layer.num_layers - 1] || - framerate_per_100s != encoder_context->brc.framerate_per_100s[encoder_context->layer.num_layers - 1]) { + framerate.num != encoder_context->brc.framerate[encoder_context->layer.num_layers - 1].num || + framerate.den != encoder_context->brc.framerate[encoder_context->layer.num_layers - 1].den) { encoder_context->brc.num_pframes_in_gop = num_pframes_in_gop; encoder_context->brc.num_bframes_in_gop = num_bframes_in_gop; - encoder_context->brc.bits_per_second[encoder_context->layer.num_layers - 1] = bits_per_second; - encoder_context->brc.framerate_per_100s[encoder_context->layer.num_layers - 1] = framerate_per_100s; + encoder_context->brc.framerate[encoder_context->layer.num_layers - 1] = framerate; encoder_context->brc.need_reset = 1; } @@ -361,6 +389,8 @@ intel_encoder_check_brc_h264_sequence_parameter(VADriverContextP ctx, encoder_context->brc.hrd_initial_buffer_fullness = seq_param->bits_per_second; } + *seq_bits_per_second = seq_param->bits_per_second; + return VA_STATUS_SUCCESS; error: @@ -370,10 +400,11 @@ error: static VAStatus intel_encoder_check_brc_vp8_sequence_parameter(VADriverContextP ctx, struct encode_state *encode_state, - struct intel_encoder_context *encoder_context) + struct intel_encoder_context *encoder_context, + unsigned int *seq_bits_per_second) { VAEncSequenceParameterBufferVP8 *seq_param = (VAEncSequenceParameterBufferVP8 *)encode_state->seq_param_ext->buffer; - unsigned int num_pframes_in_gop, bits_per_second; + unsigned int num_pframes_in_gop; if (!encoder_context->is_new_sequence) return VA_STATUS_SUCCESS; @@ -390,17 +421,17 @@ intel_encoder_check_brc_vp8_sequence_parameter(VADriverContextP ctx, } num_pframes_in_gop = encoder_context->brc.gop_size - 1; - bits_per_second = seq_param->bits_per_second; // for the highest layer - if (!encoder_context->brc.framerate_per_100s[encoder_context->layer.num_layers - 1]) { - encoder_context->brc.framerate_per_100s[encoder_context->layer.num_layers - 1] = 3000; // for the highest layer + if (!encoder_context->brc.framerate[encoder_context->layer.num_layers - 1].num) { + // for the highest layer + encoder_context->brc.framerate[encoder_context->layer.num_layers - 1] = (struct intel_fraction) { + 30, 1 + }; encoder_context->brc.need_reset = 1; } - if (num_pframes_in_gop != encoder_context->brc.num_pframes_in_gop || - bits_per_second != encoder_context->brc.bits_per_second[encoder_context->layer.num_layers - 1]) { + if (num_pframes_in_gop != encoder_context->brc.num_pframes_in_gop) { encoder_context->brc.num_pframes_in_gop = num_pframes_in_gop; - encoder_context->brc.bits_per_second[encoder_context->layer.num_layers - 1] = bits_per_second; encoder_context->brc.need_reset = 1; } @@ -411,29 +442,133 @@ intel_encoder_check_brc_vp8_sequence_parameter(VADriverContextP ctx, encoder_context->brc.need_reset = 1; } + *seq_bits_per_second = seq_param->bits_per_second; + + return VA_STATUS_SUCCESS; +} + +static VAStatus +intel_encoder_check_brc_hevc_sequence_parameter(VADriverContextP ctx, + struct encode_state *encode_state, + struct intel_encoder_context *encoder_context, + unsigned int *seq_bits_per_second) +{ + VAEncSequenceParameterBufferHEVC *seq_param = (VAEncSequenceParameterBufferHEVC*)encode_state->seq_param_ext->buffer; + struct intel_fraction framerate; + unsigned int gop_size, num_iframes_in_gop, num_pframes_in_gop, num_bframes_in_gop; + + if (!encoder_context->is_new_sequence) + return VA_STATUS_SUCCESS; + if (!seq_param) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + if (!seq_param->vui_time_scale || !seq_param->vui_num_units_in_tick) + framerate = (struct intel_fraction) { + 30, 1 + }; + else + framerate = (struct intel_fraction) { + seq_param->vui_time_scale, seq_param->vui_num_units_in_tick + }; + framerate = reduce_fraction(framerate); + + num_iframes_in_gop = 1; + if (seq_param->intra_period == 0) { + gop_size = -1; + num_pframes_in_gop = -1; + } else if (seq_param->intra_period == 1) { + gop_size = 1; + num_pframes_in_gop = 0; + } else { + gop_size = seq_param->intra_period; + num_pframes_in_gop = (seq_param->intra_period + seq_param->ip_period - 1) / seq_param->ip_period - 1; + } + num_bframes_in_gop = gop_size - num_iframes_in_gop - num_pframes_in_gop; + + if (encoder_context->brc.framerate[0].num != framerate.num || + encoder_context->brc.framerate[0].den != framerate.den) { + encoder_context->brc.framerate[0] = framerate; + encoder_context->brc.need_reset = 1; + } + + if (encoder_context->brc.gop_size != gop_size || + encoder_context->brc.num_iframes_in_gop != num_iframes_in_gop || + encoder_context->brc.num_pframes_in_gop != num_pframes_in_gop || + encoder_context->brc.num_bframes_in_gop != num_bframes_in_gop) { + encoder_context->brc.gop_size = gop_size; + encoder_context->brc.num_iframes_in_gop = num_iframes_in_gop; + encoder_context->brc.num_pframes_in_gop = num_pframes_in_gop; + encoder_context->brc.num_bframes_in_gop = num_bframes_in_gop; + encoder_context->brc.need_reset = 1; + } + + *seq_bits_per_second = seq_param->bits_per_second; + + return VA_STATUS_SUCCESS; +} + +static VAStatus +intel_encoder_check_brc_vp9_sequence_parameter(VADriverContextP ctx, + struct encode_state *encode_state, + struct intel_encoder_context *encoder_context, + unsigned int *seq_bits_per_second) +{ + VAEncSequenceParameterBufferVP9 *seq_param = (VAEncSequenceParameterBufferVP9*)encode_state->seq_param_ext->buffer; + unsigned int gop_size; + + if (!encoder_context->is_new_sequence) + return VA_STATUS_SUCCESS; + if (!seq_param) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + if (seq_param->intra_period == 0) + gop_size = -1; // Dummy value (infinity). + else + gop_size = seq_param->intra_period; + + if (encoder_context->brc.gop_size != gop_size) { + encoder_context->brc.gop_size = gop_size; + encoder_context->brc.need_reset = 1; + } + + *seq_bits_per_second = seq_param->bits_per_second; + return VA_STATUS_SUCCESS; } static VAStatus intel_encoder_check_brc_sequence_parameter(VADriverContextP ctx, struct encode_state *encode_state, - struct intel_encoder_context *encoder_context) + struct intel_encoder_context *encoder_context, + unsigned int *seq_bits_per_second) { - if (encoder_context->codec == CODEC_H264 || - encoder_context->codec == CODEC_H264_MVC) - return intel_encoder_check_brc_h264_sequence_parameter(ctx, encode_state, encoder_context); + *seq_bits_per_second = 0; - if (encoder_context->codec == CODEC_VP8) - return intel_encoder_check_brc_vp8_sequence_parameter(ctx, encode_state, encoder_context); + switch (encoder_context->codec) { + case CODEC_H264: + case CODEC_H264_MVC: + return intel_encoder_check_brc_h264_sequence_parameter(ctx, encode_state, encoder_context, seq_bits_per_second); - // TODO: other codecs - return VA_STATUS_SUCCESS; + case CODEC_VP8: + return intel_encoder_check_brc_vp8_sequence_parameter(ctx, encode_state, encoder_context, seq_bits_per_second); + + case CODEC_HEVC: + return intel_encoder_check_brc_hevc_sequence_parameter(ctx, encode_state, encoder_context, seq_bits_per_second); + + case CODEC_VP9: + return intel_encoder_check_brc_vp9_sequence_parameter(ctx, encode_state, encoder_context, seq_bits_per_second); + + default: + // TODO: other codecs + return VA_STATUS_SUCCESS; + } } static void intel_encoder_check_rate_control_parameter(VADriverContextP ctx, struct intel_encoder_context *encoder_context, - VAEncMiscParameterRateControl *misc) + VAEncMiscParameterRateControl *misc, + int *hl_bitrate_updated) { int temporal_id = 0; @@ -460,6 +595,18 @@ intel_encoder_check_rate_control_parameter(VADriverContextP ctx, encoder_context->brc.target_percentage[temporal_id] = misc->target_percentage; encoder_context->brc.need_reset = 1; } + + if (encoder_context->brc.window_size != misc->window_size || + encoder_context->brc.initial_qp != misc->initial_qp || + encoder_context->brc.min_qp != misc->min_qp) { + encoder_context->brc.window_size = misc->window_size; + encoder_context->brc.initial_qp = misc->initial_qp; + encoder_context->brc.min_qp = misc->min_qp; + encoder_context->brc.need_reset = 1; + } + + if (temporal_id == encoder_context->layer.num_layers - 1) + *hl_bitrate_updated = 1; } static void @@ -480,7 +627,7 @@ intel_encoder_check_framerate_parameter(VADriverContextP ctx, struct intel_encoder_context *encoder_context, VAEncMiscParameterFrameRate *misc) { - int framerate_per_100s; + struct intel_fraction framerate; int temporal_id = 0; if (encoder_context->layer.num_layers >= 2) @@ -490,12 +637,18 @@ intel_encoder_check_framerate_parameter(VADriverContextP ctx, return; if (misc->framerate & 0xffff0000) - framerate_per_100s = (misc->framerate & 0xffff) * 100 / ((misc->framerate >> 16) & 0xffff); + framerate = (struct intel_fraction) { + misc->framerate & 0xffff, misc->framerate >> 16 & 0xffff + }; else - framerate_per_100s = misc->framerate * 100; - - if (encoder_context->brc.framerate_per_100s[temporal_id] != framerate_per_100s) { - encoder_context->brc.framerate_per_100s[temporal_id] = framerate_per_100s; + framerate = (struct intel_fraction) { + misc->framerate, 1 + }; + framerate = reduce_fraction(framerate); + + if (encoder_context->brc.framerate[temporal_id].num != framerate.num || + encoder_context->brc.framerate[temporal_id].den != framerate.den) { + encoder_context->brc.framerate[temporal_id] = framerate; encoder_context->brc.need_reset = 1; } } @@ -532,14 +685,15 @@ intel_encoder_check_brc_parameter(VADriverContextP ctx, VAStatus ret; VAEncMiscParameterBuffer *misc_param; int i, j; + int hl_bitrate_updated = 0; // Indicate whether the bitrate for the highest level is changed in misc parameters + unsigned int seq_bits_per_second = 0; - if (!(encoder_context->rate_control_mode & (VA_RC_CBR | VA_RC_VBR))) - return VA_STATUS_SUCCESS; - - ret = intel_encoder_check_brc_sequence_parameter(ctx, encode_state, encoder_context); + if (encoder_context->rate_control_mode & (VA_RC_CBR | VA_RC_VBR)) { + ret = intel_encoder_check_brc_sequence_parameter(ctx, encode_state, encoder_context, &seq_bits_per_second); - if (ret) - return ret; + if (ret) + return ret; + } for (i = 0; i < ARRAY_ELEMS(encode_state->misc_param); i++) { for (j = 0; j < ARRAY_ELEMS(encode_state->misc_param[0]); j++) { @@ -548,6 +702,11 @@ intel_encoder_check_brc_parameter(VADriverContextP ctx, misc_param = (VAEncMiscParameterBuffer *)encode_state->misc_param[i][j]->buffer; + if (!(encoder_context->rate_control_mode & (VA_RC_CBR | VA_RC_VBR))) { + if (misc_param->type != VAEncMiscParameterTypeROI) + continue; + } + switch (misc_param->type) { case VAEncMiscParameterTypeFrameRate: intel_encoder_check_framerate_parameter(ctx, @@ -558,7 +717,8 @@ intel_encoder_check_brc_parameter(VADriverContextP ctx, case VAEncMiscParameterTypeRateControl: intel_encoder_check_rate_control_parameter(ctx, encoder_context, - (VAEncMiscParameterRateControl *)misc_param->data); + (VAEncMiscParameterRateControl *)misc_param->data, + &hl_bitrate_updated); break; case VAEncMiscParameterTypeHRD: @@ -579,6 +739,14 @@ intel_encoder_check_brc_parameter(VADriverContextP ctx, } } + if (!hl_bitrate_updated && seq_bits_per_second && + encoder_context->brc.bits_per_second[encoder_context->layer.num_layers - 1] != seq_bits_per_second) { + + encoder_context->brc.bits_per_second[encoder_context->layer.num_layers - 1] = seq_bits_per_second; + encoder_context->brc.need_reset = 1; + + } + return VA_STATUS_SUCCESS; } @@ -650,10 +818,22 @@ intel_encoder_check_temporal_layer_structure(VADriverContextP ctx, static VAStatus intel_encoder_check_misc_parameter(VADriverContextP ctx, - struct encode_state *encode_state, - struct intel_encoder_context *encoder_context) + VAProfile profile, + struct encode_state *encode_state, + struct intel_encoder_context *encoder_context) { + struct i965_driver_data *i965 = i965_driver_data(ctx); VAStatus ret = VA_STATUS_SUCCESS; + int min_width_height = I965_MIN_CODEC_ENC_RESOLUTION_WIDTH_HEIGHT; + + if (encoder_context->frame_width_in_pixel > 0 && + encoder_context->frame_height_in_pixel > 0) { + if (profile == VAProfileJPEGBaseline) + min_width_height = 1; + if (encoder_context->frame_width_in_pixel < min_width_height || + encoder_context->frame_height_in_pixel < min_width_height) + return VA_STATUS_ERROR_INVALID_PARAMETER; + } if (encode_state->misc_param[VAEncMiscParameterTypeQualityLevel][0] && encode_state->misc_param[VAEncMiscParameterTypeQualityLevel][0]->buffer) { @@ -661,9 +841,30 @@ intel_encoder_check_misc_parameter(VADriverContextP ctx, VAEncMiscParameterBufferQualityLevel* param_quality_level = (VAEncMiscParameterBufferQualityLevel*)pMiscParam->data; encoder_context->quality_level = param_quality_level->quality_level; - if (encoder_context->quality_level == 0) - encoder_context->quality_level = ENCODER_DEFAULT_QUALITY; - else if (encoder_context->quality_level > encoder_context->quality_range) { + if (encoder_context->quality_level == 0) { + switch (profile) { + case VAProfileH264ConstrainedBaseline: + case VAProfileH264Main: + case VAProfileH264High: + case VAProfileH264MultiviewHigh: + case VAProfileH264StereoHigh: + if (IS_GEN9(i965->intel.device_info) || + IS_GEN10(i965->intel.device_info)) + encoder_context->quality_level = ENCODER_DEFAULT_QUALITY_AVC; + break; + + case VAProfileHEVCMain: + case VAProfileHEVCMain10: + encoder_context->quality_level = ENCODER_DEFAULT_QUALITY_HEVC; + break; + + default: + encoder_context->quality_level = ENCODER_DEFAULT_QUALITY; + break; + } + } else if (encoder_context->quality_level > encoder_context->quality_range) { + i965_log_info(ctx, "VAEncMiscParameterBufferQualityLevel.quality_level (%d) out of range (max %d).\n", + encoder_context->quality_level, encoder_context->quality_range); ret = VA_STATUS_ERROR_INVALID_PARAMETER; goto out; } @@ -686,29 +887,47 @@ intel_encoder_check_avc_parameter(VADriverContextP ctx, struct intel_encoder_context *encoder_context) { struct i965_driver_data *i965 = i965_driver_data(ctx); - struct object_surface *obj_surface; + struct object_surface *obj_surface; struct object_buffer *obj_buffer; VAEncPictureParameterBufferH264 *pic_param = (VAEncPictureParameterBufferH264 *)encode_state->pic_param_ext->buffer; VAEncSequenceParameterBufferH264 *seq_param = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer; int i; - assert(!(pic_param->CurrPic.flags & VA_PICTURE_H264_INVALID)); + if (seq_param->level_idc != encoder_context->codec_level && + !i965_avc_level_is_valid(seq_param->level_idc)) { + i965_log_info(ctx, "VAEncSequenceParameterBufferH264.level_idc (%d) does not appear to be valid.\n", + seq_param->level_idc); + encoder_context->codec_level = seq_param->level_idc; + // Only print this the first time we see it, and continue anyway - this could be a correct future + // value or an unknown extension. + } - if (pic_param->CurrPic.flags & VA_PICTURE_H264_INVALID) + if (pic_param->CurrPic.flags & VA_PICTURE_H264_INVALID) { + i965_log_info(ctx, "VAEncPictureParameterBufferH264.CurrPic.flags (%#x) is invalid.\n", + pic_param->CurrPic.flags); goto error; + } obj_surface = SURFACE(pic_param->CurrPic.picture_id); - assert(obj_surface); /* It is possible the store buffer isn't allocated yet */ - - if (!obj_surface) + if (!obj_surface) { + i965_log_info(ctx, "VAEncPictureParameterBufferH264.CurrPic.picture_id (%#x) is not a valid surface.\n", + pic_param->CurrPic.picture_id); goto error; + } encode_state->reconstructed_object = obj_surface; obj_buffer = BUFFER(pic_param->coded_buf); - assert(obj_buffer && obj_buffer->buffer_store && obj_buffer->buffer_store->bo); + if (!obj_buffer || !obj_buffer->buffer_store || !obj_buffer->buffer_store->bo) { + i965_log_info(ctx, "VAEncPictureParameterBufferH264.coded_buf (%#x) is not a valid buffer.\n", + pic_param->coded_buf); + goto error; + } - if (!obj_buffer || !obj_buffer->buffer_store || !obj_buffer->buffer_store->bo) + if (encode_state->num_slice_params_ext > encoder_context->max_slice_or_seg_num) { + i965_log_info(ctx, "Too many slices in picture submission: %d, max supported is %d.\n", + encode_state->num_slice_params_ext, encoder_context->max_slice_or_seg_num); goto error; + } encode_state->coded_buf_object = obj_buffer; @@ -718,19 +937,16 @@ intel_encoder_check_avc_parameter(VADriverContextP ctx, break; else { obj_surface = SURFACE(pic_param->ReferenceFrames[i].picture_id); - assert(obj_surface); - - if (!obj_surface) + if (!obj_surface || !obj_surface->bo) { + i965_log_info(ctx, "VAEncPictureParameterBufferH264.ReferenceFrames[%d].picture_id (%#x)" + " is not a valid surface.\n", i, pic_param->ReferenceFrames[i].picture_id); goto error; - - if (obj_surface->bo) - encode_state->reference_objects[i] = obj_surface; - else - encode_state->reference_objects[i] = NULL; /* FIXME: Warning or Error ??? */ + } + encode_state->reference_objects[i] = obj_surface; } } - for ( ; i < 16; i++) + for (; i < 16; i++) encode_state->reference_objects[i] = NULL; /* @@ -753,23 +969,77 @@ error: } static VAStatus +intel_pre_encoder_check_avc_parameter(VADriverContextP ctx, + struct encode_state *encode_state, + struct intel_encoder_context *encoder_context) +{ + struct i965_driver_data *i965 = i965_driver_data(ctx); + struct object_surface *obj_surface = NULL; + VAStatsStatisticsParameterH264 *stat_param_h264 = NULL; + VAStatsStatisticsParameter*stat_param = NULL; + + if (!encode_state->stat_param_ext) + goto error; + stat_param_h264 = + (VAStatsStatisticsParameterH264 *) encode_state->stat_param_ext->buffer; + stat_param = (VAStatsStatisticsParameter *)(&stat_param_h264->stats_params); + + if (stat_param->input.flags == VA_PICTURE_STATS_INVALID) + goto error; + + obj_surface = SURFACE(encoder_context->input_yuv_surface); + if (!obj_surface) + goto error; + +#if 0 + /* FeiPreEncFixme: Since the driver is doing internal CSC for non NV12 + input surfaces, this check may fail here */ + /* Make sure the same input yuv has been provided in vaBeginPicture() + * and VAStatsStatisticsParameter */ + if (obj_surface != SURFACE(stat_param->input.picture_id)) + goto error; +#endif + + /* There is no reconstructed object in preenc. Here we just assigning + * the input yuv object to reconstructed object pointer inorder + * to use the same encode code path later on */ + encode_state->reconstructed_object = obj_surface; + + encoder_context->frame_width_in_pixel = obj_surface->orig_width; + encoder_context->frame_height_in_pixel = obj_surface->orig_height; + + /* PreEnc only supports maxium of 1 past and 1 future reference */ + if (stat_param->num_past_references > 1 || stat_param->num_future_references > 1) + goto error; + + return VA_STATUS_SUCCESS; +error: + return VA_STATUS_ERROR_INVALID_PARAMETER; +} + +static VAStatus intel_encoder_check_mpeg2_parameter(VADriverContextP ctx, struct encode_state *encode_state, struct intel_encoder_context *encoder_context) { struct i965_driver_data *i965 = i965_driver_data(ctx); VAEncPictureParameterBufferMPEG2 *pic_param = (VAEncPictureParameterBufferMPEG2 *)encode_state->pic_param_ext->buffer; - struct object_surface *obj_surface; + VAEncSequenceParameterBufferMPEG2 *seq_param = NULL; + struct object_surface *obj_surface; struct object_buffer *obj_buffer; int i = 0; - + + if (encode_state->seq_param_ext && + encode_state->seq_param_ext->buffer) + seq_param = (VAEncSequenceParameterBufferMPEG2 *)encode_state->seq_param_ext->buffer; + obj_surface = SURFACE(pic_param->reconstructed_picture); assert(obj_surface); /* It is possible the store buffer isn't allocated yet */ - + if (!obj_surface) goto error; - - encode_state->reconstructed_object = obj_surface; + + encode_state->reconstructed_object = obj_surface; obj_buffer = BUFFER(pic_param->coded_buf); assert(obj_buffer && obj_buffer->buffer_store && obj_buffer->buffer_store->bo); @@ -806,12 +1076,17 @@ intel_encoder_check_mpeg2_parameter(VADriverContextP ctx, goto error; encode_state->reference_objects[i++] = obj_surface; - } else + } else goto error; - for ( ; i < 16; i++) + for (; i < 16; i++) encode_state->reference_objects[i] = NULL; + if (seq_param) { + encoder_context->frame_width_in_pixel = seq_param->picture_width; + encoder_context->frame_height_in_pixel = seq_param->picture_height; + } + return VA_STATUS_SUCCESS; error: @@ -820,8 +1095,8 @@ error: static VAStatus intel_encoder_check_jpeg_parameter(VADriverContextP ctx, - struct encode_state *encode_state, - struct intel_encoder_context *encoder_context) + struct encode_state *encode_state, + struct intel_encoder_context *encoder_context) { struct i965_driver_data *i965 = i965_driver_data(ctx); struct object_buffer *obj_buffer; @@ -838,6 +1113,9 @@ intel_encoder_check_jpeg_parameter(VADriverContextP ctx, encode_state->coded_buf_object = obj_buffer; + encoder_context->frame_width_in_pixel = pic_param->picture_width; + encoder_context->frame_height_in_pixel = pic_param->picture_height; + return VA_STATUS_SUCCESS; error: @@ -846,8 +1124,8 @@ error: static VAStatus intel_encoder_check_vp8_parameter(VADriverContextP ctx, - struct encode_state *encode_state, - struct intel_encoder_context *encoder_context) + struct encode_state *encode_state, + struct intel_encoder_context *encoder_context) { struct i965_driver_data *i965 = i965_driver_data(ctx); VAEncPictureParameterBufferVP8 *pic_param = (VAEncPictureParameterBufferVP8 *)encode_state->pic_param_ext->buffer; @@ -856,13 +1134,13 @@ intel_encoder_check_vp8_parameter(VADriverContextP ctx, struct object_buffer *obj_buffer; int i = 0; int is_key_frame = !pic_param->pic_flags.bits.frame_type; - + obj_surface = SURFACE(pic_param->reconstructed_frame); assert(obj_surface); /* It is possible the store buffer isn't allocated yet */ - + if (!obj_surface) goto error; - + encode_state->reconstructed_object = obj_surface; obj_buffer = BUFFER(pic_param->coded_buf); assert(obj_buffer && obj_buffer->buffer_store && obj_buffer->buffer_store->bo); @@ -901,7 +1179,7 @@ intel_encoder_check_vp8_parameter(VADriverContextP ctx, encode_state->reference_objects[i++] = obj_surface; } - for ( ; i < 16; i++) + for (; i < 16; i++) encode_state->reference_objects[i] = NULL; encoder_context->is_new_sequence = (is_key_frame && seq_param); @@ -920,33 +1198,49 @@ error: static VAStatus intel_encoder_check_hevc_parameter(VADriverContextP ctx, - struct encode_state *encode_state, - struct intel_encoder_context *encoder_context) + struct encode_state *encode_state, + struct intel_encoder_context *encoder_context) { struct i965_driver_data *i965 = i965_driver_data(ctx); - struct object_surface *obj_surface; + struct object_surface *obj_surface; struct object_buffer *obj_buffer; VAEncPictureParameterBufferHEVC *pic_param = (VAEncPictureParameterBufferHEVC *)encode_state->pic_param_ext->buffer; VAEncSliceParameterBufferHEVC *slice_param; + VAEncSequenceParameterBufferHEVC *seq_param; int i; - assert(!(pic_param->decoded_curr_pic.flags & VA_PICTURE_HEVC_INVALID)); + seq_param = NULL; + + if (encode_state->seq_param_ext && + encode_state->seq_param_ext->buffer) + seq_param = (VAEncSequenceParameterBufferHEVC *)(encode_state->seq_param_ext->buffer); - if (pic_param->decoded_curr_pic.flags & VA_PICTURE_HEVC_INVALID) + if (pic_param->decoded_curr_pic.flags & VA_PICTURE_HEVC_INVALID) { + i965_log_info(ctx, "VAEncPictureParameterBufferHEVC.decoded_curr_pic.flags (%#x) is invalid.\n", + pic_param->decoded_curr_pic.flags); goto error; + } obj_surface = SURFACE(pic_param->decoded_curr_pic.picture_id); - assert(obj_surface); /* It is possible the store buffer isn't allocated yet */ - - if (!obj_surface) + if (!obj_surface) { + i965_log_info(ctx, "VAEncPictureParameterBufferHEVC.decoded_curr_pic.picture_id (%#x) is not a valid surface.\n", + pic_param->decoded_curr_pic.picture_id); goto error; + } encode_state->reconstructed_object = obj_surface; obj_buffer = BUFFER(pic_param->coded_buf); - assert(obj_buffer && obj_buffer->buffer_store && obj_buffer->buffer_store->bo); + if (!obj_buffer || !obj_buffer->buffer_store || !obj_buffer->buffer_store->bo) { + i965_log_info(ctx, "VAEncPictureParameterBufferHEVC.coded_buf (%#x) is not a valid buffer.\n", + pic_param->coded_buf); + goto error; + } - if (!obj_buffer || !obj_buffer->buffer_store || !obj_buffer->buffer_store->bo) + if (encode_state->num_slice_params_ext > encoder_context->max_slice_or_seg_num) { + i965_log_info(ctx, "Too many slices in picture submission: %d, max supported is %d.\n", + encode_state->num_slice_params_ext, encoder_context->max_slice_or_seg_num); goto error; + } encode_state->coded_buf_object = obj_buffer; @@ -956,19 +1250,16 @@ intel_encoder_check_hevc_parameter(VADriverContextP ctx, break; else { obj_surface = SURFACE(pic_param->reference_frames[i].picture_id); - assert(obj_surface); - - if (!obj_surface) + if (!obj_surface || !obj_surface->bo) { + i965_log_info(ctx, "VAEncPictureParameterBufferHEVC.reference_frames[%d].picture_id (%#x)" + " is not a valid surface.\n", i, pic_param->reference_frames[i].picture_id); goto error; - - if (obj_surface->bo) - encode_state->reference_objects[i] = obj_surface; - else - encode_state->reference_objects[i] = NULL; /* FIXME: Warning or Error ??? */ + } + encode_state->reference_objects[i] = obj_surface; } } - for ( ; i < 15; i++) + for (; i < 15; i++) encode_state->reference_objects[i] = NULL; for (i = 0; i < encode_state->num_slice_params_ext; i++) { @@ -982,6 +1273,14 @@ intel_encoder_check_hevc_parameter(VADriverContextP ctx, /* TODO: add more check here */ } + encoder_context->is_new_sequence = (pic_param->pic_fields.bits.idr_pic_flag && seq_param); + + if (encoder_context->is_new_sequence) { + encoder_context->num_frames_in_sequence = 0; + encoder_context->frame_width_in_pixel = seq_param->pic_width_in_luma_samples; + encoder_context->frame_height_in_pixel = seq_param->pic_height_in_luma_samples; + } + return VA_STATUS_SUCCESS; error: @@ -995,6 +1294,7 @@ intel_encoder_check_vp9_parameter(VADriverContextP ctx, { struct i965_driver_data *i965 = i965_driver_data(ctx); VAEncPictureParameterBufferVP9 *pic_param; + VAEncSequenceParameterBufferVP9 *seq_param; struct object_surface *obj_surface; struct object_buffer *obj_buffer; int i = 0; @@ -1005,6 +1305,11 @@ intel_encoder_check_vp9_parameter(VADriverContextP ctx, encode_state->pic_param_ext->buffer == NULL) return VA_STATUS_ERROR_INVALID_PARAMETER; + seq_param = NULL; + if (encode_state->seq_param_ext && + encode_state->seq_param_ext->buffer) + seq_param = (VAEncSequenceParameterBufferVP9 *)(encode_state->seq_param_ext->buffer); + pic_param = (VAEncPictureParameterBufferVP9 *)encode_state->pic_param_ext->buffer; obj_surface = SURFACE(pic_param->reconstructed_frame); @@ -1047,9 +1352,14 @@ intel_encoder_check_vp9_parameter(VADriverContextP ctx, encode_state->reference_objects[i++] = NULL; } - for ( ; i < 16; i++) + for (; i < 16; i++) encode_state->reference_objects[i] = NULL; + encoder_context->is_new_sequence = (is_key_frame && seq_param); + + encoder_context->frame_width_in_pixel = pic_param->frame_width_src; + encoder_context->frame_height_in_pixel = pic_param->frame_height_src; + return VA_STATUS_SUCCESS; error: @@ -1071,11 +1381,20 @@ intel_encoder_sanity_check_input(VADriverContextP ctx, case VAProfileH264High: case VAProfileH264MultiviewHigh: case VAProfileH264StereoHigh: { - vaStatus = intel_encoder_check_avc_parameter(ctx, encode_state, encoder_context); - if (vaStatus != VA_STATUS_SUCCESS) + if (!encoder_context->preenc_enabled) { + vaStatus = intel_encoder_check_avc_parameter(ctx, encode_state, encoder_context); + if (vaStatus != VA_STATUS_SUCCESS) + goto out; + vaStatus = intel_encoder_check_yuv_surface(ctx, profile, encode_state, encoder_context); + break; + } else { + vaStatus = intel_encoder_check_yuv_surface(ctx, profile, encode_state, encoder_context); + if (vaStatus != VA_STATUS_SUCCESS) + goto out; + + vaStatus = intel_pre_encoder_check_avc_parameter(ctx, encode_state, encoder_context); goto out; - vaStatus = intel_encoder_check_yuv_surface(ctx, profile, encode_state, encoder_context); - break; + } } case VAProfileMPEG2Simple: @@ -1094,10 +1413,10 @@ intel_encoder_sanity_check_input(VADriverContextP ctx, vaStatus = intel_encoder_check_jpeg_yuv_surface(ctx, profile, encode_state, encoder_context); break; } - + case VAProfileVP8Version0_3: { vaStatus = intel_encoder_check_vp8_parameter(ctx, encode_state, encoder_context); - if (vaStatus != VA_STATUS_SUCCESS) + if (vaStatus != VA_STATUS_SUCCESS) goto out; vaStatus = intel_encoder_check_yuv_surface(ctx, profile, encode_state, encoder_context); break; @@ -1125,15 +1444,15 @@ intel_encoder_sanity_check_input(VADriverContextP ctx, } if (vaStatus == VA_STATUS_SUCCESS) - vaStatus = intel_encoder_check_misc_parameter(ctx, encode_state, encoder_context); + vaStatus = intel_encoder_check_misc_parameter(ctx, profile, encode_state, encoder_context); -out: +out: return vaStatus; } - + static VAStatus -intel_encoder_end_picture(VADriverContextP ctx, - VAProfile profile, +intel_encoder_end_picture(VADriverContextP ctx, + VAProfile profile, union codec_state *codec_state, struct hw_context *hw_context) { @@ -1148,12 +1467,30 @@ intel_encoder_end_picture(VADriverContextP ctx, encoder_context->mfc_brc_prepare(encode_state, encoder_context); - if((encoder_context->vme_context && encoder_context->vme_pipeline)) { + /* VME or PAK stages are separately invoked if middleware configured the corresponding + * FEI modes through confgiruation attributes. On the other hand, ENC_PAK mode + * will invoke both VME and PAK similar to the non fei use case. + * PreEnc always invoke the VME */ + if (encoder_context->fei_enabled || encoder_context->preenc_enabled) { + if ((encoder_context->fei_function_mode == VA_FEI_FUNCTION_ENC) || + (encoder_context->preenc_enabled)) { + if ((encoder_context->vme_context && encoder_context->vme_pipeline)) + return encoder_context->vme_pipeline(ctx, profile, encode_state, encoder_context); + } else if (encoder_context->fei_function_mode == VA_FEI_FUNCTION_PAK) { + if ((encoder_context->mfc_context && encoder_context->mfc_pipeline)) + return encoder_context->mfc_pipeline(ctx, profile, encode_state, encoder_context); + } + /* Setting ENC and PAK as ENC|PAK is invalid */ + assert(encoder_context->fei_function_mode != (VA_FEI_FUNCTION_ENC | VA_FEI_FUNCTION_PAK)); + } + + if ((encoder_context->vme_context && encoder_context->vme_pipeline)) { vaStatus = encoder_context->vme_pipeline(ctx, profile, encode_state, encoder_context); if (vaStatus != VA_STATUS_SUCCESS) return vaStatus; } + assert(encoder_context->mfc_pipeline != NULL); encoder_context->mfc_pipeline(ctx, profile, encode_state, encoder_context); encoder_context->num_frames_in_sequence++; encoder_context->brc.need_reset = 0; @@ -1174,13 +1511,19 @@ intel_encoder_context_destroy(void *hw_context) encoder_context->mfc_context_destroy(encoder_context->mfc_context); if (encoder_context->vme_context_destroy && encoder_context->vme_context) - encoder_context->vme_context_destroy(encoder_context->vme_context); + encoder_context->vme_context_destroy(encoder_context->vme_context); if (encoder_context->enc_priv_state) { free(encoder_context->enc_priv_state); encoder_context->enc_priv_state = NULL; } + if (encoder_context->is_tmp_id) { + assert(encoder_context->input_yuv_surface != VA_INVALID_SURFACE); + i965_DestroySurfaces(encoder_context->ctx, &encoder_context->input_yuv_surface, 1); + encoder_context->is_tmp_id = 0; + } + intel_batchbuffer_free(encoder_context->base.batch); free(encoder_context); } @@ -1198,7 +1541,7 @@ intel_encoder_get_status(VADriverContextP ctx, struct hw_context *hw_context, vo return VA_STATUS_ERROR_UNIMPLEMENTED; } -typedef Bool (* hw_init_func)(VADriverContextP, struct intel_encoder_context *); +typedef Bool(* hw_init_func)(VADriverContextP, struct intel_encoder_context *); static struct hw_context * intel_enc_hw_context_init(VADriverContextP ctx, @@ -1206,6 +1549,7 @@ intel_enc_hw_context_init(VADriverContextP ctx, hw_init_func vme_context_init, hw_init_func mfc_context_init) { + struct i965_driver_data *i965 = i965_driver_data(ctx); struct intel_driver_data *intel = intel_driver_data(ctx); struct intel_encoder_context *encoder_context = calloc(1, sizeof(struct intel_encoder_context)); int i; @@ -1222,6 +1566,8 @@ intel_enc_hw_context_init(VADriverContextP ctx, encoder_context->quality_level = ENCODER_DEFAULT_QUALITY; encoder_context->quality_range = 1; encoder_context->layer.num_layers = 1; + encoder_context->max_slice_or_seg_num = 1; + encoder_context->ctx = ctx; if (obj_config->entrypoint == VAEntrypointEncSliceLP) encoder_context->low_power_mode = 1; @@ -1231,7 +1577,7 @@ intel_enc_hw_context_init(VADriverContextP ctx, case VAProfileMPEG2Main: encoder_context->codec = CODEC_MPEG2; break; - + case VAProfileH264ConstrainedBaseline: case VAProfileH264Main: case VAProfileH264High: @@ -1239,30 +1585,66 @@ intel_enc_hw_context_init(VADriverContextP ctx, if (obj_config->entrypoint == VAEntrypointEncSliceLP) encoder_context->quality_range = ENCODER_LP_QUALITY_RANGE; - else + else if (IS_GEN9(i965->intel.device_info) || + IS_GEN10(i965->intel.device_info)) { + encoder_context->quality_level = ENCODER_DEFAULT_QUALITY_AVC; + encoder_context->quality_range = ENCODER_QUALITY_RANGE_AVC; + } else encoder_context->quality_range = ENCODER_QUALITY_RANGE; + + if (obj_config->entrypoint == VAEntrypointFEI) { + encoder_context->fei_enabled = 1; + /* check which attribute has been configured for FEI, this is + * required for VME/PAK disable or enable as per user request */ + for (i = 0; i < obj_config->num_attribs; i++) { + if (obj_config->attrib_list[i].type == VAConfigAttribFEIFunctionType) + encoder_context->fei_function_mode = obj_config->attrib_list[i].value; + } + } + + if (obj_config->entrypoint == VAEntrypointStats) + encoder_context->preenc_enabled = 1; + break; case VAProfileH264StereoHigh: case VAProfileH264MultiviewHigh: + if (IS_GEN9(i965->intel.device_info) || + IS_GEN10(i965->intel.device_info)) { + encoder_context->quality_level = ENCODER_DEFAULT_QUALITY_AVC; + encoder_context->quality_range = ENCODER_QUALITY_RANGE_AVC; + } encoder_context->codec = CODEC_H264_MVC; break; - + case VAProfileJPEGBaseline: encoder_context->codec = CODEC_JPEG; break; case VAProfileVP8Version0_3: encoder_context->codec = CODEC_VP8; + encoder_context->quality_range = ENCODER_QUALITY_RANGE; + break; case VAProfileHEVCMain: case VAProfileHEVCMain10: encoder_context->codec = CODEC_HEVC; + + encoder_context->quality_level = ENCODER_DEFAULT_QUALITY_HEVC; + encoder_context->quality_range = ENCODER_QUALITY_RANGE_HEVC; + + encoder_context->max_slice_or_seg_num = I965_MAX_NUM_SLICE; break; case VAProfileVP9Profile0: encoder_context->codec = CODEC_VP9; + + if (obj_config->entrypoint == VAEntrypointEncSliceLP) { + encoder_context->quality_level = ENCODER_DEFAULT_QUALITY_VP9; + encoder_context->quality_range = ENCODER_QUALITY_RANGE_VP9; + } + break; default: @@ -1285,6 +1667,11 @@ intel_enc_hw_context_init(VADriverContextP ctx, if (encoder_context->codec == CODEC_H264) encoder_context->context_roi = 1; } + if (obj_config->attrib_list[i].type == VAConfigAttribEncMaxSlices) { + if (encoder_context->codec == CODEC_H264 || + encoder_context->codec == CODEC_HEVC) + encoder_context->max_slice_or_seg_num = obj_config->attrib_list[i].value; + } } if (vme_context_init) {