#include <pthread.h>
#include <va/va.h>
+#include <va/va_enc_h264.h>
#include "va_display.h"
#define NAL_REF_IDC_NONE 0
static int pb_period = 5;
static int frame_bit_rate = -1;
-#define BR_CBR 0
-#define BR_VBR 1
-#define BR_CQP 2
-
#define MAX_SLICES 32
static int
static void
upload_yuv_to_surface(FILE *yuv_fp, VASurfaceID surface_id);
-struct {
+static struct {
+ VAProfile profile;
VAEncSequenceParameterBufferH264 seq_param;
VAEncPictureParameterBufferH264 pic_param;
VAEncSliceParameterBufferH264 slice_param[MAX_SLICES];
- VAEncH264DecRefPicMarkingBuffer dec_ref_pic_marking;
VAContextID context_id;
VAConfigID config_id;
VABufferID seq_param_buf_id; /* Sequence level parameter */
VABufferID pic_param_buf_id; /* Picture level parameter */
VABufferID slice_param_buf_id[MAX_SLICES]; /* Slice level parameter, multil slices */
- VABufferID dec_ref_pic_marking_buf_id;
VABufferID codedbuf_buf_id; /* Output buffer, compressed data */
VABufferID packed_seq_header_param_buf_id;
VABufferID packed_seq_buf_id;
VABufferID packed_pic_header_param_buf_id;
VABufferID packed_pic_buf_id;
+ VABufferID misc_parameter_hrd_buf_id;
+
int num_slices;
int codedbuf_i_size;
int codedbuf_pb_size;
int current_input_surface;
+ int rate_control_method;
struct upload_thread_param upload_thread_param;
pthread_t upload_thread_id;
int upload_thread_value;
va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
CHECK_VASTATUS(va_status, "vaInitialize");
- vaQueryConfigEntrypoints(va_dpy, VAProfileH264Baseline, entrypoints,
+ vaQueryConfigEntrypoints(va_dpy, avcenc_context.profile, entrypoints,
&num_entrypoints);
for (slice_entrypoint = 0; slice_entrypoint < num_entrypoints; slice_entrypoint++) {
/* find out the format for the render target, and rate control mode */
attrib[0].type = VAConfigAttribRTFormat;
attrib[1].type = VAConfigAttribRateControl;
- vaGetConfigAttributes(va_dpy, VAProfileH264Baseline, VAEntrypointEncSlice,
+ vaGetConfigAttributes(va_dpy, avcenc_context.profile, VAEntrypointEncSlice,
&attrib[0], 2);
if ((attrib[0].value & VA_RT_FORMAT_YUV420) == 0) {
assert(0);
}
- if ((attrib[1].value & VA_RC_VBR) == 0) {
+ if ((attrib[1].value & avcenc_context.rate_control_method) == 0) {
/* Can't find matched RC mode */
- printf("VBR mode doesn't found, exit\n");
+ printf("Can't find the desired RC mode, exit\n");
assert(0);
}
attrib[0].value = VA_RT_FORMAT_YUV420; /* set to desired RT format */
- attrib[1].value = VA_RC_VBR; /* set to desired RC mode */
+ attrib[1].value = avcenc_context.rate_control_method; /* set to desired RC mode */
- va_status = vaCreateConfig(va_dpy, VAProfileH264Baseline, VAEntrypointEncSlice,
+ va_status = vaCreateConfig(va_dpy, avcenc_context.profile, VAEntrypointEncSlice,
&attrib[0], 2,&avcenc_context.config_id);
CHECK_VASTATUS(va_status, "vaCreateConfig");
pic_param->ReferenceFrames[1].picture_id = surface_ids[SID_REFERENCE_PICTURE_L1];
pic_param->ReferenceFrames[2].picture_id = VA_INVALID_ID;
assert(avcenc_context.codedbuf_buf_id != VA_INVALID_ID);
- pic_param->CodedBuf = avcenc_context.codedbuf_buf_id;
+ pic_param->coded_buf = avcenc_context.codedbuf_buf_id;
pic_param->frame_num = frame_num;
pic_param->pic_fields.bits.idr_pic_flag = !!is_idr;
pic_param->pic_fields.bits.reference_pic_flag = (slice_type != SLICE_TYPE_B);
// Slice level
i = 0;
slice_param = &avcenc_context.slice_param[i];
- slice_param->starting_macroblock_address = 0;
- slice_param->number_of_mbs = picture_height_in_mbs * picture_width_in_mbs;
+ slice_param->macroblock_address = 0;
+ slice_param->num_macroblocks = picture_height_in_mbs * picture_width_in_mbs;
slice_param->pic_parameter_set_id = 0;
slice_param->slice_type = slice_type;
slice_param->direct_spatial_mv_pred_flag = 0;
slice_param->slice_beta_offset_div2 = 2;
slice_param->idr_pic_id = 0;
- /* ref_pic_list_modification() */
- slice_param->ref_pic_list_modification_flag_l0 = 0;
- slice_param->ref_pic_list_modification_flag_l1 = 0;
/* FIXME: fill other fields */
va_status = vaCreateBuffer(va_dpy,
#if 0
slice_param = &avcenc_context.slice_param[i];
- slice_param->starting_macroblock_address = picture_height_in_mbs * picture_width_in_mbs / 2;
- slice_param->number_of_mbs = picture_height_in_mbs * picture_width_in_mbs / 2;
+ slice_param->macroblock_address = picture_height_in_mbs * picture_width_in_mbs / 2;
+ slice_param->num_macroblocks = picture_height_in_mbs * picture_width_in_mbs / 2;
slice_param->pic_parameter_set_id = 0;
slice_param->slice_type = slice_type;
slice_param->direct_spatial_mv_pred_flag = 0;
slice_param->slice_beta_offset_div2 = 2;
slice_param->idr_pic_id = 0;
- /* ref_pic_list_modification() */
- slice_param->ref_pic_list_modification_flag_l0 = 0;
- slice_param->ref_pic_list_modification_flag_l1 = 0;
/* FIXME: fill other fields */
va_status = vaCreateBuffer(va_dpy,
assert(slice_type == SLICE_TYPE_I);
length_in_bits = build_packed_seq_buffer(&packed_seq_buffer);
offset_in_bytes = 0;
- packed_header_param_buffer.type = VAEncPackedHeaderSPS;
- packed_header_param_buffer.insert_emulation_bytes = 1;
- packed_header_param_buffer.skip_emulation_check_count = 5; /* ignore start code & nal type for emulation prevetion check */
- packed_header_param_buffer.num_headers = 1;
- packed_header_param_buffer.length_in_bits = &length_in_bits;
- packed_header_param_buffer.offset_in_bytes = &offset_in_bytes;
+ packed_header_param_buffer.type = VAEncPackedHeaderSequence;
+ packed_header_param_buffer.bit_length = length_in_bits;
+ packed_header_param_buffer.has_emulation_bytes = 0;
va_status = vaCreateBuffer(va_dpy,
avcenc_context.context_id,
VAEncPackedHeaderParameterBufferType,
length_in_bits = build_packed_pic_buffer(&packed_pic_buffer);
offset_in_bytes = 0;
- packed_header_param_buffer.type = VAEncPackedHeaderPPS;
- packed_header_param_buffer.insert_emulation_bytes = 1;
- packed_header_param_buffer.skip_emulation_check_count = 5; /* ignore start code & nal type for emulation prevetion check */
- packed_header_param_buffer.num_headers = 1;
- packed_header_param_buffer.length_in_bits = &length_in_bits;
- packed_header_param_buffer.offset_in_bytes = &offset_in_bytes;
+ packed_header_param_buffer.type = VAEncPackedHeaderPicture;
+ packed_header_param_buffer.bit_length = length_in_bits;
+ packed_header_param_buffer.has_emulation_bytes = 0;
va_status = vaCreateBuffer(va_dpy,
avcenc_context.context_id,
VAEncSequenceParameterBufferType,
sizeof(*seq_param), 1, seq_param,
&avcenc_context.seq_param_buf_id);
- CHECK_VASTATUS(va_status,"vaCreateBuffer");;
+ CHECK_VASTATUS(va_status,"vaCreateBuffer");
+
+
+ /* hrd parameter */
+ VAEncMiscParameterBuffer *misc_param;
+ VAEncMiscParameterHRD *misc_hrd_param;
+ vaCreateBuffer(va_dpy,
+ avcenc_context.context_id,
+ VAEncMiscParameterBufferType,
+ sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterRateControl),
+ 1,
+ NULL,
+ &avcenc_context.misc_parameter_hrd_buf_id);
+ CHECK_VASTATUS(va_status, "vaCreateBuffer");
+
+ vaMapBuffer(va_dpy,
+ avcenc_context.misc_parameter_hrd_buf_id,
+ (void **)&misc_param);
+ misc_param->type = VAEncMiscParameterTypeHRD;
+ misc_hrd_param = (VAEncMiscParameterHRD *)misc_param->data;
+
+ if (frame_bit_rate > 0) {
+ misc_hrd_param->initial_buffer_fullness = frame_bit_rate * 1024 * 4;
+ misc_hrd_param->buffer_size = frame_bit_rate * 1024 * 8;
+ } else {
+ misc_hrd_param->initial_buffer_fullness = 0;
+ misc_hrd_param->buffer_size = 0;
+ }
+
+ vaUnmapBuffer(va_dpy, avcenc_context.misc_parameter_hrd_buf_id);
/* slice parameter */
avcenc_update_slice_parameter(slice_type);
va_buffers[num_va_buffers++] = avcenc_context.seq_param_buf_id;
va_buffers[num_va_buffers++] = avcenc_context.pic_param_buf_id;
- if (avcenc_context.dec_ref_pic_marking_buf_id != VA_INVALID_ID)
- va_buffers[num_va_buffers++] = avcenc_context.dec_ref_pic_marking_buf_id;
-
if (avcenc_context.packed_seq_header_param_buf_id != VA_INVALID_ID)
va_buffers[num_va_buffers++] = avcenc_context.packed_seq_header_param_buf_id;
if (avcenc_context.packed_pic_buf_id != VA_INVALID_ID)
va_buffers[num_va_buffers++] = avcenc_context.packed_pic_buf_id;
+ if (avcenc_context.misc_parameter_hrd_buf_id != VA_INVALID_ID)
+ va_buffers[num_va_buffers++] = avcenc_context.misc_parameter_hrd_buf_id;
+
va_status = vaBeginPicture(va_dpy,
avcenc_context.context_id,
surface_ids[avcenc_context.current_input_surface]);
avcenc_destroy_buffers(&avcenc_context.seq_param_buf_id, 1);
avcenc_destroy_buffers(&avcenc_context.pic_param_buf_id, 1);
- avcenc_destroy_buffers(&avcenc_context.dec_ref_pic_marking_buf_id, 1);
avcenc_destroy_buffers(&avcenc_context.packed_seq_header_param_buf_id, 1);
avcenc_destroy_buffers(&avcenc_context.packed_seq_buf_id, 1);
avcenc_destroy_buffers(&avcenc_context.packed_pic_header_param_buf_id, 1);
avcenc_destroy_buffers(&avcenc_context.packed_pic_buf_id, 1);
avcenc_destroy_buffers(&avcenc_context.slice_param_buf_id[0], avcenc_context.num_slices);
avcenc_destroy_buffers(&avcenc_context.codedbuf_buf_id, 1);
+ avcenc_destroy_buffers(&avcenc_context.misc_parameter_hrd_buf_id, 1);
+
memset(avcenc_context.slice_param, 0, sizeof(avcenc_context.slice_param));
avcenc_context.num_slices = 0;
}
static void sps_rbsp(bitstream *bs)
{
VAEncSequenceParameterBufferH264 *seq_param = &avcenc_context.seq_param;
+ int profile_idc = PROFILE_IDC_BASELINE;
+
+ if (avcenc_context.profile == VAProfileH264High)
+ profile_idc = PROFILE_IDC_HIGH;
+ else if (avcenc_context.profile == VAProfileH264Main)
+ profile_idc = PROFILE_IDC_MAIN;
- bitstream_put_ui(bs, seq_param->profile_idc, 8); /* profile_idc */
+ bitstream_put_ui(bs, profile_idc, 8); /* profile_idc */
bitstream_put_ui(bs, 0, 1); /* constraint_set0_flag */
bitstream_put_ui(bs, 1, 1); /* constraint_set1_flag */
bitstream_put_ui(bs, 0, 1); /* constraint_set2_flag */
bitstream_put_ui(bs, seq_param->level_idc, 8); /* level_idc */
bitstream_put_ue(bs, seq_param->seq_parameter_set_id); /* seq_parameter_set_id */
- if (seq_param->profile_idc >= PROFILE_IDC_HIGH) {
- /* FIXME: fix for high profile */
- assert(0);
- }
+ bitstream_put_ue(bs, seq_param->seq_fields.bits.log2_max_frame_num_minus4); /* log2_max_frame_num_minus4 */
+ bitstream_put_ue(bs, seq_param->seq_fields.bits.pic_order_cnt_type); /* pic_order_cnt_type */
- bitstream_put_ue(bs, seq_param->log2_max_frame_num_minus4); /* log2_max_frame_num_minus4 */
- bitstream_put_ue(bs, seq_param->pic_order_cnt_type); /* pic_order_cnt_type */
-
- if (seq_param->pic_order_cnt_type == 0)
- bitstream_put_ue(bs, seq_param->log2_max_pic_order_cnt_lsb_minus4); /* log2_max_pic_order_cnt_lsb_minus4 */
+ if (seq_param->seq_fields.bits.pic_order_cnt_type == 0)
+ bitstream_put_ue(bs, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4); /* log2_max_pic_order_cnt_lsb_minus4 */
else {
assert(0);
}
bitstream_put_ue(bs, seq_param->picture_width_in_mbs - 1); /* pic_width_in_mbs_minus1 */
bitstream_put_ue(bs, seq_param->picture_height_in_mbs - 1); /* pic_height_in_map_units_minus1 */
- bitstream_put_ui(bs, seq_param->frame_mbs_only_flag, 1); /* frame_mbs_only_flag */
+ bitstream_put_ui(bs, seq_param->seq_fields.bits.frame_mbs_only_flag, 1); /* frame_mbs_only_flag */
- if (!seq_param->frame_mbs_only_flag) {
+ if (!seq_param->seq_fields.bits.frame_mbs_only_flag) {
assert(0);
}
- bitstream_put_ui(bs, seq_param->direct_8x8_inference_flag, 1); /* direct_8x8_inference_flag */
+ bitstream_put_ui(bs, seq_param->seq_fields.bits.direct_8x8_inference_flag, 1); /* direct_8x8_inference_flag */
bitstream_put_ui(bs, seq_param->frame_cropping_flag, 1); /* frame_cropping_flag */
if (seq_param->frame_cropping_flag) {
bitstream_put_ue(bs, 0); /* first_mb_in_slice: 0 */
bitstream_put_ue(bs, slice_type); /* slice_type */
bitstream_put_ue(bs, 0); /* pic_parameter_set_id: 0 */
- bitstream_put_ui(bs, frame_num & 0x0F, seq_param->log2_max_frame_num_minus4 + 4); /* frame_num */
+ bitstream_put_ui(bs, frame_num & 0x0F, seq_param->seq_fields.bits.log2_max_frame_num_minus4 + 4); /* frame_num */
/* frame_mbs_only_flag == 1 */
- if (!seq_param->frame_mbs_only_flag) {
+ if (!seq_param->seq_fields.bits.frame_mbs_only_flag) {
/* FIXME: */
assert(0);
}
if (is_idr)
bitstream_put_ue(bs, 0); /* idr_pic_id: 0 */
- if (seq_param->pic_order_cnt_type == 0) {
- bitstream_put_ui(bs, (display_frame*2) & 0x3F, seq_param->log2_max_pic_order_cnt_lsb_minus4 + 4);
+ if (seq_param->seq_fields.bits.pic_order_cnt_type == 0) {
+ bitstream_put_ui(bs, (display_frame*2) & 0x3F, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 + 4);
/* only support frame */
} else {
/* FIXME: */
int frame_crop_bottom_offset = 0;
seq_param->seq_parameter_set_id = 0;
- seq_param->profile_idc = PROFILE_IDC_MAIN;
seq_param->level_idc = 41;
seq_param->intra_period = intra_period;
seq_param->ip_period = 0; /* FIXME: ??? */
seq_param->max_num_ref_frames = 4;
seq_param->picture_width_in_mbs = width_in_mbs;
seq_param->picture_height_in_mbs = height_in_mbs;
- seq_param->frame_mbs_only_flag = 1;
- seq_param->target_usage = 1;
+ seq_param->seq_fields.bits.frame_mbs_only_flag = 1;
- /* 0:CBR, 1:VBR, 2:Constant QP */
- if (qp_value == -1)
- seq_param->rate_control_method = BR_CBR;
- else if (qp_value == -2)
- seq_param->rate_control_method = BR_VBR;
- else {
- assert(qp_value >= 0 && qp_value <= 51);
- seq_param->rate_control_method = BR_CQP;
- }
-
if (frame_bit_rate > 0)
seq_param->bits_per_second = 1024 * frame_bit_rate; /* use kbps as input */
else
seq_param->bits_per_second = 0;
-
- if (seq_param->rate_control_method == BR_VBR) {
- seq_param->max_bits_per_second = 0; /* FIXME: set it later */
- seq_param->min_bits_per_second = 0;
- }
-
- if ( frame_bit_rate > 0) {
- seq_param->initial_hrd_buffer_fullness = frame_bit_rate * 1024 * 4;
- seq_param->hrd_buffer_size = frame_bit_rate * 1024 * 8;
- } else {
- seq_param->initial_hrd_buffer_fullness = 0;
- seq_param->hrd_buffer_size = 0;
- }
+
seq_param->time_scale = 900;
seq_param->num_units_in_tick = 15; /* Tc = num_units_in_tick / time_sacle */
if (height_in_mbs * 16 - height) {
frame_cropping_flag = 1;
frame_crop_bottom_offset =
- (height_in_mbs * 16 - height) / (2 * (!seq_param->frame_mbs_only_flag + 1));
+ (height_in_mbs * 16 - height) / (2 * (!seq_param->seq_fields.bits.frame_mbs_only_flag + 1));
}
seq_param->frame_cropping_flag = frame_cropping_flag;
seq_param->frame_crop_top_offset = 0;
seq_param->frame_crop_bottom_offset = frame_crop_bottom_offset;
- seq_param->pic_order_cnt_type = 0;
- seq_param->direct_8x8_inference_flag = 0;
+ seq_param->seq_fields.bits.pic_order_cnt_type = 0;
+ seq_param->seq_fields.bits.direct_8x8_inference_flag = 0;
- seq_param->log2_max_frame_num_minus4 = 0;
- seq_param->log2_max_pic_order_cnt_lsb_minus4 = 2;
+ seq_param->seq_fields.bits.log2_max_frame_num_minus4 = 0;
+ seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = 2;
- if ( frame_bit_rate > 0)
- seq_param->vui_flag = 1; //HRD info located in vui
- else
- seq_param->vui_flag = 0;
+ if (frame_bit_rate > 0)
+ seq_param->vui_parameters_present_flag = 1; //HRD info located in vui
+ else
+ seq_param->vui_parameters_present_flag = 0;
}
static void avcenc_context_pic_param_init(VAEncPictureParameterBufferH264 *pic_param)
pic_param->last_picture = 0;
pic_param->frame_num = 0;
- pic_param->coding_type = 0;
pic_param->pic_init_qp = (qp_value >= 0 ? qp_value : 26);
pic_param->num_ref_idx_l0_active_minus1 = 0;
{
int i;
memset(&avcenc_context, 0, sizeof(avcenc_context));
+ avcenc_context.profile = VAProfileH264Main;
avcenc_context.seq_param_buf_id = VA_INVALID_ID;
avcenc_context.pic_param_buf_id = VA_INVALID_ID;
- avcenc_context.dec_ref_pic_marking_buf_id = VA_INVALID_ID;
avcenc_context.packed_seq_header_param_buf_id = VA_INVALID_ID;
avcenc_context.packed_seq_buf_id = VA_INVALID_ID;
avcenc_context.packed_pic_header_param_buf_id = VA_INVALID_ID;
avcenc_context.packed_pic_buf_id = VA_INVALID_ID;
avcenc_context.codedbuf_buf_id = VA_INVALID_ID;
+ avcenc_context.misc_parameter_hrd_buf_id = VA_INVALID_ID;
avcenc_context.codedbuf_i_size = width * height;
avcenc_context.codedbuf_pb_size = 0;
avcenc_context.current_input_surface = SID_INPUT_PICTURE_0;
avcenc_context.upload_thread_value = -1;
+ if (qp_value == -1)
+ avcenc_context.rate_control_method = VA_RC_CBR;
+ else if (qp_value == -2)
+ avcenc_context.rate_control_method = VA_RC_VBR;
+ else {
+ assert(qp_value >= 0 && qp_value <= 51);
+ avcenc_context.rate_control_method = VA_RC_CQP;
+ }
+
for (i = 0; i < MAX_SLICES; i++) {
avcenc_context.slice_param_buf_id[i] = VA_INVALID_ID;
}