Encoding: Use the different delimeter to pass packed_rawdata and slice_header based...
authorZhao, Yakui <yakui.zhao@intel.com>
Thu, 12 Jun 2014 00:54:41 +0000 (08:54 +0800)
committerXiang, Haihao <haihao.xiang@intel.com>
Mon, 16 Jun 2014 04:00:11 +0000 (12:00 +0800)
Currently the packed_slice_header is optional. And it uses the VAEncSliceParameterBuffer
as the delimeter to decide how to insert the packed rawdata/slice_header
for one slice. This is not convenient under some scenario. For example: some
user hope to be more flexible. When the user is responsible for generating the
packed slice_header, it hopes to use the packed slice_header as the delimeter
to determine how to inser the packed rawdata/slice_header for the given slice.
So the VAConfigAttribEncPackedHeaders attriburation of encoding_context is
used to decide which kind of delimeter.
a. When the VAEncPackedSlice is set when calling vaCreateConfig, it will use
the packed slice_header as delimeter. Of course the packed rawdata should be
parsed before the packed slice_header for one given slice. For exmaple:
for the slice 0: the packed rawdata should be parsed before paring the first
packed slice_header. After one packed slice_header is parsed, it will start
to parse the corresponding data for a new slice.

b. When the VAEncPackedSlice is not set when calling vaCreateConfig, it will
use the VAEncSliceParameterBuffer as delimeter.

V1->V2: Return an error instead of only complaining warning message when packed
slice_header is missing for some slice under the VAEncPackedSlice mode. This
is the suggestion from Gwenole and Sreerenj Balachandran.

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

src/i965_drv_video.c
src/i965_drv_video.h

