C++程序  |  1551行  |  52.58 KB

/******************************************************************************
 *
 * 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;
}