#include "i965_encoder.h"
#include "gen6_vme.h"
#include "gen6_mfc.h"
+#include "gen9_mfc.h"
+#include "intel_media.h"
+#include "gen9_vp9_encapi.h"
+#include "i965_post_processing.h"
#ifdef SURFACE_STATE_PADDED_SIZE
#undef SURFACE_STATE_PADDED_SIZE
&vme_context->gpe_context,
obj_surface,
BINDING_TABLE_OFFSET(index),
- SURFACE_STATE_OFFSET(index));
+ SURFACE_STATE_OFFSET(index),
+ 0);
}
static void
&vme_context->gpe_context,
obj_surface,
BINDING_TABLE_OFFSET(index),
- SURFACE_STATE_OFFSET(index));
+ SURFACE_STATE_OFFSET(index),
+ 0);
}
static void
/*Setup surfaces state*/
/* current picture for encoding */
obj_surface = encode_state->input_yuv_object;
+ assert(obj_surface);
gen9_vme_source_surface_state(ctx, 0, obj_surface, encoder_context);
gen9_vme_media_source_surface_state(ctx, 4, obj_surface, encoder_context);
gen9_vme_media_chroma_source_surface_state(ctx, 6, obj_surface, encoder_context);
/* VME output */
gen9_vme_avc_output_buffer_setup(ctx, encode_state, 3, encoder_context);
gen9_vme_avc_output_vme_batchbuffer_setup(ctx, encode_state, 5, encoder_context);
+ intel_h264_setup_cost_surface(ctx, encode_state, encoder_context,
+ BINDING_TABLE_OFFSET(INTEL_COST_TABLE_OFFSET),
+ SURFACE_STATE_OFFSET(INTEL_COST_TABLE_OFFSET));
return VA_STATUS_SUCCESS;
}
dri_bo *bo;
unsigned char *desc_ptr;
- bo = vme_context->gpe_context.dynamic_state.bo;
+ bo = vme_context->gpe_context.idrt.bo;
dri_bo_map(bo, 1);
assert(bo->virtual);
- desc_ptr = (unsigned char *)bo->virtual + vme_context->gpe_context.idrt_offset;
+ desc_ptr = (unsigned char *)bo->virtual + vme_context->gpe_context.idrt.offset;
desc = (struct gen8_interface_descriptor_data *)desc_ptr;
static VAStatus gen9_vme_constant_setup(VADriverContextP ctx,
struct encode_state *encode_state,
- struct intel_encoder_context *encoder_context)
+ struct intel_encoder_context *encoder_context,
+ int denom)
{
struct gen6_vme_context *vme_context = encoder_context->vme_context;
unsigned char *constant_buffer;
if (encoder_context->codec == CODEC_H264 ||
encoder_context->codec == CODEC_H264_MVC) {
if (vme_context->h264_level >= 30) {
- mv_num = 16;
+ mv_num = 16 / denom;
if (vme_context->h264_level >= 31)
- mv_num = 8;
+ mv_num = 8 / denom;
}
} else if (encoder_context->codec == CODEC_MPEG2) {
- mv_num = 2;
+ mv_num = 2 / denom;
}else if (encoder_context->codec == CODEC_HEVC) {
if (vme_context->hevc_level >= 30*3) {
mv_num = 16;
vme_state_message[31] = mv_num;
- dri_bo_map(vme_context->gpe_context.dynamic_state.bo, 1);
- assert(vme_context->gpe_context.dynamic_state.bo->virtual);
- constant_buffer = (unsigned char *)vme_context->gpe_context.dynamic_state.bo->virtual +
- vme_context->gpe_context.curbe_offset;
+ dri_bo_map(vme_context->gpe_context.curbe.bo, 1);
+ assert(vme_context->gpe_context.curbe.bo->virtual);
+ constant_buffer = (unsigned char *)vme_context->gpe_context.curbe.bo->virtual +
+ vme_context->gpe_context.curbe.offset;
/* VME MV/Mb cost table is passed by using const buffer */
/* Now it uses the fixed search path. So it is constructed directly
*/
memcpy(constant_buffer, (char *)vme_context->vme_state_message, 128);
- dri_bo_unmap(vme_context->gpe_context.dynamic_state.bo);
+ dri_bo_unmap(vme_context->gpe_context.curbe.bo);
return VA_STATUS_SUCCESS;
}
int mb_x = 0, mb_y = 0;
int i, s;
unsigned int *command_ptr;
+ struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
+ VAEncPictureParameterBufferH264 *pic_param = (VAEncPictureParameterBufferH264 *)encode_state->pic_param_ext->buffer;
+ VAEncSliceParameterBufferH264 *slice_param = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[0]->buffer;
+ int qp;
+ int slice_type = intel_avc_enc_slice_type_fixup(slice_param->slice_type);
+ int qp_mb, qp_index;
+
+ if (encoder_context->rate_control_mode == VA_RC_CQP)
+ qp = pic_param->pic_init_qp + slice_param->slice_qp_delta;
+ else
+ qp = mfc_context->brc.qp_prime_y[encoder_context->layer.curr_frame_layer_id][slice_type];
dri_bo_map(vme_context->vme_batchbuffer.bo, 1);
command_ptr = vme_context->vme_batchbuffer.bo->virtual;
if ((i == mb_width) && slice_mb_x) {
mb_intra_ub &= ~(INTRA_PRED_AVAIL_FLAG_D);
}
- *command_ptr++ = (CMD_MEDIA_OBJECT | (8 - 2));
+ *command_ptr++ = (CMD_MEDIA_OBJECT | (9 - 2));
*command_ptr++ = kernel;
*command_ptr++ = 0;
*command_ptr++ = 0;
/*inline data */
*command_ptr++ = (mb_width << 16 | mb_y << 8 | mb_x);
*command_ptr++ = ((encoder_context->quality_level << 24) | (1 << 16) | transform_8x8_mode_flag | (mb_intra_ub << 8));
+ /* qp occupies one byte */
+ if (vme_context->roi_enabled) {
+ qp_index = mb_y * mb_width + mb_x;
+ qp_mb = *(vme_context->qp_per_mb + qp_index);
+ } else
+ qp_mb = qp;
+ *command_ptr++ = qp_mb;
*command_ptr++ = CMD_MEDIA_STATE_FLUSH;
*command_ptr++ = 0;
}
if ((pSliceParameter->slice_type == SLICE_TYPE_I) ||
- (pSliceParameter->slice_type == SLICE_TYPE_I)) {
+ (pSliceParameter->slice_type == SLICE_TYPE_SI)) {
kernel_shader = VME_INTRA_SHADER;
} else if ((pSliceParameter->slice_type == SLICE_TYPE_P) ||
(pSliceParameter->slice_type == SLICE_TYPE_SP)) {
gen9_gpe_pipeline_setup(ctx, &vme_context->gpe_context, batch);
BEGIN_BATCH(batch, 3);
OUT_BATCH(batch, MI_BATCH_BUFFER_START | (1 << 8) | (1 << 0));
- OUT_RELOC(batch,
+ OUT_RELOC64(batch,
vme_context->vme_batchbuffer.bo,
I915_GEM_DOMAIN_COMMAND, 0,
0);
- OUT_BATCH(batch, 0);
ADVANCE_BATCH(batch);
gen9_gpe_pipeline_end(ctx, &vme_context->gpe_context, batch);
}
intel_vme_update_mbmv_cost(ctx, encode_state, encoder_context);
+ intel_h264_initialize_mbmv_cost(ctx, encode_state, encoder_context);
+ intel_h264_enc_roi_config(ctx, encode_state, encoder_context);
/*Setup all the memory object*/
gen9_vme_surface_setup(ctx, encode_state, is_intra, encoder_context);
gen9_vme_interface_setup(ctx, encode_state, encoder_context);
//gen9_vme_vme_state_setup(ctx, encode_state, is_intra, encoder_context);
- gen9_vme_constant_setup(ctx, encode_state, encoder_context);
+ gen9_vme_constant_setup(ctx, encode_state, encoder_context, (pSliceParameter->slice_type == SLICE_TYPE_B) ? 2 : 1);
/*Programing media pipeline*/
gen9_vme_pipeline_programing(ctx, encode_state, encoder_context);
gen9_gpe_pipeline_setup(ctx, &vme_context->gpe_context, batch);
BEGIN_BATCH(batch, 4);
OUT_BATCH(batch, MI_BATCH_BUFFER_START | (1 << 8) | (1 << 0));
- OUT_RELOC(batch,
+ OUT_RELOC64(batch,
vme_context->vme_batchbuffer.bo,
I915_GEM_DOMAIN_COMMAND, 0,
0);
OUT_BATCH(batch, 0);
- OUT_BATCH(batch, 0);
ADVANCE_BATCH(batch);
gen9_gpe_pipeline_end(ctx, &vme_context->gpe_context, batch);
gen9_vme_interface_setup(ctx, encode_state, encoder_context);
//gen9_vme_vme_state_setup(ctx, encode_state, slice_param->is_intra_slice, encoder_context);
intel_vme_mpeg2_state_setup(ctx, encode_state, encoder_context);
- gen9_vme_constant_setup(ctx, encode_state, encoder_context);
+ gen9_vme_constant_setup(ctx, encode_state, encoder_context, 1);
/*Programing media pipeline*/
gen9_vme_mpeg2_pipeline_programing(ctx, encode_state, slice_param->is_intra_slice, encoder_context);
gen9_gpe_pipeline_setup(ctx, &vme_context->gpe_context, batch);
BEGIN_BATCH(batch, 4);
OUT_BATCH(batch, MI_BATCH_BUFFER_START | (1 << 8) | (1 << 0));
- OUT_RELOC(batch,
+ OUT_RELOC64(batch,
vme_context->vme_batchbuffer.bo,
I915_GEM_DOMAIN_COMMAND, 0,
0);
OUT_BATCH(batch, 0);
- OUT_BATCH(batch, 0);
ADVANCE_BATCH(batch);
gen9_gpe_pipeline_end(ctx, &vme_context->gpe_context, batch);
/*Setup all the memory object*/
gen9_vme_vp8_surface_setup(ctx, encode_state, is_intra, encoder_context);
gen9_vme_interface_setup(ctx, encode_state, encoder_context);
- gen9_vme_constant_setup(ctx, encode_state, encoder_context);
+ gen9_vme_constant_setup(ctx, encode_state, encoder_context, 1);
/*Programing media pipeline*/
gen9_vme_vp8_pipeline_programing(ctx, encode_state, is_intra, encoder_context);
struct intel_encoder_context *encoder_context)
{
struct object_surface *obj_surface;
+ VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
+ GenHevcSurface *hevc_encoder_surface = NULL;
/*Setup surfaces state*/
/* current picture for encoding */
obj_surface = encode_state->input_yuv_object;
+
+ if((pSequenceParameter->seq_fields.bits.bit_depth_luma_minus8 > 0)
+ || (pSequenceParameter->seq_fields.bits.bit_depth_chroma_minus8 > 0)) {
+ hevc_encoder_surface = (GenHevcSurface *) obj_surface->private_data;
+ assert(hevc_encoder_surface);
+ obj_surface = hevc_encoder_surface->nv12_surface_obj;
+ }
gen9_vme_source_surface_state(ctx, 0, obj_surface, encoder_context);
gen9_vme_media_source_surface_state(ctx, 4, obj_surface, encoder_context);
gen9_vme_media_chroma_source_surface_state(ctx, 6, obj_surface, encoder_context);
gen9_gpe_pipeline_setup(ctx, &vme_context->gpe_context, batch);
BEGIN_BATCH(batch, 3);
OUT_BATCH(batch, MI_BATCH_BUFFER_START | (1 << 8) | (1 << 0));
- OUT_RELOC(batch,
+ OUT_RELOC64(batch,
vme_context->vme_batchbuffer.bo,
I915_GEM_DOMAIN_COMMAND, 0,
0);
- OUT_BATCH(batch, 0);
ADVANCE_BATCH(batch);
gen9_gpe_pipeline_end(ctx, &vme_context->gpe_context, batch);
intel_batchbuffer_end_atomic(batch);
}
+static VAStatus gen9_intel_init_hevc_surface(VADriverContextP ctx,
+ struct intel_encoder_context *encoder_context,
+ struct encode_state *encode_state,
+ struct object_surface *input_obj_surface)
+{
+ struct i965_driver_data *i965 = i965_driver_data(ctx);
+ struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
+ VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
+ GenHevcSurface *hevc_encoder_surface;
+ struct i965_surface src_surface, dst_surface;
+ struct object_surface *obj_surface;
+ VARectangle rect;
+ VAStatus status;
+
+ uint32_t size;
+
+ obj_surface = input_obj_surface;
+ assert(obj_surface && obj_surface->bo);
+
+ if (obj_surface->private_data == NULL) {
+
+ if (mfc_context->pic_size.ctb_size == 16)
+ size = ((pSequenceParameter->pic_width_in_luma_samples + 63) >> 6) *
+ ((pSequenceParameter->pic_height_in_luma_samples + 15) >> 4);
+ else
+ size = ((pSequenceParameter->pic_width_in_luma_samples + 31) >> 5) *
+ ((pSequenceParameter->pic_height_in_luma_samples + 31) >> 5);
+ size <<= 6; /* in unit of 64bytes */
+
+ hevc_encoder_surface = calloc(sizeof(GenHevcSurface), 1);
+
+ assert(hevc_encoder_surface);
+ hevc_encoder_surface->motion_vector_temporal_bo =
+ dri_bo_alloc(i965->intel.bufmgr,
+ "motion vector temporal buffer",
+ size,
+ 0x1000);
+ assert(hevc_encoder_surface->motion_vector_temporal_bo);
+
+ hevc_encoder_surface->ctx = ctx;
+ hevc_encoder_surface->nv12_surface_obj = NULL;
+ hevc_encoder_surface->nv12_surface_id = VA_INVALID_SURFACE;
+ hevc_encoder_surface->has_p010_to_nv12_done = 0;
+
+ obj_surface->private_data = (void *)hevc_encoder_surface;
+ obj_surface->free_private_data = (void *)gen_free_hevc_surface;
+ }
+
+ hevc_encoder_surface = (GenHevcSurface *) obj_surface->private_data;
+
+ if(!hevc_encoder_surface->has_p010_to_nv12_done && obj_surface->fourcc == VA_FOURCC_P010)
+ {
+ // convert input
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = obj_surface->orig_width;
+ rect.height = obj_surface->orig_height;
+
+ src_surface.base = (struct object_base *)obj_surface;
+ src_surface.type = I965_SURFACE_TYPE_SURFACE;
+ src_surface.flags = I965_SURFACE_FLAG_FRAME;
+
+ if(SURFACE(hevc_encoder_surface->nv12_surface_id) == NULL)
+ {
+ status = i965_CreateSurfaces(ctx,
+ obj_surface->orig_width,
+ obj_surface->orig_height,
+ VA_RT_FORMAT_YUV420,
+ 1,
+ &hevc_encoder_surface->nv12_surface_id);
+ assert(status == VA_STATUS_SUCCESS);
+
+ if (status != VA_STATUS_SUCCESS)
+ return status;
+ }
+
+ obj_surface = SURFACE(hevc_encoder_surface->nv12_surface_id);
+ hevc_encoder_surface->nv12_surface_obj = obj_surface;
+ assert(obj_surface);
+ i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
+
+ dst_surface.base = (struct object_base *)obj_surface;
+ dst_surface.type = I965_SURFACE_TYPE_SURFACE;
+ dst_surface.flags = I965_SURFACE_FLAG_FRAME;
+
+ status = i965_image_processing(ctx,
+ &src_surface,
+ &rect,
+ &dst_surface,
+ &rect);
+ assert(status == VA_STATUS_SUCCESS);
+ hevc_encoder_surface->has_p010_to_nv12_done = 1;
+ }
+ return VA_STATUS_SUCCESS;
+}
+
+static VAStatus gen9_intel_hevc_input_check(VADriverContextP ctx,
+ struct encode_state *encode_state,
+ struct intel_encoder_context *encoder_context)
+{
+ struct i965_driver_data *i965 = i965_driver_data(ctx);
+ struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
+ struct object_surface *obj_surface;
+ GenHevcSurface *hevc_encoder_surface = NULL;
+ int i;
+ int fourcc;
+
+ obj_surface = SURFACE(encode_state->current_render_target);
+ assert(obj_surface && obj_surface->bo);
+ hevc_encoder_surface = (GenHevcSurface *) obj_surface->private_data;
+ if(hevc_encoder_surface)
+ hevc_encoder_surface->has_p010_to_nv12_done = 0;
+ gen9_intel_init_hevc_surface(ctx,encoder_context,encode_state,obj_surface);
+
+ fourcc = obj_surface->fourcc;
+ /* Setup current frame and current direct mv buffer*/
+ obj_surface = encode_state->reconstructed_object;
+ if(fourcc == VA_FOURCC_P010)
+ i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC_P010, SUBSAMPLE_YUV420);
+ else
+ i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
+ hevc_encoder_surface = NULL;
+ hevc_encoder_surface = (GenHevcSurface *) obj_surface->private_data;
+ if(hevc_encoder_surface)
+ hevc_encoder_surface->has_p010_to_nv12_done = 1;
+ gen9_intel_init_hevc_surface(ctx,encoder_context,encode_state,obj_surface);
+
+ /* Setup reference frames and direct mv buffers*/
+ for (i = 0; i < MAX_HCP_REFERENCE_SURFACES; i++) {
+ obj_surface = encode_state->reference_objects[i];
+
+ if (obj_surface && obj_surface->bo) {
+ mfc_context->reference_surfaces[i].bo = obj_surface->bo;
+ dri_bo_reference(obj_surface->bo);
+
+ gen9_intel_init_hevc_surface(ctx,encoder_context,encode_state,obj_surface);
+ } else {
+ break;
+ }
+ }
+
+ return VA_STATUS_SUCCESS;
+}
+
static VAStatus gen9_vme_hevc_prepare(VADriverContextP ctx,
struct encode_state *encode_state,
struct intel_encoder_context *encoder_context)
vme_context->hevc_level = pSequenceParameter->general_level_idc;
}
+ //internal input check for main10
+ gen9_intel_hevc_input_check(ctx,encode_state,encoder_context);
+
intel_vme_hevc_update_mbmv_cost(ctx, encode_state, encoder_context);
/*Setup all the memory object*/
gen9_vme_hevc_surface_setup(ctx, encode_state, is_intra, encoder_context);
gen9_vme_interface_setup(ctx, encode_state, encoder_context);
//gen9_vme_vme_state_setup(ctx, encode_state, is_intra, encoder_context);
- gen9_vme_constant_setup(ctx, encode_state, encoder_context);
+ gen9_vme_constant_setup(ctx, encode_state, encoder_context, 1);
/*Programing media pipeline*/
gen9_vme_hevc_pipeline_programing(ctx, encode_state, encoder_context);
dri_bo_unreference(vme_context->vme_batchbuffer.bo);
vme_context->vme_batchbuffer.bo = NULL;
- if (vme_context->vme_state_message) {
- free(vme_context->vme_state_message);
- vme_context->vme_state_message = NULL;
- }
+ free(vme_context->vme_state_message);
+ vme_context->vme_state_message = NULL;
+
+ dri_bo_unreference(vme_context->i_qp_cost_table);
+ vme_context->i_qp_cost_table = NULL;
+
+ dri_bo_unreference(vme_context->p_qp_cost_table);
+ vme_context->p_qp_cost_table = NULL;
+
+ dri_bo_unreference(vme_context->b_qp_cost_table);
+ vme_context->b_qp_cost_table = NULL;
+
+ free(vme_context->qp_per_mb);
+ vme_context->qp_per_mb = NULL;
free(vme_context);
}
Bool gen9_vme_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context)
{
- struct gen6_vme_context *vme_context = calloc(1, sizeof(struct gen6_vme_context));
+ struct i965_driver_data *i965 = i965_driver_data(ctx);
+ struct gen6_vme_context *vme_context;
struct i965_kernel *vme_kernel_list = NULL;
int i965_kernel_num;
+ if (encoder_context->low_power_mode || encoder_context->codec == CODEC_JPEG) {
+ encoder_context->vme_context = NULL;
+ encoder_context->vme_pipeline = NULL;
+ encoder_context->vme_context_destroy = NULL;
+
+ return True;
+ } else if (encoder_context->codec == CODEC_VP9) {
+ return gen9_vp9_vme_context_init(ctx, encoder_context);
+ }
+
+ vme_context = calloc(1, sizeof(struct gen6_vme_context));
+
switch (encoder_context->codec) {
case CODEC_H264:
case CODEC_H264_MVC:
break;
}
+
+ assert(vme_context);
vme_context->vme_kernel_sum = i965_kernel_num;
vme_context->gpe_context.surface_state_binding_table.length = (SURFACE_STATE_PADDED_SIZE + sizeof(unsigned int)) * MAX_MEDIA_SURFACES_GEN6;
- vme_context->gpe_context.idrt_size = sizeof(struct gen8_interface_descriptor_data) * MAX_INTERFACE_DESC_GEN6;
- vme_context->gpe_context.curbe_size = CURBE_TOTAL_DATA_LENGTH;
- vme_context->gpe_context.sampler_size = 0;
+ vme_context->gpe_context.idrt.entry_size = ALIGN(sizeof(struct gen8_interface_descriptor_data), 64);
+ vme_context->gpe_context.idrt.max_entries = MAX_INTERFACE_DESC_GEN6;
+ vme_context->gpe_context.curbe.length = CURBE_TOTAL_DATA_LENGTH;
+ vme_context->gpe_context.sampler.entry_size = 0;
+ vme_context->gpe_context.sampler.max_entries = 0;
+ if (i965->intel.eu_total > 0) {
+ vme_context->gpe_context.vfe_state.max_num_threads = 6 *
+ i965->intel.eu_total;
+ } else
+ vme_context->gpe_context.vfe_state.max_num_threads = 60 - 1;
- vme_context->gpe_context.vfe_state.max_num_threads = 60 - 1;
vme_context->gpe_context.vfe_state.num_urb_entries = 64;
vme_context->gpe_context.vfe_state.gpgpu_mode = 0;
vme_context->gpe_context.vfe_state.urb_entry_size = 16;