OSDN Git Service

Fix a typo
[android-x86/hardware-intel-common-vaapi.git] / src / i965_encoder.c
index d874322..3e28fcb 100644 (file)
 #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;
 
-    switchobj_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) {