Revision f1b94134a4b879bc55c3dacdb496690c8ebdc03f authored by Vikram Fugro on 11 March 2016, 12:16:11 UTC, committed by Jean-Baptiste Kempf on 11 March 2016, 14:57:34 UTC
Allocate the output vlc pictures with dimensions padded,
as requested by the decoder (for alignments). This further
increases the chances of direct rendering.

Signed-off-by: Jean-Baptiste Kempf <jb@videolan.org>
1 parent 6c813cb
Raw File
hevc_nal.c
/*****************************************************************************
 * Copyright © 2010-2014 VideoLAN
 *
 * Authors: Thomas Guillem <thomas.guillem@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "hevc_nal.h"
#include "hxxx_nal.h"

#include <vlc_common.h>
#include <vlc_bits.h>

#include <limits.h>

typedef uint8_t  nal_u1_t;
typedef uint8_t  nal_u2_t;
typedef uint8_t  nal_u3_t;
typedef uint8_t  nal_u4_t;
typedef uint8_t  nal_u5_t;
typedef uint8_t  nal_u6_t;
typedef uint8_t  nal_u7_t;
typedef uint8_t  nal_u8_t;
typedef int32_t  nal_se_t;
typedef uint32_t nal_ue_t;

typedef struct
{
    nal_u2_t profile_space;
    nal_u1_t tier_flag;
    nal_u5_t profile_idc;
    uint32_t profile_compatibility_flag; /* nal_u1_t * 32 */
    nal_u1_t progressive_source_flag;
    nal_u1_t interlaced_source_flag;
    nal_u1_t non_packed_constraint_flag;
    nal_u1_t frame_only_constraint_flag;
    struct
    {
        nal_u1_t max_12bit_constraint_flag;
        nal_u1_t max_10bit_constraint_flag;
        nal_u1_t max_8bit_constraint_flag;
        nal_u1_t max_422chroma_constraint_flag;
        nal_u1_t max_420chroma_constraint_flag;
        nal_u1_t max_monochrome_constraint_flag;
        nal_u1_t intra_constraint_flag;
        nal_u1_t one_picture_only_constraint_flag;
        nal_u1_t lower_bit_rate_constraint_flag;
    } idc4to7;
    struct
    {
        nal_u1_t inbld_flag;
    } idc1to5;
} hevc_inner_profile_tier_level_t;

#define HEVC_MAX_SUBLAYERS 8
typedef struct
{
    hevc_inner_profile_tier_level_t general;
    nal_u8_t general_level_idc;
    uint8_t  sublayer_profile_present_flag;  /* nal_u1_t * 8 */
    uint8_t  sublayer_level_present_flag;    /* nal_u1_t * 8 */
    hevc_inner_profile_tier_level_t sub_layer[HEVC_MAX_SUBLAYERS];
    nal_u8_t sub_layer_level_idc[HEVC_MAX_SUBLAYERS];
} hevc_profile_tier_level_t;

#define HEVC_MAX_SHORT_TERM_REF_PIC_SET 65
#define HEVC_MAX_LONG_TERM_REF_PIC_SET 33

typedef struct
{
    unsigned num_delta_pocs;
} hevc_short_term_ref_pic_set_t;

typedef struct
{
    nal_u1_t aspect_ratio_info_present_flag;
    struct
    {
        nal_u8_t aspect_ratio_idc;
        uint16_t sar_width;
        uint16_t sar_height;
    } ar;
    nal_u1_t overscan_info_present_flag;
    nal_u1_t overscan_appropriate_flag;

    nal_u1_t video_signal_type_present_flag;
    struct
    {
        nal_u3_t video_format;
        nal_u1_t video_full_range_flag;
        nal_u1_t colour_description_present_flag;
        struct
        {
            nal_u8_t colour_primaries;
            nal_u8_t transfer_characteristics;
            nal_u8_t matrix_coeffs;
        } colour;
    } vs;

    nal_u1_t chroma_loc_info_present_flag;
    struct
    {
        nal_ue_t sample_loc_type_top_field;
        nal_ue_t sample_loc_type_bottom_field;
    } chroma;

    nal_u1_t neutral_chroma_indication_flag;
    nal_u1_t field_seq_flag;
    nal_u1_t frame_field_info_present_flag;

    nal_u1_t default_display_window_flag;
    struct
    {
        nal_ue_t win_left_offset;
        nal_ue_t win_right_offset;
        nal_ue_t win_top_offset;
        nal_ue_t win_bottom_offset;
    } def_disp;

    nal_u1_t vui_timing_info_present_flag;
    struct
    {
        uint32_t vui_num_units_in_tick;
        uint32_t vui_time_scale;
        /* incomplete */
    } timing;

    /* incomplete */
} hevc_vui_parameters_t;

struct hevc_video_parameter_set_t
{
    nal_u4_t vps_video_parameter_set_id;
    nal_u1_t vps_base_layer_internal_flag;
    nal_u1_t vps_base_layer_available_flag;
    nal_u6_t vps_max_layers_minus1;
    nal_u3_t vps_max_sub_layers_minus1;
    nal_u1_t vps_temporal_id_nesting_flag;

    hevc_profile_tier_level_t profile_tier_level;

    nal_u1_t vps_sub_layer_ordering_info_present_flag;
    struct
    {
        nal_ue_t dec_pic_buffering_minus1;
        nal_ue_t num_reorder_pics;
        nal_ue_t max_latency_increase_plus1;
    } vps_max[1 + HEVC_MAX_SUBLAYERS];

    nal_u6_t vps_max_layer_id;
    nal_ue_t vps_num_layer_set_minus1;
    // layer_id_included_flag; read but discarded

    nal_u1_t vps_timing_info_present_flag;
    uint32_t vps_num_units_in_tick;
    uint32_t vps_time_scale;

    /* incomplete */
};

struct hevc_sequence_parameter_set_t
{
    nal_u4_t sps_video_parameter_set_id;
    nal_u3_t sps_max_sub_layers_minus1;
    nal_u1_t sps_temporal_id_nesting_flag;

