change the attribute of hw_codec_info so that it can be updated dynamically
[platform/upstream/libva-intel-driver.git] / src / i965_drv_video.c
old mode 100755 (executable)
new mode 100644 (file)
index d8b50dc..ba7c7be
@@ -28,6 +28,7 @@
  */
 
 #include "sysdeps.h"
+#include <unistd.h>
 
 #ifdef HAVE_VA_X11
 # include "i965_output_dri.h"
@@ -627,6 +628,7 @@ i965_GetConfigAttributes(VADriverContextP ctx,
                          int num_attribs)
 {
     VAStatus va_status;
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
     int i;
 
     va_status = i965_validate_config(ctx, profile, entrypoint);
@@ -658,8 +660,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;
             }
@@ -670,6 +674,16 @@ i965_GetConfigAttributes(VADriverContextP ctx,
                break;
            }
 
+       case VAConfigAttribEncQualityRange:
+           if (entrypoint == VAEntrypointEncSlice) {
+               attrib_list[i].value = 1;
+                if (profile == VAProfileH264ConstrainedBaseline ||
+                    profile == VAProfileH264Main ||
+                    profile == VAProfileH264High )
+                    attrib_list[i].value = ENCODER_QUALITY_RANGE;
+               break;
+           }
+
         default:
             /* Do nothing */
             attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
@@ -1650,6 +1664,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);
@@ -1770,6 +1790,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;
@@ -1786,12 +1807,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.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 {
@@ -1913,6 +1950,7 @@ i965_create_buffer_internal(VADriverContextP ctx,
     obj_buffer->num_elements = num_elements;
     obj_buffer->size_element = size;
     obj_buffer->type = type;
+    obj_buffer->export_refcount = 0;
     obj_buffer->buffer_store = NULL;
     buffer_store = calloc(1, sizeof(struct buffer_store));
     assert(buffer_store);
@@ -2226,9 +2264,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.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]);
@@ -2236,6 +2276,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);
@@ -2475,13 +2516,27 @@ 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) {
-                    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,
+                                                          (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)) {
                         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
                         return vaStatus;
@@ -2495,7 +2550,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,16 +2564,74 @@ 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) {
+
+                /* 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->slice_index]++;
+                    if (encode->last_packed_header_type == VAEncPackedHeaderSlice) {
+                        /* 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);
+                        }
+                        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);
+                            }
+                        }
                     }
-                    encode->slice_rawdata_count[encode->num_slice_params_ext]++;
                 }
             } else {
                 ASSERT_RET(encode->last_packed_header_type == VAEncPackedHeaderSequence ||
@@ -2531,6 +2645,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;       
         }
 
@@ -2651,6 +2766,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;
@@ -5024,6 +5147,130 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
     return vaStatus;
 }
 
+/* Acquires buffer handle for external API usage (internal implementation) */
+static VAStatus
+i965_acquire_buffer_handle(struct object_buffer *obj_buffer,
+    uint32_t mem_type, VABufferInfo *out_buf_info)
+{
+    struct buffer_store *buffer_store;
+
+    buffer_store = obj_buffer->buffer_store;
+    if (!buffer_store || !buffer_store->bo)
+        return VA_STATUS_ERROR_INVALID_BUFFER;
+
+    /* Synchronization point */
+    drm_intel_bo_wait_rendering(buffer_store->bo);
+
+    if (obj_buffer->export_refcount > 0) {
+        if (obj_buffer->export_state.mem_type != mem_type)
+            return VA_STATUS_ERROR_INVALID_PARAMETER;
+    }
+    else {
+        VABufferInfo * const buf_info = &obj_buffer->export_state;
+
+        switch (mem_type) {
+        case VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM: {
+            uint32_t name;
+            if (drm_intel_bo_flink(buffer_store->bo, &name) != 0)
+                return VA_STATUS_ERROR_INVALID_BUFFER;
+            buf_info->handle = name;
+            break;
+        }
+        case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: {
+            int fd;
+            if (drm_intel_bo_gem_export_to_prime(buffer_store->bo, &fd) != 0)
+                return VA_STATUS_ERROR_INVALID_BUFFER;
+            buf_info->handle = (intptr_t)fd;
+            break;
+        }
+        }
+
+        buf_info->type = obj_buffer->type;
+        buf_info->mem_type = mem_type;
+        buf_info->mem_size =
+            obj_buffer->num_elements * obj_buffer->size_element;
+    }
+
+    obj_buffer->export_refcount++;
+    *out_buf_info = obj_buffer->export_state;
+    return VA_STATUS_SUCCESS;
+}
+
+/* Releases buffer handle after usage (internal implementation) */
+static VAStatus
+i965_release_buffer_handle(struct object_buffer *obj_buffer)
+{
+    if (obj_buffer->export_refcount == 0)
+        return VA_STATUS_ERROR_INVALID_BUFFER;
+
+    if (--obj_buffer->export_refcount == 0) {
+        VABufferInfo * const buf_info = &obj_buffer->export_state;
+
+        switch (buf_info->mem_type) {
+        case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: {
+            close((intptr_t)buf_info->handle);
+            break;
+        }
+        }
+        buf_info->mem_type = 0;
+    }
+    return VA_STATUS_SUCCESS;
+}
+
+/** Acquires buffer handle for external API usage */
+static VAStatus
+i965_AcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id,
+    VABufferInfo *buf_info)
+{
+    struct i965_driver_data * const i965 = i965_driver_data(ctx);
+    struct object_buffer * const obj_buffer = BUFFER(buf_id);
+    uint32_t i, mem_type;
+
+    /* List of supported memory types, in preferred order */
+    static const uint32_t mem_types[] = {
+        VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
+        VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM,
+        0
+    };
+
+    if (!obj_buffer)
+        return VA_STATUS_ERROR_INVALID_BUFFER;
+    /* XXX: only VA surface|image like buffers are supported for now */
+    if (obj_buffer->type != VAImageBufferType)
+        return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
+
+    if (!buf_info)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    if (!buf_info->mem_type)
+        mem_type = mem_types[0];
+    else {
+        mem_type = 0;
+        for (i = 0; mem_types[i] != 0; i++) {
+            if (buf_info->mem_type & mem_types[i]) {
+                mem_type = buf_info->mem_type;
+                break;
+            }
+        }
+        if (!mem_type)
+            return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
+    }
+    return i965_acquire_buffer_handle(obj_buffer, mem_type, buf_info);
+}
+
+/** Releases buffer handle after usage from external API */
+static VAStatus
+i965_ReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id)
+{
+    struct i965_driver_data * const i965 = i965_driver_data(ctx);
+    struct object_buffer * const obj_buffer = BUFFER(buf_id);
+
+    if (!obj_buffer)
+        return VA_STATUS_ERROR_INVALID_BUFFER;
+
+    return i965_release_buffer_handle(obj_buffer);
+}
+
 static int
 i965_os_has_ring_support(VADriverContextP ctx,
                          int ring)