index 68a6052..b7a0485 100755 (executable)
@@ -1778,6 +1778,7 @@ i965_CreateContext(VADriverContextP ctx,
             assert(i965->codec_info->proc_hw_context_init);
             obj_context->hw_context = i965->codec_info->proc_hw_context_init(ctx, obj_config);
         } else if (VAEntrypointEncSlice == obj_config->entrypoint) { /*encode routin only*/
+            VAConfigAttrib *packed_attrib;
             obj_context->codec_type = CODEC_ENC;
             memset(&obj_context->codec_state.encode, 0, sizeof(obj_context->codec_state.encode));
             obj_context->codec_state.encode.current_render_target = VA_INVALID_ID;
@@ -1794,15 +1795,28 @@ i965_CreateContext(VADriverContextP ctx,
                 calloc(obj_context->codec_state.encode.max_packed_header_data_ext,
                        sizeof(struct buffer_store *));
 
-            obj_context->codec_state.encode.slice_num = NUM_SLICES;
+            obj_context->codec_state.encode.max_slice_num = NUM_SLICES;
             obj_context->codec_state.encode.slice_rawdata_index =
-                calloc(obj_context->codec_state.encode.slice_num, sizeof(int));
+                calloc(obj_context->codec_state.encode.max_slice_num, sizeof(int));
             obj_context->codec_state.encode.slice_rawdata_count =
-                calloc(obj_context->codec_state.encode.slice_num, sizeof(int));
+                calloc(obj_context->codec_state.encode.max_slice_num, sizeof(int));
 
             obj_context->codec_state.encode.slice_header_index =
-                calloc(obj_context->codec_state.encode.slice_num, sizeof(int));
-
+                calloc(obj_context->codec_state.encode.max_slice_num, sizeof(int));
+
+            obj_context->codec_state.encode.slice_index = 0;
+            packed_attrib = i965_lookup_config_attribute(obj_config, VAConfigAttribEncPackedHeaders);
+            if (packed_attrib)
+                obj_context->codec_state.encode.packed_header_flag = packed_attrib->value;
+            else {
+                /* use the default value. SPS/PPS/RAWDATA is passed from user
+                 * while Slice_header data is generated by driver.
+                 */
+                obj_context->codec_state.encode.packed_header_flag =
+                               VA_ENC_PACKED_HEADER_SEQUENCE |
+                               VA_ENC_PACKED_HEADER_PICTURE |
+                               VA_ENC_PACKED_HEADER_RAW_DATA;
+            }
             assert(i965->codec_info->enc_hw_context_init);
             obj_context->hw_context = i965->codec_info->enc_hw_context_init(ctx, obj_config);
         } else {
@@ -2237,11 +2251,11 @@ i965_BeginPicture(VADriverContextP ctx,
         obj_context->codec_state.encode.current_render_target = render_target;     /*This is input new frame*/
         obj_context->codec_state.encode.last_packed_header_type = 0;
         memset(obj_context->codec_state.encode.slice_rawdata_index, 0,
-               sizeof(int) * obj_context->codec_state.encode.slice_num);
+               sizeof(int) * obj_context->codec_state.encode.max_slice_num);
         memset(obj_context->codec_state.encode.slice_rawdata_count, 0,
-               sizeof(int) * obj_context->codec_state.encode.slice_num);
+               sizeof(int) * obj_context->codec_state.encode.max_slice_num);
         memset(obj_context->codec_state.encode.slice_header_index, 0,
-               sizeof(int) * obj_context->codec_state.encode.slice_num);
+               sizeof(int) * obj_context->codec_state.encode.max_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]);
@@ -2249,6 +2263,7 @@ i965_BeginPicture(VADriverContextP ctx,
             i965_release_buffer_store(&obj_context->codec_state.encode.packed_header_data_ext[i]);
         obj_context->codec_state.encode.num_packed_header_params_ext = 0;
         obj_context->codec_state.encode.num_packed_header_data_ext = 0;
+        obj_context->codec_state.encode.slice_index = 0;
     } else {
         obj_context->codec_state.decode.current_render_target = render_target;
         i965_release_buffer_store(&obj_context->codec_state.decode.pic_param);
@@ -2488,21 +2503,25 @@ i965_encoder_render_picture(VADriverContextP ctx,
                  * to reallocate the arrays that is used to store
                  * 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;
+                if (!(encode->packed_header_flag & VA_ENC_PACKED_HEADER_SLICE)) {
+                   encode->slice_index++;
+                }
+                if (encode->slice_index == encode->max_slice_num) {
+                    int slice_num = encode->max_slice_num;
                     encode->slice_rawdata_index = realloc(encode->slice_rawdata_index,
-                                                          encode->slice_num * sizeof(int));
+                                                          (slice_num + NUM_SLICES) * sizeof(int));
                     encode->slice_rawdata_count = realloc(encode->slice_rawdata_count,
-                                                          encode->slice_num * sizeof(int));
+                                                          (slice_num + NUM_SLICES) * sizeof(int));
                     encode->slice_header_index = realloc(encode->slice_header_index,
-                                                          encode->slice_num * sizeof(int));
+                                                          (slice_num + NUM_SLICES) * 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);
+
+                    encode->max_slice_num += NUM_SLICES;
                     if ((encode->slice_rawdata_index == NULL) ||
                         (encode->slice_header_index == NULL)  ||
                         (encode->slice_rawdata_count == NULL)) {
@@ -2540,20 +2559,64 @@ i965_encoder_render_picture(VADriverContextP ctx,
             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) {
+
+                /* When the PACKED_SLICE_HEADER flag is passed, it will use
+                 * the packed_slice_header as the delimeter to decide how
+                 * the packed rawdata is inserted for the given slice.
+                 * Otherwise it will use the VAEncSequenceParameterBuffer
+                 * as the delimeter
+                 */
+                if (encode->packed_header_flag & VA_ENC_PACKED_HEADER_SLICE) {
                     /* store the first index of the packed header data for current slice */
-                    if (encode->slice_rawdata_index[encode->num_slice_params_ext] == 0) {
-                        encode->slice_rawdata_index[encode->num_slice_params_ext] =
-                             SLICE_PACKED_DATA_INDEX_TYPE | (encode->num_packed_header_data_ext - 1);
+                    if (encode->slice_rawdata_index[encode->slice_index] == 0) {
+                        encode->slice_rawdata_index[encode->slice_index] =
+                            SLICE_PACKED_DATA_INDEX_TYPE | (encode->num_packed_header_data_ext - 1);
                     }
-                    encode->slice_rawdata_count[encode->num_slice_params_ext]++;
+                    encode->slice_rawdata_count[encode->slice_index]++;
                     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] =
+                        /* find one packed slice_header delimeter. And the following
+                         * packed data is for the next slice
+                         */
+                        encode->slice_header_index[encode->slice_index] =
+                            SLICE_PACKED_DATA_INDEX_TYPE | (encode->num_packed_header_data_ext - 1);
+                        encode->slice_index++;
+                        /* Reallocate the buffer to record the index/count of
+                         * packed_data for one slice.
+                         */
+                        if (encode->slice_index == encode->max_slice_num) {
+                            int slice_num = encode->max_slice_num;
+
+                            encode->slice_rawdata_index = realloc(encode->slice_rawdata_index,
+                                                          (slice_num + NUM_SLICES) * sizeof(int));
+                            encode->slice_rawdata_count = realloc(encode->slice_rawdata_count,
+                                                          (slice_num + NUM_SLICES) * sizeof(int));
+                            encode->slice_header_index = realloc(encode->slice_header_index,
+                                                          (slice_num + NUM_SLICES) * 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);
+                            encode->max_slice_num += NUM_SLICES;
+                        }
+                    }
+                } else {
+                    if (vaStatus == VA_STATUS_SUCCESS) {
+                        /* store the first index of the packed header data for current slice */
+                        if (encode->slice_rawdata_index[encode->slice_index] == 0) {
+                            encode->slice_rawdata_index[encode->slice_index] =
                                 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);
+                        }
+                        encode->slice_rawdata_count[encode->slice_index]++;
+                        if (encode->last_packed_header_type == VAEncPackedHeaderSlice) {
+                            if (encode->slice_header_index[encode->slice_index] == 0) {
+                                encode->slice_header_index[encode->slice_index] =
+                                    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->slice_index);
+                            }
                         }
                     }
                 }
