Files
BPI-CM9-Linux/aml-comp/hardware/amlogic/libencoder/multiEnc/amvenc_lib/h264bitstream.c
T

805 lines
29 KiB
C
Raw Normal View History

2026-08-13 11:28:40 +08:00
/*
**
** Copyright 2012 The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#include "h264bitstream.h"
//7.3.2.11 RBSP trailing bits syntax
void read_rbsp_trailing_bits(bs_t* b)
{
/* rbsp_stop_one_bit */ bs_skip_u(b, 1);
while ( !bs_byte_aligned(b) )
{
/* rbsp_alignment_zero_bit */ bs_skip_u(b, 1);
}
}
//7.3.2.11 RBSP trailing bits syntax
void write_rbsp_trailing_bits(bs_t* b)
{
/* rbsp_stop_one_bit */ bs_write_u(b, 1, 1);
while ( !bs_byte_aligned(b) )
{
/* rbsp_alignment_zero_bit */ bs_write_u(b, 1, 0);
}
}
/**
Calculate the log base 2 of the argument, rounded up.
Zero or negative arguments return zero
Idea from http://www.southwindsgames.com/blog/2009/01/19/fast-integer-log2-function-in-cc/
*/
int intlog2(int x)
{
int log = 0;
if (x < 0) { x = 0; }
while ((x >> log) > 0)
{
log++;
}
if (log > 0 && x == 1<<(log-1)) { log--; }
return log;
}
int more_rbsp_data(bs_t* bs)
{
// TODO this version handles reading only. writing version?
// no more data
if (bs_eof(bs)) { return 0; }
// no rbsp_stop_bit yet
if (bs_peek_u1(bs) == 0) { return 1; }
// next bit is 1, is it the rsbp_stop_bit? only if the rest of bits are 0
bs_t bs_tmp;
bs_clone(&bs_tmp, bs);
bs_skip_u1(&bs_tmp);
while (!bs_eof(&bs_tmp))
{
// A later bit was 1, it wasn't the rsbp_stop_bit
if (bs_read_u1(&bs_tmp) == 1) { return 1; }
}
// All following bits were 0, it was the rsbp_stop_bit
return 0;
}
//7.3.2.1.1 Scaling list syntax
void read_scaling_list(bs_t* b, int* scalingList, int sizeOfScalingList, int* useDefaultScalingMatrixFlag )
{
// NOTE need to be able to set useDefaultScalingMatrixFlag when reading, hence passing as pointer
int lastScale = 8;
int nextScale = 8;
int delta_scale;
for ( int j = 0; j < sizeOfScalingList; j++ )
{
if ( nextScale != 0 )
{
if ( 0 )
{
nextScale = scalingList[ j ];
if (useDefaultScalingMatrixFlag[0]) { nextScale = 0; }
delta_scale = (nextScale - lastScale) % 256 ;
}
/*
* Open source code, reserved.
*/
/* coverity[value_overwrite] */
delta_scale = bs_read_se(b);
if ( 1 )
{
nextScale = ( lastScale + delta_scale + 256 ) % 256;
useDefaultScalingMatrixFlag[0] = ( j == 0 && nextScale == 0 );
}
}
if ( 1 )
{
scalingList[ j ] = ( nextScale == 0 ) ? lastScale : nextScale;
}
lastScale = scalingList[ j ];
}
}
//7.3.2.1.1 Scaling list syntax
void write_scaling_list(bs_t* b, int* scalingList, int sizeOfScalingList, int* useDefaultScalingMatrixFlag )
{
// NOTE need to be able to set useDefaultScalingMatrixFlag when reading, hence passing as pointer
int lastScale = 8;
int nextScale = 8;
int delta_scale;
for ( int j = 0; j < sizeOfScalingList; j++ )
{
if ( nextScale != 0 )
{
if ( 1 )
{
nextScale = scalingList[ j ];
if (useDefaultScalingMatrixFlag[0]) { nextScale = 0; }
delta_scale = (nextScale - lastScale) % 256 ;
}
bs_write_se(b, delta_scale);
if ( 0 )
{
nextScale = ( lastScale + delta_scale + 256 ) % 256;
useDefaultScalingMatrixFlag[0] = ( j == 0 && nextScale == 0 );
}
}
if ( 0 )
{
scalingList[ j ] = ( nextScale == 0 ) ? lastScale : nextScale;
}
lastScale = scalingList[ j ];
}
}
//Appendix E.1.2 HRD parameters syntax
void read_hrd_parameters(hrd_t* hrd, bs_t* b)
{
hrd->cpb_cnt_minus1 = bs_read_ue(b);
hrd->bit_rate_scale = bs_read_u(b, 4);
hrd->cpb_size_scale = bs_read_u(b, 4);
for ( int SchedSelIdx = 0; SchedSelIdx <= hrd->cpb_cnt_minus1; SchedSelIdx++ )
{
hrd->bit_rate_value_minus1[ SchedSelIdx ] = bs_read_ue(b);
hrd->cpb_size_value_minus1[ SchedSelIdx ] = bs_read_ue(b);
hrd->cbr_flag[ SchedSelIdx ] = bs_read_u1(b);
}
hrd->initial_cpb_removal_delay_length_minus1 = bs_read_u(b, 5);
hrd->cpb_removal_delay_length_minus1 = bs_read_u(b, 5);
hrd->dpb_output_delay_length_minus1 = bs_read_u(b, 5);
hrd->time_offset_length = bs_read_u(b, 5);
}
//Appendix E.1.2 HRD parameters syntax
void write_hrd_parameters(hrd_t* hrd, bs_t* b)
{
bs_write_ue(b, hrd->cpb_cnt_minus1);
bs_write_u(b, 4, hrd->bit_rate_scale);
bs_write_u(b, 4, hrd->cpb_size_scale);
for ( int SchedSelIdx = 0; SchedSelIdx <= hrd->cpb_cnt_minus1; SchedSelIdx++ )
{
bs_write_ue(b, hrd->bit_rate_value_minus1[ SchedSelIdx ]);
bs_write_ue(b, hrd->cpb_size_value_minus1[ SchedSelIdx ]);
bs_write_u1(b, hrd->cbr_flag[ SchedSelIdx ]);
}
bs_write_u(b, 5, hrd->initial_cpb_removal_delay_length_minus1);
bs_write_u(b, 5, hrd->cpb_removal_delay_length_minus1);
bs_write_u(b, 5, hrd->dpb_output_delay_length_minus1);
bs_write_u(b, 5, hrd->time_offset_length);
}
//Appendix E.1.1 VUI parameters syntax
void read_vui_parameters(sps_t* sps, bs_t* b)
{
sps->vui.aspect_ratio_info_present_flag = bs_read_u1(b);
if ( sps->vui.aspect_ratio_info_present_flag )
{
sps->vui.aspect_ratio_idc = bs_read_u8(b);
if ( sps->vui.aspect_ratio_idc == SAR_Extended )
{
sps->vui.sar_width = bs_read_u(b, 16);
sps->vui.sar_height = bs_read_u(b, 16);
}
}
sps->vui.overscan_info_present_flag = bs_read_u1(b);
if ( sps->vui.overscan_info_present_flag )
{
sps->vui.overscan_appropriate_flag = bs_read_u1(b);
}
sps->vui.video_signal_type_present_flag = bs_read_u1(b);
if ( sps->vui.video_signal_type_present_flag )
{
sps->vui.video_format = bs_read_u(b, 3);
sps->vui.video_full_range_flag = bs_read_u1(b);
sps->vui.colour_description_present_flag = bs_read_u1(b);
if ( sps->vui.colour_description_present_flag )
{
sps->vui.colour_primaries = bs_read_u8(b);
sps->vui.transfer_characteristics = bs_read_u8(b);
sps->vui.matrix_coefficients = bs_read_u8(b);
}
}
sps->vui.chroma_loc_info_present_flag = bs_read_u1(b);
if ( sps->vui.chroma_loc_info_present_flag )
{
sps->vui.chroma_sample_loc_type_top_field = bs_read_ue(b);
sps->vui.chroma_sample_loc_type_bottom_field = bs_read_ue(b);
}
sps->vui.timing_info_present_flag = bs_read_u1(b);
if ( sps->vui.timing_info_present_flag )
{
sps->vui.num_units_in_tick = bs_read_u(b, 32);
sps->vui.time_scale = bs_read_u(b, 32);
sps->vui.fixed_frame_rate_flag = bs_read_u1(b);
}
sps->vui.nal_hrd_parameters_present_flag = bs_read_u1(b);
if ( sps->vui.nal_hrd_parameters_present_flag )
{
read_hrd_parameters(&sps->hrd_nal, b);
}
sps->vui.vcl_hrd_parameters_present_flag = bs_read_u1(b);
if ( sps->vui.vcl_hrd_parameters_present_flag )
{
read_hrd_parameters(&sps->hrd_vcl, b);
}
if ( sps->vui.nal_hrd_parameters_present_flag || sps->vui.vcl_hrd_parameters_present_flag )
{
sps->vui.low_delay_hrd_flag = bs_read_u1(b);
}
sps->vui.pic_struct_present_flag = bs_read_u1(b);
sps->vui.bitstream_restriction_flag = bs_read_u1(b);
if ( sps->vui.bitstream_restriction_flag )
{
sps->vui.motion_vectors_over_pic_boundaries_flag = bs_read_u1(b);
sps->vui.max_bytes_per_pic_denom = bs_read_ue(b);
sps->vui.max_bits_per_mb_denom = bs_read_ue(b);
sps->vui.log2_max_mv_length_horizontal = bs_read_ue(b);
sps->vui.log2_max_mv_length_vertical = bs_read_ue(b);
sps->vui.num_reorder_frames = bs_read_ue(b);
sps->vui.max_dec_frame_buffering = bs_read_ue(b);
}
}
void write_sei_rbsp(bs_t *s, unsigned char *payload, int payload_size)
{
int i;
bs_write_u(s, 1, 0);//forbidden_zero_bit
bs_write_u(s, 2, 0);//nal_ref_idc
bs_write_u(s, 5, 6);//nal_type
bs_write_u(s, 8, 5);//user_sei
bs_write_u(s,8,payload_size);
for (i = 0; i < 16; i++)
bs_write_u(s,8,payload[i]);
for (i = 16; i < payload_size; i++)
bs_write_u(s, 8, payload[i]);
}
//7.3.2.1 Sequence parameter set RBSP syntax
void read_seq_parameter_set_rbsp(sps_t* sps, bs_t* b)
{
int i;
if ( 1 )
{
memset(sps, 0, sizeof(sps_t));
sps->chroma_format_idc = 1;
}
sps->profile_idc = bs_read_u8(b);
sps->constraint_set0_flag = bs_read_u1(b);
sps->constraint_set1_flag = bs_read_u1(b);
sps->constraint_set2_flag = bs_read_u1(b);
sps->constraint_set3_flag = bs_read_u1(b);
sps->constraint_set4_flag = bs_read_u1(b);
sps->constraint_set5_flag = bs_read_u1(b);
/* reserved_zero_2bits */ bs_skip_u(b, 2);
sps->level_idc = bs_read_u8(b);
sps->seq_parameter_set_id = bs_read_ue(b);
if ( sps->profile_idc == 100 || sps->profile_idc == 110 ||
sps->profile_idc == 122 || sps->profile_idc == 244 ||
sps->profile_idc == 44 || sps->profile_idc == 83 ||
sps->profile_idc == 86 || sps->profile_idc == 118 ||
sps->profile_idc == 128 || sps->profile_idc == 138 ||
sps->profile_idc == 139 || sps->profile_idc == 134
)
{
sps->chroma_format_idc = bs_read_ue(b);
if ( sps->chroma_format_idc == 3 )
{
sps->residual_colour_transform_flag = bs_read_u1(b);
}
sps->bit_depth_luma_minus8 = bs_read_ue(b);
sps->bit_depth_chroma_minus8 = bs_read_ue(b);
sps->qpprime_y_zero_transform_bypass_flag = bs_read_u1(b);
sps->seq_scaling_matrix_present_flag = bs_read_u1(b);
if ( sps->seq_scaling_matrix_present_flag )
{
for ( i = 0; i < ((sps->chroma_format_idc != 3) ? 8 : 12); i++ )
{
sps->seq_scaling_list_present_flag[ i ] = bs_read_u1(b);
if ( sps->seq_scaling_list_present_flag[ i ] )
{
if ( i < 6 )
{
read_scaling_list( b, sps->ScalingList4x4[ i ], 16,
&( sps->UseDefaultScalingMatrix4x4Flag[ i ] ) );
}
else
{
read_scaling_list( b, sps->ScalingList8x8[ i - 6 ], 64,
&( sps->UseDefaultScalingMatrix8x8Flag[ i - 6 ] ) );
}
}
}
}
}
sps->log2_max_frame_num_minus4 = bs_read_ue(b);
sps->pic_order_cnt_type = bs_read_ue(b);
if ( sps->pic_order_cnt_type == 0 )
{
sps->log2_max_pic_order_cnt_lsb_minus4 = bs_read_ue(b);
}
else if ( sps->pic_order_cnt_type == 1 )
{
sps->delta_pic_order_always_zero_flag = bs_read_u1(b);
sps->offset_for_non_ref_pic = bs_read_se(b);
sps->offset_for_top_to_bottom_field = bs_read_se(b);
sps->num_ref_frames_in_pic_order_cnt_cycle = bs_read_ue(b);
for ( i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++ )
{
sps->offset_for_ref_frame[ i ] = bs_read_se(b);
}
}
sps->num_ref_frames = bs_read_ue(b);
sps->gaps_in_frame_num_value_allowed_flag = bs_read_u1(b);
sps->pic_width_in_mbs_minus1 = bs_read_ue(b);
sps->pic_height_in_map_units_minus1 = bs_read_ue(b);
sps->frame_mbs_only_flag = bs_read_u1(b);
if ( !sps->frame_mbs_only_flag )
{
sps->mb_adaptive_frame_field_flag = bs_read_u1(b);
}
sps->direct_8x8_inference_flag = bs_read_u1(b);
sps->frame_cropping_flag = bs_read_u1(b);
if ( sps->frame_cropping_flag )
{
sps->frame_crop_left_offset = bs_read_ue(b);
sps->frame_crop_right_offset = bs_read_ue(b);
sps->frame_crop_top_offset = bs_read_ue(b);
sps->frame_crop_bottom_offset = bs_read_ue(b);
}
sps->vui_parameters_present_flag = bs_read_u1(b);
if ( sps->vui_parameters_present_flag )
{
read_vui_parameters(sps, b);
}
}
void read_debug_scaling_list(bs_t* b, int* scalingList, int sizeOfScalingList, int* useDefaultScalingMatrixFlag )
{
// NOTE need to be able to set useDefaultScalingMatrixFlag when reading, hence passing as pointer
int lastScale = 8;
int nextScale = 8;
int delta_scale;
for ( int j = 0; j < sizeOfScalingList; j++ )
{
if ( nextScale != 0 )
{
if ( 0 )
{
nextScale = scalingList[ j ];
if (useDefaultScalingMatrixFlag[0]) { nextScale = 0; }
delta_scale = (nextScale - lastScale) % 256 ;
}
/*
* Open source code, reserved.
*/
/* coverity[value_overwrite] */
delta_scale = bs_read_se(b);
if ( 1 )
{
nextScale = ( lastScale + delta_scale + 256 ) % 256;
useDefaultScalingMatrixFlag[0] = ( j == 0 && nextScale == 0 );
}
}
if ( 1 )
{
scalingList[ j ] = ( nextScale == 0 ) ? lastScale : nextScale;
}
lastScale = scalingList[ j ];
}
}
//7.3.2.2 Picture parameter set RBSP syntax
void read_pic_parameter_set_rbsp(pps_t* pps, bs_t* b)
{
// pps_t* pps = h->pps;
if ( 1 )
{
memset(pps, 0, sizeof(pps_t));
}
pps->pic_parameter_set_id = bs_read_ue(b);
pps->seq_parameter_set_id = bs_read_ue(b);
pps->entropy_coding_mode_flag = bs_read_u1(b);
pps->pic_order_present_flag = bs_read_u1(b);
pps->num_slice_groups_minus1 = bs_read_ue(b);
if ( pps->num_slice_groups_minus1 > 0 )
{
pps->slice_group_map_type = bs_read_ue(b);
// printf("%ld.%d: ", (long int)(b->p - b->start), b->bits_left); pps->slice_group_map_type = bs_read_ue(b); printf("pps->slice_group_map_type: %d \n", pps->slice_group_map_type);
if ( pps->slice_group_map_type == 0 )
{
for ( int i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++ )
{
pps->run_length_minus1[ i_group ] = bs_read_ue(b);
//printf("%ld.%d: ", (long int)(b->p - b->start), b->bits_left); pps->run_length_minus1[ i_group ] = bs_read_ue(b); printf("pps->run_length_minus1[ i_group ]: %d \n", pps->run_length_minus1[ i_group ]);
}
}
else if ( pps->slice_group_map_type == 2 )
{
for ( int i_group = 0; i_group < pps->num_slice_groups_minus1; i_group++ )
{
pps->top_left[ i_group ] = bs_read_ue(b);
pps->bottom_right[ i_group ] = bs_read_ue(b);
//printf("%ld.%d: ", (long int)(b->p - b->start), b->bits_left); pps->top_left[ i_group ] = bs_read_ue(b); printf("pps->top_left[ i_group ]: %d \n", pps->top_left[ i_group ]);
//printf("%ld.%d: ", (long int)(b->p - b->start), b->bits_left); pps->bottom_right[ i_group ] = bs_read_ue(b); printf("pps->bottom_right[ i_group ]: %d \n", pps->bottom_right[ i_group ]);
}
}
else if ( pps->slice_group_map_type == 3 ||
pps->slice_group_map_type == 4 ||
pps->slice_group_map_type == 5 )
{
pps->slice_group_change_direction_flag = bs_read_u1(b);
pps->slice_group_change_rate_minus1 = bs_read_ue(b);
//printf("%ld.%d: ", (long int)(b->p - b->start), b->bits_left); pps->slice_group_change_direction_flag = bs_read_u1(b); printf("pps->slice_group_change_direction_flag: %d \n", pps->slice_group_change_direction_flag);
//printf("%ld.%d: ", (long int)(b->p - b->start), b->bits_left); pps->slice_group_change_rate_minus1 = bs_read_ue(b); printf("pps->slice_group_change_rate_minus1: %d \n", pps->slice_group_change_rate_minus1);
}
else if ( pps->slice_group_map_type == 6 )
{
pps->pic_size_in_map_units_minus1 = bs_read_ue(b);
//printf("%ld.%d: ", (long int)(b->p - b->start), b->bits_left); pps->pic_size_in_map_units_minus1 = bs_read_ue(b); printf("pps->pic_size_in_map_units_minus1: %d \n", pps->pic_size_in_map_units_minus1);
for ( int i = 0; i <= pps->pic_size_in_map_units_minus1; i++ )
{
int v = intlog2( pps->num_slice_groups_minus1 + 1 );
pps->slice_group_id[ i ] = bs_read_u(b, v);
//int v = intlog2( pps->num_slice_groups_minus1 + 1 );
//printf("%ld.%d: ", (long int)(b->p - b->start), b->bits_left); pps->slice_group_id[ i ] = bs_read_u(b, v); printf("pps->slice_group_id[ i ]: %d \n", pps->slice_group_id[ i ]);
}
}
}
pps->num_ref_idx_l0_active_minus1 = bs_read_ue(b);
pps->num_ref_idx_l1_active_minus1 = bs_read_ue(b);
pps->weighted_pred_flag = bs_read_u1(b);
pps->weighted_bipred_idc = bs_read_u(b, 2);
pps->pic_init_qp_minus26 = bs_read_se(b);
pps->pic_init_qs_minus26 = bs_read_se(b);
pps->chroma_qp_index_offset = bs_read_se(b);
pps->deblocking_filter_control_present_flag = bs_read_u1(b);
pps->constrained_intra_pred_flag = bs_read_u1(b);
pps->redundant_pic_cnt_present_flag = bs_read_u1(b);
int have_more_data = 0;
if ( 1 ) { have_more_data = more_rbsp_data(b); }
if ( 0 )
{
have_more_data = pps->transform_8x8_mode_flag | pps->pic_scaling_matrix_present_flag | pps->second_chroma_qp_index_offset != 0;
}
if ( have_more_data )
{
pps->transform_8x8_mode_flag = bs_read_u1(b);
pps->pic_scaling_matrix_present_flag = bs_read_u1(b);
if ( pps->pic_scaling_matrix_present_flag )
{
for ( int i = 0; i < 6 + 2* pps->transform_8x8_mode_flag; i++ )
{
pps->pic_scaling_list_present_flag[ i ] = bs_read_u1(b);
//printf("%ld.%d: ", (long int)(b->p - b->start), b->bits_left); pps->pic_scaling_list_present_flag[ i ] = bs_read_u1(b); printf("pps->pic_scaling_list_present_flag[ i ]: %d \n", pps->pic_scaling_list_present_flag[ i ]);
if ( pps->pic_scaling_list_present_flag[ i ] )
{
if ( i < 6 )
{
read_debug_scaling_list( b, pps->ScalingList4x4[ i ], 16,
&( pps->UseDefaultScalingMatrix4x4Flag[ i ] ) );
}
else
{
read_debug_scaling_list( b, pps->ScalingList8x8[ i - 6 ], 64,
&( pps->UseDefaultScalingMatrix8x8Flag[ i - 6 ] ) );
}
}
}
}
pps->second_chroma_qp_index_offset = bs_read_se(b);
}
}
//7.3.2.2 Picture parameter set RBSP syntax
void write_pic_parameter_set_rbsp(pps_t* pps, bs_t* b)
{
//pps_t* pps = h->pps;
if ( 0 )
{
memset(pps, 0, sizeof(pps_t));
}
bs_write_ue(b, pps->pic_parameter_set_id);
bs_write_ue(b, pps->seq_parameter_set_id);
bs_write_u1(b, pps->entropy_coding_mode_flag);
bs_write_u1(b, pps->pic_order_present_flag);
bs_write_ue(b, pps->num_slice_groups_minus1);
if ( pps->num_slice_groups_minus1 > 0 )
{
bs_write_ue(b, pps->slice_group_map_type);
if ( pps->slice_group_map_type == 0 )
{
for ( int i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++ )
{
bs_write_ue(b, pps->run_length_minus1[ i_group ]);
}
}
else if ( pps->slice_group_map_type == 2 )
{
for ( int i_group = 0; i_group < pps->num_slice_groups_minus1; i_group++ )
{
bs_write_ue(b, pps->top_left[ i_group ]);
bs_write_ue(b, pps->bottom_right[ i_group ]);
}
}
else if ( pps->slice_group_map_type == 3 ||
pps->slice_group_map_type == 4 ||
pps->slice_group_map_type == 5 )
{
bs_write_u1(b, pps->slice_group_change_direction_flag);
bs_write_ue(b, pps->slice_group_change_rate_minus1);
}
else if ( pps->slice_group_map_type == 6 )
{
bs_write_ue(b, pps->pic_size_in_map_units_minus1);
for ( int i = 0; i <= pps->pic_size_in_map_units_minus1; i++ )
{
int v = intlog2( pps->num_slice_groups_minus1 + 1 );
bs_write_u(b, v, pps->slice_group_id[ i ]);
}
}
}
bs_write_ue(b, pps->num_ref_idx_l0_active_minus1);
bs_write_ue(b, pps->num_ref_idx_l1_active_minus1);
bs_write_u1(b, pps->weighted_pred_flag);
bs_write_u(b, 2, pps->weighted_bipred_idc);
bs_write_se(b, pps->pic_init_qp_minus26);
bs_write_se(b, pps->pic_init_qs_minus26);
bs_write_se(b, pps->chroma_qp_index_offset);
bs_write_u1(b, pps->deblocking_filter_control_present_flag);
bs_write_u1(b, pps->constrained_intra_pred_flag);
bs_write_u1(b, pps->redundant_pic_cnt_present_flag);
int have_more_data = 0;
if ( 0 ) { have_more_data = more_rbsp_data(b); }
if ( 1 )
{
have_more_data = pps->transform_8x8_mode_flag | pps->pic_scaling_matrix_present_flag | pps->second_chroma_qp_index_offset != 0;
}
if ( have_more_data )
{
bs_write_u1(b, pps->transform_8x8_mode_flag);
bs_write_u1(b, pps->pic_scaling_matrix_present_flag);
if ( pps->pic_scaling_matrix_present_flag )
{
for ( int i = 0; i < 6 + 2* pps->transform_8x8_mode_flag; i++ )
{
bs_write_u1(b, pps->pic_scaling_list_present_flag[ i ]);
if ( pps->pic_scaling_list_present_flag[ i ] )
{
if ( i < 6 )
{
write_scaling_list( b, pps->ScalingList4x4[ i ], 16,
&( pps->UseDefaultScalingMatrix4x4Flag[ i ] ) );
}
else
{
write_scaling_list( b, pps->ScalingList8x8[ i - 6 ], 64,
&( pps->UseDefaultScalingMatrix8x8Flag[ i - 6 ] ) );
}
}
}
}
bs_write_se(b, pps->second_chroma_qp_index_offset);
}
}
//Appendix E.1.1 VUI parameters syntax
void write_vui_parameters(sps_t* sps, bs_t* b)
{
bs_write_u1(b, sps->vui.aspect_ratio_info_present_flag);
if ( sps->vui.aspect_ratio_info_present_flag )
{
bs_write_u8(b, sps->vui.aspect_ratio_idc);
if ( sps->vui.aspect_ratio_idc == SAR_Extended )
{
bs_write_u(b, 16, sps->vui.sar_width);
bs_write_u(b, 16, sps->vui.sar_height);
}
}
bs_write_u1(b, sps->vui.overscan_info_present_flag);
if ( sps->vui.overscan_info_present_flag )
{
bs_write_u1(b, sps->vui.overscan_appropriate_flag);
}
bs_write_u1(b, sps->vui.video_signal_type_present_flag);
if ( sps->vui.video_signal_type_present_flag )
{
bs_write_u(b, 3, sps->vui.video_format);
bs_write_u1(b, sps->vui.video_full_range_flag);
bs_write_u1(b, sps->vui.colour_description_present_flag);
if ( sps->vui.colour_description_present_flag )
{
bs_write_u8(b, sps->vui.colour_primaries);
bs_write_u8(b, sps->vui.transfer_characteristics);
bs_write_u8(b, sps->vui.matrix_coefficients);
}
}
bs_write_u1(b, sps->vui.chroma_loc_info_present_flag);
if ( sps->vui.chroma_loc_info_present_flag )
{
bs_write_ue(b, sps->vui.chroma_sample_loc_type_top_field);
bs_write_ue(b, sps->vui.chroma_sample_loc_type_bottom_field);
}
bs_write_u1(b, sps->vui.timing_info_present_flag);
if ( sps->vui.timing_info_present_flag )
{
bs_write_u(b, 32, sps->vui.num_units_in_tick);
bs_write_u(b, 32, sps->vui.time_scale);
bs_write_u1(b, sps->vui.fixed_frame_rate_flag);
}
bs_write_u1(b, sps->vui.nal_hrd_parameters_present_flag);
if ( sps->vui.nal_hrd_parameters_present_flag )
{
write_hrd_parameters(&sps->hrd_nal, b);
}
bs_write_u1(b, sps->vui.vcl_hrd_parameters_present_flag);
if ( sps->vui.vcl_hrd_parameters_present_flag )
{
write_hrd_parameters(&sps->hrd_vcl, b);
}
if ( sps->vui.nal_hrd_parameters_present_flag || sps->vui.vcl_hrd_parameters_present_flag )
{
bs_write_u1(b, sps->vui.low_delay_hrd_flag);
}
bs_write_u1(b, sps->vui.pic_struct_present_flag);
bs_write_u1(b, sps->vui.bitstream_restriction_flag);
if ( sps->vui.bitstream_restriction_flag )
{
bs_write_u1(b, sps->vui.motion_vectors_over_pic_boundaries_flag);
bs_write_ue(b, sps->vui.max_bytes_per_pic_denom);
bs_write_ue(b, sps->vui.max_bits_per_mb_denom);
bs_write_ue(b, sps->vui.log2_max_mv_length_horizontal);
bs_write_ue(b, sps->vui.log2_max_mv_length_vertical);
bs_write_ue(b, sps->vui.num_reorder_frames);
bs_write_ue(b, sps->vui.max_dec_frame_buffering);
}
}
//7.3.2.1 Sequence parameter set RBSP syntax
void write_seq_parameter_set_rbsp(sps_t* sps, bs_t* b)
{
int i;
if ( 0 )
{
memset(sps, 0, sizeof(sps_t));
sps->chroma_format_idc = 1;
}
bs_write_u8(b, sps->profile_idc);
bs_write_u1(b, sps->constraint_set0_flag);
bs_write_u1(b, sps->constraint_set1_flag);
bs_write_u1(b, sps->constraint_set2_flag);
bs_write_u1(b, sps->constraint_set3_flag);
bs_write_u1(b, sps->constraint_set4_flag);
bs_write_u1(b, sps->constraint_set5_flag);
/* reserved_zero_2bits */ bs_write_u(b, 2, 0);
bs_write_u8(b, sps->level_idc);
bs_write_ue(b, sps->seq_parameter_set_id);
if ( sps->profile_idc == 100 || sps->profile_idc == 110 ||
sps->profile_idc == 122 || sps->profile_idc == 244 ||
sps->profile_idc == 44 || sps->profile_idc == 83 ||
sps->profile_idc == 86 || sps->profile_idc == 118 ||
sps->profile_idc == 128 || sps->profile_idc == 138 ||
sps->profile_idc == 139 || sps->profile_idc == 134
)
{
bs_write_ue(b, sps->chroma_format_idc);
if ( sps->chroma_format_idc == 3 )
{
bs_write_u1(b, sps->residual_colour_transform_flag);
}
bs_write_ue(b, sps->bit_depth_luma_minus8);
bs_write_ue(b, sps->bit_depth_chroma_minus8);
bs_write_u1(b, sps->qpprime_y_zero_transform_bypass_flag);
bs_write_u1(b, sps->seq_scaling_matrix_present_flag);
if ( sps->seq_scaling_matrix_present_flag )
{
for ( i = 0; i < 8; i++ )
{
bs_write_u1(b, sps->seq_scaling_list_present_flag[ i ]);
if ( sps->seq_scaling_list_present_flag[ i ] )
{
if ( i < 6 )
{
write_scaling_list( b, sps->ScalingList4x4[ i ], 16,
&( sps->UseDefaultScalingMatrix4x4Flag[ i ] ) );
}
else
{
write_scaling_list( b, sps->ScalingList8x8[ i - 6 ], 64,
&( sps->UseDefaultScalingMatrix8x8Flag[ i - 6 ] ) );
}
}
}
}
}
bs_write_ue(b, sps->log2_max_frame_num_minus4);
bs_write_ue(b, sps->pic_order_cnt_type);
if ( sps->pic_order_cnt_type == 0 )
{
bs_write_ue(b, sps->log2_max_pic_order_cnt_lsb_minus4);
}
else if ( sps->pic_order_cnt_type == 1 )
{
bs_write_u1(b, sps->delta_pic_order_always_zero_flag);
bs_write_se(b, sps->offset_for_non_ref_pic);
bs_write_se(b, sps->offset_for_top_to_bottom_field);
bs_write_ue(b, sps->num_ref_frames_in_pic_order_cnt_cycle);
for ( i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++ )
{
bs_write_se(b, sps->offset_for_ref_frame[ i ]);
}
}
bs_write_ue(b, sps->num_ref_frames);
bs_write_u1(b, sps->gaps_in_frame_num_value_allowed_flag);
bs_write_ue(b, sps->pic_width_in_mbs_minus1);
bs_write_ue(b, sps->pic_height_in_map_units_minus1);
bs_write_u1(b, sps->frame_mbs_only_flag);
if ( !sps->frame_mbs_only_flag )
{
bs_write_u1(b, sps->mb_adaptive_frame_field_flag);
}
bs_write_u1(b, sps->direct_8x8_inference_flag);
bs_write_u1(b, sps->frame_cropping_flag);
if ( sps->frame_cropping_flag )
{
bs_write_ue(b, sps->frame_crop_left_offset);
bs_write_ue(b, sps->frame_crop_right_offset);
bs_write_ue(b, sps->frame_crop_top_offset);
bs_write_ue(b, sps->frame_crop_bottom_offset);
}
bs_write_u1(b, sps->vui_parameters_present_flag);
if ( sps->vui_parameters_present_flag )
{
write_vui_parameters(sps, b);
}
}