@@ -5274,7 +5521,7 @@ VAStatus i965_QueryVideoProcPipelineCaps(
     return VA_STATUS_SUCCESS;
 }
 
-extern const struct hw_codec_info *i965_get_codec_info(int devid);
+extern struct hw_codec_info *i965_get_codec_info(int devid);
 
 static bool
 i965_driver_data_init(VADriverContextP ctx)
@@ -5422,6 +5669,9 @@ i965_Init(VADriverContextP ctx)
             break;
     }
 
+    if (i965->codec_info->preinit_hw_codec)
+        i965->codec_info->preinit_hw_codec(ctx, i965->codec_info);
+
     if (i == ARRAY_ELEMS(i965_sub_ops)) {
         switch (i965->intel.device_id) {
 #undef CHIPSET
@@ -5550,6 +5800,10 @@ VA_DRIVER_INIT_FUNC(  VADriverContextP ctx )
     vtable->vaQuerySurfaceAttributes = i965_QuerySurfaceAttributes;
     vtable->vaCreateSurfaces2 = i965_CreateSurfaces2;
 
+    /* 0.36.0 */
+    vtable->vaAcquireBufferHandle = i965_AcquireBufferHandle;
+    vtable->vaReleaseBufferHandle = i965_ReleaseBufferHandle;
+
     vtable_vpp->vaQueryVideoProcFilters = i965_QueryVideoProcFilters;
     vtable_vpp->vaQueryVideoProcFilterCaps = i965_QueryVideoProcFilterCaps;
     vtable_vpp->vaQueryVideoProcPipelineCaps = i965_QueryVideoProcPipelineCaps;