/****************************************************************************** * * Copyright (C) 2015 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. * ***************************************************************************** * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore */ /** ******************************************************************************* * @file * ih264e_encode_header.c * * @brief * This file contains function definitions related to header encoding. * * @author * ittiam * * @par List of Functions: * - ih264e_generate_nal_unit_header() * - ih264e_generate_sps() * - ih264e_generate_pps() * - ih264e_generate_slice_header() * - ih264e_get_level() * - ih264e_populate_sps() * - ih264e_populate_pps() * - ih264e_populate_slice_header() * - ih264e_add_filler_nal_unit() * * @remarks * None * ******************************************************************************* */ /*****************************************************************************/ /* File Includes */ /*****************************************************************************/ /* System include files */ #include <stdio.h> #include <stddef.h> #include <stdlib.h> #include <string.h> #include <assert.h> /* User Include Files */ #include "ih264_typedefs.h" #include "iv2.h" #include "ive2.h" #include "ih264e.h" #include "ithread.h" #include "ih264e_config.h" #include "ih264e_trace.h" #include "ih264e_error.h" #include "ih264e_bitstream.h" #include "ih264_debug.h" #include "ih264_defs.h" #include "ime_distortion_metrics.h" #include "ime_defs.h" #include "ime_structs.h" #include "ih264_error.h" #include "ih264_structs.h" #include "ih264_trans_quant_itrans_iquant.h" #include "ih264_inter_pred_filters.h" #include "ih264_mem_fns.h" #include "ih264_padding.h" #include "ih264_intra_pred_filters.h" #include "ih264_deblk_edge_filters.h" #include "ih264_cabac_tables.h" #include "ih264e_defs.h" #include "irc_cntrl_param.h" #include "irc_frame_info_collector.h" #include "ih264e_rate_control.h" #include "ih264e_cabac_structs.h" #include "ih264e_structs.h" #include "ih264e_encode_header.h" #include "ih264_common_tables.h" #include "ih264_macros.h" #include "ih264e_utils.h" /*****************************************************************************/ /* Function Definitions */ /*****************************************************************************/ /** ****************************************************************************** * * @brief Generate nal unit header in the stream as per section 7.4.1 * * @par Description * Inserts Nal unit header syntax as per section 7.4.1 * * @param[inout] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] nal_unit_type * nal type to be inserted * * @param[in] nal_ref_idc * nal ref idc to be inserted * * @return success or failure error code * ****************************************************************************** */ static WORD32 ih264e_generate_nal_unit_header(bitstrm_t *ps_bitstrm, WORD32 nal_unit_type, WORD32 nal_ref_idc) { WORD32 return_status = IH264E_SUCCESS; /* sanity checks */ ASSERT((nal_unit_type > 0) && (nal_unit_type < 32)); /* forbidden_zero_bit + nal_ref_idc + nal_unit_type */ PUT_BITS(ps_bitstrm, ((nal_ref_idc << 5) + nal_unit_type), (1+2+5), /*1 forbidden zero bit + 2 nal_ref_idc + 5 nal_unit_type */ return_status, "nal_unit_header"); return(return_status); } /** ****************************************************************************** * * @brief Generates VUI (Video usability information) * * @par Description * This function generates VUI header as per the spec * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] ps_vui * pointer to structure containing VUI data * * @return success or failure error code * ****************************************************************************** */ WORD32 ih264e_generate_vui(bitstrm_t *ps_bitstrm, vui_t *ps_vui) { WORD32 return_status = IH264E_SUCCESS; /* aspect_ratio_info_present_flag */ PUT_BITS(ps_bitstrm, ps_vui->u1_aspect_ratio_info_present_flag, 1, return_status, "aspect_ratio_info_present_flag"); if(ps_vui->u1_aspect_ratio_info_present_flag) { /* aspect_ratio_idc */ PUT_BITS(ps_bitstrm, ps_vui->u1_aspect_ratio_idc, 8, return_status, "aspect_ratio_idc"); if(255 == ps_vui->u1_aspect_ratio_idc) /* Extended_SAR */ { /* sar_width */ PUT_BITS(ps_bitstrm, ps_vui->u2_sar_width, 16, return_status, "sar_width"); /* sar_height */ PUT_BITS(ps_bitstrm, ps_vui->u2_sar_height, 16, return_status, "sar_height"); } } /* overscan_info_present_flag */ PUT_BITS(ps_bitstrm, ps_vui->u1_overscan_info_present_flag, 1, return_status, "overscan_info_present_flag"); if(ps_vui->u1_overscan_info_present_flag) { /* overscan_appropriate_flag */ PUT_BITS(ps_bitstrm, ps_vui->u1_overscan_appropriate_flag, 1, return_status, "overscan_appropriate_flag"); } /* video_signal_type_present_flag */ PUT_BITS(ps_bitstrm, ps_vui->u1_video_signal_type_present_flag, 1, return_status, "video_signal_type_present_flag"); if(ps_vui->u1_video_signal_type_present_flag) { /* video_format */ PUT_BITS(ps_bitstrm, ps_vui->u1_video_format, 3, return_status, "video_format"); /* video_full_range_flag */ PUT_BITS(ps_bitstrm, ps_vui->u1_video_full_range_flag, 1, return_status, "video_full_range_flag"); /* colour_description_present_flag */ PUT_BITS(ps_bitstrm, ps_vui->u1_colour_description_present_flag, 1, return_status, "colour_description_present_flag"); if(ps_vui->u1_colour_description_present_flag) { /* colour_primaries */ PUT_BITS(ps_bitstrm, ps_vui->u1_colour_primaries, 8, return_status, "colour_primaries"); /* transfer_characteristics */ PUT_BITS(ps_bitstrm, ps_vui->u1_transfer_characteristics, 8, return_status, "transfer_characteristics"); /* matrix_coefficients */ PUT_BITS(ps_bitstrm, ps_vui->u1_matrix_coefficients, 8, return_status, "matrix_coefficients"); } } /* chroma_loc_info_present_flag */ PUT_BITS(ps_bitstrm, ps_vui->u1_chroma_loc_info_present_flag, 1, return_status, "chroma_loc_info_present_flag"); if(ps_vui->u1_chroma_loc_info_present_flag) { /* chroma_sample_loc_type_top_field */ PUT_BITS_UEV(ps_bitstrm, ps_vui->u1_chroma_sample_loc_type_top_field, return_status, "chroma_sample_loc_type_top_field"); /* chroma_sample_loc_type_bottom_field */ PUT_BITS_UEV(ps_bitstrm, ps_vui->u1_chroma_sample_loc_type_bottom_field, return_status, "chroma_sample_loc_type_bottom_field"); } /* timing_info_present_flag */ PUT_BITS(ps_bitstrm, ps_vui->u1_vui_timing_info_present_flag, 1, return_status, "timing_info_present_flag"); if(ps_vui->u1_vui_timing_info_present_flag) { /* num_units_in_tick */ PUT_BITS(ps_bitstrm, ps_vui->u4_vui_num_units_in_tick, 32, return_status, "num_units_in_tick"); /* time_scale */ PUT_BITS(ps_bitstrm, ps_vui->u4_vui_time_scale, 32, return_status, "time_scale"); /* fixed_frame_rate_flag */ PUT_BITS(ps_bitstrm, ps_vui->u1_fixed_frame_rate_flag, 1, return_status, "fixed_frame_rate_flag"); } /* nal_hrd_parameters_present_flag */ PUT_BITS(ps_bitstrm, ps_vui->u1_nal_hrd_parameters_present_flag, 1, return_status, "nal_hrd_parameters_present_flag"); if(ps_vui->u1_nal_hrd_parameters_present_flag) { hrd_params_t * ps_hrd_params = &ps_vui->s_nal_hrd_parameters; WORD32 i; /* cpb_cnt_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_hrd_params->u1_cpb_cnt_minus1, return_status, "cpb_cnt_minus1"); /* bit_rate_scale */ PUT_BITS(ps_bitstrm, ps_hrd_params->u4_bit_rate_scale, 4, return_status, "bit_rate_scale"); /* cpb_size_scale */ PUT_BITS(ps_bitstrm, ps_hrd_params->u4_cpb_size_scale, 4, return_status, "cpb_size_scale"); for(i = 0; i < ps_hrd_params->u1_cpb_cnt_minus1; i++) { /* bit_rate_value_minus1[SchedSelIdx] */ PUT_BITS_UEV(ps_bitstrm, ps_hrd_params->au4_bit_rate_value_minus1[i], return_status, "bit_rate_value_minus1[SchedSelIdx]"); /* cpb_size_value_minus1[SchedSelIdx] */ PUT_BITS_UEV(ps_bitstrm, ps_hrd_params->au4_cpb_size_value_minus1[i], return_status, "cpb_size_value_minus1[SchedSelIdx]"); /* cbr_flag[SchedSelIdx] */ PUT_BITS(ps_bitstrm, ps_hrd_params->au1_cbr_flag[i], 1, return_status, "cbr_flag[SchedSelIdx]"); } /* initial_cpb_removal_delay_length_minus1 */ PUT_BITS(ps_bitstrm, ps_hrd_params->u1_initial_cpb_removal_delay_length_minus1, 5, return_status, "initial_cpb_removal_delay_length_minus1"); /* cpb_removal_delay_length_minus1 */ PUT_BITS(ps_bitstrm, ps_hrd_params->u1_cpb_removal_delay_length_minus1, 5, return_status, "cpb_removal_delay_length_minus1"); /* dpb_output_delay_length_minus1 */ PUT_BITS(ps_bitstrm, ps_hrd_params->u1_dpb_output_delay_length_minus1, 5, return_status, "dpb_output_delay_length_minus1"); /* time_offset_length */ PUT_BITS(ps_bitstrm, ps_hrd_params->u1_time_offset_length, 5, return_status, "time_offset_length"); } /* vcl_hrd_parameters_present_flag */ PUT_BITS(ps_bitstrm, ps_vui->u1_vcl_hrd_parameters_present_flag, 1, return_status, "vcl_hrd_parameters_present_flag"); if(ps_vui->u1_vcl_hrd_parameters_present_flag) { hrd_params_t * ps_hrd_params = &ps_vui->s_vcl_hrd_parameters; WORD32 i; /* cpb_cnt_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_hrd_params->u1_cpb_cnt_minus1, return_status, "cpb_cnt_minus1"); /* bit_rate_scale */ PUT_BITS(ps_bitstrm, ps_hrd_params->u4_bit_rate_scale, 4, return_status, "bit_rate_scale"); /* cpb_size_scale */ PUT_BITS(ps_bitstrm, ps_hrd_params->u4_cpb_size_scale, 4, return_status, "cpb_size_scale"); for(i = 0; i < ps_hrd_params->u1_cpb_cnt_minus1; i++) { /* bit_rate_value_minus1[SchedSelIdx] */ PUT_BITS_UEV(ps_bitstrm, ps_hrd_params->au4_bit_rate_value_minus1[i], return_status, "bit_rate_value_minus1[SchedSelIdx]"); /* cpb_size_value_minus1[SchedSelIdx] */ PUT_BITS_UEV(ps_bitstrm, ps_hrd_params->au4_cpb_size_value_minus1[i], return_status, "cpb_size_value_minus1[SchedSelIdx]"); /* cbr_flag[SchedSelIdx] */ PUT_BITS(ps_bitstrm, ps_hrd_params->au1_cbr_flag[i], 1, return_status, "cbr_flag[SchedSelIdx]"); } /* initial_cpb_removal_delay_length_minus1 */ PUT_BITS(ps_bitstrm, ps_hrd_params->u1_initial_cpb_removal_delay_length_minus1, 5, return_status, "initial_cpb_removal_delay_length_minus1"); /* cpb_removal_delay_length_minus1 */ PUT_BITS(ps_bitstrm, ps_hrd_params->u1_cpb_removal_delay_length_minus1, 5, return_status, "cpb_removal_delay_length_minus1"); /* dpb_output_delay_length_minus1 */ PUT_BITS(ps_bitstrm, ps_hrd_params->u1_dpb_output_delay_length_minus1, 5, return_status, "dpb_output_delay_length_minus1"); /* time_offset_length */ PUT_BITS(ps_bitstrm, ps_hrd_params->u1_time_offset_length, 5, return_status, "time_offset_length"); } if(ps_vui->u1_nal_hrd_parameters_present_flag || ps_vui->u1_vcl_hrd_parameters_present_flag) { /* low_delay_hrd_flag */ PUT_BITS(ps_bitstrm, ps_vui->u1_low_delay_hrd_flag, 1, return_status, "low_delay_hrd_flag"); } /* pic_struct_present_flag */ PUT_BITS(ps_bitstrm, ps_vui->u1_pic_struct_present_flag, 1, return_status, "pic_struct_present_flag"); /* bitstream_restriction_flag */ PUT_BITS(ps_bitstrm, ps_vui->u1_bitstream_restriction_flag, 1, return_status, "bitstream_restriction_flag"); if(ps_vui->u1_bitstream_restriction_flag == 1) { /* motion_vectors_over_pic_boundaries_flag */ PUT_BITS(ps_bitstrm, ps_vui->u1_motion_vectors_over_pic_boundaries_flag, 1, return_status, "motion_vectors_over_pic_boundaries_flag"); /* max_bytes_per_pic_denom */ PUT_BITS_UEV(ps_bitstrm, ps_vui->u1_max_bytes_per_pic_denom, return_status, "max_bytes_per_pic_denom"); /* max_bits_per_mb_denom */ PUT_BITS_UEV(ps_bitstrm, ps_vui->u1_max_bits_per_mb_denom, return_status, "max_bits_per_mb_denom"); /* log2_max_mv_length_horizontal */ PUT_BITS_UEV(ps_bitstrm, ps_vui->u1_log2_max_mv_length_horizontal, return_status, "log2_max_mv_length_horizontal"); /* log2_max_mv_length_vertical */ PUT_BITS_UEV(ps_bitstrm, ps_vui->u1_log2_max_mv_length_vertical, return_status, "log2_max_mv_length_vertical"); /* max_num_reorder_frames */ PUT_BITS_UEV(ps_bitstrm, ps_vui->u1_num_reorder_frames, return_status, "max_num_reorder_frames"); /* max_dec_frame_buffering */ PUT_BITS_UEV(ps_bitstrm, ps_vui->u1_max_dec_frame_buffering, return_status, "max_dec_frame_buffering"); } return return_status; } /** ****************************************************************************** * * @brief Generates SPS (Sequence Parameter Set) * * @par Description * This function generates Sequence Parameter Set header as per the spec * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] ps_sps * pointer to structure containing SPS data * * @param[in] ps_vui * pointer to structure containing VUI data * * @return success or failure error code * ****************************************************************************** */ WORD32 ih264e_generate_sps(bitstrm_t *ps_bitstrm, sps_t *ps_sps, vui_t *ps_vui) { WORD32 return_status = IH264E_SUCCESS; WORD32 i; WORD8 i1_nal_unit_type = 7; WORD8 i1_nal_ref_idc = 3; /* Insert Start Code */ return_status |= ih264e_put_nal_start_code_prefix(ps_bitstrm, 1); /* Insert Nal Unit Header */ return_status |= ih264e_generate_nal_unit_header(ps_bitstrm, i1_nal_unit_type, i1_nal_ref_idc); /* profile_idc */ PUT_BITS(ps_bitstrm, ps_sps->u1_profile_idc, 8, return_status, "profile_idc"); /* constrained_set_flags */ PUT_BITS(ps_bitstrm, ps_sps->u1_constraint_set0_flag, 1, return_status, "constrained_set0_flag"); PUT_BITS(ps_bitstrm, ps_sps->u1_constraint_set1_flag, 1, return_status, "constrained_set1_flag"); PUT_BITS(ps_bitstrm, ps_sps->u1_constraint_set2_flag, 1, return_status, "constrained_set2_flag"); PUT_BITS(ps_bitstrm, ps_sps->u1_constraint_set3_flag, 1, return_status, "constrained_set3_flag"); /* reserved_zero_four_bits */ PUT_BITS(ps_bitstrm, 0, 4, return_status, "reserved_zero_four_bits"); /* level_idc */ PUT_BITS(ps_bitstrm, ps_sps->u1_level_idc, 8, return_status, "level_idc"); /* seq_parameter_set_id */ PUT_BITS_UEV(ps_bitstrm, ps_sps->u1_sps_id, return_status, "seq_parameter_set_id"); if (ps_sps->u1_profile_idc >= IH264_PROFILE_HIGH) { /* chroma_format_idc */ PUT_BITS_UEV(ps_bitstrm, ps_sps->u1_chroma_format_idc, return_status, "chroma_format_idc"); if (ps_sps->u1_chroma_format_idc == CHROMA_FMT_IDC_YUV444) { /* i1_residual_colour_transform_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_residual_colour_transform_flag, 1, return_status, "i1_residual_colour_transform_flag"); } /* bit_depth_luma_minus8 */ PUT_BITS_UEV(ps_bitstrm, (ps_sps->i1_bit_depth_luma - 8), return_status, "bit_depth_luma_minus8"); /* bit_depth_chroma_minus8 */ PUT_BITS_UEV(ps_bitstrm, (ps_sps->i1_bit_depth_chroma - 8), return_status, "bit_depth_chroma_minus8"); /* qpprime_y_zero_transform_bypass_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_qpprime_y_zero_transform_bypass_flag, 1, return_status, "qpprime_y_zero_transform_bypass_flag"); /* seq_scaling_matrix_present_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_seq_scaling_matrix_present_flag, 1, return_status, "seq_scaling_matrix_present_flag"); /* seq_scaling_list */ if (ps_sps->i1_seq_scaling_matrix_present_flag) { /* TODO_LATER: Will be enabled once scaling list support is added */ } } /* log2_max_frame_num_minus4 */ PUT_BITS_UEV(ps_bitstrm, (ps_sps->i1_log2_max_frame_num - 4), return_status, "log2_max_frame_num_minus4"); /* pic_order_cnt_type */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i1_pic_order_cnt_type, return_status, "pic_order_cnt_type"); if (ps_sps->i1_pic_order_cnt_type == 0) { /* log2_max_pic_order_cnt_lsb_minus4 */ PUT_BITS_UEV(ps_bitstrm, (ps_sps->i1_log2_max_pic_order_cnt_lsb - 4), return_status, "log2_max_pic_order_cnt_lsb_minus4"); } else if (ps_sps->i1_pic_order_cnt_type == 1) { /* delta_pic_order_always_zero_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_delta_pic_order_always_zero_flag, 1, return_status, "delta_pic_order_always_zero_flag"); /* offset_for_non_ref_pic */ PUT_BITS_SEV(ps_bitstrm, ps_sps->i4_offset_for_non_ref_pic, return_status, "offset_for_non_ref_pic"); /* offset_for_top_to_bottom_field */ PUT_BITS_SEV(ps_bitstrm, ps_sps->i4_offset_for_top_to_bottom_field, return_status, "offset_for_top_to_bottom_field"); /* num_ref_frames_in_pic_order_cnt_cycle */ PUT_BITS_UEV(ps_bitstrm, ps_sps->u1_num_ref_frames_in_pic_order_cnt_cycle, return_status, "num_ref_frames_in_pic_order_cnt_cycle"); /* Offset for ref frame */ for (i=0; i<ps_sps->u1_num_ref_frames_in_pic_order_cnt_cycle; i++) { /* offset_for_ref_frame */ PUT_BITS_SEV(ps_bitstrm, ps_sps->ai4_offset_for_ref_frame[i], return_status, "offset_for_ref_frame"); } } /* num_ref_frames */ PUT_BITS_UEV(ps_bitstrm, ps_sps->u1_max_num_ref_frames, return_status, "num_ref_frames"); /* gaps_in_frame_num_value_allowed_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_gaps_in_frame_num_value_allowed_flag, 1, return_status, "gaps_in_frame_num_value_allowed_flag"); /* pic_width_in_mbs_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i2_pic_width_in_mbs_minus1, return_status, "pic_width_in_mbs_minus1"); /* pic_height_in_map_units_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i2_pic_height_in_map_units_minus1, return_status, "pic_height_in_map_units_minus1"); /* frame_mbs_only_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_frame_mbs_only_flag, 1, return_status, "frame_mbs_only_flag"); if (!ps_sps->i1_frame_mbs_only_flag) { /* mb_adaptive_frame_field_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_mb_adaptive_frame_field_flag, 1, return_status, "mb_adaptive_frame_field_flag"); } /* direct_8x8_inference_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_direct_8x8_inference_flag, 1, return_status, "direct_8x8_inference_flag"); /* frame_cropping_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_frame_cropping_flag, 1, return_status, "frame_cropping_flag"); if (ps_sps->i1_frame_cropping_flag) { /* frame_crop_left_offset */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i2_frame_crop_left_offset, return_status, "frame_crop_left_offset"); /* frame_crop_right_offset */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i2_frame_crop_right_offset, return_status, "frame_crop_right_offset"); /* frame_crop_top_offset */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i2_frame_crop_top_offset, return_status, "frame_crop_top_offset"); /* frame_crop_bottom_offset */ PUT_BITS_UEV(ps_bitstrm, ps_sps->i2_frame_crop_bottom_offset, return_status, "frame_crop_bottom_offset"); } /* vui_parameters_present_flag */ PUT_BITS(ps_bitstrm, ps_sps->i1_vui_parameters_present_flag, 1, return_status, "vui_parameters_present_flag"); if (ps_sps->i1_vui_parameters_present_flag) { /* Add vui parameters to the bitstream */; return_status |= ih264e_generate_vui(ps_bitstrm, ps_vui); } /* rbsp trailing bits */ return_status |= ih264e_put_rbsp_trailing_bits(ps_bitstrm); return return_status; } /** ****************************************************************************** * * @brief Generates PPS (Picture Parameter Set) * * @par Description * Generate Picture Parameter Set as per Section 7.3.2.2 * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] ps_pps * pointer to structure containing PPS data * * @return success or failure error code * ****************************************************************************** */ WORD32 ih264e_generate_pps(bitstrm_t *ps_bitstrm, pps_t *ps_pps, sps_t *ps_sps) { WORD32 return_status = IH264E_SUCCESS; /* Insert the NAL start code */ return_status |= ih264e_put_nal_start_code_prefix(ps_bitstrm, 1); /* Insert Nal Unit Header */ PUT_BITS(ps_bitstrm, NAL_PPS_FIRST_BYTE, 8, return_status, "pps_header"); /* pic_parameter_set_id */ PUT_BITS_UEV(ps_bitstrm, ps_pps->u1_pps_id, return_status, "pic_parameter_set_id"); /* seq_parameter_set_id */ PUT_BITS_UEV(ps_bitstrm, ps_pps->u1_sps_id, return_status, "seq_parameter_set_id"); /* Entropy coding : 0-VLC; 1 - CABAC */ PUT_BITS(ps_bitstrm, ps_pps->u1_entropy_coding_mode_flag, 1, return_status, "Entropy coding : 0-VLC; 1 - CABAC"); /* Pic order present flag */ PUT_BITS(ps_bitstrm, ps_pps->u1_pic_order_present_flag, 1, return_status, "Pic order present flag"); /* Number of slice groups */ PUT_BITS_UEV(ps_bitstrm, ps_pps->u1_num_slice_groups - 1, return_status, "Number of slice groups"); if (ps_pps->u1_num_slice_groups > 1) { /* TODO_LATER: Currently the number of slice groups minus 1 is 0. * If this is not the case, we have to add Slice group map type to the bit stream*/ } /* num_ref_idx_l0_default_active_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_pps->i1_num_ref_idx_l0_default_active - 1, return_status, "num_ref_idx_l0_default_active_minus1"); /* num_ref_idx_l1_default_active_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_pps->i1_num_ref_idx_l1_default_active - 1, return_status, "num_ref_idx_l1_default_active_minus1"); /* weighted_pred_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_weighted_pred_flag, 1, return_status, "weighted_pred_flag"); /* weighted_bipred_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_weighted_bipred_idc, 2, return_status, "weighted_bipred_idc"); /* pic_init_qp_minus26 */ PUT_BITS_SEV(ps_bitstrm, ps_pps->i1_pic_init_qp - 26, return_status, "pic_init_qp_minus26"); /* pic_init_qs_minus26 */ PUT_BITS_SEV(ps_bitstrm, ps_pps->i1_pic_init_qs - 26, return_status, "pic_init_qs_minus26"); /* chroma_qp_index_offset */ PUT_BITS_SEV(ps_bitstrm, ps_pps->i1_chroma_qp_index_offset, return_status, "chroma_qp_index_offset"); /* deblocking_filter_control_present_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_deblocking_filter_control_present_flag, 1, return_status, "deblocking_filter_control_present_flag"); /* constrained_intra_pred_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_constrained_intra_pred_flag, 1, return_status, "constrained_intra_pred_flag"); /*redundant_pic_cnt_present_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_redundant_pic_cnt_present_flag, 1, return_status, "redundant_pic_cnt_present_flag"); if (ps_sps->u1_profile_idc >= IH264_PROFILE_HIGH) { /* transform_8x8_mode_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_transform_8x8_mode_flag, 1, return_status, "transform_8x8_mode_flag"); /* pic_scaling_matrix_present_flag */ PUT_BITS(ps_bitstrm, ps_pps->i1_pic_scaling_matrix_present_flag, 1, return_status, "pic_scaling_matrix_present_flag"); if(ps_pps->i1_pic_scaling_matrix_present_flag) { /* TODO_LATER: Will be enabled once scaling list support is added */ } /* Second chroma QP offset */ PUT_BITS_SEV(ps_bitstrm, ps_pps->i1_second_chroma_qp_index_offset, return_status, "Second chroma QP offset"); } return_status |= ih264e_put_rbsp_trailing_bits(ps_bitstrm); return return_status; } /** ****************************************************************************** * * @brief Generates Slice Header * * @par Description * Generate Slice Header as per Section 7.3.5.1 * * @param[inout] ps_bitstrm * pointer to bitstream context for generating slice header * * @param[in] ps_slice_hdr * pointer to slice header params * * @param[in] ps_pps * pointer to pps params referred by slice * * @param[in] ps_sps * pointer to sps params referred by slice * * @param[out] ps_dup_bit_strm_ent_offset * Bitstream struct to store bitstream state * * @param[out] pu4_first_slice_start_offset * first slice offset is returned * * @return success or failure error code * ****************************************************************************** */ WORD32 ih264e_generate_slice_header(bitstrm_t *ps_bitstrm, slice_header_t *ps_slice_hdr, pps_t *ps_pps, sps_t *ps_sps) { WORD32 return_status = IH264E_SUCCESS; /* Insert start code */ return_status |= ih264e_put_nal_start_code_prefix(ps_bitstrm, 1); /* Insert Nal Unit Header */ return_status |= ih264e_generate_nal_unit_header(ps_bitstrm, ps_slice_hdr->i1_nal_unit_type, ps_slice_hdr->i1_nal_unit_idc); /* first_mb_in_slice */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->u2_first_mb_in_slice, return_status, "first_mb_in_slice"); /* slice_type */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->u1_slice_type, return_status, "slice_type"); /* pic_parameter_set_id */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->u1_pps_id, return_status, "pic_parameter_set_id"); /* frame_num */ PUT_BITS(ps_bitstrm, ps_slice_hdr->i4_frame_num, ps_sps->i1_log2_max_frame_num, return_status, "frame_num"); if (!ps_sps->i1_frame_mbs_only_flag) { /* field_pic_flag */ PUT_BITS(ps_bitstrm, ps_slice_hdr->i1_field_pic_flag, 1, return_status, "field_pic_flag"); if(ps_slice_hdr->i1_field_pic_flag) { /* bottom_field_flag */ PUT_BITS(ps_bitstrm, ps_slice_hdr->i1_bottom_field_flag, 1, return_status, "bottom_field_flag"); } } if (ps_slice_hdr->i1_nal_unit_type == 5) { /* u2_idr_pic_id */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->u2_idr_pic_id, return_status, "u2_idr_pic_id"); } if (ps_sps->i1_pic_order_cnt_type == 0) { /* pic_order_cnt_lsb */ PUT_BITS(ps_bitstrm, ps_slice_hdr->i4_pic_order_cnt_lsb, ps_sps->i1_log2_max_pic_order_cnt_lsb, return_status, "pic_order_cnt_lsb"); if(ps_pps->u1_pic_order_present_flag && !ps_slice_hdr->i1_field_pic_flag) { /* delta_pic_order_cnt_bottom */ PUT_BITS_SEV(ps_bitstrm, ps_slice_hdr->i4_delta_pic_order_cnt_bottom, return_status, "delta_pic_order_cnt_bottom"); } } if (ps_sps->i1_pic_order_cnt_type == 1 && !ps_sps->i1_delta_pic_order_always_zero_flag) { /* delta_pic_order_cnt[0] */ PUT_BITS_SEV(ps_bitstrm, ps_slice_hdr->ai4_delta_pic_order_cnt[0], return_status, "delta_pic_order_cnt[0]"); if (ps_pps->u1_pic_order_present_flag && !ps_slice_hdr->i1_field_pic_flag) { /* delta_pic_order_cnt[1] */ PUT_BITS_SEV(ps_bitstrm, ps_slice_hdr->ai4_delta_pic_order_cnt[1], return_status, "delta_pic_order_cnt[1]"); } } if (ps_pps->i1_redundant_pic_cnt_present_flag) { /* redundant_pic_cnt */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->u1_redundant_pic_cnt, return_status, "redundant_pic_cnt"); } if (ps_slice_hdr->u1_slice_type == BSLICE) { /* direct_spatial_mv_pred_flag */ PUT_BITS(ps_bitstrm, ps_slice_hdr->u1_direct_spatial_mv_pred_flag, 1, return_status, "direct_spatial_mv_pred_flag"); } if (ps_slice_hdr->u1_slice_type == PSLICE || ps_slice_hdr->u1_slice_type == SPSLICE || ps_slice_hdr->u1_slice_type == BSLICE) { /* num_ref_idx_active_override_flag */ PUT_BITS(ps_bitstrm, ps_slice_hdr->u1_num_ref_idx_active_override_flag, 1, return_status, "num_ref_idx_active_override_flag"); if (ps_slice_hdr->u1_num_ref_idx_active_override_flag) { /* num_ref_idx_l0_active_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->i1_num_ref_idx_l0_active - 1, return_status, "num_ref_idx_l0_active_minus1"); if (ps_slice_hdr->u1_slice_type == BSLICE) { /* num_ref_idx_l1_active_minus1 */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->i1_num_ref_idx_l1_active - 1, return_status, "num_ref_idx_l1_active_minus1"); } } } /* ref_idx_reordering */ /* TODO: ref_idx_reordering */ if ((ps_slice_hdr->u1_slice_type != ISLICE) && (ps_slice_hdr->u1_slice_type != SISLICE)) { /* ref_pic_list_reordering_flag_l0 */ PUT_BITS(ps_bitstrm, ps_slice_hdr->u1_ref_idx_reordering_flag_l0, 1, return_status, "ref_pic_list_reordering_flag_l0"); if (ps_slice_hdr->u1_ref_idx_reordering_flag_l0) { } } if (ps_slice_hdr->u1_slice_type == BSLICE) { /* ref_pic_list_reordering_flag_l1 */ PUT_BITS(ps_bitstrm, ps_slice_hdr->u1_ref_idx_reordering_flag_l1, 1, return_status, "ref_pic_list_reordering_flag_l1"); if (ps_slice_hdr->u1_ref_idx_reordering_flag_l1) { } } if ((ps_pps->i1_weighted_pred_flag && (ps_slice_hdr->u1_slice_type == PSLICE || ps_slice_hdr->u1_slice_type == SPSLICE)) || (ps_slice_hdr->u1_slice_type == BSLICE && ps_pps->i1_weighted_bipred_idc == 1)) { /* TODO_LATER: Currently there is no support for weighted prediction. This needs to be updated when the support is added */ } if (ps_slice_hdr->i1_nal_unit_idc != 0) { if (ps_slice_hdr->i1_nal_unit_type == 5) { /* no_output_of_prior_pics_flag */ PUT_BITS(ps_bitstrm, ps_slice_hdr->u1_no_output_of_prior_pics_flag , 1, return_status, "no_output_of_prior_pics_flag "); /* long_term_reference_flag */ PUT_BITS(ps_bitstrm, ps_slice_hdr->u1_long_term_reference_flag , 1, return_status, "long_term_reference_flag "); } else { /* adaptive_ref_pic_marking_mode_flag */ PUT_BITS(ps_bitstrm, ps_slice_hdr->u1_adaptive_ref_pic_marking_mode_flag , 1, return_status, "adaptive_ref_pic_marking_mode_flag "); if (ps_slice_hdr->u1_adaptive_ref_pic_marking_mode_flag) { /* TODO: if the reference picture marking mode is adaptive add these fields in the bit-stream */ } } } if (ps_slice_hdr->u1_entropy_coding_mode_flag && ps_slice_hdr->u1_slice_type != ISLICE && ps_slice_hdr->u1_slice_type != SISLICE) { /* cabac_init_idc */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->i1_cabac_init_idc, return_status, "cabac_init_idc"); } /* slice_qp_delta */ PUT_BITS_SEV(ps_bitstrm, ps_slice_hdr->i1_slice_qp - ps_pps->i1_pic_init_qp, return_status, "slice_qp_delta"); if (ps_slice_hdr->u1_slice_type == SPSLICE || ps_slice_hdr->u1_slice_type == SISLICE) { if (ps_slice_hdr->u1_slice_type == SPSLICE) { /* sp_for_switch_flag */ PUT_BITS(ps_bitstrm, ps_slice_hdr->u1_sp_for_switch_flag , 1, return_status, "sp_for_switch_flag"); } /* slice_qs_delta */ PUT_BITS_SEV(ps_bitstrm, ps_slice_hdr->u1_slice_qs - ps_pps->i1_pic_init_qs, return_status, "slice_qs_delta"); } if (ps_pps->i1_deblocking_filter_control_present_flag) { /* disable_deblocking_filter_idc */ PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->u1_disable_deblocking_filter_idc, return_status, "disable_deblocking_filter_idc"); if(ps_slice_hdr->u1_disable_deblocking_filter_idc != 1) { /* slice_alpha_c0_offset_div2 */ PUT_BITS_SEV(ps_bitstrm, ps_slice_hdr->i1_slice_alpha_c0_offset_div2, return_status, "slice_alpha_c0_offset_div2"); /* slice_beta_offset_div2 */ PUT_BITS_SEV(ps_bitstrm, ps_slice_hdr->i1_slice_beta_offset_div2, return_status, "slice_beta_offset_div2"); } } if (ps_slice_hdr->u1_num_slice_groups_minus1 > 0 && ps_pps->u1_slice_group_map_type >= 3 && ps_pps->u1_slice_group_map_type <= 5) { /* slice_group_change_cycle */ /* TODO_LATER: Currently the number of slice groups minus 1 is 0. * If this is not the case, we have to add Slice group map type to the bit stream */ } return return_status; } /** ****************************************************************************** * * @brief Populates VUI structure * * @par Description * Populates VUI structure for its use in header generation * * @param[in] ps_codec * pointer to encoder context * * @return success or failure error code * ****************************************************************************** */ IH264E_ERROR_T ih264e_populate_vui(codec_t *ps_codec) { vui_t *ps_vui = &ps_codec->s_cfg.s_vui; sps_t *ps_sps = ps_codec->ps_sps_base + ps_codec->i4_sps_id; ps_vui->u1_nal_hrd_parameters_present_flag = 0; ps_vui->u1_vcl_hrd_parameters_present_flag = 0; ps_vui->u1_bitstream_restriction_flag = 1; ps_vui->u1_motion_vectors_over_pic_boundaries_flag = 1; ps_vui->u1_max_bytes_per_pic_denom = 0; ps_vui->u1_max_bits_per_mb_denom = 0; ps_vui->u1_log2_max_mv_length_horizontal = 16; ps_vui->u1_log2_max_mv_length_vertical = 16; if(ps_codec->s_cfg.u4_num_bframes == 0) { ps_vui->u1_num_reorder_frames = 0; } else { ps_vui->u1_num_reorder_frames = 1; } ps_vui->u1_max_dec_frame_buffering = ps_sps->u1_max_num_ref_frames; return 0; } /** ****************************************************************************** * * @brief Populates sps structure * * @par Description * Populates sps structure for its use in header generation * * @param[in] ps_codec * pointer to encoder context * * @param[out] ps_sps * pointer to sps params that needs to be populated * * @return success or failure error code * ****************************************************************************** */ IH264E_ERROR_T ih264e_populate_sps(codec_t *ps_codec, sps_t *ps_sps) { /* active config parameters */ cfg_params_t *ps_cfg = &(ps_codec->s_cfg); // /* level */ // IH264_LEVEL_T level_idc; /* error_status */ IH264E_ERROR_T i4_err_code = IH264E_FAIL; /* profile */ /* * Baseline profile supports, 8 bits per sample, 4:2:0 format, CAVLC. * B frames are not allowed. Further, Flexible mb ordering, Redundant slices, Arbitrary slice ordering are supported. * The constrained baseline profile is baseline profile minus ASO, FMO and redundant slices. * To the constrained baseline profile if we add support for B slices, support for encoding interlaced frames, * support for weighted prediction and introduce CABAC entropy coding then we have Main Profile. */ if ((ps_cfg->u4_num_bframes) || (ps_cfg->e_content_type != IV_PROGRESSIVE) || (ps_cfg->u4_entropy_coding_mode == CABAC) || (ps_cfg->u4_weighted_prediction)) { ps_sps->u1_profile_idc = IH264_PROFILE_MAIN; } else { ps_sps->u1_profile_idc = IH264_PROFILE_BASELINE; } /* level */ ps_sps->u1_level_idc = MAX(ps_cfg->u4_max_level, (UWORD32)ih264e_get_min_level(ps_cfg->u4_max_wd, ps_cfg->u4_max_ht)); /* constrained flags */ /* * baseline profile automatically implies set 0 flag */ ps_sps->u1_constraint_set0_flag = (ps_sps->u1_profile_idc == IH264_PROFILE_BASELINE); /* * main profile automatically implies set 1 flag * Although the encoder says it supports Baseline profile it actually supports constrained * baseline profile as ASO, FMO and redundant slices are not supported */ ps_sps->u1_constraint_set1_flag = (ps_sps->u1_profile_idc <= IH264_PROFILE_MAIN); /* * extended profile is not supported */ ps_sps->u1_constraint_set2_flag = 0x00; /* * level 1b or level 11 */ if (ps_sps->u1_level_idc == IH264_LEVEL_1B) { ps_sps->u1_constraint_set3_flag = 0; ps_sps->u1_level_idc = IH264_LEVEL_11; } else { ps_sps->u1_constraint_set3_flag = 0; } /* active sps id */ ps_sps->u1_sps_id = ps_codec->i4_sps_id; if (ps_sps->u1_profile_idc >= IH264_PROFILE_HIGH) { /* chroma format idc */ ps_sps->u1_chroma_format_idc = CHROMA_FMT_IDC_YUV420; /* residual_colour_transform_flag */ ps_sps->i1_residual_colour_transform_flag = 0; /* luma bit depth 8 */ ps_sps->i1_bit_depth_luma = 8; /* chroma bit depth 8 */ ps_sps->i1_bit_depth_chroma = 8; /* qpprime_y_zero_transform_bypass_flag */ ps_sps->i1_qpprime_y_zero_transform_bypass_flag = 0; /* seq_scaling_matrix_present_flag */ ps_sps->i1_seq_scaling_matrix_present_flag = 0; if (ps_sps->i1_seq_scaling_matrix_present_flag) { /* TODO_LATER: Will be enabled once scaling list support is added */ } } /* log2_max_frame_num_minus4 */ ps_sps->i1_log2_max_frame_num = 16; /* pic_order_cnt_type */ ps_sps->i1_pic_order_cnt_type = 2; if (ps_codec->i4_non_ref_frames_in_stream) { ps_sps->i1_pic_order_cnt_type = 0; } /* log2_max_pic_order_cnt_lsb_minus4 */ ps_sps->i1_log2_max_pic_order_cnt_lsb = 8; /* TODO : add support for other poc types */ if (ps_sps->i1_pic_order_cnt_type == 0) { } else if (ps_sps->i1_pic_order_cnt_type == 1) { } /* num_ref_frames */ /* TODO : Should we have a flexible num ref frames */ if (ps_codec->s_cfg.u4_num_bframes > 0) { ps_sps->u1_max_num_ref_frames = 2; } else { ps_sps->u1_max_num_ref_frames = 1; } /* gaps_in_frame_num_value_allowed_flag */ ps_sps->i1_gaps_in_frame_num_value_allowed_flag = 0; /* pic width in mb - 1 */ ps_sps->i2_pic_width_in_mbs_minus1 = ps_cfg->i4_wd_mbs - 1; /* pic height in mb - 1 */ ps_sps->i2_pic_height_in_map_units_minus1 = ps_cfg->i4_ht_mbs - 1;; /* frame_mbs_only_flag, no support for interlace encoding */ ps_sps->i1_frame_mbs_only_flag = 1; /* mb_adaptive_frame_field_flag */ if (ps_sps->i1_frame_mbs_only_flag == 0) { ps_sps->i1_mb_adaptive_frame_field_flag = 0; } /* direct_8x8_inference_flag */ if (ps_sps->u1_level_idc < IH264_LEVEL_30) { ps_sps->i1_direct_8x8_inference_flag = 0; } else { ps_sps->i1_direct_8x8_inference_flag = 1; } /* cropping params */ /*NOTE : Cropping values depend on the chroma format * For our case ,decoder interprets the cropping values as 2*num pixels * Hence the difference in the disp width and width must be halved before sending * to get the expected results */ ps_sps->i1_frame_cropping_flag = 0; ps_sps->i2_frame_crop_left_offset = 0; ps_sps->i2_frame_crop_right_offset = (ps_codec->s_cfg.u4_wd - ps_codec->s_cfg.u4_disp_wd)>>1; ps_sps->i2_frame_crop_top_offset = 0; ps_sps->i2_frame_crop_bottom_offset = (ps_codec->s_cfg.u4_ht - ps_codec->s_cfg.u4_disp_ht)>>1; if (ps_sps->i2_frame_crop_left_offset || ps_sps->i2_frame_crop_right_offset || ps_sps->i2_frame_crop_top_offset || ps_sps->i2_frame_crop_bottom_offset) { ps_sps->i1_frame_cropping_flag = 1; } /* vui params */ ps_sps->i1_vui_parameters_present_flag = 1; if (ps_sps->i1_vui_parameters_present_flag) { /* populate vui params */ ih264e_populate_vui(ps_codec); } return i4_err_code; } /** ****************************************************************************** * * @brief Populates pps structure * * @par Description * Populates pps structure for its use in header generation * * @param[in] ps_codec * pointer to encoder context * * @param[out] ps_pps * pointer to pps params that needs to be populated * * @return success or failure error code * ****************************************************************************** */ IH264E_ERROR_T ih264e_populate_pps(codec_t *ps_codec, pps_t *ps_pps) { /* active config parameters */ cfg_params_t *ps_cfg = &(ps_codec->s_cfg); /* seq_parameter_set_id */ ps_pps->u1_sps_id = ps_codec->i4_sps_id; /* pic_parameter_set_id */ ps_pps->u1_pps_id = ps_codec->i4_pps_id; /* entropy_coding_mode */ ps_pps->u1_entropy_coding_mode_flag = ps_cfg->u4_entropy_coding_mode; /* pic_order_present_flag is unset if we don't have feilds */ ps_pps->u1_pic_order_present_flag = 0; /* Currently number of slice groups supported are 1 */ ps_pps->u1_num_slice_groups = 1; if (ps_pps->u1_num_slice_groups - 1) { /* TODO_LATER: Currently the number of slice groups minus 1 is 0. * If this is not the case, we have to add Slice group map type to the bit stream*/ } /* number of reference frames for list 0 */ /* FIXME : fix this hard coded value */ ps_pps->i1_num_ref_idx_l0_default_active = 1; /* number of reference frames for list 1 */ ps_pps->i1_num_ref_idx_l1_default_active = 1; /* weighted prediction for now is disabled */ ps_pps->i1_weighted_pred_flag = 0; ps_pps->i1_weighted_bipred_idc = 0; /* The intent is to not signal qp from pps. Rather send the same in slice headers */ ps_pps->i1_pic_init_qp = 0; /* The intent is to not signal qp from pps. Rather send the same in slice headers */ ps_pps->i1_pic_init_qs = 0; /* The intent is to not signal qp from pps. Rather send the same in slice headers */ ps_pps->i1_chroma_qp_index_offset = 0; /* deblocking filter flags present in slice header */ ps_pps->i1_deblocking_filter_control_present_flag = 1; /* constrained intra prediction */ ps_pps->i1_constrained_intra_pred_flag = ps_cfg->u4_constrained_intra_pred; /* sending redundant slices is not supported for now */ ps_pps->i1_redundant_pic_cnt_present_flag = 0; ps_pps->u1_slice_group_map_type = 0; return IH264E_SUCCESS; } /** ****************************************************************************** * * @brief Populates slice header structure * * @par Description * Populates slice header structure for its use in header generation * * @param[in] ps_proc * pointer to proc context * * @param[out] ps_slice_hdr * pointer to slice header structure that needs to be populated * * @param[in] ps_pps * pointer to pps params structure referred by the slice * * @param[in] ps_sps * pointer to sps params referred by the pps * * @return success or failure error code * ****************************************************************************** */ WORD32 ih264e_populate_slice_header(process_ctxt_t *ps_proc, slice_header_t *ps_slice_hdr, pps_t *ps_pps, sps_t *ps_sps) { /* entropy context */ entropy_ctxt_t *ps_entropy = &ps_proc->s_entropy; codec_t *ps_codec = ps_proc->ps_codec; if (ps_proc->ps_codec->u4_is_curr_frm_ref) { ps_slice_hdr->i1_nal_unit_idc = 3; } else { ps_slice_hdr->i1_nal_unit_idc = 0; } /* start mb address */ ps_slice_hdr->u2_first_mb_in_slice = ps_entropy->i4_mb_start_add; /* slice type */ ps_slice_hdr->u1_slice_type = ps_proc->i4_slice_type; /* pic_parameter_set_id */ ps_slice_hdr->u1_pps_id = ps_pps->u1_pps_id; /* Separate color plane flag is 0, * hence the syntax element color_plane_id not included */ /* frame num */ ps_slice_hdr->i4_frame_num = ps_proc->i4_frame_num; /* frame_mbs_only_flag, no support for interlace encoding */ if (!ps_sps->i1_frame_mbs_only_flag) { ps_slice_hdr->i1_field_pic_flag = 0; if (ps_slice_hdr->i1_field_pic_flag) { ps_slice_hdr->i1_bottom_field_flag = 0; } } /* idr pic id */ if (ps_proc->u4_is_idr) { ps_slice_hdr->u2_idr_pic_id = ps_proc->u4_idr_pic_id; ps_slice_hdr->i1_nal_unit_type = 5; } else { ps_slice_hdr->i1_nal_unit_type = 1; } if (ps_sps->i1_pic_order_cnt_type == 0) { WORD32 i4_poc; i4_poc = ps_codec->i4_poc; i4_poc %= (1 << ps_sps->i1_log2_max_pic_order_cnt_lsb); ps_slice_hdr->i4_pic_order_cnt_lsb = i4_poc; } /* TODO add support for poc type 1 */ else if (ps_sps->i1_pic_order_cnt_type == 1) { } /* * redundant slices are not currently supported. * Hence the syntax element redundant slice cnt is not initialized */ if (ps_pps->i1_redundant_pic_cnt_present_flag) { } /* direct spatial mv pred flag */ if (ps_proc->i4_slice_type == BSLICE) { ps_slice_hdr->u1_direct_spatial_mv_pred_flag = 1; } if (ps_proc->i4_slice_type == PSLICE || ps_proc->i4_slice_type == SPSLICE || ps_proc->i4_slice_type == BSLICE) { /* num_ref_idx_active_override_flag */ ps_slice_hdr->u1_num_ref_idx_active_override_flag = 0; if (ps_slice_hdr->u1_num_ref_idx_active_override_flag) { /* num_ref_idx_l0_active_minus1 */ if (ps_proc->i4_slice_type == BSLICE) { /* num_ref_idx_l1_active_minus1 */ } } } /* ref_idx_reordering */ /* TODO: ref_idx_reordering */ if ((ps_proc->i4_slice_type != ISLICE) && (ps_proc->i4_slice_type != SISLICE)) { /* ref_pic_list_reordering_flag_l0 */ ps_slice_hdr->u1_ref_idx_reordering_flag_l0 = 0; if (ps_slice_hdr->u1_ref_idx_reordering_flag_l0) { } /* ref_pic_list_reordering_flag_l1 */ ps_slice_hdr->u1_ref_idx_reordering_flag_l1 = 0; if (ps_slice_hdr->u1_ref_idx_reordering_flag_l1) { } } /* Currently we do not support weighted pred */ /* ps_slice_hdr->u1_weighted_bipred_idc = 0; */ if ((ps_pps->i1_weighted_pred_flag && (ps_proc->i4_slice_type == PSLICE || ps_proc->i4_slice_type == SPSLICE)) || (ps_proc->i4_slice_type == BSLICE && ps_pps->i1_weighted_bipred_idc == 1)) { /* TODO_LATER: Currently there is no support for weighted prediction. This needs to be updated when the support is added */ } if (ps_slice_hdr->i1_nal_unit_idc != 0) { if (ps_slice_hdr->i1_nal_unit_type == 5) { /* no_output_of_prior_pics_flag */ ps_slice_hdr->u1_no_output_of_prior_pics_flag = 0; /* long_term_reference_flag */ ps_slice_hdr->u1_long_term_reference_flag = 0; } else { /* adaptive_ref_pic_marking_mode_flag */ ps_slice_hdr->u1_adaptive_ref_pic_marking_mode_flag = 0; if (ps_slice_hdr->u1_adaptive_ref_pic_marking_mode_flag) { /* TODO: if the reference picture marking mode is adaptive add these fields in the bit-stream */ } } } /* entropy coding mode flag */ ps_slice_hdr->u1_entropy_coding_mode_flag = ps_entropy->u1_entropy_coding_mode_flag; if (ps_slice_hdr->u1_entropy_coding_mode_flag && ps_proc->i4_slice_type != ISLICE && ps_proc->i4_slice_type != SISLICE) { /* cabac_init_idc */ } /* slice qp */ ps_slice_hdr->i1_slice_qp = ps_proc->u4_frame_qp; if (ps_proc->i4_slice_type == SPSLICE || ps_proc->i4_slice_type == SISLICE) { if (ps_proc->i4_slice_type == SPSLICE) { /* sp_for_switch_flag */ } /* slice_qs_delta */ } if (ps_pps->i1_deblocking_filter_control_present_flag) { /* disable_deblocking_filter_idc */ ps_slice_hdr->u1_disable_deblocking_filter_idc = ps_proc->u4_disable_deblock_level; if (ps_slice_hdr->u1_disable_deblocking_filter_idc != 1) { /* slice_alpha_c0_offset_div2 */ ps_slice_hdr->i1_slice_alpha_c0_offset_div2 = 0; /* slice_beta_offset_div2 */ ps_slice_hdr->i1_slice_beta_offset_div2 = 0; } } ps_slice_hdr->u1_num_slice_groups_minus1 = 0; if(ps_slice_hdr->u1_num_slice_groups_minus1 > 0 && ps_pps->u1_slice_group_map_type >= 3 && ps_pps->u1_slice_group_map_type <= 5) { /* slice_group_change_cycle */ /* TODO_LATER: Currently the number of slice groups minus 1 is 0. * If this is not the case, we have to add Slice group map type to the bit stream */ } ps_slice_hdr->i1_cabac_init_idc = CABAC_INIT_IDC; return IH264E_SUCCESS; } /** ****************************************************************************** * * @brief inserts FILLER Nal Unit. * * @par Description * In constant bit rate rc mode, when the bits generated by the codec is * underflowing the target bit rate, the encoder library inserts filler nal unit. * * @param[in] ps_bitstrm * pointer to bitstream context (handle) * * @param[in] insert_fill_bytes * Number of fill bytes to be inserted * * @return success or failure error code * ****************************************************************************** */ IH264E_ERROR_T ih264e_add_filler_nal_unit(bitstrm_t *ps_bitstrm, WORD32 insert_fill_bytes) { WORD32 i4_num_words_to_fill, i4_words_filled; IH264E_ERROR_T return_status = IH264E_SUCCESS; /* Insert the NAL start code */ return_status |= ih264e_put_nal_start_code_prefix(ps_bitstrm, 1); if (ps_bitstrm->u4_strm_buf_offset + insert_fill_bytes >= ps_bitstrm->u4_max_strm_size) { return (IH264E_BITSTREAM_BUFFER_OVERFLOW); } /* Insert Nal Unit Header */ PUT_BITS(ps_bitstrm, NAL_FILLER_FIRST_BYTE, 8, return_status, "filler_header"); PUT_BITS(ps_bitstrm, 0xFFFFFF, 24, return_status, "fill bytes"); /* Initializing Variables */ i4_words_filled = 1; /****************************************************/ /* Flooring the number of bytes for be stuffed to */ /* WORD unit */ /****************************************************/ i4_num_words_to_fill = (insert_fill_bytes >> 2); /****************************************************/ /* Reducing already 4 bytes filled. In case stuffing*/ /* is <= 4 bytes, we are actually not stuffing */ /* anything */ /****************************************************/ i4_num_words_to_fill -= i4_words_filled; while (i4_num_words_to_fill > 0) { /* Insert Nal Unit Header */ PUT_BITS(ps_bitstrm, 0xFFFFFFFF, 32, return_status, "fill bytes"); i4_num_words_to_fill-- ; } return_status |= ih264e_put_rbsp_trailing_bits(ps_bitstrm); return return_status; }