    hevc_profile_tier_level_t profile_tier_level;

    nal_ue_t sps_seq_parameter_set_id;
    nal_ue_t chroma_format_idc;
    nal_u1_t separate_colour_plane_flag;

    nal_ue_t pic_width_in_luma_samples;
    nal_ue_t pic_height_in_luma_samples;

    nal_u1_t conformance_window_flag;
    struct
    {
    nal_ue_t left_offset;
    nal_ue_t right_offset;
    nal_ue_t top_offset;
    nal_ue_t bottom_offset;
    } conf_win;

    nal_ue_t bit_depth_luma_minus8;
    nal_ue_t bit_depth_chroma_minus8;
    nal_ue_t log2_max_pic_order_cnt_lsb_minus4;

    nal_u1_t sps_sub_layer_ordering_info_present_flag;
    struct
    {
    nal_ue_t dec_pic_buffering_minus1;
    nal_ue_t num_reorder_pics;
    nal_ue_t latency_increase_plus1;
    } sps_max[1 + HEVC_MAX_SUBLAYERS];

    nal_ue_t log2_min_luma_coding_block_size_minus3;
    nal_ue_t log2_diff_max_min_luma_coding_block_size;
    nal_ue_t log2_min_luma_transform_block_size_minus2;
    nal_ue_t log2_diff_max_min_luma_transform_block_size;

    /* incomplete */
    nal_ue_t max_transform_hierarchy_depth_inter;
    nal_ue_t max_transform_hierarchy_depth_intra;
    nal_u1_t scaling_list_enabled;
    nal_u1_t sps_scaling_list_data_present_flag;
    // scaling_list_data; read but discarded

    nal_u1_t amp_enabled_flag;
    nal_u1_t sample_adaptive_offset_enabled_flag;

    nal_u1_t pcm_enabled_flag;
    nal_u4_t pcm_sample_bit_depth_luma_minus1;
    nal_u4_t pcm_sample_bit_depth_chroma_minus1;
    nal_ue_t log2_min_pcm_luma_coding_block_size_minus3;
    nal_ue_t log2_diff_max_min_pcm_luma_coding_block_size;
    nal_u1_t pcm_loop_filter_disabled_flag;

    nal_ue_t num_short_term_ref_pic_sets;
    // st_ref_pic_set

    nal_u1_t long_term_ref_pics_present_flag;
    nal_ue_t num_long_term_ref_pics_sps;
    //

    nal_u1_t sps_temporal_mvp_enabled_flag;
    nal_u1_t strong_intra_smoothing_enabled_flag;

    nal_u1_t vui_parameters_present_flag;
    hevc_vui_parameters_t vui;
    /* incomplete */
};

struct hevc_picture_parameter_set_t
{
    nal_ue_t pps_pic_parameter_set_id;
    nal_ue_t pps_seq_parameter_set_id;
    nal_u1_t dependent_slice_segments_enabled_flag;
    nal_u1_t output_flag_present_flag;
    nal_u3_t num_extra_slice_header_bits;
    nal_u1_t sign_data_hiding_enabled_flag;
    nal_u1_t cabac_init_present_flag;
    nal_ue_t num_ref_idx_l0_default_active_minus1;
    nal_ue_t num_ref_idx_l1_default_active_minus1;
    nal_se_t init_qp_minus26;
    nal_u1_t constrained_intra_pred_flag;
    nal_u1_t transform_skip_enabled_flag;

    nal_u1_t cu_qp_delta_enabled_flag;
    nal_ue_t diff_cu_qp_delta_depth;

    nal_se_t pps_cb_qp_offset;
    nal_se_t pps_cr_qp_offset;
    nal_u1_t pic_slice_level_chroma_qp_offsets_present_flag;
    nal_u1_t weighted_pred_flag;
    nal_u1_t weighted_bipred_flag;
    nal_u1_t transquant_bypass_enable_flag;

    nal_u1_t tiles_enabled_flag;
    nal_u1_t entropy_coding_sync_enabled_flag;
    nal_ue_t num_tile_columns_minus1;
    nal_ue_t num_tile_rows_minus1;
    nal_u1_t uniform_spacing_flag;
    // nal_ue_t *p_column_width_minus1; read but discarded
    // nal_ue_t *p_row_height_minus1; read but discarded
    nal_u1_t loop_filter_across_tiles_enabled_flag;

    nal_u1_t pps_loop_filter_across_slices_enabled_flag;

    nal_u1_t deblocking_filter_control_present_flag;
    nal_u1_t deblocking_filter_override_enabled_flag;
    nal_u1_t pps_deblocking_filter_disabled_flag;
    nal_se_t pps_beta_offset_div2;
    nal_se_t pps_tc_offset_div2;

    nal_u1_t scaling_list_data_present_flag;
    // scaling_list_data; read but discarded

    nal_u1_t lists_modification_present_flag;
    nal_ue_t log2_parallel_merge_level_minus2;
    nal_u1_t slice_header_extension_present_flag;

    nal_u1_t pps_extension_present_flag;
    nal_u1_t pps_range_extension_flag;
    nal_u1_t pps_multilayer_extension_flag;
    nal_u1_t pps_3d_extension_flag;
    nal_u5_t pps_extension_5bits;
    /* incomplete */

};

struct hevc_slice_segment_header_t
{
    nal_u1_t first_slice_segment_in_pic_flag;
    nal_u1_t no_output_of_prior_pics_flag;
    nal_ue_t slice_pic_parameter_set_id;
    nal_u1_t dependent_slice_segment_flag;
    // slice_segment_address; read but discarded
    nal_ue_t slice_type;
    nal_u1_t pic_output_flag;
    /* incomplete */

};

