block_t *h264_AnnexB_NAL_to_avcC( uint8_t i_nal_length_size, const uint8_t *p_sps_buf, size_t i_sps_size, const uint8_t *p_pps_buf, size_t i_pps_size ) { if( !hxxx_strip_AnnexB_startcode( &p_sps_buf, &i_sps_size ) || !hxxx_strip_AnnexB_startcode( &p_pps_buf, &i_pps_size ) ) return NULL; return h264_NAL_to_avcC( i_nal_length_size, p_sps_buf, i_sps_size, p_pps_buf, i_pps_size ); }
static void PutPPS( decoder_t *p_dec, block_t *p_frag ) { decoder_sys_t *p_sys = p_dec->p_sys; const uint8_t *p_buffer = p_frag->p_buffer; size_t i_buffer = p_frag->i_buffer; if( !hxxx_strip_AnnexB_startcode( &p_buffer, &i_buffer ) ) { block_Release( p_frag ); return; } h264_picture_parameter_set_t *p_pps = h264_decode_pps( p_buffer, i_buffer, true ); if( !p_pps ) { msg_Warn( p_dec, "invalid PPS" ); block_Release( p_frag ); return; } /* We have a new PPS */ if( !p_sys->pps[p_pps->i_id].p_pps ) msg_Dbg( p_dec, "found NAL_PPS (pps_id=%d sps_id=%d)", p_pps->i_id, p_pps->i_sps_id ); StorePPS( p_sys, p_pps->i_id, p_frag, p_pps ); }
block_t *h264_AnnexB_NAL_to_avcC( uint8_t i_nal_length_size, const uint8_t *p_sps_buf, size_t i_sps_size, const uint8_t *p_pps_buf, size_t i_pps_size ) { if( i_pps_size > UINT16_MAX || i_sps_size > UINT16_MAX ) return NULL; if( !hxxx_strip_AnnexB_startcode( &p_sps_buf, &i_sps_size ) || !hxxx_strip_AnnexB_startcode( &p_pps_buf, &i_pps_size ) ) return NULL; /* 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; bo_t bo; /* 6 * int(8), i_sps_size, 1 * int(8), i_pps_size */ if( bo_init( &bo, 7 + i_sps_size + i_pps_size ) != true ) return NULL; bo_add_8( &bo, 1 ); /* configuration version */ bo_add_mem( &bo, 3, &p_sps_buf[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_size > 0 ? 1 : 0) ); /* 0b11100000 | sps_count */ if( i_sps_size ) { bo_add_16be( &bo, i_sps_size ); bo_add_mem( &bo, i_sps_size, p_sps_buf ); } bo_add_8( &bo, (i_pps_size > 0 ? 1 : 0) ); /* pps_count */ if( i_pps_size ) { bo_add_16be( &bo, i_pps_size ); bo_add_mem( &bo, i_pps_size, p_pps_buf ); } return bo.b; }
static void PutSPS( decoder_t *p_dec, block_t *p_frag ) { decoder_sys_t *p_sys = p_dec->p_sys; const uint8_t *p_buffer = p_frag->p_buffer; size_t i_buffer = p_frag->i_buffer; if( !hxxx_strip_AnnexB_startcode( &p_buffer, &i_buffer ) ) return; h264_sequence_parameter_set_t *p_sps = h264_decode_sps( p_buffer, i_buffer, true ); if( !p_sps ) { msg_Warn( p_dec, "invalid SPS" ); block_Release( p_frag ); return; } p_dec->fmt_out.i_profile = p_sps->i_profile; p_dec->fmt_out.i_level = p_sps->i_level; (void) h264_get_picture_size( p_sps, &p_dec->fmt_out.video.i_width, &p_dec->fmt_out.video.i_height, &p_dec->fmt_out.video.i_visible_width, &p_dec->fmt_out.video.i_visible_height ); if( p_sps->vui.i_sar_num != 0 && p_sps->vui.i_sar_den != 0 ) { p_dec->fmt_out.video.i_sar_num = p_sps->vui.i_sar_num; p_dec->fmt_out.video.i_sar_den = p_sps->vui.i_sar_den; } p_sys->i_log2_max_frame_num = p_sps->i_log2_max_frame_num; p_sys->b_frame_mbs_only = p_sps->frame_mbs_only_flag; p_sys->i_pic_order_cnt_type = p_sps->i_pic_order_cnt_type; p_sys->i_delta_pic_order_always_zero_flag = p_sps->i_delta_pic_order_always_zero_flag; p_sys->i_log2_max_pic_order_cnt_lsb = p_sps->i_log2_max_pic_order_cnt_lsb; if( p_sps->vui.b_valid ) { p_sys->b_timing_info_present_flag = p_sps->vui.b_timing_info_present_flag; p_sys->i_num_units_in_tick = p_sps->vui.i_num_units_in_tick; p_sys->i_time_scale = p_sps->vui.i_time_scale; p_sys->b_fixed_frame_rate = p_sps->vui.b_fixed_frame_rate; p_sys->b_pic_struct_present_flag = p_sps->vui.b_pic_struct_present_flag; p_sys->b_cpb_dpb_delays_present_flag = p_sps->vui.b_hrd_parameters_present_flag; p_sys->i_cpb_removal_delay_length_minus1 = p_sps->vui.i_cpb_removal_delay_length_minus1; p_sys->i_dpb_output_delay_length_minus1 = p_sps->vui.i_dpb_output_delay_length_minus1; if( p_sps->vui.b_fixed_frame_rate && !p_dec->fmt_out.video.i_frame_rate_base ) { p_dec->fmt_out.video.i_frame_rate_base = p_sps->vui.i_num_units_in_tick; p_dec->fmt_out.video.i_frame_rate = p_sps->vui.i_time_scale >> 1 /* num_clock_ts == 2 */; }
/* 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 ParseSliceHeader( decoder_t *p_dec, const block_t *p_frag, h264_slice_t *p_slice ) { decoder_sys_t *p_sys = p_dec->p_sys; const uint8_t *p_stripped = p_frag->p_buffer; size_t i_stripped = p_frag->i_buffer; if( !hxxx_strip_AnnexB_startcode( &p_stripped, &i_stripped ) || i_stripped < 2 ) return false; if( !h264_decode_slice( p_stripped, i_stripped, GetSPSPPS, p_sys, p_slice ) ) return false; const h264_sequence_parameter_set_t *p_sps; const h264_picture_parameter_set_t *p_pps; GetSPSPPS( p_slice->i_pic_parameter_set_id, p_sys, &p_sps, &p_pps ); if( unlikely( !p_sps || !p_pps) ) return false; ActivateSets( p_dec, p_sps, p_pps ); return true; }
static block_t *ParseVCL(decoder_t *p_dec, uint8_t i_nal_type, block_t *p_frag) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_frame = NULL; const uint8_t *p_buffer = p_frag->p_buffer; size_t i_buffer = p_frag->i_buffer; if(unlikely(!hxxx_strip_AnnexB_startcode(&p_buffer, &i_buffer) || i_buffer < 3)) { block_ChainAppend(&p_sys->p_frame, p_frag); /* might corrupt */ return NULL; } bool b_first_slice_in_pic = p_buffer[2] & 0x80; if (b_first_slice_in_pic) { if(p_sys->p_frame) { /* Starting new frame, gather and return previous frame data */ p_frame = block_ChainGather(p_sys->p_frame); p_sys->p_frame = NULL; p_sys->pp_frame_last = &p_sys->p_frame; } switch(i_nal_type) { case HEVC_NAL_BLA_W_LP: case HEVC_NAL_BLA_W_RADL: case HEVC_NAL_BLA_N_LP: case HEVC_NAL_IDR_W_RADL: case HEVC_NAL_IDR_N_LP: case HEVC_NAL_CRA: p_frag->i_flags |= BLOCK_FLAG_TYPE_I; break; default: { hevc_slice_segment_header_t *p_sli = hevc_decode_slice_header( p_buffer, i_buffer, true, p_sys->rgi_p_decsps, p_sys->rgi_p_decpps ); if( p_sli ) { enum hevc_slice_type_e type; if( hevc_get_slice_type( p_sli, &type ) ) { if( type == HEVC_SLICE_TYPE_P ) p_frag->i_flags |= BLOCK_FLAG_TYPE_P; else p_frag->i_flags |= BLOCK_FLAG_TYPE_B; } hevc_rbsp_release_slice_header( p_sli ); } else p_frag->i_flags |= BLOCK_FLAG_TYPE_B; } break; } } block_ChainLastAppend(&p_sys->pp_frame_last, p_frag); return p_frame; }
static bool InsertXPS(decoder_t *p_dec, uint8_t i_nal_type, uint8_t i_id, block_t *p_nalb) { decoder_sys_t *p_sys = p_dec->p_sys; switch(i_nal_type) { case HEVC_NAL_VPS: if(i_id >= HEVC_VPS_MAX) return false; break; case HEVC_NAL_SPS: if(i_id >= HEVC_SPS_MAX) return false; break; case HEVC_NAL_PPS: if(i_id >= HEVC_PPS_MAX) return false; break; default: return false; } /* Free associated decoded version */ if(i_nal_type == HEVC_NAL_SPS && p_sys->rgi_p_decsps[i_id]) { hevc_rbsp_release_sps(p_sys->rgi_p_decsps[i_id]); p_sys->rgi_p_decsps[i_id] = NULL; } else if(i_nal_type == HEVC_NAL_PPS && p_sys->rgi_p_decpps[i_id]) { hevc_rbsp_release_pps(p_sys->rgi_p_decpps[i_id]); p_sys->rgi_p_decpps[i_id] = NULL; } else if(i_nal_type == HEVC_NAL_VPS && p_sys->rgi_p_decvps[i_id]) { hevc_rbsp_release_vps(p_sys->rgi_p_decvps[i_id]); p_sys->rgi_p_decvps[i_id] = NULL; } const uint8_t *p_buffer = p_nalb->p_buffer; size_t i_buffer = p_nalb->i_buffer; if( hxxx_strip_AnnexB_startcode( &p_buffer, &i_buffer ) ) { /* Create decoded entries */ if(i_nal_type == HEVC_NAL_SPS) { p_sys->rgi_p_decsps[i_id] = hevc_decode_sps(p_buffer, i_buffer, true); if(!p_sys->rgi_p_decsps[i_id]) { msg_Err(p_dec, "Failed decoding SPS id %d", i_id); return false; } } else if(i_nal_type == HEVC_NAL_PPS) { p_sys->rgi_p_decpps[i_id] = hevc_decode_pps(p_buffer, i_buffer, true); if(!p_sys->rgi_p_decpps[i_id]) { msg_Err(p_dec, "Failed decoding PPS id %d", i_id); return false; } } else if(i_nal_type == HEVC_NAL_VPS) { p_sys->rgi_p_decvps[i_id] = hevc_decode_vps(p_buffer, i_buffer, true); if(!p_sys->rgi_p_decvps[i_id]) { msg_Err(p_dec, "Failed decoding VPS id %d", i_id); return false; } } return true; } return false; }
static block_t *ParseVCL(decoder_t *p_dec, uint8_t i_nal_type, block_t *p_frag) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_outputchain = NULL; const uint8_t *p_buffer = p_frag->p_buffer; size_t i_buffer = p_frag->i_buffer; if(unlikely(!hxxx_strip_AnnexB_startcode(&p_buffer, &i_buffer) || i_buffer < 3)) { block_ChainLastAppend(&p_sys->frame.pp_chain_last, p_frag); /* might be corrupted */ return NULL; } const uint8_t i_layer = hevc_getNALLayer( p_buffer ); bool b_first_slice_in_pic = p_buffer[2] & 0x80; if (b_first_slice_in_pic) { if(p_sys->frame.p_chain) { /* Starting new frame: return previous frame data for output */ p_outputchain = OutputQueues(p_sys, p_sys->b_init_sequence_complete); } switch(i_nal_type) { case HEVC_NAL_BLA_W_LP: case HEVC_NAL_BLA_W_RADL: case HEVC_NAL_BLA_N_LP: case HEVC_NAL_IDR_W_RADL: case HEVC_NAL_IDR_N_LP: case HEVC_NAL_CRA: p_frag->i_flags |= BLOCK_FLAG_TYPE_I; break; default: { hevc_slice_segment_header_t *p_sli = hevc_decode_slice_header( p_buffer, i_buffer, true, p_sys->rgi_p_decsps, p_sys->rgi_p_decpps ); if( p_sli ) { enum hevc_slice_type_e type; if( hevc_get_slice_type( p_sli, &type ) ) { if( type == HEVC_SLICE_TYPE_P ) p_frag->i_flags |= BLOCK_FLAG_TYPE_P; else p_frag->i_flags |= BLOCK_FLAG_TYPE_B; } hevc_rbsp_release_slice_header( p_sli ); } else p_frag->i_flags |= BLOCK_FLAG_TYPE_B; } break; } } if(!p_sys->b_init_sequence_complete && i_layer == 0 && (p_frag->i_flags & BLOCK_FLAG_TYPE_I) && XPSReady(p_sys)) { p_sys->b_init_sequence_complete = true; } if( !p_sys->b_init_sequence_complete ) cc_storage_reset( p_sys->p_ccs ); block_ChainLastAppend(&p_sys->frame.pp_chain_last, p_frag); return p_outputchain; }