*/
#include "sysdeps.h"
+#include <unistd.h>
#ifdef HAVE_VA_X11
# include "i965_output_dri.h"
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);
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;
}
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;
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);
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;
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 {
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);
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]);
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);
* 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;
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,
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 ||
obj_buffer,
va_enc_packed_type_to_idx(encode->last_packed_header_type));
}
+ encode->last_packed_header_type = 0;
break;
}
(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;
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)
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)
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
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;