diff --git a/modules/codec/hxxx_helper.c b/modules/codec/hxxx_helper.c index a0db670dc8..03fe5d3942 100644 --- a/modules/codec/hxxx_helper.c +++ b/modules/codec/hxxx_helper.c @@ -201,34 +201,38 @@ h264_helper_parse_nal(struct hxxx_helper *hh, const uint8_t *p_nal, size_t i_nal return VLC_EGENERIC; const enum h264_nal_unit_type_e i_nal_type = p_nal[0] & 0x1F; + uint8_t i_id; if (i_nal_type == H264_NAL_SPS) { + h264_get_xps_id(p_nal, i_nal, &i_id); LOAD_xPS(hh->h264.sps_list, hh->h264.i_sps_count, - p_xps->i_id, H264_SPS_ID_MAX, + i_id, H264_SPS_ID_MAX, h264_sequence_parameter_set_t, h264_decode_sps, h264_release_sps); - hh->h264.i_current_sps = ((h264_sequence_parameter_set_t*)p_xps)->i_id; - msg_Dbg(hh->p_obj, "new SPS parsed: %u", hh->h264.i_current_sps); + hh->h264.i_current_sps = i_id; + msg_Dbg(hh->p_obj, "new SPS parsed: %u", i_id); } else if (i_nal_type == H264_NAL_PPS) { + h264_get_xps_id(p_nal, i_nal, &i_id); LOAD_xPS(hh->h264.pps_list, hh->h264.i_pps_count, - p_xps->i_id, H264_PPS_ID_MAX, + i_id, H264_PPS_ID_MAX, h264_picture_parameter_set_t, h264_decode_pps, h264_release_pps); - msg_Dbg(hh->p_obj, "new PPS parsed: %u", ((h264_picture_parameter_set_t*)p_xps)->i_id); + msg_Dbg(hh->p_obj, "new PPS parsed: %u", i_id); } else if(i_nal_type == H264_NAL_SPS_EXT) { + h264_get_xps_id(p_nal, i_nal, &i_id); LOAD_xPS(hh->h264.spsext_list, hh->h264.i_spsext_count, - p_xps->i_sps_id, H264_SPSEXT_ID_MAX, + i_id, H264_SPSEXT_ID_MAX, h264_sequence_parameter_set_extension_t, h264_decode_sps_extension, h264_release_sps_extension); - msg_Dbg(hh->p_obj, "new SPSEXT parsed: %u", ((h264_sequence_parameter_set_extension_t*)p_xps)->i_sps_id); + msg_Dbg(hh->p_obj, "new SPSEXT parsed: %u", i_id); } else if (i_nal_type <= H264_NAL_SLICE_IDR && i_nal_type != H264_NAL_UNKNOWN) @@ -254,14 +258,14 @@ h264_helper_parse_nal(struct hxxx_helper *hh, const uint8_t *p_nal, size_t i_nal return VLC_EGENERIC; struct hxxx_helper_nal *hsps = - &hh->h264.sps_list[hpps->h264_pps->i_sps_id]; + &hh->h264.sps_list[h264_get_pps_sps_id(hpps->h264_pps)]; if (hsps->b == NULL) return VLC_EGENERIC; - assert(hpps->h264_pps->i_sps_id == hsps->h264_sps->i_id); - if (hsps->h264_sps->i_id != hh->h264.i_current_sps) + assert(h264_get_pps_sps_id(hpps->h264_pps) == h264_get_sps_id(hsps->h264_sps)); + if (h264_get_sps_id(hsps->h264_sps) != hh->h264.i_current_sps) { - hh->h264.i_current_sps = hsps->h264_sps->i_id; + hh->h264.i_current_sps = h264_get_sps_id(hsps->h264_sps); hh->i_config_version++; } } @@ -874,12 +878,9 @@ hxxx_helper_get_current_profile_level(const struct hxxx_helper *hh, if(hh->i_codec == VLC_CODEC_H264) { const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh); - if (hsps) - { - *p_profile = hsps->h264_sps->i_profile; - *p_level = hsps->h264_sps->i_level; + if (hsps && hsps->h264_sps && + h264_get_sps_profile_tier_level(hsps->h264_sps, p_profile, p_level)) return VLC_SUCCESS; - } } else if(hh->i_codec == VLC_CODEC_HEVC) { @@ -896,11 +897,9 @@ int h264_helper_get_constraint_flag(const struct hxxx_helper *hh, assert(hh->i_codec == VLC_CODEC_H264); const struct hxxx_helper_nal *hsps = h264_helper_get_current_sps(hh); - if (hsps) - { - *pi_constraints = hsps->h264_sps->i_constraint_set_flags; + if (hsps && hsps->h264_sps && + h264_get_constraints_set(hsps->h264_sps, pi_constraints)) return VLC_SUCCESS; - } return VLC_EGENERIC; } diff --git a/modules/codec/videotoolbox/decoder.c b/modules/codec/videotoolbox/decoder.c index 61c489e47a..94fe1c3f2c 100644 --- a/modules/codec/videotoolbox/decoder.c +++ b/modules/codec/videotoolbox/decoder.c @@ -201,7 +201,7 @@ static void GetxPSH264(uint8_t i_pps_id, void *priv, if (*pp_pps == NULL) *pp_sps = NULL; else - *pp_sps = h264ctx->hh.h264.sps_list[(*pp_pps)->i_sps_id].h264_sps; + *pp_sps = h264ctx->hh.h264.sps_list[h264_get_pps_sps_id(*pp_pps)].h264_sps; } struct sei_callback_h264_s @@ -271,7 +271,7 @@ static bool FillReorderInfoH264(decoder_t *p_dec, const block_t *p_block, p_info->b_keyframe = slicetype == H264_SLICE_TYPE_I; p_info->b_flush = p_info->b_keyframe || h264_has_mmco5(slice); p_info->b_field = h264_is_field_pic(slice); - p_info->b_progressive = !p_sps->mb_adaptive_frame_field_flag && + p_info->b_progressive = !h264_using_adaptive_frames(p_sps) && !p_info->b_field; struct sei_callback_h264_s sei; diff --git a/modules/packetizer/h264.c b/modules/packetizer/h264.c index 54f91ead87..acdafd23d1 100644 --- a/modules/packetizer/h264.c +++ b/modules/packetizer/h264.c @@ -200,8 +200,12 @@ static void ActivateSets( decoder_t *p_dec, const h264_sequence_parameter_set_t if( p_sps ) { - p_dec->fmt_out.i_profile = p_sps->i_profile; - p_dec->fmt_out.i_level = p_sps->i_level; + uint8_t pl[2]; + if( h264_get_sps_profile_tier_level( p_sps, pl, &pl[1] ) ) + { + p_dec->fmt_out.i_profile = pl[0]; + p_dec->fmt_out.i_level = pl[1]; + } (void) h264_get_picture_size( p_sps, &p_dec->fmt_out.video.i_x_offset, @@ -789,7 +793,7 @@ static block_t *OutputPicture( decoder_t *p_dec ) if( p_sys->i_recoveryfnum != UINT_MAX ) { assert(p_sys->b_recovered == false); - const unsigned maxFrameNum = 1 << (p_sps->i_log2_max_frame_num + 4); + const unsigned maxFrameNum = h264_get_max_frame_num( p_sps ); if( ( p_sys->i_recoveryfnum > maxFrameNum && i_frame_num < p_sys->i_recoverystartfnum && @@ -851,7 +855,7 @@ static block_t *OutputPicture( decoder_t *p_dec ) unsigned i_num_clock_ts = h264_get_num_ts( p_sps, p_sys->p_slice, p_sys->i_pic_struct, tFOC, bFOC ); - if( p_sps->frame_mbs_only_flag == 0 && p_sps->vui.b_pic_struct_present_flag ) + if( !h264_is_frames_only( p_sps ) && p_sys->i_pic_struct != UINT8_MAX ) { switch( p_sys->i_pic_struct ) { @@ -1138,7 +1142,7 @@ static void GetSPSPPS( uint8_t i_pps_id, void *priv, if( *pp_pps == NULL ) *pp_sps = NULL; else - *pp_sps = p_sys->sps[(*pp_pps)->i_sps_id].p_sps; + *pp_sps = p_sys->sps[h264_get_pps_sps_id(*pp_pps)].p_sps; } static h264_slice_t * ParseSliceHeader( decoder_t *p_dec, const block_t *p_frag ) diff --git a/modules/packetizer/h264_nal.c b/modules/packetizer/h264_nal.c index 27ebdda184..2ceef560f1 100644 --- a/modules/packetizer/h264_nal.c +++ b/modules/packetizer/h264_nal.c @@ -774,6 +774,16 @@ bool h264_get_xps_id( const uint8_t *p_buf, size_t i_buf, uint8_t *pi_id ) return !bs_error( &bs ) && *pi_id <= i_max; } +uint8_t h264_get_sps_id( const h264_sequence_parameter_set_t *p_sps ) +{ + return p_sps->i_id; +} + +uint8_t h264_get_pps_sps_id( const h264_picture_parameter_set_t *p_pps ) +{ + return p_pps->i_sps_id; +} + 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; @@ -844,6 +854,37 @@ bool h264_get_dpb_values( const h264_sequence_parameter_set_t *p_sps, return true; } +unsigned h264_get_max_frame_num( const h264_sequence_parameter_set_t *p_sps ) +{ + return 1 << (p_sps->i_log2_max_frame_num + 4); +} + +bool h264_is_frames_only( const h264_sequence_parameter_set_t *p_sps ) +{ + return p_sps->frame_mbs_only_flag; +} + +bool h264_using_adaptive_frames( const h264_sequence_parameter_set_t *p_sps ) +{ + return p_sps->mb_adaptive_frame_field_flag; +} + + +bool h264_get_sps_profile_tier_level( const h264_sequence_parameter_set_t *p_sps, + uint8_t *pi_profile, uint8_t *pi_level) +{ + *pi_profile = p_sps->i_profile; + *pi_level = p_sps->i_level; + return true; +} + +bool h264_get_constraints_set( const h264_sequence_parameter_set_t *p_sps, + uint8_t *pi_constraints ) +{ + *pi_constraints = p_sps->i_constraint_set_flags; + return true; +} + bool h264_get_picture_size( const h264_sequence_parameter_set_t *p_sps, unsigned *p_ox, unsigned *p_oy, unsigned *p_w, unsigned *p_h, diff --git a/modules/packetizer/h264_nal.h b/modules/packetizer/h264_nal.h index 60fe448056..bc0496f110 100644 --- a/modules/packetizer/h264_nal.h +++ b/modules/packetizer/h264_nal.h @@ -99,6 +99,9 @@ void h264_release_sps( h264_sequence_parameter_set_t * ); void h264_release_pps( h264_picture_parameter_set_t * ); void h264_release_sps_extension( h264_sequence_parameter_set_extension_t * ); +uint8_t h264_get_sps_id( const h264_sequence_parameter_set_t * ); +uint8_t h264_get_pps_sps_id( const h264_picture_parameter_set_t * ); + struct h264_sequence_parameter_set_t { uint8_t i_id; @@ -207,6 +210,14 @@ uint8_t * h264_avcC_to_AnnexB_NAL( const uint8_t *p_buf, size_t i_buf, bool h264_get_dpb_values( const h264_sequence_parameter_set_t *, uint8_t *pi_depth, unsigned *pi_delay ); +unsigned h264_get_max_frame_num( const h264_sequence_parameter_set_t * ); +bool h264_is_frames_only( const h264_sequence_parameter_set_t * ); +bool h264_using_adaptive_frames( const h264_sequence_parameter_set_t * ); + +bool h264_get_sps_profile_tier_level( const h264_sequence_parameter_set_t *, + uint8_t *pi_profile, uint8_t *pi_level ); +bool h264_get_constraints_set( const h264_sequence_parameter_set_t *p_sps, + uint8_t *pi_constraints ); bool h264_get_picture_size( const h264_sequence_parameter_set_t *, unsigned *p_ox, unsigned *p_oy, unsigned *p_w, unsigned *p_h, diff --git a/modules/packetizer/h264_slice.c b/modules/packetizer/h264_slice.c index 6f75858f13..2a8ddc3b24 100644 --- a/modules/packetizer/h264_slice.c +++ b/modules/packetizer/h264_slice.c @@ -89,27 +89,9 @@ void h264_slice_release( h264_slice_t *p_slice ) free( p_slice ); } -void h264_slice_init( h264_slice_t *p_slice ) -{ - p_slice->i_nal_type = -1; - p_slice->i_nal_ref_idc = -1; - p_slice->i_idr_pic_id = -1; - p_slice->i_frame_num = 0; - p_slice->type = H264_SLICE_TYPE_UNKNOWN; - p_slice->i_pic_parameter_set_id = -1; - p_slice->i_field_pic_flag = 0; - p_slice->i_bottom_field_flag = -1; - p_slice->i_pic_order_cnt_type = -1; - p_slice->i_pic_order_cnt_lsb = -1; - p_slice->i_delta_pic_order_cnt_bottom = -1; - p_slice->i_delta_pic_order_cnt0 = 0; - p_slice->i_delta_pic_order_cnt1 = 0; - p_slice->has_mmco5 = false; -} - void h264_slice_copy_idr_id( const h264_slice_t *src, h264_slice_t *dst ) { - if( !src || dst->i_idr_pic_id != -1 ) + if( !src || src->i_nal_type != H264_NAL_SLICE_IDR ) /* value only set on IDR */ return; dst->i_idr_pic_id = src->i_idr_pic_id; } @@ -123,7 +105,6 @@ h264_slice_t * h264_decode_slice( const uint8_t *p_buffer, size_t i_buffer, h264_slice_t *p_slice = calloc( 1, sizeof(*p_slice) ); if( !p_slice ) return NULL; - h264_slice_init( p_slice ); int i_slice_type; bs_t s; @@ -495,22 +476,23 @@ bool h264_IsFirstVCLNALUnit( const h264_slice_t *p_prev, const h264_slice_t *p_c p_cur->i_field_pic_flag != p_prev->i_field_pic_flag || !p_cur->i_nal_ref_idc != !p_prev->i_nal_ref_idc ) return true; - if( (p_cur->i_bottom_field_flag != -1) && - (p_prev->i_bottom_field_flag != -1) && - (p_cur->i_bottom_field_flag != p_prev->i_bottom_field_flag) ) - return true; - if( p_cur->i_pic_order_cnt_type == 0 && - ( p_cur->i_pic_order_cnt_lsb != p_prev->i_pic_order_cnt_lsb || - p_cur->i_delta_pic_order_cnt_bottom != p_prev->i_delta_pic_order_cnt_bottom ) ) - return true; - else if( p_cur->i_pic_order_cnt_type == 1 && - ( p_cur->i_delta_pic_order_cnt0 != p_prev->i_delta_pic_order_cnt0 || - p_cur->i_delta_pic_order_cnt1 != p_prev->i_delta_pic_order_cnt1 ) ) + if( p_cur->i_field_pic_flag && /* present in both and differs in value */ + p_cur->i_bottom_field_flag != p_prev->i_bottom_field_flag ) return true; + if( p_cur->i_pic_order_cnt_type == p_prev->i_pic_order_cnt_type ) + { + if( p_cur->i_pic_order_cnt_type == 0 && + ( p_cur->i_pic_order_cnt_lsb != p_prev->i_pic_order_cnt_lsb || + p_cur->i_delta_pic_order_cnt_bottom != p_prev->i_delta_pic_order_cnt_bottom ) ) + return true; + else if( p_cur->i_pic_order_cnt_type == 1 && + ( p_cur->i_delta_pic_order_cnt0 != p_prev->i_delta_pic_order_cnt0 || + p_cur->i_delta_pic_order_cnt1 != p_prev->i_delta_pic_order_cnt1 ) ) + return true; + } if( ( p_cur->i_nal_type == H264_NAL_SLICE_IDR || p_prev->i_nal_type == H264_NAL_SLICE_IDR ) && ( p_cur->i_nal_type != p_prev->i_nal_type || p_cur->i_idr_pic_id != p_prev->i_idr_pic_id ) ) return true; - return false; } diff --git a/modules/packetizer/h264_slice.h b/modules/packetizer/h264_slice.h index 9b8629ca51..4b576d62dd 100644 --- a/modules/packetizer/h264_slice.h +++ b/modules/packetizer/h264_slice.h @@ -49,7 +49,6 @@ unsigned h264_get_frame_num( const h264_slice_t *p_slice ); unsigned h264_get_nal_ref_idc( const h264_slice_t *p_slice ); bool h264_has_mmco5( const h264_slice_t *p_slice ); void h264_slice_release( h264_slice_t *p_slice ); -void h264_slice_init( h264_slice_t *p_slice ); void h264_slice_copy_idr_id( const h264_slice_t *src, h264_slice_t *dst );