/* Computes size and does check the whole struct integrity */
static size_t get_hvcC_to_AnnexB_NAL_size( const uint8_t *p_buf, size_t i_buf )
{
    size_t i_total = 0;

    if( i_buf < HEVC_MIN_HVCC_SIZE )
        return 0;

    const uint8_t i_nal_length_size = (p_buf[21] & 0x03) + 1;
    if(i_nal_length_size == 3)
        return 0;

    const uint8_t i_num_array = p_buf[22];
    p_buf += 23; i_buf -= 23;

    for( uint8_t i = 0; i < i_num_array; i++ )
    {
        if(i_buf < 3)
            return 0;

        const uint16_t i_num_nalu = p_buf[1] << 8 | p_buf[2];
        p_buf += 3; i_buf -= 3;

        for( uint16_t j = 0; j < i_num_nalu; j++ )
        {
            if(i_buf < 2)
                return 0;

            const uint16_t i_nalu_length = p_buf[0] << 8 | p_buf[1];
            if(i_buf < i_nalu_length)
                return 0;

            i_total += i_nalu_length + i_nal_length_size;
            p_buf += i_nalu_length + 2;
            i_buf -= i_nalu_length + 2;
        }
    }

    return i_total;
}

uint8_t * hevc_hvcC_to_AnnexB_NAL( const uint8_t *p_buf, size_t i_buf,
                                   size_t *pi_result, uint8_t *pi_nal_length_size )
{
    *pi_result = get_hvcC_to_AnnexB_NAL_size( p_buf, i_buf ); /* Does all checks */
    if( *pi_result == 0 )
        return NULL;

    if( pi_nal_length_size )
        *pi_nal_length_size = hevc_getNALLengthSize( p_buf );

    uint8_t *p_ret;
    uint8_t *p_out_buf = p_ret = malloc( *pi_result );
    if( !p_out_buf )
    {
        *pi_result = 0;
        return NULL;
    }

    const uint8_t i_num_array = p_buf[22];
    p_buf += 23;

    for( uint8_t i = 0; i < i_num_array; i++ )
    {
        const uint16_t i_num_nalu = p_buf[1] << 8 | p_buf[2];
        p_buf += 3;

        for( uint16_t j = 0; j < i_num_nalu; j++ )
        {
            const uint16_t i_nalu_length = p_buf[0] << 8 | p_buf[1];

            memcpy( p_out_buf, annexb_startcode4, 4 );
            memcpy( &p_out_buf[4], &p_buf[2], i_nalu_length );

            p_out_buf += 4 + i_nalu_length;
            p_buf += 2 + i_nalu_length;
        }
    }

    return p_ret;
}

static bool hevc_parse_scaling_list_rbsp( bs_t *p_bs )
{
    if( bs_remain( p_bs ) < 16 )
        return false;

    for( int i=0; i<4; i++ )
    {
        for( int j=0; j<6; j += (i == 3) ? 3 : 1 )
        {
            if( bs_read1( p_bs ) == 0 )
                bs_read_ue( p_bs );
            else
            {
                unsigned nextCoef = 8;
                unsigned coefNum = __MIN( 64, (1 << (4 + (i << 1))));
                if( i > 1 )
                {
                    nextCoef = bs_read_se( p_bs ) + 8;
                }
                for( unsigned k=0; k<coefNum; k++ )
                {
                    nextCoef = ( nextCoef + bs_read_se( p_bs ) + 256 ) % 256;
                }
            }
        }
    }

    return true;
}

static bool hevc_parse_vui_parameters_rbsp( bs_t *p_bs, hevc_vui_parameters_t *p_vui )
{
    if( bs_remain( p_bs ) < 10 )
        return false;

    p_vui->aspect_ratio_info_present_flag = bs_read1( p_bs );
    if( p_vui->aspect_ratio_info_present_flag )
    {
        p_vui->ar.aspect_ratio_idc = bs_read( p_bs, 8 );
        if( p_vui->ar.aspect_ratio_idc == 0xFF ) //HEVC_SAR__IDC_EXTENDED_SAR )
        {
            p_vui->ar.sar_width = bs_read( p_bs, 16 );
            p_vui->ar.sar_height = bs_read( p_bs, 16 );
        }
    }

    p_vui->overscan_info_present_flag = bs_read1( p_bs );
    if( p_vui->overscan_info_present_flag )
        p_vui->overscan_appropriate_flag = bs_read1( p_bs );

    p_vui->video_signal_type_present_flag = bs_read1( p_bs );
    if( p_vui->video_signal_type_present_flag )
    {
        p_vui->vs.video_format = bs_read( p_bs, 3 );
        p_vui->vs.video_full_range_flag = bs_read1( p_bs );
        p_vui->vs.colour_description_present_flag = bs_read1( p_bs );
        if( p_vui->vs.colour_description_present_flag )
        {
            p_vui->vs.colour.colour_primaries = bs_read( p_bs, 8 );
            p_vui->vs.colour.transfer_characteristics = bs_read( p_bs, 8 );
            p_vui->vs.colour.matrix_coeffs = bs_read( p_bs, 8 );
        }
    }

    p_vui->chroma_loc_info_present_flag = bs_read1( p_bs );
    if( p_vui->chroma_loc_info_present_flag )
    {
        p_vui->chroma.sample_loc_type_top_field = bs_read_ue( p_bs );
        p_vui->chroma.sample_loc_type_bottom_field = bs_read_ue( p_bs );
    }

    p_vui->neutral_chroma_indication_flag = bs_read1( p_bs );
    p_vui->field_seq_flag = bs_read1( p_bs );
    p_vui->frame_field_info_present_flag = bs_read1( p_bs );

    p_vui->default_display_window_flag = bs_read1( p_bs );
    if( p_vui->default_display_window_flag )
    {
        p_vui->def_disp.win_left_offset = bs_read_ue( p_bs );
        p_vui->def_disp.win_right_offset = bs_read_ue( p_bs );
        p_vui->def_disp.win_top_offset = bs_read_ue( p_bs );
        p_vui->def_disp.win_bottom_offset = bs_read_ue( p_bs );
    }

    p_vui->vui_timing_info_present_flag = bs_read1( p_bs );
    if( p_vui->vui_timing_info_present_flag )
    {
        p_vui->timing.vui_num_units_in_tick =  bs_read( p_bs, 32 );
        p_vui->timing.vui_time_scale =  bs_read( p_bs, 32 );

        if( bs_remain( p_bs ) < 3 )
            return false;
    }
    /* incomplete */

    if( bs_remain( p_bs ) < 1 ) /* late fail */
        return false;

    return true;
}

