H264_Encoding: Add the support of packed slice header to be flexible
authorZhao, Yakui <yakui.zhao@intel.com>
Mon, 26 May 2014 00:40:15 +0000 (08:40 +0800)
committerXiang, Haihao <haihao.xiang@intel.com>
Mon, 16 Jun 2014 03:53:35 +0000 (11:53 +0800)
Under some encoding scenario, the user hopes to generate the packed slice
header data by themself and then the driver can insert the passed slice
header packed data into the coded clip.
1.The VA_ENC_PACKED_HEADER_SLICE flag is exported and it is treated as optional.
This is to say: if packed slice header data is passed, it will be
inserted directly. If no packed slice header data is passed, the driver will
help to generate it.
2.Another restriction is that the packed slice header data is inserted after
the packed rawdata for one slice. That is to say: If it needs to insert the
packed rawdata and slice header data, the packed rawdata will be inserted
firstly(This is handled by the driver).

Signed-off-by: Zhao, Yakui <yakui.zhao@intel.com>
(cherry picked from commit 00111e8a8bfa67b971419b72577eaa1b9f47bc34)

Conflicts:
src/gen75_mfc.c
src/gen8_mfc.c

src/gen6_mfc.c
src/gen6_mfc_common.c
src/gen75_mfc.c
src/gen8_mfc.c
src/i965_drv_video.c
src/i965_drv_video.h

index c6702e8..f1b29b9 100644 (file)
@@ -788,8 +788,6 @@ gen6_mfc_avc_pipeline_slice_programing(VADriverContextP ctx,
     int i,x,y;
     int qp = pPicParameter->pic_init_qp + pSliceParameter->slice_qp_delta;
     unsigned int rate_control_mode = encoder_context->rate_control_mode;
-    unsigned char *slice_header = NULL;
-    int slice_header_length_in_bits = 0;
     unsigned int tail_data[] = { 0x0, 0x0 };
     int slice_type = intel_avc_enc_slice_type_fixup(pSliceParameter->slice_type);
     int is_intra = slice_type == SLICE_TYPE_I;
@@ -816,14 +814,6 @@ gen6_mfc_avc_pipeline_slice_programing(VADriverContextP ctx,
 
     intel_avc_slice_insert_packed_data(ctx, encode_state, encoder_context, slice_index, slice_batch);
 
-    slice_header_length_in_bits = build_avc_slice_header(pSequenceParameter, pPicParameter, pSliceParameter, &slice_header);
-
-    // slice hander
-    mfc_context->insert_object(ctx, encoder_context,
-                               (unsigned int *)slice_header, ALIGN(slice_header_length_in_bits, 32) >> 5, slice_header_length_in_bits & 0x1f,
-                               5,  /* first 5 bytes are start code + nal unit type */
-                               1, 0, 1, slice_batch);
-
     dri_bo_map(vme_context->vme_output.bo , 1);
     msg = (unsigned int *)vme_context->vme_output.bo->virtual;
 
@@ -869,7 +859,6 @@ gen6_mfc_avc_pipeline_slice_programing(VADriverContextP ctx,
                                    1, 1, 1, 0, slice_batch);
     }
 
-    free(slice_header);
 
 }
 
