static void encoder_state_write_bitstream_vid_parameter_set(encoder_state * const encoder_state) { bitstream * const stream = &encoder_state->stream; int i; #ifdef _DEBUG printf("=========== Video Parameter Set ID: 0 ===========\n"); #endif WRITE_U(stream, 0, 4, "vps_video_parameter_set_id"); WRITE_U(stream, 3, 2, "vps_reserved_three_2bits" ); WRITE_U(stream, 0, 6, "vps_reserved_zero_6bits" ); WRITE_U(stream, 1, 3, "vps_max_sub_layers_minus1"); WRITE_U(stream, 0, 1, "vps_temporal_id_nesting_flag"); WRITE_U(stream, 0xffff, 16, "vps_reserved_ffff_16bits"); encoder_state_write_bitstream_PTL(encoder_state); WRITE_U(stream, 0, 1, "vps_sub_layer_ordering_info_present_flag"); //for each layer for (i = 0; i < 1; i++) { WRITE_UE(stream, 1, "vps_max_dec_pic_buffering"); WRITE_UE(stream, 0, "vps_num_reorder_pics"); WRITE_UE(stream, 0, "vps_max_latency_increase"); } WRITE_U(stream, 0, 6, "vps_max_nuh_reserved_zero_layer_id"); WRITE_UE(stream, 0, "vps_max_op_sets_minus1"); WRITE_U(stream, 0, 1, "vps_timing_info_present_flag"); //IF timing info //END IF WRITE_U(stream, 0, 1, "vps_extension_flag"); }
static void encoder_state_write_bitstream_scaling_list(encoder_state_t * const state) { const encoder_control_t * const encoder = state->encoder_control; bitstream_t * const stream = &state->stream; uint32_t size_id; for (size_id = 0; size_id < SCALING_LIST_SIZE_NUM; size_id++) { int32_t list_id; for (list_id = 0; list_id < kvz_g_scaling_list_num[size_id]; list_id++) { uint8_t scaling_list_pred_mode_flag = 1; int32_t pred_list_idx; int32_t i; uint32_t ref_matrix_id = UINT32_MAX; for (pred_list_idx = list_id; pred_list_idx >= 0; pred_list_idx--) { const int32_t * const pred_list = (list_id == pred_list_idx) ? kvz_scalinglist_get_default(size_id, pred_list_idx) : encoder->scaling_list.scaling_list_coeff[size_id][pred_list_idx]; if (!memcmp(encoder->scaling_list.scaling_list_coeff[size_id][list_id], pred_list, sizeof(int32_t) * MIN(8, kvz_g_scaling_list_size[size_id])) && ((size_id < SCALING_LIST_16x16) || (encoder->scaling_list.scaling_list_dc[size_id][list_id] == encoder->scaling_list.scaling_list_dc[size_id][pred_list_idx]))) { ref_matrix_id = pred_list_idx; scaling_list_pred_mode_flag = 0; break; } } WRITE_U(stream, scaling_list_pred_mode_flag, 1, "scaling_list_pred_mode_flag" ); if (!scaling_list_pred_mode_flag) { WRITE_UE(stream, list_id - ref_matrix_id, "scaling_list_pred_matrix_id_delta"); } else { int32_t delta; const int32_t coef_num = MIN(MAX_MATRIX_COEF_NUM, kvz_g_scaling_list_size[size_id]); const uint32_t * const scan_cg = (size_id == 0) ? g_sig_last_scan_16x16 : g_sig_last_scan_32x32; int32_t next_coef = 8; const int32_t * const coef_list = encoder->scaling_list.scaling_list_coeff[size_id][list_id]; if (size_id >= SCALING_LIST_16x16) { WRITE_SE(stream, encoder->scaling_list.scaling_list_dc[size_id][list_id] - 8, "scaling_list_dc_coef_minus8"); next_coef = encoder->scaling_list.scaling_list_dc[size_id][list_id]; } for (i = 0; i < coef_num; i++) { delta = coef_list[scan_cg[i]] - next_coef; next_coef = coef_list[scan_cg[i]]; if (delta > 127) delta -= 256; if (delta < -128) delta += 256; WRITE_SE(stream, delta, "scaling_list_delta_coef"); } } } } }
static void encoder_state_write_bitstream_seq_parameter_set(encoder_state_t * const state) { bitstream_t * const stream = &state->stream; const encoder_control_t * encoder = state->encoder_control; #ifdef KVZ_DEBUG printf("=========== Sequence Parameter Set ID: 0 ===========\n"); #endif // TODO: profile IDC and level IDC should be defined later on WRITE_U(stream, 0, 4, "sps_video_parameter_set_id"); WRITE_U(stream, 1, 3, "sps_max_sub_layers_minus1"); WRITE_U(stream, 0, 1, "sps_temporal_id_nesting_flag"); encoder_state_write_bitstream_PTL(state); WRITE_UE(stream, 0, "sps_seq_parameter_set_id"); WRITE_UE(stream, state->encoder_control->in.video_format, "chroma_format_idc"); if (state->encoder_control->in.video_format == 3) { WRITE_U(stream, 0, 1, "separate_colour_plane_flag"); } WRITE_UE(stream, encoder->in.width, "pic_width_in_luma_samples"); WRITE_UE(stream, encoder->in.height, "pic_height_in_luma_samples"); if (encoder->in.width != encoder->in.real_width || encoder->in.height != encoder->in.real_height) { // The standard does not seem to allow setting conf_win values such that // the number of luma samples is not a multiple of 2. Options are to either // hide one line or show an extra line of non-video. Neither seems like a // very good option, so let's not even try. assert(!(encoder->in.width % 2)); WRITE_U(stream, 1, 1, "conformance_window_flag"); WRITE_UE(stream, 0, "conf_win_left_offset"); WRITE_UE(stream, (encoder->in.width - encoder->in.real_width) >> 1, "conf_win_right_offset"); WRITE_UE(stream, 0, "conf_win_top_offset"); WRITE_UE(stream, (encoder->in.height - encoder->in.real_height) >> 1, "conf_win_bottom_offset"); } else {
static void encoder_state_write_bitstream_VUI(encoder_state_t * const state) { bitstream_t * const stream = &state->stream; const encoder_control_t * const encoder = state->encoder_control; #ifdef KVZ_DEBUG printf("=========== VUI Set ID: 0 ===========\n"); #endif if (encoder->vui.sar_width > 0 && encoder->vui.sar_height > 0) { int i; static const struct { uint8_t width; uint8_t height; uint8_t idc; } sar[] = { // aspect_ratio_idc = 0 -> unspecified { 1, 1, 1 }, { 12, 11, 2 }, { 10, 11, 3 }, { 16, 11, 4 }, { 40, 33, 5 }, { 24, 11, 6 }, { 20, 11, 7 }, { 32, 11, 8 }, { 80, 33, 9 }, { 18, 11, 10}, { 15, 11, 11}, { 64, 33, 12}, {160, 99, 13}, { 4, 3, 14}, { 3, 2, 15}, { 2, 1, 16}, // aspect_ratio_idc = [17..254] -> reserved { 0, 0, 255 } }; for (i = 0; sar[i].idc != 255; i++) if (sar[i].width == encoder->vui.sar_width && sar[i].height == encoder->vui.sar_height) break; WRITE_U(stream, 1, 1, "aspect_ratio_info_present_flag"); WRITE_U(stream, sar[i].idc, 8, "aspect_ratio_idc"); if (sar[i].idc == 255) { // EXTENDED_SAR WRITE_U(stream, encoder->vui.sar_width, 16, "sar_width"); WRITE_U(stream, encoder->vui.sar_height, 16, "sar_height"); } } else WRITE_U(stream, 0, 1, "aspect_ratio_info_present_flag"); //IF aspect ratio info //ENDIF if (encoder->vui.overscan > 0) { WRITE_U(stream, 1, 1, "overscan_info_present_flag"); WRITE_U(stream, encoder->vui.overscan - 1, 1, "overscan_appropriate_flag"); } else WRITE_U(stream, 0, 1, "overscan_info_present_flag"); //IF overscan info //ENDIF if (encoder->vui.videoformat != 5 || encoder->vui.fullrange || encoder->vui.colorprim != 2 || encoder->vui.transfer != 2 || encoder->vui.colormatrix != 2) { WRITE_U(stream, 1, 1, "video_signal_type_present_flag"); WRITE_U(stream, encoder->vui.videoformat, 3, "video_format"); WRITE_U(stream, encoder->vui.fullrange, 1, "video_full_range_flag"); if (encoder->vui.colorprim != 2 || encoder->vui.transfer != 2 || encoder->vui.colormatrix != 2) { WRITE_U(stream, 1, 1, "colour_description_present_flag"); WRITE_U(stream, encoder->vui.colorprim, 8, "colour_primaries"); WRITE_U(stream, encoder->vui.transfer, 8, "transfer_characteristics"); WRITE_U(stream, encoder->vui.colormatrix, 8, "matrix_coeffs"); } else WRITE_U(stream, 0, 1, "colour_description_present_flag"); } else WRITE_U(stream, 0, 1, "video_signal_type_present_flag"); //IF video type //ENDIF if (encoder->vui.chroma_loc > 0) { WRITE_U(stream, 1, 1, "chroma_loc_info_present_flag"); WRITE_UE(stream, encoder->vui.chroma_loc, "chroma_sample_loc_type_top_field"); WRITE_UE(stream, encoder->vui.chroma_loc, "chroma_sample_loc_type_bottom_field"); } else WRITE_U(stream, 0, 1, "chroma_loc_info_present_flag"); //IF chroma loc info //ENDIF WRITE_U(stream, 0, 1, "neutral_chroma_indication_flag"); WRITE_U(stream, state->encoder_control->vui.field_seq_flag, 1, "field_seq_flag"); // 0: frames, 1: fields WRITE_U(stream, state->encoder_control->vui.frame_field_info_present_flag, 1, "frame_field_info_present_flag"); WRITE_U(stream, 0, 1, "default_display_window_flag"); //IF default display window //ENDIF WRITE_U(stream, 0, 1, "vui_timing_info_present_flag"); //IF timing info //ENDIF WRITE_U(stream, 0, 1, "bitstream_restriction_flag"); //IF bitstream restriction //ENDIF }