OSDN Git Service

Enc:support multi slice for AVC encoder on SKL/APL/KBL
authorPengfei Qu <Pengfei.Qu@intel.com>
Mon, 17 Apr 2017 08:00:15 +0000 (16:00 +0800)
committerXiang, Haihao <haihao.xiang@intel.com>
Thu, 4 May 2017 01:07:04 +0000 (09:07 +0800)
this patch enable the multi slice of AVC encoder. The VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS is added.

Fixes #142

Signed-off-by: Pengfei Qu <Pengfei.Qu@intel.com>
src/gen9_avc_encoder.c
src/i965_drv_video.c

index 604d9db..d0bd697 100644 (file)
@@ -718,6 +718,52 @@ failed_allocation:
     return VA_STATUS_ERROR_ALLOCATION_FAILED;
 }
 
+static void
+gen9_avc_generate_slice_map(VADriverContextP ctx,
+                            struct encode_state *encode_state,
+                            struct intel_encoder_context *encoder_context)
+{
+    struct encoder_vme_mfc_context * vme_context = (struct encoder_vme_mfc_context *)encoder_context->vme_context;
+    struct i965_avc_encoder_context * avc_ctx = (struct i965_avc_encoder_context *)vme_context->private_enc_ctx;
+    struct generic_enc_codec_state * generic_state = (struct generic_enc_codec_state *)vme_context->generic_enc_state;
+    struct avc_enc_state * avc_state = (struct avc_enc_state *)vme_context->private_enc_state;
+
+    struct i965_gpe_resource *gpe_resource = NULL;
+    VAEncSliceParameterBufferH264 * slice_param = NULL;
+    unsigned int * data = NULL;
+    unsigned int * data_row = NULL;
+    int i, j, count = 0;
+    unsigned int pitch = ALIGN((generic_state->frame_width_in_mbs + 1) * 4, 64) / 4;
+
+    if (!avc_state->arbitrary_num_mbs_in_slice)
+        return;
+
+    gpe_resource = &(avc_ctx->res_mbenc_slice_map_surface);
+    assert(gpe_resource);
+
+    i965_zero_gpe_resource(gpe_resource);
+
+    data_row = (unsigned int *)i965_map_gpe_resource(gpe_resource);
+    assert(data_row);
+
+    data = data_row;
+    for (i = 0; i < avc_state->slice_num; i++) {
+        slice_param = avc_state->slice_param[i];
+        for (j = 0; j < slice_param->num_macroblocks; j++) {
+            *data++ = i;
+            if ((count > 0) && (count % generic_state->frame_width_in_mbs == 0)) {
+                data_row += pitch;
+                data = data_row;
+                *data++ = i;
+            }
+            count++;
+        }
+    }
+    *data++ = 0xFFFFFFFF;
+
+    i965_unmap_gpe_resource(gpe_resource);
+}
+
 static VAStatus
 gen9_avc_allocate_resources(VADriverContextP ctx,
                             struct encode_state *encode_state,
@@ -750,7 +796,7 @@ gen9_avc_allocate_resources(VADriverContextP ctx,
     /* scaling related surface   */
     if (avc_state->mb_status_supported) {
         i965_free_gpe_resource(&avc_ctx->res_mb_status_buffer);
-        size = (generic_state->frame_width_in_mbs * generic_state->frame_height_in_mbs * 16 * 4 + 1023)&~0x3ff;
+        size = (generic_state->frame_width_in_mbs * generic_state->frame_height_in_mbs * 16 * 4 + 1023) & ~0x3ff;
         allocate_flag = i965_allocate_gpe_resource(i965->intel.bufmgr,
                                                    &avc_ctx->res_mb_status_buffer,
                                                    ALIGN(size, 0x1000),
@@ -967,7 +1013,7 @@ gen9_avc_allocate_resources(VADriverContextP ctx,
 
     /*     mbenc related surface. it share most of surface with other kernels     */
     if (avc_state->arbitrary_num_mbs_in_slice) {
-        width = (generic_state->frame_width_in_mbs + 1) * 64;
+        width = ALIGN((generic_state->frame_width_in_mbs + 1) * 4, 64);
         height = generic_state->frame_height_in_mbs ;
         i965_free_gpe_resource(&avc_ctx->res_mbenc_slice_map_surface);
         allocate_flag = i965_gpe_allocate_2d_resource(i965->intel.bufmgr,
@@ -977,6 +1023,7 @@ gen9_avc_allocate_resources(VADriverContextP ctx,
                                                       "slice map buffer");
         if (!allocate_flag)
             goto failed_allocation;
+        i965_zero_gpe_resource(&avc_ctx->res_mbenc_slice_map_surface);
 
         /*generate slice map,default one slice per frame.*/
     }
@@ -3839,6 +3886,7 @@ gen9_avc_send_surface_mbenc(VADriverContextP ctx,
                                        1,
                                        I965_SURFACEFORMAT_R8_UNORM,
                                        GEN9_AVC_MBENC_SLICEMAP_DATA_INDEX);
+        gen9_avc_generate_slice_map(ctx, encode_state, encoder_context);
     }
 
     /* BRC distortion data buffer for I frame */
@@ -5086,8 +5134,8 @@ gen9_avc_update_parameters(VADriverContextP ctx,
     struct generic_enc_codec_state * generic_state = (struct generic_enc_codec_state *)vme_context->generic_enc_state;
     struct avc_enc_state * avc_state = (struct avc_enc_state *)vme_context->private_enc_state;
     VAEncSequenceParameterBufferH264 *seq_param;
-    VAEncSliceParameterBufferH264 * slice_param;
-    int i, j;
+    VAEncSliceParameterBufferH264 *slice_param;
+    int i, j, slice_index;
     unsigned int preset = generic_state->preset;
 
     /* seq/pic/slice parameter setting */
@@ -5097,26 +5145,14 @@ gen9_avc_update_parameters(VADriverContextP ctx,
     avc_state->seq_param = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
     avc_state->pic_param = (VAEncPictureParameterBufferH264 *)encode_state->pic_param_ext->buffer;
 
-
-    avc_state->enable_avc_ildb = 0;
     avc_state->slice_num = 0;
-    for (j = 0; j < encode_state->num_slice_params_ext && avc_state->enable_avc_ildb == 0; j++) {
-        assert(encode_state->slice_params_ext && encode_state->slice_params_ext[j]->buffer);
+    slice_index = 0;
+    for (j = 0; j < encode_state->num_slice_params_ext; j++) {
         slice_param = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[j]->buffer;
-
         for (i = 0; i < encode_state->slice_params_ext[j]->num_elements; i++) {
-            assert((slice_param->slice_type == SLICE_TYPE_I) ||
-                   (slice_param->slice_type == SLICE_TYPE_SI) ||
-                   (slice_param->slice_type == SLICE_TYPE_P) ||
-                   (slice_param->slice_type == SLICE_TYPE_SP) ||
-                   (slice_param->slice_type == SLICE_TYPE_B));
-
-            if (slice_param->disable_deblocking_filter_idc != 1) {
-                avc_state->enable_avc_ildb = 1;
-            }
-
-            avc_state->slice_param[i] = slice_param;
+            avc_state->slice_param[slice_index] = slice_param;
             slice_param++;
+            slice_index++;
             avc_state->slice_num++;
         }
     }
@@ -5399,9 +5435,12 @@ gen9_avc_encode_check_parameter(VADriverContextP ctx,
     /*slice check,all the slices use the same slice height except the last slice*/
     avc_state->arbitrary_num_mbs_in_slice = 0;
     for (i = 0; i < avc_state->slice_num; i++) {
-        assert(avc_state->slice_param[i]->num_macroblocks % generic_state->frame_width_in_mbs == 0);
-        avc_state->slice_height = avc_state->slice_param[i]->num_macroblocks / generic_state->frame_width_in_mbs;
-        /*add it later for muli slices map*/
+        if (avc_state->slice_param[i]->num_macroblocks % generic_state->frame_width_in_mbs > 0) {
+            avc_state->arbitrary_num_mbs_in_slice = 1;
+            avc_state->slice_height = 1; /* slice height will be ignored by kernel ans here set it as default value */
+        } else {
+            avc_state->slice_height = avc_state->slice_param[i]->num_macroblocks / generic_state->frame_width_in_mbs;
+        }
     }
 
     if (generic_state->frame_type == SLICE_TYPE_I) {
@@ -6348,7 +6387,7 @@ gen9_mfc_avc_insert_aud_packed_data(VADriverContextP ctx,
 
         skip_emul_byte_cnt = intel_avc_find_skipemulcnt((unsigned char *)header_data, length_in_bits);
 
-        if ((*(nal_type+skip_emul_byte_cnt-1)&0x1f) == AVC_NAL_DELIMITER ) {
+        if ((*(nal_type + skip_emul_byte_cnt - 1) & 0x1f) == AVC_NAL_DELIMITER) {
             gen9_mfc_avc_insert_object(ctx,
                                        encoder_context,
                                        header_data,
@@ -6400,7 +6439,7 @@ gen9_mfc_avc_insert_slice_packed_data(VADriverContextP ctx,
         skip_emul_byte_cnt = intel_avc_find_skipemulcnt((unsigned char *)header_data, length_in_bits);
 
         /* skip the slice header packed data type as it is lastly inserted */
-        if (param->type == VAEncPackedHeaderSlice || (*(nal_type+skip_emul_byte_cnt-1)&0x1f) == AVC_NAL_DELIMITER)
+        if (param->type == VAEncPackedHeaderSlice || (*(nal_type + skip_emul_byte_cnt - 1) & 0x1f) == AVC_NAL_DELIMITER)
             continue;
 
         /* as the slice header is still required, the last header flag is set to
@@ -6489,7 +6528,7 @@ gen9_mfc_avc_inset_headers(VADriverContextP ctx,
     if (slice_index == 0) {
 
         /* if AUD exist and insert it firstly */
-        gen9_mfc_avc_insert_aud_packed_data(ctx,encode_state,encoder_context,batch);
+        gen9_mfc_avc_insert_aud_packed_data(ctx, encode_state, encoder_context, batch);
 
         if (encode_state->packed_header_data[idx]) {
             VAEncPackedHeaderParameterBuffer *param = NULL;
@@ -6957,12 +6996,14 @@ gen9_avc_pak_slice_level(VADriverContextP ctx,
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct i965_gpe_table *gpe = &i965->gpe_table;
+    struct encoder_vme_mfc_context * pak_context = (struct encoder_vme_mfc_context *)encoder_context->vme_context;
+    struct avc_enc_state * avc_state = (struct avc_enc_state *)pak_context->private_enc_state;
     struct intel_batchbuffer *batch = encoder_context->base.batch;
     struct gpe_mi_flush_dw_parameter mi_flush_dw_params;
     VAEncSliceParameterBufferH264 *slice_param, *next_slice_param, *next_slice_group_param;
     int i, j;
     int slice_index = 0;
-    int is_frame_level = 1;       /* check it for SKL,now single slice per frame */
+    int is_frame_level = (avc_state->slice_num > 1) ? 0 : 1;   /* check it for SKL,now single slice per frame */
     int has_tail = 0;             /* check it later */
 
     for (j = 0; j < encode_state->num_slice_params_ext; j++) {
@@ -6990,10 +7031,6 @@ gen9_avc_pak_slice_level(VADriverContextP ctx,
 
             if (is_frame_level)
                 break;
-            else {
-                /* remove assert(0) and add other commands here */
-                assert(0);
-            }
         }
 
         if (is_frame_level)
index 993a82c..399e8cf 100644 (file)
@@ -1124,16 +1124,14 @@ i965_GetConfigAttributes(VADriverContextP ctx,
             break;
 
         case VAConfigAttribEncMaxSlices:
+            attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
             if (entrypoint == VAEntrypointEncSlice) {
                 if ((profile == VAProfileH264ConstrainedBaseline ||
                      profile == VAProfileH264Main ||
                      profile == VAProfileH264High) ||
                     profile == VAProfileH264StereoHigh ||
                     profile == VAProfileH264MultiviewHigh) {
-                    if (IS_GEN9(i965->intel.device_info))
-                        attrib_list[i].value = 1;
-                    else
-                        attrib_list[i].value = I965_MAX_NUM_SLICE;
+                    attrib_list[i].value = I965_MAX_NUM_SLICE;
                 } else if (profile == VAProfileHEVCMain ||
                            profile == VAProfileHEVCMain10) {
                     attrib_list[i].value = I965_MAX_NUM_SLICE;
@@ -1145,20 +1143,25 @@ i965_GetConfigAttributes(VADriverContextP ctx,
                     profile == VAProfileH264StereoHigh ||
                     profile == VAProfileH264MultiviewHigh)
                     attrib_list[i].value = I965_MAX_NUM_SLICE;
-            } else
-                attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
+            }
 
             break;
 
         case VAConfigAttribEncSliceStructure:
+            attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
             if (entrypoint == VAEntrypointEncSlice) {
-                if (profile == VAProfileHEVCMain ||
-                    profile == VAProfileHEVCMain10)
+                if ((profile == VAProfileH264ConstrainedBaseline ||
+                     profile == VAProfileH264Main ||
+                     profile == VAProfileH264High) ||
+                    profile == VAProfileH264StereoHigh ||
+                    profile == VAProfileH264MultiviewHigh ||
+                   profile == VAProfileHEVCMain ||
+                    profile == VAProfileHEVCMain10) {
                     attrib_list[i].value = VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS;
+                }
             }
 
             break;
-
         default:
             /* Do nothing */
             attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
@@ -1255,7 +1258,8 @@ i965_CreateConfig(VADriverContextP ctx,
 
     for (i = 0; i < num_attribs; i++) {
         // add it later and ignore the user input for VAConfigAttribEncMaxSlices
-        if (attrib_list[i].type == VAConfigAttribEncMaxSlices)
+        if (attrib_list[i].type == VAConfigAttribEncMaxSlices ||
+            attrib_list[i].type == VAConfigAttribEncSliceStructure)
             continue;
         vaStatus = i965_ensure_config_attribute(obj_config, &attrib_list[i]);
         if (vaStatus != VA_STATUS_SUCCESS)
@@ -1283,10 +1287,7 @@ i965_CreateConfig(VADriverContextP ctx,
                  profile == VAProfileH264High) ||
                 profile == VAProfileH264StereoHigh ||
                 profile == VAProfileH264MultiviewHigh) {
-                if (IS_GEN9(i965->intel.device_info))
-                    attrib.value = 1;
-                else
-                    attrib.value = I965_MAX_NUM_SLICE;
+                attrib.value = I965_MAX_NUM_SLICE;
             } else if (profile == VAProfileHEVCMain ||
                        profile == VAProfileHEVCMain10)
                 attrib.value = I965_MAX_NUM_SLICE;
@@ -1297,8 +1298,25 @@ i965_CreateConfig(VADriverContextP ctx,
                 profile == VAProfileH264StereoHigh ||
                 profile == VAProfileH264MultiviewHigh)
                 attrib.value = I965_MAX_NUM_SLICE;
-        } else
-            attrib.value = VA_ATTRIB_NOT_SUPPORTED;
+        }
+
+        if (attrib.value != VA_ATTRIB_NOT_SUPPORTED)
+            vaStatus = i965_append_config_attribute(obj_config, &attrib);
+    }
+
+    if (vaStatus == VA_STATUS_SUCCESS) {
+        VAConfigAttrib attrib;
+        attrib.type = VAConfigAttribEncSliceStructure;
+        attrib.value = VA_ATTRIB_NOT_SUPPORTED;
+        if (entrypoint == VAEntrypointEncSlice) {
+            if ((profile == VAProfileH264ConstrainedBaseline ||
+                 profile == VAProfileH264Main ||
+                 profile == VAProfileH264High) ||
+                profile == VAProfileH264StereoHigh ||
+                profile == VAProfileH264MultiviewHigh) {
+                attrib.value = VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS;
+            }
+        }
 
         if (attrib.value != VA_ATTRIB_NOT_SUPPORTED)
             vaStatus = i965_append_config_attribute(obj_config, &attrib);