@@ -1176,8 +1165,6 @@ gen6_mfc_avc_batchbuffer_slice(VADriverContextP ctx,
     int last_slice = (pSliceParameter->macroblock_address + pSliceParameter->num_macroblocks) == (width_in_mbs * height_in_mbs);
     int qp = pPicParameter->pic_init_qp + pSliceParameter->slice_qp_delta;
     unsigned int rate_control_mode = encoder_context->rate_control_mode;
-    unsigned char *slice_header = NULL;
-    int slice_header_length_in_bits = 0;
     unsigned int tail_data[] = { 0x0, 0x0 };
     long head_offset;
     int old_used = intel_batchbuffer_used_size(slice_batch), used;
@@ -1210,21 +1197,6 @@ gen6_mfc_avc_batchbuffer_slice(VADriverContextP ctx,
 
     intel_avc_slice_insert_packed_data(ctx, encode_state, encoder_context, slice_index, slice_batch);
 
-    slice_header_length_in_bits = build_avc_slice_header(pSequenceParameter, pPicParameter, pSliceParameter, &slice_header);
-
-    // slice hander
-    mfc_context->insert_object(ctx,
-                               encoder_context,
-                               (unsigned int *)slice_header,
-                               ALIGN(slice_header_length_in_bits, 32) >> 5,
-                               slice_header_length_in_bits & 0x1f,
-                               5,  /* first 5 bytes are start code + nal unit type */
-                               1,
-                               0,
-                               1,
-                               slice_batch);
-    free(slice_header);
-
     intel_batchbuffer_align(slice_batch, 16); /* aligned by an Oword */
     used = intel_batchbuffer_used_size(slice_batch);
     head_size = (used - old_used) / 16;
index 44e6e95..e500feb 100644 (file)
@@ -1528,10 +1528,12 @@ void intel_avc_slice_insert_packed_data(VADriverContextP ctx,
     VAEncPackedHeaderParameterBuffer *param = NULL;
     unsigned int *header_data = NULL;
     struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
+    int slice_header_index;
 
-    /* If the number of packed data for current slice is zero, return */
-    if (encode_state->slice_rawdata_count[slice_index] == 0)
-        return;
+    if (encode_state->slice_header_index[slice_index] == 0)
+        slice_header_index = -1;
+    else
+        slice_header_index = (encode_state->slice_header_index[slice_index] & SLICE_PACKED_DATA_INDEX_MASK);
 
     count = encode_state->slice_rawdata_count[slice_index];
     start_index = (encode_state->slice_rawdata_index[slice_index] & SLICE_PACKED_DATA_INDEX_MASK);
@@ -1543,6 +1545,11 @@ void intel_avc_slice_insert_packed_data(VADriverContextP ctx,
 
         param = (VAEncPackedHeaderParameterBuffer *)
                     (encode_state->packed_header_params_ext[start_index + i]->buffer);
+
+        /* skip the slice header packed data type as it is lastly inserted */
+        if (param->type == VAEncPackedHeaderSlice)
+            continue;
+
         length_in_bits = param->bit_length;
 
         skip_emul_byte_cnt = intel_avc_find_skipemulcnt((unsigned char *)header_data, length_in_bits);
@@ -1561,5 +1568,53 @@ void intel_avc_slice_insert_packed_data(VADriverContextP ctx,
                                    !param->has_emulation_bytes,
                                    slice_batch);
     }
+
+    if (slice_header_index == -1) {
+        unsigned char *slice_header = NULL;
+        int slice_header_length_in_bits = 0;
+        VAEncSequenceParameterBufferH264 *pSequenceParameter = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
+        VAEncPictureParameterBufferH264 *pPicParameter = (VAEncPictureParameterBufferH264 *)encode_state->pic_param_ext->buffer;
+        VAEncSliceParameterBufferH264 *pSliceParameter = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[slice_index]->buffer;
+
+        /* No slice header data is passed. And the driver needs to generate it */
+        /* For the Normal H264 */
+        slice_header_length_in_bits = build_avc_slice_header(pSequenceParameter,
+                                                             pPicParameter,
+                                                             pSliceParameter,
+                                                             &slice_header);
+        mfc_context->insert_object(ctx, encoder_context,
+                                   (unsigned int *)slice_header,
+                                   ALIGN(slice_header_length_in_bits, 32) >> 5,
+                                   slice_header_length_in_bits & 0x1f,
+                                   5,  /* first 5 bytes are start code + nal unit type */
+                                   1, 0, 1, slice_batch);
+
+        free(slice_header);
+    } else {
+        unsigned int skip_emul_byte_cnt;
+
+        header_data = (unsigned int *)encode_state->packed_header_data_ext[start_index + i]->buffer;
+
+        param = (VAEncPackedHeaderParameterBuffer *)
+                    (encode_state->packed_header_params_ext[start_index + i]->buffer);
+        length_in_bits = param->bit_length;
+
+        /* as the slice header is the last header data for one slice,
+         * the last header flag is set to one.
+         */
+        skip_emul_byte_cnt = intel_avc_find_skipemulcnt((unsigned char *)header_data, length_in_bits);
+
+        mfc_context->insert_object(ctx,
+                                   encoder_context,
+                                   header_data,
+                                   ALIGN(length_in_bits, 32) >> 5,
+                                   length_in_bits & 0x1f,
+                                   skip_emul_byte_cnt,
+                                   1,
+                                   0,
+                                   !param->has_emulation_bytes,
+                                   slice_batch);
+    }
+
     return;
 }
index 18a588f..1051dd5 100644 (file)
@@ -1166,8 +1166,6 @@ gen75_mfc_avc_pipeline_slice_programing(VADriverContextP ctx,
     int i,x,y;
     int qp = pPicParameter->pic_init_qp + pSliceParameter->slice_qp_delta;
     unsigned int rate_control_mode = encoder_context->rate_control_mode;
-    unsigned char *slice_header = NULL;
-    int slice_header_length_in_bits = 0;
     unsigned int tail_data[] = { 0x0, 0x0 };
     int slice_type = intel_avc_enc_slice_type_fixup(pSliceParameter->slice_type);
     int is_intra = slice_type == SLICE_TYPE_I;
@@ -1194,16 +1192,6 @@ gen75_mfc_avc_pipeline_slice_programing(VADriverContextP ctx,
 
     intel_avc_slice_insert_packed_data(ctx, encode_state, encoder_context, slice_index, slice_batch);
 
-    slice_header_length_in_bits = build_avc_slice_header(pSequenceParameter, pPicParameter, pSliceParameter, &slice_header);
-
-    // slice hander
-    mfc_context->insert_object(ctx, encoder_context,
-                               (unsigned int *)slice_header, ALIGN(slice_header_length_in_bits, 32) >> 5, slice_header_length_in_bits & 0x1f,
-                               5,  /* first 5 bytes are start code + nal unit type */
-                               1, 0, 1, slice_batch);
-
-    free(slice_header);
-
     dri_bo_map(vme_context->vme_output.bo , 1);
     msg_ptr = (unsigned char *)vme_context->vme_output.bo->virtual;
 
@@ -1516,8 +1504,6 @@ gen75_mfc_avc_batchbuffer_slice(VADriverContextP ctx,
     int last_slice = (pSliceParameter->macroblock_address + pSliceParameter->num_macroblocks) == (width_in_mbs * height_in_mbs);
     int qp = pPicParameter->pic_init_qp + pSliceParameter->slice_qp_delta;
     unsigned int rate_control_mode = encoder_context->rate_control_mode;
-    unsigned char *slice_header = NULL;
-    int slice_header_length_in_bits = 0;
     unsigned int tail_data[] = { 0x0, 0x0 };
     long head_offset;
     int slice_type = intel_avc_enc_slice_type_fixup(pSliceParameter->slice_type);
@@ -1547,22 +1533,6 @@ gen75_mfc_avc_batchbuffer_slice(VADriverContextP ctx,
 
     intel_avc_slice_insert_packed_data(ctx, encode_state, encoder_context, slice_index, slice_batch);
 
-    slice_header_length_in_bits = build_avc_slice_header(pSequenceParameter, pPicParameter, pSliceParameter, &slice_header);
-
-    // slice hander
-    mfc_context->insert_object(ctx,
-                               encoder_context,
-                               (unsigned int *)slice_header,
-                               ALIGN(slice_header_length_in_bits, 32) >> 5,
-                               slice_header_length_in_bits & 0x1f,
-                               5,  /* first 5 bytes are start code + nal unit type */
-                               1,
-                               0,
-                               1,
-                               slice_batch);
-
-    free(slice_header);
-
     intel_batchbuffer_align(slice_batch, 16); /* aligned by an Oword */
     head_offset = intel_batchbuffer_used_size(slice_batch);
 
index 2fc1fac..c86cf09 100644 (file)
@@ -1029,8 +1029,6 @@ gen8_mfc_avc_pipeline_slice_programing(VADriverContextP ctx,
     int i,x,y;
     int qp = pPicParameter->pic_init_qp + pSliceParameter->slice_qp_delta;
     unsigned int rate_control_mode = encoder_context->rate_control_mode;
-    unsigned char *slice_header = NULL;
-    int slice_header_length_in_bits = 0;
     unsigned int tail_data[] = { 0x0, 0x0 };
     int slice_type = intel_avc_enc_slice_type_fixup(pSliceParameter->slice_type);
     int is_intra = slice_type == SLICE_TYPE_I;
@@ -1058,16 +1056,6 @@ gen8_mfc_avc_pipeline_slice_programing(VADriverContextP ctx,
 
     intel_avc_slice_insert_packed_data(ctx, encode_state, encoder_context, slice_index, slice_batch);
 
-    slice_header_length_in_bits = build_avc_slice_header(pSequenceParameter, pPicParameter, pSliceParameter, &slice_header);
-
-    // slice hander
-    mfc_context->insert_object(ctx, encoder_context,
-                               (unsigned int *)slice_header, ALIGN(slice_header_length_in_bits, 32) >> 5, slice_header_length_in_bits & 0x1f,
-                               5,  /* first 5 bytes are start code + nal unit type */
-                               1, 0, 1, slice_batch);
-
-    free(slice_header);
-
     dri_bo_map(vme_context->vme_output.bo , 1);
     msg_ptr = (unsigned char *)vme_context->vme_output.bo->virtual;
 
@@ -1409,8 +1397,6 @@ gen8_mfc_avc_batchbuffer_slice(VADriverContextP ctx,
     int last_slice = (pSliceParameter->macroblock_address + pSliceParameter->num_macroblocks) == (width_in_mbs * height_in_mbs);
     int qp = pPicParameter->pic_init_qp + pSliceParameter->slice_qp_delta;
     unsigned int rate_control_mode = encoder_context->rate_control_mode;
-    unsigned char *slice_header = NULL;
-    int slice_header_length_in_bits = 0;
     unsigned int tail_data[] = { 0x0, 0x0 };
     long head_offset;
     int old_used = intel_batchbuffer_used_size(slice_batch), used;
@@ -1443,22 +1429,6 @@ gen8_mfc_avc_batchbuffer_slice(VADriverContextP ctx,
 
     intel_avc_slice_insert_packed_data(ctx, encode_state, encoder_context, slice_index, slice_batch);
 
-    slice_header_length_in_bits = build_avc_slice_header(pSequenceParameter, pPicParameter, pSliceParameter, &slice_header);
-
-    // slice hander
-    mfc_context->insert_object(ctx,
-                               encoder_context,
-                               (unsigned int *)slice_header,
-                               ALIGN(slice_header_length_in_bits, 32) >> 5,
-                               slice_header_length_in_bits & 0x1f,
-                               5,  /* first 5 bytes are start code + nal unit type */
-                               1,
-                               0,
-                               1,
-                               slice_batch);
-
-    free(slice_header);
-
     intel_batchbuffer_align(slice_batch, 16); /* aligned by an Oword */
     used = intel_batchbuffer_used_size(slice_batch);
     head_size = (used - old_used) / 16;
index cf42b68..8da5a94 100755 (executable)
@@ -659,7 +659,8 @@ i965_GetConfigAttributes(VADriverContextP ctx,
                     profile == VAProfileH264Main ||
                     profile == VAProfileH264High ||
                     profile == VAProfileH264MultiviewHigh) {
-                    attrib_list[i].value |= VA_ENC_PACKED_HEADER_RAW_DATA;
+                    attrib_list[i].value |= (VA_ENC_PACKED_HEADER_RAW_DATA |
+                                             VA_ENC_PACKED_HEADER_SLICE);
                 }
                 break;
             }
@@ -1650,6 +1651,12 @@ i965_destroy_context(struct object_heap *heap, struct object_base *obj)
             free(obj_context->codec_state.encode.slice_rawdata_count);
             obj_context->codec_state.encode.slice_rawdata_count = NULL;
         }
+
+        if (obj_context->codec_state.encode.slice_header_index) {
+            free(obj_context->codec_state.encode.slice_header_index);
+            obj_context->codec_state.encode.slice_header_index = NULL;
+        }
+
         for (i = 0; i < obj_context->codec_state.encode.num_packed_header_params_ext; i++)
             i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_params_ext[i]);
         free(obj_context->codec_state.encode.packed_header_params_ext);
@@ -1792,6 +1799,9 @@ i965_CreateContext(VADriverContextP ctx,
             obj_context->codec_state.encode.slice_rawdata_count =
                 calloc(obj_context->codec_state.encode.slice_num, sizeof(int));
 
+            obj_context->codec_state.encode.slice_header_index =
+                calloc(obj_context->codec_state.encode.slice_num, sizeof(int));
+
             assert(i965->codec_info->enc_hw_context_init);
             obj_context->hw_context = i965->codec_info->enc_hw_context_init(ctx, obj_config);
         } else {
@@ -2229,6 +2239,8 @@ i965_BeginPicture(VADriverContextP ctx,
                sizeof(int) * obj_context->codec_state.encode.slice_num);
         memset(obj_context->codec_state.encode.slice_rawdata_count, 0,
                sizeof(int) * obj_context->codec_state.encode.slice_num);
+        memset(obj_context->codec_state.encode.slice_header_index, 0,
+               sizeof(int) * obj_context->codec_state.encode.slice_num);
 
         for (i = 0; i < obj_context->codec_state.encode.num_packed_header_params_ext; i++)
             i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_params_ext[i]);
@@ -2481,7 +2493,10 @@ i965_encoder_render_picture(VADriverContextP ctx,
                                                           encode->slice_num * sizeof(int));
                     encode->slice_rawdata_count = realloc(encode->slice_rawdata_count,
                                                           encode->slice_num * sizeof(int));
+                    encode->slice_header_index = realloc(encode->slice_header_index,
+                                                          encode->slice_num * sizeof(int));
                     if ((encode->slice_rawdata_index == NULL) ||
+                        (encode->slice_header_index == NULL)  ||
                         (encode->slice_rawdata_count == NULL)) {
                         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
                         return vaStatus;
@@ -2495,7 +2510,8 @@ i965_encoder_render_picture(VADriverContextP ctx,
             VAEncPackedHeaderParameterBuffer *param = (VAEncPackedHeaderParameterBuffer *)obj_buffer->buffer_store->buffer;
             encode->last_packed_header_type = param->type;
 
-            if (param->type == VAEncPackedHeaderRawData) {
+            if ((param->type == VAEncPackedHeaderRawData) ||
+                (param->type == VAEncPackedHeaderSlice)) {
                 vaStatus = I965_RENDER_ENCODE_BUFFER(packed_header_params_ext);
             } else {
                 vaStatus = i965_encoder_render_packed_header_parameter_buffer(ctx,
@@ -2513,7 +2529,8 @@ i965_encoder_render_picture(VADriverContextP ctx,
                 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
                 return vaStatus;
             }
-            if (encode->last_packed_header_type == VAEncPackedHeaderRawData) {
+            if (encode->last_packed_header_type == VAEncPackedHeaderRawData ||
+                encode->last_packed_header_type == VAEncPackedHeaderSlice) {
                 vaStatus = I965_RENDER_ENCODE_BUFFER(packed_header_data_ext);
                 if (vaStatus == VA_STATUS_SUCCESS) {
                     /* store the first index of the packed header data for current slice */
@@ -2522,6 +2539,15 @@ i965_encoder_render_picture(VADriverContextP ctx,
                              SLICE_PACKED_DATA_INDEX_TYPE | (encode->num_packed_header_data_ext - 1);
                     }
                     encode->slice_rawdata_count[encode->num_slice_params_ext]++;
+                    if (encode->last_packed_header_type == VAEncPackedHeaderSlice) {
+                        if (encode->slice_header_index[encode->num_slice_params_ext] == 0) {
+                            encode->slice_header_index[encode->num_slice_params_ext] =
+                                SLICE_PACKED_DATA_INDEX_TYPE | (encode->num_packed_header_data_ext - 1);
+                        } else {
+                            WARN_ONCE("Multi slice header data is passed for"
+                                      " slice %d!\n", encode->num_slice_params_ext);
+                        }
+                    }
                 }
             } else {
                 ASSERT_RET(encode->last_packed_header_type == VAEncPackedHeaderSequence ||
index 9827209..29e550f 100644 (file)
@@ -165,6 +165,9 @@ struct encode_state
     /* This is to store the number of packed data for one slice */
     int *slice_rawdata_count;
 
+    /* This is to store the index of packed slice header for one slice */
+    int *slice_header_index;
+
     int last_packed_header_type;
 
     struct buffer_store *misc_param[16];