/* Shortcut for retrieving vps/sps/pps id */
bool hevc_get_xps_id(const uint8_t *p_buf, size_t i_buf, uint8_t *pi_id)
{
    if(unlikely(!hxxx_strip_AnnexB_startcode(&p_buf, &i_buf) || i_buf < 3))
        return false;
    /* No need to lookup convert from emulation for that data */
    uint8_t i_nal_type = hevc_getNALType(p_buf);
    bs_t bs;
    bs_init(&bs, &p_buf[2], i_buf - 2);
    if(i_nal_type == HEVC_NAL_PPS)
        *pi_id = bs_read_ue( &bs );
    else
        *pi_id = bs_read( &bs, 4 );

    return true;
}

static bool hevc_parse_inner_profile_tier_level_rbsp( bs_t *p_bs,
                                                      hevc_inner_profile_tier_level_t *p_in )
{
    if( bs_remain( p_bs ) < 88 )
        return false;

    p_in->profile_space = bs_read( p_bs, 2 );
    p_in->tier_flag = bs_read1( p_bs );
    p_in->profile_idc = bs_read( p_bs, 5 );
    p_in->profile_compatibility_flag = bs_read( p_bs, 32 );
    p_in->progressive_source_flag = bs_read1( p_bs );
    p_in->interlaced_source_flag = bs_read1( p_bs );
    p_in->non_packed_constraint_flag = bs_read1( p_bs );
    p_in->frame_only_constraint_flag = bs_read1( p_bs );

    if( ( p_in->profile_idc >= 4 && p_in->profile_idc <= 7 ) ||
        ( p_in->profile_compatibility_flag & 0x0F000000 ) )
    {
        p_in->idc4to7.max_12bit_constraint_flag = bs_read1( p_bs );
        p_in->idc4to7.max_10bit_constraint_flag = bs_read1( p_bs );
        p_in->idc4to7.max_8bit_constraint_flag = bs_read1( p_bs );
        p_in->idc4to7.max_422chroma_constraint_flag = bs_read1( p_bs );
        p_in->idc4to7.max_420chroma_constraint_flag = bs_read1( p_bs );
        p_in->idc4to7.max_monochrome_constraint_flag = bs_read1( p_bs );
        p_in->idc4to7.intra_constraint_flag = bs_read1( p_bs );
        p_in->idc4to7.one_picture_only_constraint_flag = bs_read1( p_bs );
        p_in->idc4to7.lower_bit_rate_constraint_flag = bs_read1( p_bs );
        (void) bs_read( p_bs, 2 );
    }
    else
    {
        (void) bs_read( p_bs, 11 );
    }
    (void) bs_read( p_bs, 32 );

    if( ( p_in->profile_idc >= 1 && p_in->profile_idc <= 5 ) ||
        ( p_in->profile_compatibility_flag & 0x7C000000 ) )
        p_in->idc1to5.inbld_flag = bs_read1( p_bs );
    else
        (void) bs_read1( p_bs );

    return true;
}

static bool hevc_parse_profile_tier_level_rbsp( bs_t *p_bs, bool profile_present,
                                                uint8_t max_num_sub_layers_minus1,
                                                hevc_profile_tier_level_t *p_ptl )
{
    if( profile_present && !hevc_parse_inner_profile_tier_level_rbsp( p_bs, &p_ptl->general ) )
        return false;

    if( bs_remain( p_bs ) < 8)
        return false;

    p_ptl->general_level_idc = bs_read( p_bs, 8 );

    if( max_num_sub_layers_minus1 > 0 )
    {
        if( bs_remain( p_bs ) < 16 )
            return false;

        for( uint8_t i=0; i< 8; i++ )
        {
            if( i < max_num_sub_layers_minus1 )
            {
                if( bs_read1( p_bs ) )
                    p_ptl->sublayer_profile_present_flag |= (0x80 >> i);
                if( bs_read1( p_bs ) )
                    p_ptl->sublayer_level_present_flag |= (0x80 >> i);
            }
            else
                bs_read( p_bs, 2 );
        }

        for( uint8_t i=0; i < max_num_sub_layers_minus1; i++ )
        {
            if( ( p_ptl->sublayer_profile_present_flag & (0x80 >> i) ) &&
                ! hevc_parse_inner_profile_tier_level_rbsp( p_bs, &p_ptl->sub_layer[i] ) )
                return false;

            if( p_ptl->sublayer_profile_present_flag & (0x80 >> i) )
            {
                if( bs_remain( p_bs ) < 8 )
                    return false;
                p_ptl->sub_layer_level_idc[i] = bs_read( p_bs, 8 );
            }
        }
    }

    return true;
}

static bool hevc_parse_video_parameter_set_rbsp( bs_t *p_bs,
                                                 hevc_video_parameter_set_t *p_vps )
{
    if( bs_remain( p_bs ) < 134 )
        return false;

    p_vps->vps_video_parameter_set_id = bs_read( p_bs, 4 );
    p_vps->vps_base_layer_internal_flag = bs_read1( p_bs );
    p_vps->vps_base_layer_available_flag = bs_read1( p_bs );
    p_vps->vps_max_layers_minus1 = bs_read( p_bs, 6 );
    p_vps->vps_max_sub_layers_minus1 = bs_read( p_bs, 3 );
    p_vps->vps_temporal_id_nesting_flag = bs_read1( p_bs );
    bs_skip( p_bs, 16 );

    if( !hevc_parse_profile_tier_level_rbsp( p_bs, true, p_vps->vps_max_sub_layers_minus1,
                                            &p_vps->profile_tier_level ) )
        return false;

    p_vps->vps_sub_layer_ordering_info_present_flag = bs_read1( p_bs );
    for( unsigned i= (p_vps->vps_sub_layer_ordering_info_present_flag ?
                      0 : p_vps->vps_max_sub_layers_minus1);
         i<= p_vps->vps_max_sub_layers_minus1; i++ )
    {
        (void) bs_read_ue( p_bs ); //nal_ue_t dec_pic_buffering_minus1;
        (void) bs_read_ue( p_bs ); //nal_ue_t num_reorder_pics;
        (void) bs_read_ue( p_bs ); //nal_ue_t max_latency_increase_plus1;
    }
    if( bs_remain( p_bs ) < 10 )
        return false;

    p_vps->vps_max_layer_id = bs_read( p_bs, 6 );
    p_vps->vps_num_layer_set_minus1 = bs_read_ue( p_bs );
    // layer_id_included_flag; read but discarded
    bs_skip( p_bs, p_vps->vps_num_layer_set_minus1 * (p_vps->vps_max_layer_id + 1) );
    if( bs_remain( p_bs ) < 2 )
        return false;

    p_vps->vps_timing_info_present_flag = bs_read1( p_bs );
    if( p_vps->vps_timing_info_present_flag )
    {
        p_vps->vps_num_units_in_tick = bs_read( p_bs, 32 );
        p_vps->vps_time_scale = bs_read( p_bs, 32 );
    }
    /* parsing incomplete */

    if( bs_remain( p_bs ) < 1 )
        return false;

    return true;
}

