/***************************************************************************** * Copyright © 2010-2014 VideoLAN * * Authors: Jean-Baptiste Kempf * * 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. *****************************************************************************/ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include "h264_nal.h" #include "hxxx_nal.h" #include #include #include #include /* H264 Level limits from Table A-1 */ typedef struct { unsigned i_max_dpb_mbs; } h264_level_limits_t; enum h264_level_numbers_e { H264_LEVEL_NUMBER_1_B = 9, /* special level not following the 10x rule */ H264_LEVEL_NUMBER_1 = 10, H264_LEVEL_NUMBER_1_1 = 11, H264_LEVEL_NUMBER_1_2 = 12, H264_LEVEL_NUMBER_1_3 = 13, H264_LEVEL_NUMBER_2 = 20, H264_LEVEL_NUMBER_2_1 = 21, H264_LEVEL_NUMBER_2_2 = 22, H264_LEVEL_NUMBER_3 = 30, H264_LEVEL_NUMBER_3_1 = 31, H264_LEVEL_NUMBER_3_2 = 32, H264_LEVEL_NUMBER_4 = 40, H264_LEVEL_NUMBER_4_1 = 41, H264_LEVEL_NUMBER_4_2 = 42, H264_LEVEL_NUMBER_5 = 50, H264_LEVEL_NUMBER_5_1 = 51, H264_LEVEL_NUMBER_5_2 = 52, }; const struct { const uint16_t i_level; const h264_level_limits_t limits; } h264_levels_limits[] = { { H264_LEVEL_NUMBER_1_B, { 396 } }, { H264_LEVEL_NUMBER_1, { 396 } }, { H264_LEVEL_NUMBER_1_1, { 900 } }, { H264_LEVEL_NUMBER_1_2, { 2376 } }, { H264_LEVEL_NUMBER_1_3, { 2376 } }, { H264_LEVEL_NUMBER_2, { 2376 } }, { H264_LEVEL_NUMBER_2_1, { 4752 } }, { H264_LEVEL_NUMBER_2_2, { 8100 } }, { H264_LEVEL_NUMBER_3, { 8100 } }, { H264_LEVEL_NUMBER_3_1, { 18000 } }, { H264_LEVEL_NUMBER_3_2, { 20480 } }, { H264_LEVEL_NUMBER_4, { 32768 } }, { H264_LEVEL_NUMBER_4_1, { 32768 } }, { H264_LEVEL_NUMBER_4_2, { 34816 } }, { H264_LEVEL_NUMBER_5, { 110400 } }, { H264_LEVEL_NUMBER_5_1, { 184320 } }, { H264_LEVEL_NUMBER_5_2, { 184320 } }, }; /* * For avcC specification, see ISO/IEC 14496-15, * For Annex B specification, see ISO/IEC 14496-10 */ bool h264_isavcC( const uint8_t *p_buf, size_t i_buf ) { return ( i_buf >= H264_MIN_AVCC_SIZE && p_buf[0] != 0x00 && p_buf[1] != 0x00 /* /!\Broken quicktime streams does not respect reserved bits (p_buf[4] & 0xFC) == 0xFC && (p_buf[4] & 0x03) != 0x02 && (p_buf[5] & 0x1F) > 0x00 */ ); } static size_t get_avcC_to_AnnexB_NAL_size( const uint8_t *p_buf, size_t i_buf ) { size_t i_total = 0; if( i_buf < H264_MIN_AVCC_SIZE ) return 0; p_buf += 5; i_buf -= 5; for ( unsigned int j = 0; j < 2; j++ ) { /* First time is SPS, Second is PPS */ const unsigned int i_loop_end = p_buf[0] & (j == 0 ? 0x1f : 0xff); p_buf++; i_buf--; for ( unsigned int i = 0; i < i_loop_end; i++ ) { if( i_buf < 2 ) return 0; uint16_t i_nal_size = (p_buf[0] << 8) | p_buf[1]; if(i_nal_size > i_buf - 2) return 0; i_total += i_nal_size + 4; p_buf += i_nal_size + 2; i_buf -= i_nal_size + 2; } if( j == 0 && i_buf < 1 ) return 0; } return i_total; } uint8_t *h264_avcC_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_avcC_to_AnnexB_NAL_size( p_buf, i_buf ); /* Does check min size */ if( *pi_result == 0 ) return NULL; /* Read infos in first 6 bytes */ if ( pi_nal_length_size ) *pi_nal_length_size = (p_buf[4] & 0x03) + 1; uint8_t *p_ret; uint8_t *p_out_buf = p_ret = malloc( *pi_result ); if( !p_out_buf ) { *pi_result = 0; return NULL; } p_buf += 5; for ( unsigned int j = 0; j < 2; j++ ) { const unsigned int i_loop_end = p_buf[0] & (j == 0 ? 0x1f : 0xff); p_buf++; for ( unsigned int i = 0; i < i_loop_end; i++) { uint16_t i_nal_size = (p_buf[0] << 8) | p_buf[1]; p_buf += 2; memcpy( p_out_buf, annexb_startcode4, 4 ); p_out_buf += 4; memcpy( p_out_buf, p_buf, i_nal_size ); p_out_buf += i_nal_size; p_buf += i_nal_size; } } return p_ret; } void h264_AVC_to_AnnexB( uint8_t *p_buf, uint32_t i_len, uint8_t i_nal_length_size ) { uint32_t nal_len = 0; uint8_t nal_pos = 0; if( i_nal_length_size != 4 ) return; /* This only works for a NAL length size of 4 */ /* TODO: realloc/memmove if i_nal_length_size is 2 or 1 */ while( i_len > 0 ) { if( nal_pos < i_nal_length_size ) { unsigned int i; for( i = 0; nal_pos < i_nal_length_size && i < i_len; i++, nal_pos++ ) { nal_len = (nal_len << 8) | p_buf[i]; p_buf[i] = 0; } if( nal_pos < i_nal_length_size ) return; p_buf[i - 1] = 1; p_buf += i; i_len -= i; } if( nal_len > INT_MAX ) return; if( nal_len > i_len ) { nal_len -= i_len; return; } else { p_buf += nal_len; i_len -= nal_len; nal_len = 0; nal_pos = 0; } } } bool h264_AnnexB_get_spspps( const uint8_t *p_buf, size_t i_buf, const uint8_t **pp_sps, size_t *p_sps_size, const uint8_t **pp_pps, size_t *p_pps_size, const uint8_t **pp_ext, size_t *p_ext_size ) { if( pp_sps ) { *p_sps_size = 0; *pp_sps = NULL; } if( pp_pps ) { *p_pps_size = 0; *pp_pps = NULL; } if( pp_ext ) { *p_ext_size = 0; *pp_ext = NULL; } hxxx_iterator_ctx_t it; hxxx_iterator_init( &it, p_buf, i_buf, 0 ); const uint8_t *p_nal; size_t i_nal; while( hxxx_annexb_iterate_next( &it, &p_nal, &i_nal ) ) { if( i_nal < 2 ) continue; const enum h264_nal_unit_type_e i_nal_type = p_nal[0] & 0x1F; if ( i_nal_type <= H264_NAL_SLICE_IDR && i_nal_type != H264_NAL_UNKNOWN ) break; #define IFSET_NAL(type, var) \ if( i_nal_type == type && pp_##var && *pp_##var == NULL )\ { *pp_##var = p_nal; *p_##var##_size = i_nal; } IFSET_NAL(H264_NAL_SPS, sps) else IFSET_NAL(H264_NAL_PPS, pps) else IFSET_NAL(H264_NAL_SPS_EXT, ext); #undef IFSET_NAL } return (pp_sps && *p_sps_size) || (pp_pps && *p_pps_size); } void h264_release_sps( h264_sequence_parameter_set_t *p_sps ) { free( p_sps ); } #define H264_CONSTRAINT_SET_FLAG(N) (0x80 >> N) static bool h264_parse_sequence_parameter_set_rbsp( bs_t *p_bs, h264_sequence_parameter_set_t *p_sps ) { int i_tmp; int i_profile_idc = bs_read( p_bs, 8 ); p_sps->i_profile = i_profile_idc; p_sps->i_constraint_set_flags = bs_read( p_bs, 8 ); p_sps->i_level = bs_read( p_bs, 8 ); /* sps id */ uint32_t i_sps_id = bs_read_ue( p_bs ); if( i_sps_id > H264_SPS_ID_MAX ) return false; p_sps->i_id = i_sps_id; if( i_profile_idc == PROFILE_H264_HIGH || i_profile_idc == PROFILE_H264_HIGH_10 || i_profile_idc == PROFILE_H264_HIGH_422 || i_profile_idc == PROFILE_H264_HIGH_444 || /* Old one, no longer on spec */ i_profile_idc == PROFILE_H264_HIGH_444_PREDICTIVE || i_profile_idc == PROFILE_H264_CAVLC_INTRA || i_profile_idc == PROFILE_H264_SVC_BASELINE || i_profile_idc == PROFILE_H264_SVC_HIGH || i_profile_idc == PROFILE_H264_MVC_MULTIVIEW_HIGH || i_profile_idc == PROFILE_H264_MVC_STEREO_HIGH || i_profile_idc == PROFILE_H264_MVC_MULTIVIEW_DEPTH_HIGH || i_profile_idc == PROFILE_H264_MVC_ENHANCED_MULTIVIEW_DEPTH_HIGH || i_profile_idc == PROFILE_H264_MFC_HIGH ) { /* chroma_format_idc */ p_sps->i_chroma_idc = bs_read_ue( p_bs ); if( p_sps->i_chroma_idc == 3 ) p_sps->b_separate_colour_planes_flag = bs_read1( p_bs ); else p_sps->b_separate_colour_planes_flag = 0; /* bit_depth_luma_minus8 */ p_sps->i_bit_depth_luma = bs_read_ue( p_bs ) + 8; /* bit_depth_chroma_minus8 */ p_sps->i_bit_depth_chroma = bs_read_ue( p_bs ) + 8; /* qpprime_y_zero_transform_bypass_flag */ bs_skip( p_bs, 1 ); /* seq_scaling_matrix_present_flag */ i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { for( int i = 0; i < ((3 != p_sps->i_chroma_idc) ? 8 : 12); i++ ) { /* seq_scaling_list_present_flag[i] */ i_tmp = bs_read( p_bs, 1 ); if( !i_tmp ) continue; const int i_size_of_scaling_list = (i < 6 ) ? 16 : 64; /* scaling_list (...) */ int i_lastscale = 8; int i_nextscale = 8; for( int j = 0; j < i_size_of_scaling_list; j++ ) { if( i_nextscale != 0 ) { /* delta_scale */ i_tmp = bs_read_se( p_bs ); i_nextscale = ( i_lastscale + i_tmp + 256 ) % 256; /* useDefaultScalingMatrixFlag = ... */ } /* scalinglist[j] */ i_lastscale = ( i_nextscale == 0 ) ? i_lastscale : i_nextscale; } } } } else { p_sps->i_chroma_idc = 1; /* Not present == inferred to 4:2:0 */ p_sps->i_bit_depth_luma = 8; p_sps->i_bit_depth_chroma = 8; } /* Skip i_log2_max_frame_num */ p_sps->i_log2_max_frame_num = bs_read_ue( p_bs ); if( p_sps->i_log2_max_frame_num > 12) p_sps->i_log2_max_frame_num = 12; /* Read poc_type */ p_sps->i_pic_order_cnt_type = bs_read_ue( p_bs ); if( p_sps->i_pic_order_cnt_type == 0 ) { /* skip i_log2_max_poc_lsb */ p_sps->i_log2_max_pic_order_cnt_lsb = bs_read_ue( p_bs ); if( p_sps->i_log2_max_pic_order_cnt_lsb > 12 ) p_sps->i_log2_max_pic_order_cnt_lsb = 12; } else if( p_sps->i_pic_order_cnt_type == 1 ) { p_sps->i_delta_pic_order_always_zero_flag = bs_read( p_bs, 1 ); p_sps->offset_for_non_ref_pic = bs_read_se( p_bs ); p_sps->offset_for_top_to_bottom_field = bs_read_se( p_bs ); p_sps->i_num_ref_frames_in_pic_order_cnt_cycle = bs_read_ue( p_bs ); if( p_sps->i_num_ref_frames_in_pic_order_cnt_cycle > 255 ) return false; for( int i=0; ii_num_ref_frames_in_pic_order_cnt_cycle; i++ ) p_sps->offset_for_ref_frame[i] = bs_read_se( p_bs ); } /* i_num_ref_frames */ bs_read_ue( p_bs ); /* b_gaps_in_frame_num_value_allowed */ bs_skip( p_bs, 1 ); /* Read size */ p_sps->pic_width_in_mbs_minus1 = bs_read_ue( p_bs ); p_sps->pic_height_in_map_units_minus1 = bs_read_ue( p_bs ); /* b_frame_mbs_only */ p_sps->frame_mbs_only_flag = bs_read( p_bs, 1 ); if( !p_sps->frame_mbs_only_flag ) p_sps->mb_adaptive_frame_field_flag = bs_read( p_bs, 1 ); /* b_direct8x8_inference */ bs_skip( p_bs, 1 ); /* crop */ if( bs_read1( p_bs ) ) /* frame_cropping_flag */ { p_sps->frame_crop.left_offset = bs_read_ue( p_bs ); p_sps->frame_crop.right_offset = bs_read_ue( p_bs ); p_sps->frame_crop.top_offset = bs_read_ue( p_bs ); p_sps->frame_crop.bottom_offset = bs_read_ue( p_bs ); } /* vui */ i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { p_sps->vui.b_valid = true; /* read the aspect ratio part if any */ i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { static const struct { int w, h; } sar[17] = { { 0, 0 }, { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, { 160,99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, }; int i_sar = bs_read( p_bs, 8 ); int w, h; if( i_sar < 17 ) { w = sar[i_sar].w; h = sar[i_sar].h; } else if( i_sar == 255 ) { w = bs_read( p_bs, 16 ); h = bs_read( p_bs, 16 ); } else { w = 0; h = 0; } if( w != 0 && h != 0 ) { p_sps->vui.i_sar_num = w; p_sps->vui.i_sar_den = h; } else { p_sps->vui.i_sar_num = 1; p_sps->vui.i_sar_den = 1; } } /* overscan */ i_tmp = bs_read( p_bs, 1 ); if ( i_tmp ) bs_read( p_bs, 1 ); /* video signal type */ i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { bs_read( p_bs, 3 ); p_sps->vui.colour.b_full_range = bs_read( p_bs, 1 ); /* colour desc */ i_tmp = bs_read( p_bs, 1 ); if ( i_tmp ) { p_sps->vui.colour.i_colour_primaries = bs_read( p_bs, 8 ); p_sps->vui.colour.i_transfer_characteristics = bs_read( p_bs, 8 ); p_sps->vui.colour.i_matrix_coefficients = bs_read( p_bs, 8 ); } else { p_sps->vui.colour.i_colour_primaries = HXXX_PRIMARIES_UNSPECIFIED; p_sps->vui.colour.i_transfer_characteristics = HXXX_TRANSFER_UNSPECIFIED; p_sps->vui.colour.i_matrix_coefficients = HXXX_MATRIX_UNSPECIFIED; } } /* chroma loc info */ i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { bs_read_ue( p_bs ); bs_read_ue( p_bs ); } /* timing info */ p_sps->vui.b_timing_info_present_flag = bs_read( p_bs, 1 ); if( p_sps->vui.b_timing_info_present_flag ) { p_sps->vui.i_num_units_in_tick = bs_read( p_bs, 32 ); p_sps->vui.i_time_scale = bs_read( p_bs, 32 ); p_sps->vui.b_fixed_frame_rate = bs_read( p_bs, 1 ); } /* Nal hrd & VC1 hrd parameters */ p_sps->vui.b_hrd_parameters_present_flag = false; for ( int i=0; i<2; i++ ) { i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { p_sps->vui.b_hrd_parameters_present_flag = true; uint32_t count = bs_read_ue( p_bs ) + 1; if( count > 31 ) return false; bs_read( p_bs, 4 ); bs_read( p_bs, 4 ); for( uint32_t j = 0; j < count; j++ ) { if( bs_remain( p_bs ) < 23 ) return false; bs_read_ue( p_bs ); bs_read_ue( p_bs ); bs_read( p_bs, 1 ); } bs_read( p_bs, 5 ); p_sps->vui.i_cpb_removal_delay_length_minus1 = bs_read( p_bs, 5 ); p_sps->vui.i_dpb_output_delay_length_minus1 = bs_read( p_bs, 5 ); bs_read( p_bs, 5 ); } } if( p_sps->vui.b_hrd_parameters_present_flag ) bs_read( p_bs, 1 ); /* low delay hrd */ /* pic struct info */ p_sps->vui.b_pic_struct_present_flag = bs_read( p_bs, 1 ); p_sps->vui.b_bitstream_restriction_flag = bs_read( p_bs, 1 ); if( p_sps->vui.b_bitstream_restriction_flag ) { bs_read( p_bs, 1 ); /* motion vector pic boundaries */ bs_read_ue( p_bs ); /* max bytes per pic */ bs_read_ue( p_bs ); /* max bits per mb */ bs_read_ue( p_bs ); /* log2 max mv h */ bs_read_ue( p_bs ); /* log2 max mv v */ p_sps->vui.i_max_num_reorder_frames = bs_read_ue( p_bs ); bs_read_ue( p_bs ); /* max dec frame buffering */ } } return true; } void h264_release_pps( h264_picture_parameter_set_t *p_pps ) { free( p_pps ); } static bool h264_parse_picture_parameter_set_rbsp( bs_t *p_bs, h264_picture_parameter_set_t *p_pps ) { uint32_t i_pps_id = bs_read_ue( p_bs ); // pps id uint32_t i_sps_id = bs_read_ue( p_bs ); // sps id if( i_pps_id > H264_PPS_ID_MAX || i_sps_id > H264_SPS_ID_MAX ) return false; p_pps->i_id = i_pps_id; p_pps->i_sps_id = i_sps_id; bs_skip( p_bs, 1 ); // entropy coding mode flag p_pps->i_pic_order_present_flag = bs_read( p_bs, 1 ); unsigned num_slice_groups = bs_read_ue( p_bs ) + 1; if( num_slice_groups > 8 ) /* never has value > 7. Annex A, G & J */ return false; if( num_slice_groups > 1 ) { unsigned slice_group_map_type = bs_read_ue( p_bs ); if( slice_group_map_type == 0 ) { for( unsigned i = 0; i < num_slice_groups; i++ ) bs_read_ue( p_bs ); /* run_length_minus1[group] */ } else if( slice_group_map_type == 2 ) { for( unsigned i = 0; i < num_slice_groups; i++ ) { bs_read_ue( p_bs ); /* top_left[group] */ bs_read_ue( p_bs ); /* bottom_right[group] */ } } else if( slice_group_map_type > 2 && slice_group_map_type < 6 ) { bs_read1( p_bs ); /* slice_group_change_direction_flag */ bs_read_ue( p_bs ); /* slice_group_change_rate_minus1 */ } else if( slice_group_map_type == 6 ) { unsigned pic_size_in_maps_units = bs_read_ue( p_bs ) + 1; unsigned sliceGroupSize = 1; while(num_slice_groups > 1) { sliceGroupSize++; num_slice_groups = ((num_slice_groups - 1) >> 1) + 1; } for( unsigned i = 0; i < pic_size_in_maps_units; i++ ) { bs_skip( p_bs, sliceGroupSize ); } } } bs_read_ue( p_bs ); /* num_ref_idx_l0_default_active_minus1 */ bs_read_ue( p_bs ); /* num_ref_idx_l1_default_active_minus1 */ p_pps->weighted_pred_flag = bs_read( p_bs, 1 ); p_pps->weighted_bipred_idc = bs_read( p_bs, 2 ); bs_read_se( p_bs ); /* pic_init_qp_minus26 */ bs_read_se( p_bs ); /* pic_init_qs_minus26 */ bs_read_se( p_bs ); /* chroma_qp_index_offset */ bs_read( p_bs, 1 ); /* deblocking_filter_control_present_flag */ bs_read( p_bs, 1 ); /* constrained_intra_pred_flag */ p_pps->i_redundant_pic_present_flag = bs_read( p_bs, 1 ); /* TODO */ return true; } static bool h264_parse_sequence_parameter_set_extension_rbsp( bs_t *p_bs, h264_sequence_parameter_set_extension_t *p_sps_ext ) { p_sps_ext->i_sps_id = bs_read_ue( p_bs ); if( p_sps_ext->i_sps_id > H264_SPSEXT_ID_MAX ) return false; return true; } void h264_release_sps_extension( h264_sequence_parameter_set_extension_t *p_sps_ext ) { free( p_sps_ext ); } #define IMPL_h264_generic_decode( name, h264type, decode, release ) \ h264type * name( const uint8_t *p_buf, size_t i_buf, bool b_escaped ) \ { \ h264type *p_h264type = calloc(1, sizeof(h264type)); \ if(likely(p_h264type)) \ { \ 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, 8 ); /* Skip nal_unit_header */ \ if( !decode( &bs, p_h264type ) ) \ { \ release( p_h264type ); \ p_h264type = NULL; \ } \ } \ return p_h264type; \ } IMPL_h264_generic_decode( h264_decode_sps, h264_sequence_parameter_set_t, h264_parse_sequence_parameter_set_rbsp, h264_release_sps ) IMPL_h264_generic_decode( h264_decode_pps, h264_picture_parameter_set_t, h264_parse_picture_parameter_set_rbsp, h264_release_pps ) IMPL_h264_generic_decode( h264_decode_sps_extension, h264_sequence_parameter_set_extension_t, h264_parse_sequence_parameter_set_extension_rbsp, h264_release_sps_extension ) block_t *h264_NAL_to_avcC( uint8_t i_nal_length_size, const uint8_t **pp_sps_buf, const size_t *p_sps_size, uint8_t i_sps_count, const uint8_t **pp_pps_buf, const size_t *p_pps_size, uint8_t i_pps_count, const uint8_t **pp_sps_ext_buf, const size_t *p_sps_ext_size, uint8_t i_sps_ext_count ) { /* The length of the NAL size is encoded using 1, 2 or 4 bytes */ if( i_nal_length_size != 1 && i_nal_length_size != 2 && i_nal_length_size != 4 ) return NULL; if( i_sps_count == 0 || i_sps_count > H264_SPS_ID_MAX || i_pps_count == 0 ) return NULL; /* Calculate the total size of all SPS and PPS NALs */ size_t i_spspps_size = 0; for( size_t i = 0; i < i_sps_count; ++i ) { assert( pp_sps_buf[i] && p_sps_size[i] ); if( p_sps_size[i] < 4 || p_sps_size[i] > UINT16_MAX ) return NULL; i_spspps_size += p_sps_size[i] + 2 /* 16be size place holder */; } for( size_t i = 0; i < i_pps_count; ++i ) { assert( pp_pps_buf[i] && p_pps_size[i] ); if( p_pps_size[i] > UINT16_MAX) return NULL; i_spspps_size += p_pps_size[i] + 2 /* 16be size place holder */; } bo_t bo; /* 1 + 3 + 1 + 1 + 1 + i_spspps_size */ if( bo_init( &bo, 7 + i_spspps_size ) != true ) return NULL; bo_add_8( &bo, 1 ); /* configuration version */ bo_add_mem( &bo, 3, &pp_sps_buf[0][1] ); /* i_profile/profile_compatibility/level */ bo_add_8( &bo, 0xfc | (i_nal_length_size - 1) ); /* 0b11111100 | lengthsize - 1*/ bo_add_8( &bo, 0xe0 | i_sps_count ); /* 0b11100000 | sps_count */ for( size_t i = 0; i < i_sps_count; ++i ) { bo_add_16be( &bo, p_sps_size[i] ); bo_add_mem( &bo, p_sps_size[i], pp_sps_buf[i] ); } bo_add_8( &bo, i_pps_count ); /* pps_count */ for( size_t i = 0; i < i_pps_count; ++i ) { bo_add_16be( &bo, p_pps_size[i] ); bo_add_mem( &bo, p_pps_size[i], pp_pps_buf[i] ); } const uint8_t i_profile = pp_sps_buf[0][1]; if( i_profile == PROFILE_H264_HIGH || i_profile == PROFILE_H264_HIGH_10 || i_profile == PROFILE_H264_HIGH_422 || i_profile == PROFILE_H264_HIGH_444 ) { h264_sequence_parameter_set_t *p_sps = h264_decode_sps( pp_sps_buf[0], p_sps_size[0], true ); bo_add_8( &bo, 0xfc | (p_sps ? p_sps->i_chroma_idc : 0) ); bo_add_8( &bo, 0xf8 | (p_sps ? (p_sps->i_bit_depth_luma - 8) : 0) ); bo_add_8( &bo, 0xf8 | (p_sps ? (p_sps->i_bit_depth_chroma - 8) : 0) ); if( p_sps ) h264_release_sps( p_sps ); bo_add_8( &bo, i_sps_ext_count ); for( size_t i = 0; i < i_sps_ext_count; ++i ) { bo_add_16be( &bo, p_sps_ext_size[i] ); bo_add_mem( &bo, p_sps_ext_size[i], pp_sps_ext_buf[i] ); } } return bo.b; } static const h264_level_limits_t * h264_get_level_limits( const h264_sequence_parameter_set_t *p_sps ) { uint16_t i_level_number = p_sps->i_level; if( i_level_number == H264_LEVEL_NUMBER_1_1 && (p_sps->i_constraint_set_flags & H264_CONSTRAINT_SET_FLAG(3)) ) { i_level_number = H264_LEVEL_NUMBER_1_B; } for( size_t i=0; i< ARRAY_SIZE(h264_levels_limits); i++ ) if( h264_levels_limits[i].i_level == i_level_number ) return & h264_levels_limits[i].limits; return NULL; } static uint8_t h264_get_max_dpb_frames( const h264_sequence_parameter_set_t *p_sps ) { const h264_level_limits_t *limits = h264_get_level_limits( p_sps ); if( limits ) { unsigned i_frame_height_in_mbs = ( p_sps->pic_height_in_map_units_minus1 + 1 ) * ( 2 - p_sps->frame_mbs_only_flag ); unsigned i_den = ( p_sps->pic_width_in_mbs_minus1 + 1 ) * i_frame_height_in_mbs; uint8_t i_max_dpb_frames = limits->i_max_dpb_mbs / i_den; if( i_max_dpb_frames < 16 ) return i_max_dpb_frames; } return 16; } bool h264_get_dpb_values( const h264_sequence_parameter_set_t *p_sps, uint8_t *pi_depth, unsigned *pi_delay ) { uint8_t i_max_num_reorder_frames = p_sps->vui.i_max_num_reorder_frames; if( !p_sps->vui.b_bitstream_restriction_flag ) { switch( p_sps->i_profile ) /* E-2.1 */ { case PROFILE_H264_CAVLC_INTRA: case PROFILE_H264_SVC_HIGH: case PROFILE_H264_HIGH: case PROFILE_H264_HIGH_10: case PROFILE_H264_HIGH_422: case PROFILE_H264_HIGH_444_PREDICTIVE: if( p_sps->i_constraint_set_flags & H264_CONSTRAINT_SET_FLAG(3) ) { i_max_num_reorder_frames = 0; /* all IDR */ break; } /* fallthrough */ default: i_max_num_reorder_frames = h264_get_max_dpb_frames( p_sps ); break; } } *pi_depth = i_max_num_reorder_frames; *pi_delay = 0; return true; } bool h264_get_picture_size( const h264_sequence_parameter_set_t *p_sps, unsigned *p_w, unsigned *p_h, unsigned *p_vw, unsigned *p_vh ) { unsigned CropUnitX = 1; unsigned CropUnitY = 2 - p_sps->frame_mbs_only_flag; if( p_sps->b_separate_colour_planes_flag != 1 ) { if( p_sps->i_chroma_idc > 0 ) { unsigned SubWidthC = 2; unsigned SubHeightC = 2; if( p_sps->i_chroma_idc > 1 ) { SubHeightC = 1; if( p_sps->i_chroma_idc > 2 ) SubWidthC = 1; } CropUnitX *= SubWidthC; CropUnitY *= SubHeightC; } } *p_w = 16 * p_sps->pic_width_in_mbs_minus1 + 16; *p_h = 16 * p_sps->pic_height_in_map_units_minus1 + 16; *p_h *= ( 2 - p_sps->frame_mbs_only_flag ); *p_vw = *p_w - ( p_sps->frame_crop.left_offset + p_sps->frame_crop.right_offset ) * CropUnitX; *p_vh = *p_h - ( p_sps->frame_crop.bottom_offset + p_sps->frame_crop.top_offset ) * CropUnitY; return true; } bool h264_get_chroma_luma( const h264_sequence_parameter_set_t *p_sps, uint8_t *pi_chroma_format, uint8_t *pi_depth_luma, uint8_t *pi_depth_chroma ) { *pi_chroma_format = p_sps->i_chroma_idc; *pi_depth_luma = p_sps->i_bit_depth_luma; *pi_depth_chroma = p_sps->i_bit_depth_chroma; return true; } bool h264_get_colorimetry( const h264_sequence_parameter_set_t *p_sps, video_color_primaries_t *p_primaries, video_transfer_func_t *p_transfer, video_color_space_t *p_colorspace, bool *p_full_range ) { if( !p_sps->vui.b_valid ) return false; *p_primaries = hxxx_colour_primaries_to_vlc( p_sps->vui.colour.i_colour_primaries ); *p_transfer = hxxx_transfer_characteristics_to_vlc( p_sps->vui.colour.i_transfer_characteristics ); *p_colorspace = hxxx_matrix_coeffs_to_vlc( p_sps->vui.colour.i_matrix_coefficients ); *p_full_range = p_sps->vui.colour.b_full_range; return true; } bool h264_get_profile_level(const es_format_t *p_fmt, uint8_t *pi_profile, uint8_t *pi_level, uint8_t *pi_nal_length_size) { uint8_t *p = (uint8_t*)p_fmt->p_extra; if(p_fmt->i_extra < 8) return false; /* Check the profile / level */ if (p[0] == 1 && p_fmt->i_extra >= 12) { if (pi_nal_length_size) *pi_nal_length_size = 1 + (p[4]&0x03); p += 8; } else if(!p[0] && !p[1]) /* FIXME: WTH is setting AnnexB data here ? */ { if (!p[2] && p[3] == 1) p += 4; else if (p[2] == 1) p += 3; else return false; } else return false; if ( ((*p++)&0x1f) != 7) return false; if (pi_profile) *pi_profile = p[0]; if (pi_level) *pi_level = p[2]; return true; }