@@ -2690,6 +2753,14 @@ i965_EndPicture(VADriverContextP ctx, VAContextID context)
                 (obj_context->codec_state.encode.num_slice_params_ext <=0)) {
             return VA_STATUS_ERROR_INVALID_PARAMETER;
         }
+
+        if ((obj_context->codec_state.encode.packed_header_flag & VA_ENC_PACKED_HEADER_SLICE) &&
+            (obj_context->codec_state.encode.num_slice_params_ext !=
+             obj_context->codec_state.encode.slice_index)) {
+            WARN_ONCE("packed slice_header data is missing for some slice"
+                      " under packed SLICE_HEADER mode\n");
+            return VA_STATUS_ERROR_INVALID_PARAMETER;
+        }
     } else {
         if (obj_context->codec_state.decode.pic_param == NULL) {
             return VA_STATUS_ERROR_INVALID_PARAMETER;
index dfa2a7a..10e8778 100644 (file)
@@ -149,6 +149,12 @@ struct encode_state
     int max_slice_params_ext;
     int num_slice_params_ext;
 
+    /* Check the user-configurable packed_header attribute.
+     * Currently it is mainly used to check whether the packed slice_header data
+     * is provided by user or the driver.
+     * TBD: It will check for the packed SPS/PPS/MISC/RAWDATA and so on.
+     */
+    unsigned int packed_header_flag;
     /* For the packed data that needs to be inserted into video clip */
     /* currently it is mainly to track packed raw data and packed slice_header data. */
     struct buffer_store **packed_header_params_ext;
@@ -158,8 +164,10 @@ struct encode_state
     int max_packed_header_data_ext;
     int num_packed_header_data_ext;
 
+    /* the index of current slice */
+    int slice_index;
     /* the array is determined by max_slice_params_ext */
-    int slice_num;
+    int max_slice_num;
     /* This is to store the first index of packed data for one slice */
     int *slice_rawdata_index;
     /* This is to store the number of packed data for one slice.