void hevc_rbsp_release_vps( hevc_video_parameter_set_t *p_vps )
{
    free( p_vps );
}

#define IMPL_hevc_generic_decode( name, hevctype, decode, release ) \
    hevctype * name( const uint8_t *p_buf, size_t i_buf, bool b_escaped ) \
    { \
        hevctype *p_hevctype = calloc(1, sizeof(hevctype)); \
        if(likely(p_hevctype)) \
        { \
            bs_t bs; \
            bs_init( &bs, p_buf, i_buf ); \
            unsigned i_bitflow = 0; \
            if( b_escaped ) \
            { \
                bs.p_fwpriv = &i_bitflow; \
                bs.pf_forward = hxxx_bsfw_ep3b_to_rbsp;  /* Does the emulated 3bytes conversion to rbsp */ \
            } \
            else (void) i_bitflow;\
            bs_skip( &bs, 7 ); /* nal_unit_header */ \
            uint8_t i_nuh_layer_id = bs_read( &bs, 6 ); \
            bs_skip( &bs, 3 ); /* !nal_unit_header */ \
            if( i_nuh_layer_id > 62 || !decode( &bs, p_hevctype ) ) \
            { \
                release( p_hevctype ); \
                p_hevctype = NULL; \
            } \
        } \
        return p_hevctype; \
    }

IMPL_hevc_generic_decode( hevc_decode_vps, hevc_video_parameter_set_t,
                          hevc_parse_video_parameter_set_rbsp, hevc_rbsp_release_vps )

static bool hevc_parse_st_ref_pic_set( bs_t *p_bs, unsigned idx,
                                       unsigned num_short_term_ref_pic_sets,
                                       hevc_short_term_ref_pic_set_t *p_sets )
{
    if( idx && bs_read1( p_bs ) ) /* Interref pic set prediction flag */
    {
        nal_ue_t delta_idx_minus_1 = 0;
        if( idx == num_short_term_ref_pic_sets )
        {
            delta_idx_minus_1 = bs_read_ue( p_bs );
            if( delta_idx_minus_1 >= idx )
                return false;
        }
        if(delta_idx_minus_1 == idx)
            return false;

        nal_u1_t delta_rps_sign = bs_read1( p_bs );
        nal_ue_t abs_delta_rps_minus1 = bs_read_ue( p_bs );
        unsigned RefRpsIdx = idx - delta_idx_minus_1 - 1;
        int deltaRps = ( 1 - ( delta_rps_sign << 1 ) ) * ( abs_delta_rps_minus1 + 1 );
        VLC_UNUSED(deltaRps);

        unsigned numDeltaPocs = p_sets[RefRpsIdx].num_delta_pocs;
        for( unsigned j=0; j<= numDeltaPocs; j++ )
        {
            if( !bs_read1( p_bs ) ) /* used_by_curr_pic_flag */
                (void) bs_read1( p_bs ); /* use_delta_flag */
        }
    }
    else
    {
        nal_ue_t num_negative_pics = bs_read_ue( p_bs );
        nal_ue_t num_positive_pics = bs_read_ue( p_bs );
        for(unsigned int i=0; i<num_negative_pics; i++)
        {
            (void) bs_read_ue( p_bs ); /* delta_poc_s0_minus1 */
            (void) bs_read1( p_bs ); /* used_by_current_pic_s0_flag */
        }
        for(unsigned int i=0; i<num_positive_pics; i++)
        {
            (void) bs_read_ue( p_bs ); /* delta_poc_s1_minus1 */
            (void) bs_read1( p_bs ); /* used_by_current_pic_s1_flag */
        }
        p_sets[idx].num_delta_pocs = num_positive_pics + num_negative_pics;
    }

    return true;
}

