1666 lines
56 KiB
C
1666 lines
56 KiB
C
|
/******************************************************************************
|
||
|
*
|
||
|
* 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_sei()
|
||
|
* - 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_sei.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);
|
||
|
if(return_status != IH264E_SUCCESS)
|
||
|
{
|
||
|
return return_status;
|
||
|
}
|
||
|
/* Insert Nal Unit Header */
|
||
|
return_status = ih264e_generate_nal_unit_header(ps_bitstrm, i1_nal_unit_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_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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* 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);
|
||
|
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 SEI (Supplemental Enhancement Information)
|
||
|
*
|
||
|
* @par Description
|
||
|
* This function generates Supplemental Enhancement Information header as per the spec
|
||
|
*
|
||
|
* @param[in] ps_bitstrm
|
||
|
* pointer to bitstream context (handle)
|
||
|
*
|
||
|
* @param[in] ps_sei
|
||
|
* pointer to structure containing SEI data
|
||
|
*
|
||
|
* @return success or failure error code
|
||
|
*
|
||
|
******************************************************************************
|
||
|
*/
|
||
|
IH264E_ERROR_T ih264e_generate_sei(bitstrm_t *ps_bitstrm, sei_params_t *ps_sei,
|
||
|
UWORD32 u4_insert_per_idr)
|
||
|
{
|
||
|
WORD32 return_status = IH264E_SUCCESS;
|
||
|
WORD8 i1_nal_unit_type = NAL_SEI;
|
||
|
WORD8 i1_nal_ref_idc = 0;
|
||
|
|
||
|
/* 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 = ih264e_generate_nal_unit_header(ps_bitstrm,
|
||
|
i1_nal_unit_type, i1_nal_ref_idc);
|
||
|
if(return_status != IH264E_SUCCESS)
|
||
|
{
|
||
|
return return_status;
|
||
|
}
|
||
|
/* Mastering Display Color SEI */
|
||
|
if(1 == ps_sei->u1_sei_mdcv_params_present_flag && u4_insert_per_idr)
|
||
|
{
|
||
|
return_status = ih264e_put_sei_msg(IH264_SEI_MASTERING_DISP_COL_VOL,
|
||
|
ps_sei, ps_bitstrm);
|
||
|
if(return_status != IH264E_SUCCESS)
|
||
|
{
|
||
|
return return_status;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Content Light Level Information*/
|
||
|
if(1 == ps_sei->u1_sei_cll_params_present_flag && u4_insert_per_idr)
|
||
|
{
|
||
|
return_status = ih264e_put_sei_msg(IH264_SEI_CONTENT_LIGHT_LEVEL_DATA,
|
||
|
ps_sei, ps_bitstrm);
|
||
|
if(return_status != IH264E_SUCCESS)
|
||
|
{
|
||
|
return return_status;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Ambient viewing environment SEI */
|
||
|
if(1 == ps_sei->u1_sei_ave_params_present_flag && u4_insert_per_idr)
|
||
|
{
|
||
|
return_status = ih264e_put_sei_msg(IH264_SEI_AMBIENT_VIEWING_ENVIRONMENT,
|
||
|
ps_sei, ps_bitstrm);
|
||
|
if(return_status != IH264E_SUCCESS)
|
||
|
{
|
||
|
return return_status;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Content color volume Information*/
|
||
|
if(1 == ps_sei->u1_sei_ccv_params_present_flag)
|
||
|
{
|
||
|
return_status = ih264e_put_sei_msg(IH264_SEI_CONTENT_COLOR_VOLUME,
|
||
|
ps_sei, ps_bitstrm);
|
||
|
if(return_status != IH264E_SUCCESS)
|
||
|
{
|
||
|
return return_status;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* rbsp trailing bits */
|
||
|
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);
|
||
|
if(return_status != IH264E_SUCCESS)
|
||
|
{
|
||
|
return return_status;
|
||
|
}
|
||
|
/* 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);
|
||
|
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 (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(return_status != IH264E_SUCCESS)
|
||
|
{
|
||
|
return return_status;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|