struct encode_state *encode_state,
struct intel_encoder_context *encoder_context,
int rate_control_enable,
- int qp)
+ int qp,
+ int slice_index)
{
struct intel_batchbuffer *batch = encoder_context->base.batch;
struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
VAEncSliceParameterBufferH264 *pSliceParameter = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[0]->buffer; /* TODO: multi slices support */
+ int width_in_mbs = (mfc_context->surface_state.width + 15) / 16;
+ int height_in_mbs = (mfc_context->surface_state.height + 15) / 16;
+ int beginmb = pSliceParameter->starting_macroblock_address;
+ int endmb = beginmb + pSliceParameter->number_of_mbs;
+ int beginx = beginmb % width_in_mbs;
+ int beginy = beginmb / width_in_mbs;
+ int nextx = endmb % width_in_mbs;
+ int nexty = endmb / width_in_mbs;
+ int last_slice = (pSliceParameter->starting_macroblock_address + pSliceParameter->number_of_mbs) == (width_in_mbs * height_in_mbs);
int bit_rate_control_target;
if ( slice_type == SLICE_TYPE_I )
bit_rate_control_target = 0;
(0<<24) | /*Enable deblocking operation*/
(qp<<16) | /*Slice Quantization Parameter*/
0x0202 );
- OUT_BCS_BATCH(batch, 0); /*First MB X&Y , the postion of current slice*/
- OUT_BCS_BATCH(batch, ( ((mfc_context->surface_state.height+15)/16) << 16) );
-
+ OUT_BCS_BATCH(batch, (beginy << 24) | /*First MB X&Y , the begin postion of current slice*/
+ (beginx << 16) |
+ pSliceParameter->starting_macroblock_address );
+ OUT_BCS_BATCH(batch, (nexty << 16) | nextx); /*Next slice first MB X&Y*/
OUT_BCS_BATCH(batch,
(rate_control_enable<<31) | /*in CBR mode RateControlCounterEnable = enable*/
(1<<30) | /*ResetRateControlCounter*/
(0<<22) | /*QP mode, don't modfiy CBP*/
(0<<21) | /*MB Type Direct Conversion Enabled*/
(0<<20) | /*MB Type Skip Conversion Enabled*/
- (1<<19) | /*IsLastSlice*/
+ (last_slice << 19) | /*IsLastSlice*/
(0<<18) | /*BitstreamOutputFlag Compressed BitStream Output Disable Flag 0:enable 1:disable*/
(1<<17) | /*HeaderPresentFlag*/
(1<<16) | /*SliceData PresentFlag*/
mfc_context->bsd_mpc_row_store_scratch_buffer.bo = bo;
}
-void gen6_mfc_avc_pipeline_programing(VADriverContextP ctx,
+static void gen6_mfc_avc_pipeline_header_programing(VADriverContextP ctx,
struct encode_state *encode_state,
struct intel_encoder_context *encoder_context)
{
- struct intel_batchbuffer *batch = encoder_context->base.batch;
+ static int count = 0;
+ VAEncSequenceParameterBufferH264 *pSequenceParameter = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
+ int rate_control_mode = pSequenceParameter->rate_control_method;
+
+ if (encode_state->packed_header_data[VAEncPackedHeaderSPS]) {
+ VAEncPackedHeaderParameterBuffer *param = NULL;
+ unsigned int *header_data = (unsigned int *)encode_state->packed_header_data[VAEncPackedHeaderSPS]->buffer;
+ unsigned int length_in_bits;
+
+ assert(encode_state->packed_header_param[VAEncPackedHeaderSPS]);
+ param = (VAEncPackedHeaderParameterBuffer *)encode_state->packed_header_param[VAEncPackedHeaderSPS]->buffer;
+ length_in_bits = param->length_in_bits[0];
+
+ gen6_mfc_avc_insert_object(ctx,
+ encoder_context,
+ header_data,
+ ALIGN(length_in_bits, 32) >> 5,
+ length_in_bits & 0x1f,
+ param->skip_emulation_check_count,
+ 0,
+ 0,
+ param->insert_emulation_bytes);
+ }
+
+ if (encode_state->packed_header_data[VAEncPackedHeaderPPS]) {
+ VAEncPackedHeaderParameterBuffer *param = NULL;
+ unsigned int *header_data = (unsigned int *)encode_state->packed_header_data[VAEncPackedHeaderPPS]->buffer;
+ unsigned int length_in_bits;
+
+ assert(encode_state->packed_header_param[VAEncPackedHeaderPPS]);
+ param = (VAEncPackedHeaderParameterBuffer *)encode_state->packed_header_param[VAEncPackedHeaderPPS]->buffer;
+ length_in_bits = param->length_in_bits[0];
+
+ gen6_mfc_avc_insert_object(ctx,
+ encoder_context,
+ header_data,
+ ALIGN(length_in_bits, 32) >> 5,
+ length_in_bits & 0x1f,
+ param->skip_emulation_check_count,
+ 0,
+ 0,
+ param->insert_emulation_bytes);
+ }
+
+ if ( (rate_control_mode == 0) && encode_state->packed_header_data[VAEncPackedHeaderSPS]) { // this is frist AU
+ struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
+
+ unsigned char *sei_data = NULL;
+ int length_in_bits = build_avc_sei_buffering_period(mfc_context->vui_hrd.i_initial_cpb_removal_delay_length,
+ mfc_context->vui_hrd.i_initial_cpb_removal_delay, 0, &sei_data);
+ gen6_mfc_avc_insert_object(ctx,
+ encoder_context,
+ (unsigned int *)sei_data,
+ ALIGN(length_in_bits, 32) >> 5,
+ length_in_bits & 0x1f,
+ 4,
+ 0,
+ 0,
+ 1);
+ free(sei_data);
+ }
+
+ // SEI pic_timing header
+ if ( rate_control_mode == 0) {
+ struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
+ unsigned char *sei_data = NULL;
+ int length_in_bits = build_avc_sei_pic_timing( mfc_context->vui_hrd.i_cpb_removal_delay_length,
+ mfc_context->vui_hrd.i_cpb_removal_delay * mfc_context->vui_hrd.i_frame_number,
+ mfc_context->vui_hrd.i_dpb_output_delay_length,
+ 0, &sei_data);
+ gen6_mfc_avc_insert_object(ctx,
+ encoder_context,
+ (unsigned int *)sei_data,
+ ALIGN(length_in_bits, 32) >> 5,
+ length_in_bits & 0x1f,
+ 4,
+ 0,
+ 0,
+ 1);
+ free(sei_data);
+ }
+
+ count++;
+}
+
+static void gen6_mfc_avc_pipeline_picture_programing( VADriverContextP ctx,
+ struct encode_state *encode_state,
+ struct intel_encoder_context *encoder_context)
+{
+ gen6_mfc_pipe_mode_select(ctx, encoder_context);
+ gen6_mfc_surface_state(ctx, encoder_context);
+ gen6_mfc_ind_obj_base_addr_state(ctx, encoder_context);
+ gen6_mfc_pipe_buf_addr_state(ctx, encoder_context);
+ gen6_mfc_bsp_buf_base_addr_state(ctx, encoder_context);
+ gen6_mfc_avc_img_state(ctx, encode_state, encoder_context);
+ gen6_mfc_avc_qm_state(ctx, encoder_context);
+ gen6_mfc_avc_fqm_state(ctx, encoder_context);
+ gen6_mfc_avc_directmode_state(ctx, encoder_context);
+ gen6_mfc_avc_ref_idx_state(ctx, encoder_context);
+}
+
+static void
+gen6_mfc_avc_pipeline_slice_programing(VADriverContextP ctx,
+ struct encode_state *encode_state,
+ struct intel_encoder_context *encoder_context,
+ int slice_index)
+{
struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
struct gen6_vme_context *vme_context = encoder_context->vme_context;
VAEncSequenceParameterBufferH264 *pSequenceParameter = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
VAEncPictureParameterBufferH264 *pPicParameter = (VAEncPictureParameterBufferH264 *)encode_state->pic_param_ext->buffer;
- VAEncSliceParameterBufferH264 *pSliceParameter = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[0]->buffer; /* FIXME: multi slices */
+ VAEncSliceParameterBufferH264 *pSliceParameter = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[slice_index]->buffer;
VAEncH264DecRefPicMarkingBuffer *pDecRefPicMarking = NULL;
unsigned int *msg = NULL, offset = 0;
- int emit_new_state = 1, object_len_in_bytes;
int is_intra = pSliceParameter->slice_type == SLICE_TYPE_I;
int width_in_mbs = (mfc_context->surface_state.width + 15) / 16;
int height_in_mbs = (mfc_context->surface_state.height + 15) / 16;
- int x,y;
- int rate_control_mode = pSequenceParameter->rate_control_method;
- unsigned char target_mb_size = mfc_context->bit_rate_control_context[1-is_intra].TargetSizeInWord;
- unsigned char max_mb_size = mfc_context->bit_rate_control_context[1-is_intra].MaxSizeInWord;
+ int last_slice = (pSliceParameter->starting_macroblock_address + pSliceParameter->number_of_mbs) == (width_in_mbs * height_in_mbs);
+ int i,x,y;
int qp = pPicParameter->pic_init_qp + pSliceParameter->slice_qp_delta;
+ int rate_control_mode = pSequenceParameter->rate_control_method;
unsigned char *slice_header = NULL;
int slice_header_length_in_bits = 0;
- unsigned int tail_data[] = { 0x0 };
+ unsigned int tail_data[] = { 0x0, 0x0 };
+
+ gen6_mfc_avc_slice_state(ctx, pSliceParameter->slice_type,
+ encode_state, encoder_context,
+ (rate_control_mode == 0), qp, slice_index);
+
+ if ( slice_index == 0)
+ gen6_mfc_avc_pipeline_header_programing(ctx, encode_state, encoder_context);
if (encode_state->dec_ref_pic_marking)
pDecRefPicMarking = (VAEncH264DecRefPicMarkingBuffer *)encode_state->dec_ref_pic_marking->buffer;
-
slice_header_length_in_bits = build_avc_slice_header(pSequenceParameter, pPicParameter, pSliceParameter, pDecRefPicMarking, &slice_header);
+ // slice hander
+ gen6_mfc_avc_insert_object(ctx, encoder_context,
+ (unsigned int *)slice_header, ALIGN(slice_header_length_in_bits, 32) >> 5, slice_header_length_in_bits & 0x1f,
+ 5, /* first 5 bytes are start code + nal unit type */
+ 1, 0, 1);
+
if ( rate_control_mode == 0) {
qp = mfc_context->bit_rate_control_context[1-is_intra].QpPrimeY;
}
- intel_batchbuffer_start_atomic_bcs(batch, 0x1000);
-
if (is_intra) {
dri_bo_map(vme_context->vme_output.bo , 1);
msg = (unsigned int *)vme_context->vme_output.bo->virtual;
}
-
- for (y = 0; y < height_in_mbs; y++) {
- for (x = 0; x < width_in_mbs; x++) {
- int last_mb = (y == (height_in_mbs-1)) && ( x == (width_in_mbs-1) );
-
- if (emit_new_state) {
- intel_batchbuffer_emit_mi_flush(batch);
- gen6_mfc_pipe_mode_select(ctx, encoder_context);
- gen6_mfc_surface_state(ctx, encoder_context);
- gen6_mfc_ind_obj_base_addr_state(ctx, encoder_context);
- gen6_mfc_pipe_buf_addr_state(ctx, encoder_context);
- gen6_mfc_bsp_buf_base_addr_state(ctx, encoder_context);
- gen6_mfc_avc_img_state(ctx, encode_state,encoder_context);
- gen6_mfc_avc_qm_state(ctx, encoder_context);
- gen6_mfc_avc_fqm_state(ctx, encoder_context);
- gen6_mfc_avc_directmode_state(ctx, encoder_context);
- gen6_mfc_avc_ref_idx_state(ctx, encoder_context);
- gen6_mfc_avc_slice_state(ctx, pSliceParameter->slice_type,
- encode_state, encoder_context,
- rate_control_mode == 0, pPicParameter->pic_init_qp + pSliceParameter->slice_qp_delta);
-
- if (encode_state->packed_header_data[VAEncPackedHeaderSPS]) {
- VAEncPackedHeaderParameterBuffer *param = NULL;
- unsigned int *header_data = (unsigned int *)encode_state->packed_header_data[VAEncPackedHeaderSPS]->buffer;
- unsigned int length_in_bits;
-
- assert(encode_state->packed_header_param[VAEncPackedHeaderSPS]);
- param = (VAEncPackedHeaderParameterBuffer *)encode_state->packed_header_param[VAEncPackedHeaderSPS]->buffer;
- length_in_bits = param->length_in_bits[0];
-
- gen6_mfc_avc_insert_object(ctx,
- encoder_context,
- header_data,
- ALIGN(length_in_bits, 32) >> 5,
- length_in_bits & 0x1f,
- param->skip_emulation_check_count,
- 0,
- 0,
- param->insert_emulation_bytes);
- }
-
- if (encode_state->packed_header_data[VAEncPackedHeaderPPS]) {
- VAEncPackedHeaderParameterBuffer *param = NULL;
- unsigned int *header_data = (unsigned int *)encode_state->packed_header_data[VAEncPackedHeaderPPS]->buffer;
- unsigned int length_in_bits;
-
- assert(encode_state->packed_header_param[VAEncPackedHeaderPPS]);
- param = (VAEncPackedHeaderParameterBuffer *)encode_state->packed_header_param[VAEncPackedHeaderPPS]->buffer;
- length_in_bits = param->length_in_bits[0];
-
- gen6_mfc_avc_insert_object(ctx,
- encoder_context,
- header_data,
- ALIGN(length_in_bits, 32) >> 5,
- length_in_bits & 0x1f,
- param->skip_emulation_check_count,
- 0,
- 0,
- param->insert_emulation_bytes);
- }
-
- gen6_mfc_avc_insert_object(ctx, encoder_context,
- (unsigned int *)slice_header, ALIGN(slice_header_length_in_bits, 32) >> 5, slice_header_length_in_bits & 0x1f,
- 5, /* first 5 bytes are start code + nal unit type */
- 1, 0, 1);
- emit_new_state = 0;
- }
-
- if (is_intra) {
- assert(msg);
- object_len_in_bytes = gen6_mfc_avc_pak_object_intra(ctx, x, y, last_mb, qp, msg, encoder_context,target_mb_size, max_mb_size);
- msg += 4;
- } else {
- object_len_in_bytes = gen6_mfc_avc_pak_object_inter(ctx, x, y, last_mb, qp, offset, encoder_context, target_mb_size, max_mb_size, pSliceParameter->slice_type);
- offset += 64;
- }
-
- if (intel_batchbuffer_check_free_space(batch, object_len_in_bytes) == 0) {
- assert(0);
- intel_batchbuffer_end_atomic(batch);
- intel_batchbuffer_flush(batch);
- emit_new_state = 1;
- intel_batchbuffer_start_atomic_bcs(batch, 0x1000);
- }
+
+ for (i = pSliceParameter->starting_macroblock_address;
+ i < pSliceParameter->starting_macroblock_address + pSliceParameter->number_of_mbs; i++) {
+ int last_mb = (i == (pSliceParameter->starting_macroblock_address + pSliceParameter->number_of_mbs - 1) );
+ x = i % width_in_mbs;
+ y = i / width_in_mbs;
+
+ if (is_intra) {
+ assert(msg);
+ gen6_mfc_avc_pak_object_intra(ctx, x, y, last_mb, qp, msg, encoder_context, 0, 0);
+ msg += 4;
+ } else {
+ gen6_mfc_avc_pak_object_inter(ctx, x, y, last_mb, qp, offset, encoder_context, 0, 0, pSliceParameter->slice_type);
+ offset += 64;
}
}
-
- gen6_mfc_avc_insert_object(ctx, encoder_context,
- tail_data, sizeof(tail_data) >> 2, 32,
- sizeof(tail_data), 1, 1, 1);
-
+
if (is_intra)
dri_bo_unmap(vme_context->vme_output.bo);
+ if ( last_slice ) {
+ gen6_mfc_avc_insert_object(ctx, encoder_context,
+ tail_data, 2, 8,
+ 2, 1, 1, 0);
+ } else {
+ gen6_mfc_avc_insert_object(ctx, encoder_context,
+ tail_data, 1, 8,
+ 1, 1, 1, 0);
+ }
free(slice_header);
+}
+
+static void
+gen6_mfc_avc_pipeline_programing(VADriverContextP ctx,
+ struct encode_state *encode_state,
+ struct intel_encoder_context *encoder_context)
+{
+ struct intel_batchbuffer *batch = encoder_context->base.batch;
+ int i;
+
+ // begin programing
+ intel_batchbuffer_start_atomic_bcs(batch, 0x4000);
+ intel_batchbuffer_emit_mi_flush(batch);
+
+ // picture level programing
+ gen6_mfc_avc_pipeline_picture_programing(ctx, encode_state, encoder_context);
+
+ for ( i = 0; i < encode_state->num_slice_params_ext; i++) {
+ // slice level programing
+ gen6_mfc_avc_pipeline_slice_programing(ctx, encode_state, encoder_context, i);
+ }
+
+ // end programing
intel_batchbuffer_end_atomic(batch);
+
+ return;
}
static void
return 1;
}
+static void
+gen6_mfc_hrd_context_init(struct encode_state *encode_state,
+ struct gen6_mfc_context *mfc_context)
+{
+ VAEncSequenceParameterBufferH264 *pSequenceParameter = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
+ int rate_control_mode = pSequenceParameter->rate_control_method;
+ int target_bit_rate = pSequenceParameter->bits_per_second;
+
+ // current we only support CBR mode.
+ if ( rate_control_mode == 0) {
+ mfc_context->vui_hrd.i_bit_rate_value = target_bit_rate >> 10;
+ mfc_context->vui_hrd.i_cpb_size_value = (target_bit_rate * 8) >> 10;
+ mfc_context->vui_hrd.i_initial_cpb_removal_delay = mfc_context->vui_hrd.i_cpb_size_value * 0.5 * 1024 / target_bit_rate * 90000;
+ mfc_context->vui_hrd.i_cpb_removal_delay = 2;
+ mfc_context->vui_hrd.i_frame_number = 0;
+
+ mfc_context->vui_hrd.i_initial_cpb_removal_delay_length = 24;
+ mfc_context->vui_hrd.i_cpb_removal_delay_length = 24;
+ mfc_context->vui_hrd.i_dpb_output_delay_length = 24;
+ }
+
+}
+
+static VAStatus
+gen6_mfc_hrd_context_check(struct encode_state *encode_state,
+ struct gen6_mfc_context *mfc_context)
+{
+ return VA_STATUS_SUCCESS;
+}
+
+static void
+gen6_mfc_hrd_context_update(struct encode_state *encode_state,
+ struct gen6_mfc_context *mfc_context)
+{
+ mfc_context->vui_hrd.i_frame_number++;
+}
+
static VAStatus gen6_mfc_avc_prepare(VADriverContextP ctx,
struct encode_state *encode_state,
struct intel_encoder_context *encoder_context)
struct gen6_mfc_avc_surface_aux* gen6_avc_surface;
dri_bo *bo;
VAEncPictureParameterBufferH264 *pPicParameter = (VAEncPictureParameterBufferH264 *)encode_state->pic_param_ext->buffer;
+ VAEncSequenceParameterBufferH264 *pSequenceParameter = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
+ int rate_control_mode = pSequenceParameter->rate_control_method;
VAStatus vaStatus = VA_STATUS_SUCCESS;
int i;
if ( mfc_context->bit_rate_control_context[0].MaxSizeInWord == 0 )
gen6_mfc_bit_rate_control_context_init(encode_state, mfc_context);
+ /*Programing HRD control */
+ if ( (rate_control_mode == 0) && (mfc_context->vui_hrd.i_cpb_size_value == 0) )
+ gen6_mfc_hrd_context_init(encode_state, mfc_context);
+
/*Programing bcs pipeline*/
gen6_mfc_avc_pipeline_programing(ctx, encode_state, encoder_context); //filling the pipeline
gen6_mfc_run(ctx, encode_state, encoder_context);
gen6_mfc_stop(ctx, encode_state, encoder_context, ¤t_frame_bits_size);
if ( rate_control_mode == 0) {
- if ( gen6_mfc_bit_rate_control_context_update( encode_state, mfc_context, current_frame_bits_size) )
+ //gen6_mfc_hrd_context_check(encode_state, mfc_context);
+ if ( gen6_mfc_bit_rate_control_context_update( encode_state, mfc_context, current_frame_bits_size) ) {
+ gen6_mfc_hrd_context_update(encode_state, mfc_context);
break;
+ }
} else {
break;
}