static bool hevc_parse_sequence_parameter_set_rbsp( bs_t *p_bs,
                                                    hevc_sequence_parameter_set_t *p_sps )
{
    p_sps->sps_video_parameter_set_id = bs_read( p_bs, 4 );
    p_sps->sps_max_sub_layers_minus1 = bs_read( p_bs, 3 );
    p_sps->sps_temporal_id_nesting_flag = bs_read1( p_bs );
    if( !hevc_parse_profile_tier_level_rbsp( p_bs, true, p_sps->sps_max_sub_layers_minus1,
                                            &p_sps->profile_tier_level ) )
        return false;

    if( bs_remain( p_bs ) < 1 )
        return false;

    p_sps->sps_seq_parameter_set_id = bs_read_ue( p_bs );
    if( p_sps->sps_seq_parameter_set_id >= HEVC_SPS_MAX )
        return false;

    p_sps->chroma_format_idc = bs_read_ue( p_bs );
    if( p_sps->chroma_format_idc == 3 )
        p_sps->separate_colour_plane_flag = bs_read1( p_bs );
    p_sps->pic_width_in_luma_samples = bs_read_ue( p_bs );
    p_sps->pic_height_in_luma_samples = bs_read_ue( p_bs );
    if( !p_sps->pic_width_in_luma_samples || !p_sps->pic_height_in_luma_samples )
        return false;

    p_sps->conformance_window_flag = bs_read1( p_bs );
    if( p_sps->conformance_window_flag )
    {
        p_sps->conf_win.left_offset = bs_read_ue( p_bs );
        p_sps->conf_win.right_offset = bs_read_ue( p_bs );
        p_sps->conf_win.top_offset = bs_read_ue( p_bs );
        p_sps->conf_win.bottom_offset = bs_read_ue( p_bs );
    }

    p_sps->bit_depth_luma_minus8 = bs_read_ue( p_bs );
    p_sps->bit_depth_chroma_minus8 = bs_read_ue( p_bs );
    p_sps->log2_max_pic_order_cnt_lsb_minus4 = bs_read_ue( p_bs );

    p_sps->sps_sub_layer_ordering_info_present_flag = bs_read1( p_bs );
    for( uint8_t i=(p_sps->sps_sub_layer_ordering_info_present_flag ? 0 : p_sps->sps_max_sub_layers_minus1);
         i <= p_sps->sps_max_sub_layers_minus1; i++ )
    {
        p_sps->sps_max[i].dec_pic_buffering_minus1 = bs_read_ue( p_bs );
        p_sps->sps_max[i].num_reorder_pics = bs_read_ue( p_bs );
        p_sps->sps_max[i].latency_increase_plus1 = bs_read_ue( p_bs );
    }

    if( bs_remain( p_bs ) < 4 )
        return false;

    p_sps->log2_min_luma_coding_block_size_minus3 = bs_read_ue( p_bs );
    p_sps->log2_diff_max_min_luma_coding_block_size = bs_read_ue( p_bs );
    p_sps->log2_min_luma_transform_block_size_minus2 = bs_read_ue( p_bs );
    if( bs_remain( p_bs ) < 1 ) /* last late fail check */
        return false;
    p_sps->log2_diff_max_min_luma_transform_block_size = bs_read_ue( p_bs );

    /* parsing incomplete */

    p_sps->max_transform_hierarchy_depth_inter = bs_read_ue( p_bs );
    p_sps->max_transform_hierarchy_depth_intra = bs_read_ue( p_bs );
    p_sps->scaling_list_enabled = bs_read1( p_bs );
    if( p_sps->scaling_list_enabled )
    {
        p_sps->sps_scaling_list_data_present_flag = bs_read1( p_bs );
        if( p_sps->sps_scaling_list_data_present_flag &&
            ! hevc_parse_scaling_list_rbsp( p_bs ) )
        {
            return false;
        }
    }

    p_sps->amp_enabled_flag = bs_read1( p_bs );
    p_sps->sample_adaptive_offset_enabled_flag = bs_read1( p_bs );

    p_sps->pcm_enabled_flag = bs_read1( p_bs );
    if( p_sps->pcm_enabled_flag )
    {
        p_sps->pcm_sample_bit_depth_luma_minus1 = bs_read( p_bs, 4 );
        p_sps->pcm_sample_bit_depth_chroma_minus1 = bs_read( p_bs, 4 );
        p_sps->log2_min_pcm_luma_coding_block_size_minus3 = bs_read_ue( p_bs );
        p_sps->log2_diff_max_min_pcm_luma_coding_block_size = bs_read_ue( p_bs );
        p_sps->pcm_loop_filter_disabled_flag = bs_read1( p_bs );
    }

    p_sps->num_short_term_ref_pic_sets = bs_read_ue( p_bs );
    if( p_sps->num_short_term_ref_pic_sets > HEVC_MAX_SHORT_TERM_REF_PIC_SET )
        return false;

    hevc_short_term_ref_pic_set_t sets[HEVC_MAX_SHORT_TERM_REF_PIC_SET];
    memset(&sets, 0, sizeof(hevc_short_term_ref_pic_set_t) * HEVC_MAX_SHORT_TERM_REF_PIC_SET);
    for( unsigned int i=0; i<p_sps->num_short_term_ref_pic_sets; i++ )
    {
        if( !hevc_parse_st_ref_pic_set( p_bs, i, p_sps->num_short_term_ref_pic_sets, sets ) )
            return false;
    }

    p_sps->long_term_ref_pics_present_flag = bs_read1( p_bs );
    if( p_sps->long_term_ref_pics_present_flag )
    {
        p_sps->num_long_term_ref_pics_sps = bs_read_ue( p_bs );
        if( p_sps->num_long_term_ref_pics_sps > HEVC_MAX_LONG_TERM_REF_PIC_SET )
            return false;
        for( unsigned int i=0; i< p_sps->num_long_term_ref_pics_sps; i++ )
        {
             /* lt_ref_pic_poc_lsb_sps */
            bs_skip( p_bs, p_sps->log2_max_pic_order_cnt_lsb_minus4 + 4 );
             /* used_by_curr_pic_lt_sps_flag */
            bs_skip( p_bs, 1 );
        }
    }

    p_sps->sps_temporal_mvp_enabled_flag = bs_read1( p_bs );
    p_sps->strong_intra_smoothing_enabled_flag = bs_read1( p_bs );

    if( bs_remain( p_bs ) < 1 ) /* late fail */
        return false;

    p_sps->vui_parameters_present_flag = bs_read1( p_bs );
    if( p_sps->vui_parameters_present_flag &&
        !hevc_parse_vui_parameters_rbsp( p_bs, &p_sps->vui ) )
        return false;

    /* incomplete */

    return true;
}

void hevc_rbsp_release_sps( hevc_sequence_parameter_set_t *p_sps )
{
    free( p_sps );
}

IMPL_hevc_generic_decode( hevc_decode_sps, hevc_sequence_parameter_set_t,
                          hevc_parse_sequence_parameter_set_rbsp, hevc_rbsp_release_sps )

