Fix the segfault while encoding multiple slice per frame.
[platform/upstream/libva-intel-driver.git] / src / i965_drv_video.c
index d8b50dc..68a6052 100755 (executable)
@@ -658,8 +658,10 @@ i965_GetConfigAttributes(VADriverContextP ctx,
                 if (profile == VAProfileH264ConstrainedBaseline ||
                     profile == VAProfileH264Main ||
                     profile == VAProfileH264High ||
+                    profile == VAProfileH264StereoHigh ||
                     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 +1652,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 +1800,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 +2240,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]);
@@ -2476,12 +2489,22 @@ i965_encoder_render_picture(VADriverContextP ctx,
                  * the packed data index/count for the slice
                  */
                 if (encode->max_slice_params_ext > encode->slice_num) {
+                    int slice_num = encode->slice_num;
                     encode->slice_num = encode->max_slice_params_ext;
                     encode->slice_rawdata_index = realloc(encode->slice_rawdata_index,
                                                           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));
+                    memset(encode->slice_rawdata_index + slice_num, 0,
+                        sizeof(int) * NUM_SLICES);
+                    memset(encode->slice_rawdata_count + slice_num, 0,
+                        sizeof(int) * NUM_SLICES);
+                    memset(encode->slice_header_index + slice_num, 0,
+                        sizeof(int) * NUM_SLICES);
                     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 +2518,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,
@@ -2508,8 +2532,13 @@ i965_encoder_render_picture(VADriverContextP ctx,
 
         case VAEncPackedHeaderDataBufferType:
         {
-
-            if (encode->last_packed_header_type == VAEncPackedHeaderRawData) {
+            if (encode->last_packed_header_type == 0) {
+                WARN_ONCE("the packed header data is passed without type!\n");
+                vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
+                return vaStatus;
+            }
+            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 */
@@ -2518,6 +2547,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 ||
@@ -2531,6 +2569,7 @@ i965_encoder_render_picture(VADriverContextP ctx,
                                                                      obj_buffer,
                                                                      va_enc_packed_type_to_idx(encode->last_packed_header_type));
             }
+            encode->last_packed_header_type = 0;
             break;       
         }