| /****************************************************************************** |
| * |
| * Copyright (C) 2022 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 |
| * isvce_encode_header.c |
| * |
| * @brief |
| * This file contains function definitions related to header encoding. |
| * |
| * @author |
| * ittiam |
| * |
| * @par List of Functions: |
| * - isvce_generate_sps() |
| * - isvce_generate_pps() |
| * - isvce_generate_slice_header() |
| * - isvce_populate_sps() |
| * - isvce_populate_pps() |
| * - isvce_populate_slice_header() |
| * |
| ******************************************************************************* |
| */ |
| |
| #include "ih264_typedefs.h" |
| #include "ih264_debug.h" |
| |
| /* Dependencies of ih264e_bitstream.h */ |
| #include "ih264e_error.h" |
| |
| #include "ih264e_bitstream.h" |
| |
| #include "isvce_encode_header.h" |
| #include "isvce_utils.h" |
| |
| static FORCEINLINE IH264E_ERROR_T isvce_generate_nal_unit_header(bitstrm_t *ps_bitstrm, |
| WORD32 nal_unit_type, |
| WORD32 nal_ref_idc) |
| { |
| WORD32 return_status = IH264E_SUCCESS; |
| |
| if(!((nal_unit_type > 0) && (nal_unit_type < 32))) |
| { |
| return IH264E_FAIL; |
| } |
| |
| /* 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 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 isvce_generate_sps(bitstrm_t *ps_bitstrm, sps_t *ps_sps, NAL_UNIT_TYPE_T nal_type) |
| { |
| WORD32 return_status = IH264E_SUCCESS; |
| WORD32 i; |
| WORD8 i1_nal_ref_idc = 3; |
| vui_t *ps_vui = &ps_sps->s_vui_parameters; |
| |
| /* Insert Start Code */ |
| return_status = ih264e_put_nal_start_code_prefix(ps_bitstrm, 1); |
| if(return_status != IH264E_SUCCESS) |
| { |
| return return_status; |
| } |
| /* Insert Nal Unit Header */ |
| return_status = isvce_generate_nal_unit_header(ps_bitstrm, nal_type, i1_nal_ref_idc); |
| if(return_status != IH264E_SUCCESS) |
| { |
| return return_status; |
| } |
| |
| /* 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_SCALABLE_BASELINE) || |
| (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); |
| if(return_status != IH264E_SUCCESS) |
| { |
| return return_status; |
| } |
| } |
| |
| if(nal_type != NAL_SUBSET_SPS) |
| { |
| /* 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 isvce_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); |
| if(return_status != IH264E_SUCCESS) |
| { |
| return return_status; |
| } |
| |
| /* 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 isvce_generate_slice_header(bitstrm_t *ps_bitstrm, slice_header_t *ps_slice_hdr, |
| pps_t *ps_pps, sps_t *ps_sps, UWORD8 u1_idr_flag) |
| { |
| WORD32 return_status = IH264E_SUCCESS; |
| UWORD8 u1_slice_type; |
| |
| /* Insert start code */ |
| return_status = ih264e_put_nal_start_code_prefix(ps_bitstrm, 1); |
| if(return_status != IH264E_SUCCESS) |
| { |
| return return_status; |
| } |
| /* Insert Nal Unit Header */ |
| return_status = isvce_generate_nal_unit_header(ps_bitstrm, ps_slice_hdr->i1_nal_unit_type, |
| ps_slice_hdr->i1_nal_unit_idc); |
| if(return_status != IH264E_SUCCESS) |
| { |
| return return_status; |
| } |
| /* 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(u1_idr_flag == 1) |
| { |
| /* u2_idr_pic_id */ |
| PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->u2_idr_pic_id, return_status, "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"); |
| } |
| |
| u1_slice_type = ps_slice_hdr->u1_slice_type % EPSLICE; |
| |
| if(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(u1_slice_type == PSLICE || u1_slice_type == SPSLICE || 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(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_pic_list_modification */ |
| if((u1_slice_type != ISLICE) && (u1_slice_type != SISLICE)) |
| { |
| /* ref_pic_list_modification_flag_l0 */ |
| PUT_BITS(ps_bitstrm, ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l0, 1, |
| return_status, "ref_pic_list_modification_flag_l0"); |
| |
| if(ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l0) |
| { |
| UWORD8 i = 0; |
| |
| WORD8 *pi1_modification_of_pic_nums_idc_l0 = |
| ps_slice_hdr->s_rplm.i1_modification_of_pic_nums_idc_l0; |
| UWORD32 *pu4_abs_diff_pic_num_minus1_l0 = |
| ps_slice_hdr->s_rplm.u4_abs_diff_pic_num_minus1_l0; |
| UWORD8 *pu1_long_term_pic_num_l0 = ps_slice_hdr->s_rplm.u1_long_term_pic_num_l0; |
| |
| do |
| { |
| /* modification_of_pic_nums_idc */ |
| PUT_BITS_UEV(ps_bitstrm, pi1_modification_of_pic_nums_idc_l0[i], return_status, |
| "modification_of_pic_nums_idc"); |
| |
| if((0 == pi1_modification_of_pic_nums_idc_l0[i]) || |
| (1 == pi1_modification_of_pic_nums_idc_l0[i])) |
| { |
| /* abs_diff_pic_num_minus1 */ |
| PUT_BITS_UEV(ps_bitstrm, pu4_abs_diff_pic_num_minus1_l0[0], return_status, |
| "abs_diff_pic_num_minus1"); |
| |
| pu4_abs_diff_pic_num_minus1_l0++; |
| } |
| else if(2 == pi1_modification_of_pic_nums_idc_l0[i]) |
| { |
| /* long_term_pic_num */ |
| PUT_BITS_UEV(ps_bitstrm, pu1_long_term_pic_num_l0[0], return_status, |
| "abs_diff_pic_num_minus1"); |
| |
| pu1_long_term_pic_num_l0++; |
| } |
| } while(pi1_modification_of_pic_nums_idc_l0[i++] != 3); |
| } |
| } |
| |
| if(u1_slice_type == BSLICE) |
| { |
| /* ref_pic_list_modification_flag_l1 */ |
| PUT_BITS(ps_bitstrm, ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l1, 1, |
| return_status, "ref_pic_list_modification_flag_l1"); |
| |
| if(ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l1) |
| { |
| UWORD8 i = 0; |
| |
| WORD8 *pi1_modification_of_pic_nums_idc_l1 = |
| ps_slice_hdr->s_rplm.i1_modification_of_pic_nums_idc_l1; |
| UWORD32 *pu4_abs_diff_pic_num_minus1_l1 = |
| ps_slice_hdr->s_rplm.u4_abs_diff_pic_num_minus1_l1; |
| UWORD8 *pu1_long_term_pic_num_l1 = ps_slice_hdr->s_rplm.u1_long_term_pic_num_l1; |
| |
| do |
| { |
| /* modification_of_pic_nums_idc */ |
| PUT_BITS_UEV(ps_bitstrm, pi1_modification_of_pic_nums_idc_l1[i], return_status, |
| "modification_of_pic_nums_idc"); |
| |
| if((0 == pi1_modification_of_pic_nums_idc_l1[i]) || |
| (1 == pi1_modification_of_pic_nums_idc_l1[i])) |
| { |
| /* abs_diff_pic_num_minus1 */ |
| PUT_BITS_UEV(ps_bitstrm, pu4_abs_diff_pic_num_minus1_l1[0], return_status, |
| "abs_diff_pic_num_minus1"); |
| |
| pu4_abs_diff_pic_num_minus1_l1++; |
| } |
| else if(2 == pi1_modification_of_pic_nums_idc_l1[i]) |
| { |
| /* long_term_pic_num */ |
| PUT_BITS_UEV(ps_bitstrm, pu1_long_term_pic_num_l1[0], return_status, |
| "abs_diff_pic_num_minus1"); |
| |
| pu1_long_term_pic_num_l1++; |
| } |
| } while(pi1_modification_of_pic_nums_idc_l1[i++] != 3); |
| } |
| } |
| |
| if((ps_pps->i1_weighted_pred_flag && u1_slice_type == PSLICE) || |
| (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(u1_idr_flag == 1) |
| { |
| /* 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 && u1_slice_type != ISLICE && |
| 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 |
| * |
| ****************************************************************************** |
| */ |
| static IH264E_ERROR_T isvce_populate_vui(isvce_codec_t *ps_codec, sps_t *ps_sps) |
| { |
| vui_t *ps_vui = &ps_sps->s_vui_parameters; |
| |
| 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 isvce_populate_sps(isvce_codec_t *ps_codec, sps_t *ps_sps, UWORD8 u1_sps_id, |
| UWORD8 u1_profile_idc, isvce_inp_buf_t *ps_inp_buf, |
| UWORD8 u1_spatial_layer_id) |
| { |
| /* active config parameters */ |
| isvce_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. |
| */ |
| ps_sps->u1_profile_idc = u1_profile_idc; |
| |
| /* 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 = u1_sps_id; |
| |
| if((ps_sps->u1_profile_idc == IH264_SCALABLE_BASELINE) || |
| (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 = LOG2_MAX_FRAME_NUM_MINUS4 + 4; |
| |
| /* 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) |
| { |
| } |
| |
| ps_sps->u1_max_num_ref_frames = ps_codec->i4_max_num_reference_frames; |
| |
| /* 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_inp_buf->as_layer_yuv_buf_props[u1_spatial_layer_id].u4_width >> 4) - 1; |
| |
| /* pic height in mb - 1 */ |
| ps_sps->i2_pic_height_in_map_units_minus1 = |
| (ps_inp_buf->as_layer_yuv_buf_props[u1_spatial_layer_id].u4_height >> 4) - 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 = !(ps_cfg->u4_disable_vui); |
| |
| if(!ps_sps->i1_vui_parameters_present_flag) |
| { |
| /* populate vui params */ |
| isvce_populate_vui(ps_codec, ps_sps); |
| } |
| else |
| { |
| ps_sps->s_vui_parameters = ps_cfg->s_vui; |
| } |
| |
| 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 isvce_populate_pps(isvce_codec_t *ps_codec, pps_t *ps_pps, UWORD8 u1_sps_id, |
| UWORD8 u1_pps_id, UWORD8 u1_spatial_layer_id) |
| { |
| /* seq_parameter_set_id */ |
| ps_pps->u1_sps_id = u1_sps_id; |
| |
| /* pic_parameter_set_id */ |
| ps_pps->u1_pps_id = u1_pps_id; |
| |
| /* entropy_coding_mode */ |
| ps_pps->u1_entropy_coding_mode_flag = |
| ((ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers > 1) && (0 == u1_spatial_layer_id)) |
| ? CAVLC |
| : ps_codec->s_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_codec->au4_constrained_intra_pred[u1_spatial_layer_id]; |
| |
| /* 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 isvce_populate_slice_header(isvce_process_ctxt_t *ps_proc, slice_header_t *ps_slice_hdr, |
| pps_t *ps_pps, sps_t *ps_sps, UWORD8 u1_is_idr) |
| { |
| /* entropy context */ |
| isvce_entropy_ctxt_t *ps_entropy = &ps_proc->s_entropy; |
| |
| isvce_codec_t *ps_codec = ps_proc->ps_codec; |
| |
| if(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(u1_is_idr) |
| { |
| ps_slice_hdr->u2_idr_pic_id = ps_proc->u4_idr_pic_id; |
| ps_slice_hdr->i1_nal_unit_type = NAL_SLICE_IDR; |
| } |
| else |
| { |
| ps_slice_hdr->i1_nal_unit_type = NAL_SLICE_NON_IDR; |
| } |
| |
| if(ps_proc->u1_spatial_layer_id > 0) |
| { |
| ps_slice_hdr->i1_nal_unit_type = NAL_CODED_SLICE_EXTENSION; |
| } |
| |
| 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_pic_list_modification */ |
| if((ps_proc->i4_slice_type != ISLICE) && (ps_proc->i4_slice_type != SISLICE)) |
| { |
| /* ref_pic_list_modification_flag_l0 */ |
| ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l0 = 1; |
| |
| if(ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l0) |
| { |
| ps_slice_hdr->s_rplm.i1_modification_of_pic_nums_idc_l0[0] = 0; |
| ps_slice_hdr->s_rplm.i1_modification_of_pic_nums_idc_l0[1] = 3; |
| |
| if((ps_codec->i4_frame_num - ps_proc->aps_ref_pic[L0]->i4_frame_num) < 1) |
| { |
| return IH264E_FAIL; |
| } |
| |
| ps_slice_hdr->s_rplm.u4_abs_diff_pic_num_minus1_l0[0] = |
| ps_codec->i4_frame_num - ps_proc->aps_ref_pic[L0]->i4_frame_num - 1; |
| } |
| } |
| |
| if(ps_proc->i4_slice_type == BSLICE) |
| { |
| /* ref_pic_list_modification_flag_l1 */ |
| ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l1 = 0; |
| |
| if(ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_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(u1_is_idr) |
| { |
| /* 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 */ |
| ps_slice_hdr->i1_cabac_init_idc = CABAC_INIT_IDC; |
| } |
| |
| /* slice qp */ |
| ps_slice_hdr->i1_slice_qp = ps_proc->u1_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 Populates svc_nalu_ext structure |
| * |
| * @par Description |
| * Populates svc_nalu_ext 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 isvce_populate_svc_nalu_extension(isvce_process_ctxt_t *ps_proc, |
| svc_nalu_ext_t *ps_svc_nalu_ext, NAL_UNIT_TYPE_T nalu_type, |
| UWORD8 u1_idr_flag) |
| { |
| isvce_codec_t *ps_codec = ps_proc->ps_codec; |
| |
| ps_svc_nalu_ext->u1_idr_flag = u1_idr_flag; |
| |
| ps_svc_nalu_ext->u1_priority_id = 0; |
| |
| ps_svc_nalu_ext->u1_no_inter_layer_pred_flag = ((nalu_type == NAL_PREFIX) ? 1 : 0); |
| |
| ps_svc_nalu_ext->u1_dependency_id = |
| ((nalu_type == NAL_PREFIX) ? 0 : ps_proc->u1_spatial_layer_id); |
| |
| ps_svc_nalu_ext->u1_temporal_id = ps_proc->ps_cur_pic->i1_temporal_id; |
| |
| ps_svc_nalu_ext->u1_quality_id = 0; |
| |
| ps_svc_nalu_ext->u1_use_ref_base_pic_flag = 0; |
| |
| ps_svc_nalu_ext->u1_discardable_flag = 0; |
| |
| ps_svc_nalu_ext->u1_output_flag = 1; |
| |
| ps_svc_nalu_ext->u1_reserved_three_2bits = 3; |
| |
| ps_svc_nalu_ext->s_nalu_header.u1_nal_ref_idc = ps_codec->u4_is_curr_frm_ref ? 3 : 0; |
| |
| ps_svc_nalu_ext->s_nalu_header.u1_nal_unit_type = nalu_type; |
| |
| return IH264E_SUCCESS; |
| } |
| |
| WORD32 isvce_populate_subset_sps(isvce_codec_t *ps_codec, subset_sps_t *ps_subset_sps, |
| UWORD8 u1_sps_id, isvce_inp_buf_t *ps_inp_buf, |
| UWORD8 u1_spatial_layer_id) |
| { |
| sps_t *ps_sps = &ps_subset_sps->s_sps; |
| |
| isvce_populate_sps(ps_codec, ps_sps, u1_sps_id, IH264_SCALABLE_BASELINE, ps_inp_buf, |
| u1_spatial_layer_id); |
| |
| ps_subset_sps->s_sps_svc_ext.u1_inter_layer_deblocking_filter_control_present_flag = 1; |
| |
| ps_subset_sps->s_sps_svc_ext.i1_slice_header_restriction_flag = 1; |
| |
| ps_subset_sps->s_sps_svc_ext.u1_extended_spatial_scalability_idc = 0; |
| |
| ps_subset_sps->s_sps_svc_ext.i1_seq_tcoeff_level_prediction_flag = 0; |
| |
| ps_subset_sps->i1_svc_vui_parameters_present_flag = 0; |
| |
| ps_subset_sps->i1_additional_extension2_flag = 0; |
| |
| ps_subset_sps->s_sps_svc_ext.u1_chroma_phase_x_plus1 = 1; |
| |
| ps_subset_sps->s_sps_svc_ext.u1_chroma_phase_y_plus1 = 1; |
| |
| ps_subset_sps->s_sps_svc_ext.i1_adaptive_tcoeff_level_prediction_flag = 0; |
| |
| return IH264E_SUCCESS; |
| } |
| |
| WORD32 isvce_populate_svc_slice(isvce_process_ctxt_t *ps_proc, svc_slice_header_t *ps_svc_slice_hdr, |
| pps_t *ps_pps, subset_sps_t *ps_subset_sps, |
| svc_nalu_ext_t *ps_svc_nalu_ext) |
| { |
| WORD32 i4_return_status; |
| |
| i4_return_status = |
| isvce_populate_slice_header(ps_proc, &ps_svc_slice_hdr->s_slice_header, ps_pps, |
| &ps_subset_sps->s_sps, ps_svc_nalu_ext->u1_idr_flag); |
| |
| if(IH264E_SUCCESS != i4_return_status) |
| { |
| return IH264E_FAIL; |
| } |
| |
| ps_svc_slice_hdr->i1_slice_skip_flag = 0; |
| ps_svc_slice_hdr->i1_adaptive_residual_prediction_flag = ENABLE_RESIDUAL_PREDICTION; |
| ps_svc_slice_hdr->i1_default_residual_prediction_flag = 0; |
| ps_svc_slice_hdr->i1_adaptive_base_mode_flag = ENABLE_ILP_MV || ENABLE_IBL_MODE; |
| ps_svc_slice_hdr->i1_default_base_mode_flag = 0; |
| ps_svc_slice_hdr->i1_tcoeff_level_prediction_flag = 0; |
| ps_svc_slice_hdr->i1_constrained_intra_resampling_flag = 0; |
| ps_svc_slice_hdr->i1_adaptive_motion_prediction_flag = USE_ILP_MV_AS_MVP; |
| ps_svc_slice_hdr->i1_default_motion_prediction_flag = 0; |
| ps_svc_slice_hdr->u4_disable_inter_layer_deblocking_filter_idc = |
| !ENABLE_INTRA_BASE_DEBLOCK || ps_proc->u4_disable_deblock_level; |
| |
| if(ps_svc_slice_hdr->u4_disable_inter_layer_deblocking_filter_idc != 1) |
| { |
| /* slice_alpha_c0_offset_div2 */ |
| ps_svc_slice_hdr->i4_inter_layer_slice_alpha_c0_offset_div2 = 0; |
| |
| /* slice_beta_offset_div2 */ |
| ps_svc_slice_hdr->i4_inter_layer_slice_beta_offset_div2 = 0; |
| } |
| |
| if((ps_svc_nalu_ext->u1_quality_id == 0) && (ps_svc_nalu_ext->u1_no_inter_layer_pred_flag == 0)) |
| { |
| ps_svc_slice_hdr->u4_ref_layer_dq_id = (ps_proc->u1_spatial_layer_id - 1) << 4; |
| } |
| |
| return IH264E_SUCCESS; |
| } |
| |
| /** |
| ****************************************************************************** |
| * |
| * @brief Signals prefix_nal_unit_rbsp |
| * |
| * @par Description |
| * prefix_nal_unit_rbsp as per Section G.7.3.2.12 |
| * |
| * @param[inout] ps_bitstrm |
| * pointer to bitstream context for generating slice header |
| * |
| * @param[in] svc_nalu_ext |
| * pointer to svc NAL unit structure |
| * |
| * @param[in] ps_slice_header |
| * pointer to slice header |
| * |
| * @return success or failure error code |
| * |
| ****************************************************************************** |
| */ |
| WORD32 isvce_generate_prefix_nal(bitstrm_t *ps_bitstrm, svc_nalu_ext_t *ps_svc_nalu_ext, |
| slice_header_t *ps_slice_header, UWORD8 u1_max_num_ref_frames, |
| UWORD8 u1_num_spatial_layers) |
| { |
| WORD32 return_status = IH264E_SUCCESS; |
| |
| WORD32 i4_store_ref_base_pic_flag = 0; |
| WORD32 i4_additional_prefix_nal_unit_extension_flag = 0; |
| |
| if(ps_svc_nalu_ext->u1_dependency_id == (u1_num_spatial_layers - 1)) |
| { |
| i4_store_ref_base_pic_flag = 1; |
| if(u1_max_num_ref_frames < 2) |
| { |
| i4_store_ref_base_pic_flag = 0; |
| } |
| } |
| |
| /* store_ref_base_pic_flag */ |
| if(ps_svc_nalu_ext->s_nalu_header.u1_nal_ref_idc != 0) |
| { |
| PUT_BITS(ps_bitstrm, i4_store_ref_base_pic_flag, 1, return_status, |
| "store_ref_base_pic_flag"); |
| |
| if((ps_svc_nalu_ext->u1_use_ref_base_pic_flag || i4_store_ref_base_pic_flag) && |
| !ps_svc_nalu_ext->u1_idr_flag) |
| { |
| PUT_BITS(ps_bitstrm, ps_slice_header->u1_adaptive_ref_pic_marking_mode_flag, 1, |
| return_status, "DPRM: adaptive_ref_base_pic_marking_mode_flag"); |
| } |
| |
| PUT_BITS(ps_bitstrm, i4_additional_prefix_nal_unit_extension_flag, 1, return_status, |
| "additional_prefix_nal_unit_extension_flag"); |
| } |
| |
| /* rbsp trailing bits */ |
| return_status = ih264e_put_rbsp_trailing_bits(ps_bitstrm); |
| |
| return return_status; |
| } |
| |
| WORD32 isvce_generate_slice_header_svc(bitstrm_t *ps_bitstrm, pps_t *ps_pps, |
| svc_nalu_ext_t *ps_svc_nalu_ext, |
| svc_slice_header_t *ps_svc_slice_hdr, |
| subset_sps_t *ps_subset_sps) |
| { |
| WORD32 return_status = IH264E_SUCCESS; |
| |
| UWORD8 u1_slice_type; |
| sps_t *ps_sps = &ps_subset_sps->s_sps; |
| slice_header_t *ps_slice_hdr = &ps_svc_slice_hdr->s_slice_header; |
| |
| /* first_mb_in_slice */ |
| PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->u2_first_mb_in_slice, return_status, |
| "SH: first_mb_in_slice"); |
| |
| /* slice_type */ |
| PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->u1_slice_type, return_status, "SH: slice_type"); |
| |
| /* pic_parameter_set_id */ |
| PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->u1_pps_id, return_status, "SH: 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, |
| "SH: 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, |
| "SH: 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, |
| "SH: bottom_field_flag"); |
| } |
| } |
| |
| if(ps_svc_nalu_ext->u1_idr_flag == 1) |
| { |
| /* u2_idr_pic_id */ |
| PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->u2_idr_pic_id, return_status, "SH: 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, "SH: 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, |
| "SH: 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, |
| "SH: 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, |
| "SH: 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, |
| "SH: redundant_pic_cnt"); |
| } |
| |
| u1_slice_type = ps_slice_hdr->u1_slice_type % EPSLICE; |
| |
| if(ps_svc_nalu_ext->u1_quality_id == 0) |
| { |
| if(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, |
| "SH: direct_spatial_mv_pred_flag"); |
| } |
| |
| if(u1_slice_type == PSLICE || 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, "SH: 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, |
| "SH: num_ref_idx_l0_active_minus1"); |
| |
| if(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, "SH: num_ref_idx_l1_active_minus1"); |
| } |
| } |
| } |
| |
| /* ref_pic_list_modification */ |
| if((u1_slice_type != ISLICE) && (u1_slice_type != SISLICE)) |
| { |
| /* ref_pic_list_modification_flag_l0 */ |
| PUT_BITS(ps_bitstrm, ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l0, 1, |
| return_status, "RPLR: ref_pic_list_reordering_flag"); |
| |
| if(ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l0) |
| { |
| UWORD8 i = 0; |
| |
| WORD8 *pi1_modification_of_pic_nums_idc_l0 = |
| ps_slice_hdr->s_rplm.i1_modification_of_pic_nums_idc_l0; |
| UWORD32 *pu4_abs_diff_pic_num_minus1_l0 = |
| ps_slice_hdr->s_rplm.u4_abs_diff_pic_num_minus1_l0; |
| UWORD8 *pu1_long_term_pic_num_l0 = ps_slice_hdr->s_rplm.u1_long_term_pic_num_l0; |
| |
| do |
| { |
| /* modification_of_pic_nums_idc */ |
| PUT_BITS_UEV(ps_bitstrm, pi1_modification_of_pic_nums_idc_l0[i], return_status, |
| "RPLR: reordering_of_pic_nums_idc"); |
| |
| if((0 == pi1_modification_of_pic_nums_idc_l0[i]) || |
| (1 == pi1_modification_of_pic_nums_idc_l0[i])) |
| { |
| /* abs_diff_pic_num_minus1 */ |
| PUT_BITS_UEV(ps_bitstrm, pu4_abs_diff_pic_num_minus1_l0[0], return_status, |
| "RPLR: abs_diff_pic_num_minus1"); |
| |
| pu4_abs_diff_pic_num_minus1_l0++; |
| } |
| else if(2 == pi1_modification_of_pic_nums_idc_l0[i]) |
| { |
| /* long_term_pic_num */ |
| PUT_BITS_UEV(ps_bitstrm, pu1_long_term_pic_num_l0[0], return_status, |
| "RPLR: long_term_pic_num"); |
| |
| pu1_long_term_pic_num_l0++; |
| } |
| } while(pi1_modification_of_pic_nums_idc_l0[i++] != 3); |
| } |
| } |
| |
| if(u1_slice_type == BSLICE) |
| { |
| /* ref_pic_list_modification_flag_l1 */ |
| PUT_BITS(ps_bitstrm, ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l1, 1, |
| return_status, "SH: ref_pic_list_modification_flag_l1"); |
| |
| if(ps_slice_hdr->s_rplm.i1_ref_pic_list_modification_flag_l1) |
| { |
| UWORD8 i = 0; |
| |
| WORD8 *pi1_modification_of_pic_nums_idc_l1 = |
| ps_slice_hdr->s_rplm.i1_modification_of_pic_nums_idc_l1; |
| UWORD32 *pu4_abs_diff_pic_num_minus1_l1 = |
| ps_slice_hdr->s_rplm.u4_abs_diff_pic_num_minus1_l1; |
| UWORD8 *pu1_long_term_pic_num_l1 = ps_slice_hdr->s_rplm.u1_long_term_pic_num_l1; |
| |
| do |
| { |
| /* modification_of_pic_nums_idc */ |
| PUT_BITS_UEV(ps_bitstrm, pi1_modification_of_pic_nums_idc_l1[i], return_status, |
| "SH: modification_of_pic_nums_idc"); |
| |
| if((0 == pi1_modification_of_pic_nums_idc_l1[i]) || |
| (1 == pi1_modification_of_pic_nums_idc_l1[i])) |
| { |
| /* abs_diff_pic_num_minus1 */ |
| PUT_BITS_UEV(ps_bitstrm, pu4_abs_diff_pic_num_minus1_l1[0], return_status, |
| "SH: abs_diff_pic_num_minus1"); |
| |
| pu4_abs_diff_pic_num_minus1_l1++; |
| } |
| else if(2 == pi1_modification_of_pic_nums_idc_l1[i]) |
| { |
| /* long_term_pic_num */ |
| PUT_BITS_UEV(ps_bitstrm, pu1_long_term_pic_num_l1[0], return_status, |
| "SH: abs_diff_pic_num_minus1"); |
| |
| pu1_long_term_pic_num_l1++; |
| } |
| } while(pi1_modification_of_pic_nums_idc_l1[i++] != 3); |
| } |
| } |
| |
| if((ps_pps->i1_weighted_pred_flag && u1_slice_type == PSLICE) || |
| (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_svc_nalu_ext->u1_idr_flag) |
| { |
| /* no_output_of_prior_pics_flag */ |
| PUT_BITS(ps_bitstrm, ps_slice_hdr->u1_no_output_of_prior_pics_flag, 1, |
| return_status, "DRPM: 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, |
| "DRPM: 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, "DPRM: 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_subset_sps->s_sps_svc_ext.i1_slice_header_restriction_flag == 0) |
| { |
| WORD32 i4_store_ref_base_pic_flag = 0; |
| |
| if(ps_sps->u1_max_num_ref_frames >= 2) |
| { |
| i4_store_ref_base_pic_flag = 1; |
| } |
| |
| /* store_ref_base_pic_flag */ |
| PUT_BITS(ps_bitstrm, i4_store_ref_base_pic_flag, 1, return_status, |
| "SH: store_ref_base_pic_flag"); |
| |
| if((ps_svc_nalu_ext->u1_use_ref_base_pic_flag || i4_store_ref_base_pic_flag) && |
| (!ps_svc_nalu_ext->u1_idr_flag)) |
| { |
| PUT_BITS(ps_bitstrm, ps_slice_hdr->u1_adaptive_ref_pic_marking_mode_flag, 1, |
| return_status, "SH: adaptive_ref_base_pic_marking_mode_flag"); |
| } |
| } |
| } |
| } |
| |
| if(ps_slice_hdr->u1_entropy_coding_mode_flag && u1_slice_type != ISLICE) |
| { |
| /* cabac_init_idc */ |
| PUT_BITS_UEV(ps_bitstrm, ps_slice_hdr->i1_cabac_init_idc, return_status, |
| "SH: 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, |
| "SH: slice_qp_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, |
| "SH: 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, |
| "SH: slice_alpha_c0_offset_div2"); |
| |
| /* slice_beta_offset_div2 */ |
| PUT_BITS_SEV(ps_bitstrm, ps_slice_hdr->i1_slice_beta_offset_div2, return_status, |
| "SH: 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 */ |
| } |
| |
| if((ps_svc_nalu_ext->u1_no_inter_layer_pred_flag == 0) && (ps_svc_nalu_ext->u1_quality_id == 0)) |
| { |
| PUT_BITS_UEV(ps_bitstrm, ps_svc_slice_hdr->u4_ref_layer_dq_id, return_status, |
| "SH: ref_layer_dq_id"); |
| if(ps_subset_sps->s_sps_svc_ext.u1_inter_layer_deblocking_filter_control_present_flag) |
| { |
| PUT_BITS_UEV(ps_bitstrm, ps_svc_slice_hdr->u4_disable_inter_layer_deblocking_filter_idc, |
| return_status, "SH: disable_inter_layer_deblocking_filter_idc"); |
| if(ps_svc_slice_hdr->u4_disable_inter_layer_deblocking_filter_idc != 1) |
| { |
| PUT_BITS_SEV(ps_bitstrm, |
| ps_svc_slice_hdr->i4_inter_layer_slice_alpha_c0_offset_div2, |
| return_status, "SH: inter_layer_slice_alpha_c0_offset_div2"); |
| PUT_BITS_SEV(ps_bitstrm, ps_svc_slice_hdr->i4_inter_layer_slice_beta_offset_div2, |
| return_status, "SH: inter_layer_slice_beta_offset_div2"); |
| } |
| } |
| PUT_BITS(ps_bitstrm, ps_svc_slice_hdr->i1_constrained_intra_resampling_flag, 1, |
| return_status, "SH: constrained_intra_resampling_flag"); |
| if(ps_subset_sps->s_sps_svc_ext.u1_extended_spatial_scalability_idc == 2) |
| { |
| if(ps_sps->u1_chroma_format_idc > 0) |
| { |
| PUT_BITS(ps_bitstrm, ps_svc_slice_hdr->i1_ref_layer_chroma_phase_x_plus1_flag, 1, |
| return_status, "SH: ref_layer_chroma_phase_x_plus1_flag"); |
| PUT_BITS(ps_bitstrm, ps_svc_slice_hdr->i1_ref_layer_chroma_phase_y_plus1, 2, |
| return_status, "SH: ref_layer_chroma_phase_y_plus1"); |
| } |
| PUT_BITS_SEV(ps_bitstrm, ps_svc_slice_hdr->i4_scaled_ref_layer_left, return_status, |
| "SH: scaled_ref_layer_left_offset"); |
| PUT_BITS_SEV(ps_bitstrm, ps_svc_slice_hdr->i4_scaled_ref_layer_top, return_status, |
| "SH: scaled_ref_layer_top_offset"); |
| PUT_BITS_SEV(ps_bitstrm, ps_svc_slice_hdr->i4_scaled_ref_layer_right, return_status, |
| "SH: scaled_ref_layer_right_offset"); |
| PUT_BITS_SEV(ps_bitstrm, ps_svc_slice_hdr->i4_scaled_ref_layer_bottom, return_status, |
| "SH: scaled_ref_layer_bottom_offset"); |
| } |
| } |
| |
| if(!ps_svc_nalu_ext->u1_no_inter_layer_pred_flag) |
| { |
| PUT_BITS(ps_bitstrm, ps_svc_slice_hdr->i1_slice_skip_flag, 1, return_status, |
| "SH: slice_skip_flag"); |
| if(ps_svc_slice_hdr->i1_slice_skip_flag) |
| { |
| PUT_BITS_UEV(ps_bitstrm, ps_svc_slice_hdr->u4_num_mbs_in_slice_minus1, return_status, |
| "SH: num_mbs_in_slice_minus1"); |
| } |
| else |
| { |
| PUT_BITS(ps_bitstrm, ps_svc_slice_hdr->i1_adaptive_base_mode_flag, 1, return_status, |
| "SH: adaptive_base_mode_flag"); |
| if(!ps_svc_slice_hdr->i1_adaptive_base_mode_flag) |
| PUT_BITS(ps_bitstrm, ps_svc_slice_hdr->i1_default_base_mode_flag, 1, return_status, |
| "SH: default_base_mode_flag"); |
| |
| if(!ps_svc_slice_hdr->i1_default_base_mode_flag) |
| { |
| PUT_BITS(ps_bitstrm, ps_svc_slice_hdr->i1_adaptive_motion_prediction_flag, 1, |
| return_status, "SH: adaptive_motion_prediction_flag"); |
| if(!ps_svc_slice_hdr->i1_adaptive_motion_prediction_flag) |
| PUT_BITS(ps_bitstrm, ps_svc_slice_hdr->i1_default_motion_prediction_flag, 1, |
| return_status, "SH: default_motion_prediction_flag"); |
| } |
| PUT_BITS(ps_bitstrm, ps_svc_slice_hdr->i1_adaptive_residual_prediction_flag, 1, |
| return_status, "SH: adaptive_residual_prediction_flag"); |
| if(!ps_svc_slice_hdr->i1_adaptive_residual_prediction_flag) |
| PUT_BITS(ps_bitstrm, ps_svc_slice_hdr->i1_default_residual_prediction_flag, 1, |
| return_status, "SH: default_residual_prediction_flag"); |
| } |
| |
| if(ps_subset_sps->s_sps_svc_ext.i1_adaptive_tcoeff_level_prediction_flag) |
| { |
| PUT_BITS(ps_bitstrm, ps_svc_slice_hdr->i1_tcoeff_level_prediction_flag, 1, |
| return_status, "SH: tcoeff_level_prediction_flag"); |
| } |
| } |
| |
| if(!ps_subset_sps->s_sps_svc_ext.i1_slice_header_restriction_flag && |
| !ps_svc_slice_hdr->i1_slice_skip_flag) |
| { |
| PUT_BITS(ps_bitstrm, ps_svc_slice_hdr->u4_scan_idx_start, 4, return_status, |
| "SH: scan_idx_start"); |
| PUT_BITS(ps_bitstrm, ps_svc_slice_hdr->u4_scan_idx_end, 4, return_status, |
| "SH: scan_idx_end"); |
| } |
| |
| return return_status; |
| } |
| |
| WORD32 isvce_seq_parameter_set_svc_extension(bitstrm_t *ps_bitstrm, subset_sps_t *ps_sub_sps, |
| UWORD8 u1_chroma_format_idc) |
| { |
| WORD32 return_status = IH264E_SUCCESS; |
| |
| /* inter_layer_deblocking_filter_control_present_flag */ |
| PUT_BITS(ps_bitstrm, |
| ps_sub_sps->s_sps_svc_ext.u1_inter_layer_deblocking_filter_control_present_flag, 1, |
| return_status, "SPS: inter_layer_deblocking_filter_control_present_flag"); |
| |
| /* extended_spatial_scalability */ |
| PUT_BITS(ps_bitstrm, ps_sub_sps->s_sps_svc_ext.u1_extended_spatial_scalability_idc, 2, |
| return_status, "SPS: extended_spatial_scalability"); |
| |
| if(u1_chroma_format_idc == 1 || u1_chroma_format_idc == 2) |
| { |
| /* chroma_phase_x_plus1_flag */ |
| PUT_BITS(ps_bitstrm, ps_sub_sps->s_sps_svc_ext.u1_chroma_phase_x_plus1, 1, return_status, |
| "SPS: chroma_phase_x_plus1_flag"); |
| } |
| |
| if(u1_chroma_format_idc == 1) |
| { |
| /* chroma_phase_y_plus1 */ |
| PUT_BITS(ps_bitstrm, ps_sub_sps->s_sps_svc_ext.u1_chroma_phase_y_plus1, 2, return_status, |
| "SPS: chroma_phase_y_plus1"); |
| } |
| |
| if(ps_sub_sps->s_sps_svc_ext.u1_extended_spatial_scalability_idc == 1) |
| { |
| if(u1_chroma_format_idc > 0) |
| { |
| /* seq_ref_layer_chroma_phase_x_plus1_flag */ |
| PUT_BITS(ps_bitstrm, |
| ps_sub_sps->s_sps_svc_ext.u1_seq_ref_layer_chroma_phase_x_plus1_flag, 1, |
| return_status, "SPS: seq_ref_layer_chroma_phase_x_plus1_flag"); |
| |
| /* seq_ref_layer_chroma_phase_y_plus1 */ |
| PUT_BITS(ps_bitstrm, ps_sub_sps->s_sps_svc_ext.u1_seq_ref_layer_chroma_phase_y_plus1, 2, |
| return_status, "SPS: seq_ref_layer_chroma_phase_y_plus1"); |
| } |
| /* seq_scaled_ref_layer_left_offset */ |
| PUT_BITS_SEV(ps_bitstrm, ps_sub_sps->s_sps_svc_ext.i4_seq_scaled_ref_layer_left_offset, |
| return_status, "SPS: seq_scaled_ref_layer_left_offset"); |
| |
| /* seq_scaled_ref_layer_top_offset */ |
| PUT_BITS_SEV(ps_bitstrm, ps_sub_sps->s_sps_svc_ext.i4_seq_scaled_ref_layer_top_offset, |
| return_status, "SPS: seq_scaled_ref_layer_top_offset"); |
| |
| /* seq_scaled_ref_layer_right_offset */ |
| PUT_BITS_SEV(ps_bitstrm, ps_sub_sps->s_sps_svc_ext.i4_seq_scaled_ref_layer_right_offset, |
| return_status, "SPS: seq_scaled_ref_layer_right_offset"); |
| |
| /* seq_scaled_ref_layer_bottom_offset */ |
| PUT_BITS_SEV(ps_bitstrm, ps_sub_sps->s_sps_svc_ext.i4_seq_scaled_ref_layer_bottom_offset, |
| return_status, "SPS: seq_scaled_ref_layer_bottom_offset"); |
| } |
| |
| /* seq_tcoeff_level_prediction_flag */ |
| PUT_BITS(ps_bitstrm, ps_sub_sps->s_sps_svc_ext.i1_seq_tcoeff_level_prediction_flag, 1, |
| return_status, "SPS: seq_tcoeff_level_prediction_flag"); |
| |
| if(ps_sub_sps->s_sps_svc_ext.i1_seq_tcoeff_level_prediction_flag) |
| { |
| /* adaptive_tcoeff_level_prediction_flag */ |
| PUT_BITS(ps_bitstrm, ps_sub_sps->s_sps_svc_ext.i1_adaptive_tcoeff_level_prediction_flag, 1, |
| return_status, "SPS: adaptive_tcoeff_level_prediction_flag"); |
| } |
| |
| /* slice_header_restriction_flag */ |
| PUT_BITS(ps_bitstrm, ps_sub_sps->s_sps_svc_ext.i1_slice_header_restriction_flag, 1, |
| return_status, "SPS: slice_header_restriction_flag"); |
| |
| return return_status; |
| } |
| |
| WORD32 isvce_svc_vui_parameters_extension(bitstrm_t *ps_bitstrm, svc_vui_ext_t *ps_svc_vui) |
| { |
| WORD32 return_status = IH264E_SUCCESS; |
| UWORD32 i; |
| |
| PUT_BITS_UEV(ps_bitstrm, ps_svc_vui->u4_vui_ext_num_entries_minus1, return_status, |
| "num_layers_minus1"); |
| |
| for(i = 0; i < ps_svc_vui->u4_vui_ext_num_entries_minus1; i++) |
| { |
| /* dependency_id */ |
| PUT_BITS(ps_bitstrm, ps_svc_vui->u1_vui_ext_dependency_id[i], 3, return_status, |
| "dependency_id"); |
| |
| /* quality_id */ |
| PUT_BITS(ps_bitstrm, ps_svc_vui->u1_vui_ext_quality_id[i], 4, return_status, "quality_id"); |
| |
| /* temporal_id */ |
| PUT_BITS(ps_bitstrm, ps_svc_vui->u1_vui_ext_temporal_id[i], 3, return_status, |
| "temporal_id"); |
| |
| /* timing_info_present_flag */ |
| PUT_BITS(ps_bitstrm, ps_svc_vui->u1_vui_ext_timing_info_present_flag[i], 1, return_status, |
| "timing_info_present_flag"); |
| |
| if(ps_svc_vui->u1_vui_ext_timing_info_present_flag[i]) |
| { |
| /* num_units_in_tick */ |
| PUT_BITS(ps_bitstrm, ps_svc_vui->u4_vui_ext_num_units_in_tick[i], 32, return_status, |
| "num_units_in_tick"); |
| |
| /* time_scale */ |
| PUT_BITS(ps_bitstrm, ps_svc_vui->u4_vui_ext_time_scale[i], 32, return_status, |
| "time_scale"); |
| |
| /* fixed_frame_rate_flag */ |
| PUT_BITS(ps_bitstrm, ps_svc_vui->u1_vui_ext_fixed_frame_rate_flag[i], 1, return_status, |
| "fixed_frame_rate_flag"); |
| } |
| |
| /* nal_hrd_parameters_present_flag */ |
| PUT_BITS(ps_bitstrm, ps_svc_vui->u1_vui_ext_nal_hrd_params_present_flag[i], 1, |
| return_status, "nal_hrd_parameters_present_flag"); |
| |
| if(ps_svc_vui->u1_vui_ext_nal_hrd_params_present_flag[i]) |
| { |
| } |
| |
| /* nal_hrd_parameters_present_flag */ |
| PUT_BITS(ps_bitstrm, ps_svc_vui->u1_vui_ext_vcl_hrd_params_present_flag[i], 1, |
| return_status, "vcl_hrd_parameters_present_flag"); |
| |
| if(ps_svc_vui->u1_vui_ext_vcl_hrd_params_present_flag[i]) |
| { |
| } |
| |
| if(ps_svc_vui->u1_vui_ext_nal_hrd_params_present_flag[i] || |
| ps_svc_vui->u1_vui_ext_vcl_hrd_params_present_flag[i]) |
| { |
| /* low_delay_hrd_flag */ |
| PUT_BITS(ps_bitstrm, ps_svc_vui->u1_vui_ext_low_delay_hrd_flag[i], 1, return_status, |
| "low_delay_hrd_flag"); |
| } |
| |
| /* pic_struct_present_flag */ |
| PUT_BITS(ps_bitstrm, ps_svc_vui->u1_vui_ext_pic_struct_present_flag[i], 1, return_status, |
| "pic_struct_present_flag"); |
| } |
| |
| return return_status; |
| } |
| |
| WORD32 isvce_generate_subset_sps(bitstrm_t *ps_bitstrm, subset_sps_t *ps_subset_sps) |
| { |
| WORD32 return_status = IH264E_SUCCESS; |
| sps_t *ps_sps = &ps_subset_sps->s_sps; |
| return_status = isvce_generate_sps(ps_bitstrm, &ps_subset_sps->s_sps, NAL_SUBSET_SPS); |
| |
| /* generate subset sps */ |
| if(ps_sps->u1_profile_idc == IH264_SCALABLE_BASELINE || |
| ps_sps->u1_profile_idc == IH264_SCALABLE_HIGH_PROFILE) |
| { |
| isvce_seq_parameter_set_svc_extension(ps_bitstrm, ps_subset_sps, |
| ps_sps->u1_chroma_format_idc); |
| |
| /* svc_vui_parameters_present_flag */ |
| PUT_BITS(ps_bitstrm, ps_subset_sps->i1_svc_vui_parameters_present_flag, 1, return_status, |
| "SPS: svc_vui_parameters_present_flag"); |
| |
| if(ps_subset_sps->i1_svc_vui_parameters_present_flag == 1) |
| { |
| svc_vui_ext_t *ps_svc_vui = NULL; |
| isvce_svc_vui_parameters_extension(ps_bitstrm, ps_svc_vui); |
| } |
| |
| /* additional_extension2_flag */ |
| PUT_BITS(ps_bitstrm, ps_subset_sps->i1_additional_extension2_flag, 1, return_status, |
| "SPS: additional_extension2_flag"); |
| } |
| |
| /* rbsp trailing bits */ |
| return_status = ih264e_put_rbsp_trailing_bits(ps_bitstrm); |
| |
| return return_status; |
| } |
| /** |
| ****************************************************************************** |
| * |
| * @brief Generates svc_nalu_ext |
| * |
| * @par Description |
| * Generate svc_nalu_ext as per Section G.7.3.1.1 |
| * |
| * @param[inout] ps_bitstrm |
| * pointer to bitstream context for generating slice header |
| * |
| * @param[in] ps_svc_nalu_ext |
| * pointer to svc_nalu_ext struct |
| * |
| * @return success or failure error code |
| * |
| ****************************************************************************** |
| */ |
| WORD32 isvce_generate_svc_nalu_extension(bitstrm_t *ps_bitstrm, svc_nalu_ext_t *ps_svc_nalu_ext, |
| UWORD8 u1_nalu_id) |
| { |
| WORD32 return_status = IH264E_SUCCESS; |
| |
| /* Insert start code */ |
| return_status = ih264e_put_nal_start_code_prefix(ps_bitstrm, 1); |
| |
| if(return_status != IH264E_SUCCESS) |
| { |
| return return_status; |
| } |
| |
| /* Insert Nal Unit Header */ |
| return_status = isvce_generate_nal_unit_header(ps_bitstrm, u1_nalu_id, 3); |
| |
| if(return_status != IH264E_SUCCESS) |
| { |
| return return_status; |
| } |
| |
| /* reserved_one_bit */ |
| PUT_BITS(ps_bitstrm, 1, 1, return_status, "NAL unit header: reserved_one_bit"); |
| |
| /* idr_flag */ |
| PUT_BITS(ps_bitstrm, ps_svc_nalu_ext->u1_idr_flag, 1, return_status, |
| "NAL unit header: idr_flag"); |
| |
| /* priority_id */ |
| PUT_BITS(ps_bitstrm, ps_svc_nalu_ext->u1_priority_id, 6, return_status, |
| "NAL unit header: priority_id"); |
| |
| /* no_inter_layer_pred_flag */ |
| PUT_BITS(ps_bitstrm, ps_svc_nalu_ext->u1_no_inter_layer_pred_flag, 1, return_status, |
| "NAL unit header: no_inter_layer_pred_flag"); |
| |
| /* dependency_id */ |
| PUT_BITS(ps_bitstrm, ps_svc_nalu_ext->u1_dependency_id, 3, return_status, |
| "NAL unit header: dependency_id"); |
| |
| /* quality_id */ |
| PUT_BITS(ps_bitstrm, ps_svc_nalu_ext->u1_quality_id, 4, return_status, |
| "NAL unit header: quality_id"); |
| |
| /* temporal_id */ |
| PUT_BITS(ps_bitstrm, ps_svc_nalu_ext->u1_temporal_id, 3, return_status, |
| "NAL unit header: temporal_id"); |
| |
| /* use_ref_base_pic_flag */ |
| PUT_BITS(ps_bitstrm, ps_svc_nalu_ext->u1_use_ref_base_pic_flag, 1, return_status, |
| "NAL unit header: use_ref_base_pic_flag"); |
| |
| /* discardable_flag */ |
| PUT_BITS(ps_bitstrm, ps_svc_nalu_ext->u1_discardable_flag, 1, return_status, |
| "NAL unit header: discardable_flag"); |
| |
| /* output_flag */ |
| PUT_BITS(ps_bitstrm, ps_svc_nalu_ext->u1_output_flag, 1, return_status, |
| "NAL unit header: output_flag"); |
| |
| /* reserved_three_2bits */ |
| PUT_BITS(ps_bitstrm, ps_svc_nalu_ext->u1_reserved_three_2bits, 2, return_status, |
| "NAL unit header: reserved_three_2bits"); |
| |
| return return_status; |
| } |