static bool hevc_parse_pic_parameter_set_rbsp( bs_t *p_bs,
                                               hevc_picture_parameter_set_t *p_pps )
{
    if( bs_remain( p_bs ) < 1 )
        return false;
    p_pps->pps_pic_parameter_set_id = bs_read_ue( p_bs );
    if( p_pps->pps_pic_parameter_set_id >= HEVC_PPS_MAX || bs_remain( p_bs ) < 1 )
        return false;
    p_pps->pps_seq_parameter_set_id = bs_read_ue( p_bs );
    if( p_pps->pps_seq_parameter_set_id >= HEVC_SPS_MAX )
        return false;
    p_pps->dependent_slice_segments_enabled_flag = bs_read1( p_bs );
    p_pps->output_flag_present_flag = bs_read1( p_bs );
    p_pps->num_extra_slice_header_bits = bs_read( p_bs, 3 );
    p_pps->sign_data_hiding_enabled_flag = bs_read1( p_bs );
    p_pps->cabac_init_present_flag = bs_read1( p_bs );

    p_pps->num_ref_idx_l0_default_active_minus1 = bs_read_ue( p_bs );
    p_pps->num_ref_idx_l1_default_active_minus1 = bs_read_ue( p_bs );

    p_pps->init_qp_minus26 = bs_read_se( p_bs );
    p_pps->constrained_intra_pred_flag = bs_read1( p_bs );
    p_pps->transform_skip_enabled_flag = bs_read1( p_bs );
    p_pps->cu_qp_delta_enabled_flag = bs_read1( p_bs );
    if( p_pps->cu_qp_delta_enabled_flag )
        p_pps->diff_cu_qp_delta_depth = bs_read_ue( p_bs );

    if( bs_remain( p_bs ) < 1 )
        return false;

    p_pps->pps_cb_qp_offset = bs_read_se( p_bs );
    p_pps->pps_cr_qp_offset = bs_read_se( p_bs );
    p_pps->pic_slice_level_chroma_qp_offsets_present_flag = bs_read1( p_bs );
    p_pps->weighted_pred_flag = bs_read1( p_bs );
    p_pps->weighted_bipred_flag = bs_read1( p_bs );
    p_pps->transquant_bypass_enable_flag = bs_read1( p_bs );
    p_pps->tiles_enabled_flag = bs_read1( p_bs );
    p_pps->entropy_coding_sync_enabled_flag = bs_read1( p_bs );

    if( p_pps->tiles_enabled_flag )
    {
        p_pps->num_tile_columns_minus1 = bs_read_ue( p_bs ); /* TODO: validate max col/row values */
        p_pps->num_tile_rows_minus1 = bs_read_ue( p_bs );    /*       against sps PicWidthInCtbsY */
        p_pps->uniform_spacing_flag = bs_read1( p_bs );
        if( !p_pps->uniform_spacing_flag )
        {
            for( unsigned i=0; i< p_pps->num_tile_columns_minus1; i++ )
                (void) bs_read_ue( p_bs );
            for( unsigned i=0; i< p_pps->num_tile_rows_minus1; i++ )
                (void) bs_read_ue( p_bs );
        }
        p_pps->loop_filter_across_tiles_enabled_flag = bs_read1( p_bs );
    }

    p_pps->pps_loop_filter_across_slices_enabled_flag = bs_read1( p_bs );
    p_pps->deblocking_filter_control_present_flag = bs_read1( p_bs );
    if( p_pps->deblocking_filter_control_present_flag )
    {
        p_pps->deblocking_filter_override_enabled_flag = bs_read1( p_bs );
        p_pps->pps_deblocking_filter_disabled_flag = bs_read1( p_bs );
        if( !p_pps->pps_deblocking_filter_disabled_flag )
        {
            p_pps->pps_beta_offset_div2 = bs_read_se( p_bs );
            p_pps->pps_tc_offset_div2 = bs_read_se( p_bs );
        }
    }

    p_pps->scaling_list_data_present_flag = bs_read1( p_bs );
    if( p_pps->scaling_list_data_present_flag && !hevc_parse_scaling_list_rbsp( p_bs ) )
        return false;

    p_pps->lists_modification_present_flag = bs_read1( p_bs );
    p_pps->log2_parallel_merge_level_minus2 = bs_read_ue( p_bs );
    p_pps->slice_header_extension_present_flag = bs_read1( p_bs );

    if( bs_remain( p_bs ) < 1 )
        return false;

    p_pps->pps_extension_present_flag = bs_read1( p_bs );
    if( p_pps->pps_extension_present_flag )
    {
        p_pps->pps_range_extension_flag = bs_read1( p_bs );
        p_pps->pps_multilayer_extension_flag = bs_read1( p_bs );
        p_pps->pps_3d_extension_flag = bs_read1( p_bs );
        if( bs_remain( p_bs ) < 5 )
            return false;
        p_pps->pps_extension_5bits = bs_read( p_bs, 5 );
    }

    return true;
}

void hevc_rbsp_release_pps( hevc_picture_parameter_set_t *p_pps )
{
    free( p_pps );
}

IMPL_hevc_generic_decode( hevc_decode_pps, hevc_picture_parameter_set_t,
                          hevc_parse_pic_parameter_set_rbsp, hevc_rbsp_release_pps )

bool hevc_get_picture_size( const hevc_sequence_parameter_set_t *p_sps,
                            unsigned *p_w, unsigned *p_h, unsigned *p_vw, unsigned *p_vh )
{
    *p_w = *p_vw = p_sps->pic_width_in_luma_samples;
    *p_h = *p_vh = p_sps->pic_height_in_luma_samples;
    if( p_sps->conformance_window_flag )
    {
        *p_vh -= p_sps->conf_win.bottom_offset + p_sps->conf_win.top_offset;
        *p_vh -= p_sps->conf_win.left_offset +  p_sps->conf_win.right_offset;
    }
    return true;
}

static inline uint8_t vlc_ceil_log2( uint32_t val )
{
    uint8_t n = 31 - clz(val);
    if (((unsigned)1 << n) != val)
        n++;
    return n;
}

static bool hevc_get_picture_CtbsYsize( const hevc_sequence_parameter_set_t *p_sps, unsigned *p_w, unsigned *p_h )
{
    const unsigned int MinCbLog2SizeY = p_sps->log2_min_luma_coding_block_size_minus3 + 3;
    const unsigned int CtbLog2SizeY = MinCbLog2SizeY + p_sps->log2_diff_max_min_luma_coding_block_size;
    if( CtbLog2SizeY > 31 )
        return false;
    const unsigned int CtbSizeY = 1 << CtbLog2SizeY;
    *p_w = (p_sps->pic_width_in_luma_samples - 1) / CtbSizeY + 1;
    *p_h = (p_sps->pic_height_in_luma_samples - 1) / CtbSizeY + 1;
    return true;
}

bool hevc_get_frame_rate( const hevc_sequence_parameter_set_t *p_sps,
                          hevc_video_parameter_set_t **pp_vps,
                          unsigned *pi_num, unsigned *pi_den )
{
    if( p_sps->vui_parameters_present_flag && p_sps->vui.vui_timing_info_present_flag )
    {
        *pi_den = p_sps->vui.timing.vui_num_units_in_tick;
        *pi_num = p_sps->vui.timing.vui_time_scale;
        return (*pi_den && *pi_num);
    }
    else if( pp_vps && pp_vps[p_sps->sps_video_parameter_set_id] &&
             pp_vps[p_sps->sps_video_parameter_set_id]->vps_timing_info_present_flag )
    {
        *pi_den = pp_vps[p_sps->sps_video_parameter_set_id]->vps_num_units_in_tick;
        *pi_num = pp_vps[p_sps->sps_video_parameter_set_id]->vps_time_scale;
        return (*pi_den && *pi_num);
    }
    return false;
}

static bool hevc_parse_slice_segment_header_rbsp( bs_t *p_bs,
                                                  uint8_t i_nal_type,
                                                  hevc_sequence_parameter_set_t **pp_sps,
                                                  hevc_picture_parameter_set_t **pp_pps,
                                                  hevc_slice_segment_header_t *p_sl )
{
    if( bs_remain( p_bs ) < 3 )
        return false;

    p_sl->first_slice_segment_in_pic_flag = bs_read1( p_bs );
    if( i_nal_type >= HEVC_NAL_BLA_W_LP && i_nal_type <= HEVC_NAL_IRAP_VCL23 )
        p_sl->no_output_of_prior_pics_flag = bs_read1( p_bs );
    p_sl->slice_pic_parameter_set_id = bs_read_ue( p_bs );
    if( p_sl->slice_pic_parameter_set_id >= HEVC_PPS_MAX || bs_remain( p_bs ) < 1 )
        return false;

    const hevc_picture_parameter_set_t *p_pps = pp_pps[p_sl->slice_pic_parameter_set_id];
    if(!p_pps)
        return false;

    if( !p_sl->first_slice_segment_in_pic_flag )
    {
        if( p_pps->dependent_slice_segments_enabled_flag )
            p_sl->dependent_slice_segment_flag = bs_read1( p_bs );

        const hevc_sequence_parameter_set_t *p_sps = pp_sps[p_pps->pps_seq_parameter_set_id];
        if( !p_sps )
            return false;

        unsigned w, h;
        if( !hevc_get_picture_CtbsYsize( p_sps, &w, &h ) )
            return false;

        (void) bs_read( p_bs, vlc_ceil_log2( w * h ) ); /* slice_segment_address */
    }

    if( !p_sl->dependent_slice_segment_flag )
    {
        unsigned i=0;
        if( p_pps->num_extra_slice_header_bits > i )
        {
            i++;
            bs_skip( p_bs, 1 ); /* discardable_flag */
        }

        if( p_pps->num_extra_slice_header_bits > i )
        {
            i++;
            bs_skip( p_bs, 1 ); /* cross_layer_bla_flag */
        }

        if( i < p_pps->num_extra_slice_header_bits )
           bs_skip( p_bs, p_pps->num_extra_slice_header_bits - i );

        p_sl->slice_type = bs_read_ue( p_bs );
        if( p_sl->slice_type > HEVC_SLICE_TYPE_I )
            return false;

        if( p_pps->output_flag_present_flag )
            p_sl->pic_output_flag = bs_read1( p_bs );
    }

    if( bs_remain( p_bs ) < 1 )
        return false;

    return true;
}

void hevc_rbsp_release_slice_header( hevc_slice_segment_header_t *p_sh )
{
    free( p_sh );
}

hevc_slice_segment_header_t * hevc_decode_slice_header( const uint8_t *p_buf, size_t i_buf, bool b_escaped,
                                                        hevc_sequence_parameter_set_t **pp_sps,
                                                        hevc_picture_parameter_set_t **pp_pps )
{
    if(!pp_sps || !pp_pps)
        return NULL;

    hevc_slice_segment_header_t *p_sh = calloc(1, sizeof(hevc_slice_segment_header_t));
    if(likely(p_sh))
    {
        uint8_t i_nal_type = hevc_getNALType(p_buf);
        bs_t bs;
        bs_init( &bs, p_buf, i_buf );
        unsigned i_bitflow = 0;
        if( b_escaped )
        {
            bs.p_fwpriv = &i_bitflow;
            bs.pf_forward = hxxx_bsfw_ep3b_to_rbsp;  /* Does the emulated 3bytes conversion to rbsp */
        }
        else (void) i_bitflow;
        bs_skip( &bs, 7 ); /* nal_unit_header */
        uint8_t i_nuh_layer_id = bs_read( &bs, 6 );
        bs_skip( &bs, 3 ); /* !nal_unit_header */
        if( i_nuh_layer_id > 62 ||
           !hevc_parse_slice_segment_header_rbsp( &bs, i_nal_type, pp_sps, pp_pps, p_sh ) )
        {
            hevc_rbsp_release_slice_header( p_sh );
            p_sh = NULL;
        }
    }
    return p_sh;
}

bool hevc_get_slice_type( const hevc_slice_segment_header_t *p_sli, enum hevc_slice_type_e *pi_type )
{
    if( !p_sli->dependent_slice_segment_flag )
    {
        *pi_type = p_sli->slice_type;
        return true;
    }
    return false;
}
back to top