static block_t * ParseAUTail(decoder_t *p_dec, uint8_t i_nal_type, block_t *p_nalb) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_ret = NULL; block_ChainLastAppend(&p_sys->post.pp_chain_last, p_nalb); switch(i_nal_type) { case HEVC_NAL_EOS: case HEVC_NAL_EOB: p_ret = OutputQueues(p_sys, true); break; case HEVC_NAL_SUFF_SEI: HxxxParse_AnnexB_SEI( p_nalb->p_buffer, p_nalb->i_buffer, 2 /* nal header */, ParseSEICallback, p_dec ); break; } if(!p_ret && p_sys->frame.p_chain == NULL) p_ret = OutputQueues(p_sys, false); return p_ret; }
static block_t * ParseAUTail(decoder_t *p_dec, uint8_t i_nal_type, block_t *p_nalb) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_ret = NULL; block_ChainLastAppend(&p_sys->post.pp_chain_last, p_nalb); switch(i_nal_type) { case HEVC_NAL_EOS: case HEVC_NAL_EOB: p_ret = OutputQueues(p_sys, true); break; } if(!p_ret && p_sys->frame.p_chain == NULL) p_ret = OutputQueues(p_sys, false); return p_ret; }
/**************************************************************************** * Packetizer Helpers ****************************************************************************/ static void PacketizeReset(void *p_private, bool b_broken) { VLC_UNUSED(b_broken); decoder_t *p_dec = p_private; decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_out = OutputQueues(p_sys, false); if(p_out) block_ChainRelease(p_out); p_sys->b_init_sequence_complete = false; }
/***************************************************************************** * ParseNALBlock: parses annexB type NALs * All p_frag blocks are required to start with 0 0 0 1 4-byte startcode *****************************************************************************/ static block_t *ParseNALBlock(decoder_t *p_dec, bool *pb_ts_used, block_t *p_frag) { decoder_sys_t *p_sys = p_dec->p_sys; if(unlikely(p_frag->i_buffer < 5)) { msg_Warn(p_dec,"NAL too small"); block_Release(p_frag); *pb_ts_used = false; return NULL; } if(p_frag->p_buffer[4] & 0x80) { msg_Warn(p_dec,"Forbidden zero bit not null, corrupted NAL"); block_Release(p_frag); *pb_ts_used = false; return GatherAndValidateChain(OutputQueues(p_sys, false)); /* will drop */ } /* Get NALU type */ block_t * p_output = NULL; uint8_t i_nal_type = hevc_getNALType(&p_frag->p_buffer[4]); if (i_nal_type < HEVC_NAL_VPS) { /* NAL is a VCL NAL */ p_output = ParseVCL(p_dec, i_nal_type, p_frag); if (p_output && (p_output->i_flags & BLOCK_FLAG_CORRUPTED)) msg_Info(p_dec, "Waiting for VPS/SPS/PPS"); } else { p_output = ParseNonVCL(p_dec, i_nal_type, p_frag); } p_output = GatherAndValidateChain(p_output); *pb_ts_used = (p_output != NULL); return p_output; }
static block_t * ParseAUHead(decoder_t *p_dec, uint8_t i_nal_type, block_t *p_nalb) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_ret = NULL; if(p_sys->post.p_chain || p_sys->frame.p_chain) p_ret = OutputQueues(p_sys, true); switch(i_nal_type) { case HEVC_NAL_AUD: if(!p_ret && p_sys->pre.p_chain) p_ret = OutputQueues(p_sys, true); break; case HEVC_NAL_VPS: case HEVC_NAL_SPS: case HEVC_NAL_PPS: { uint8_t i_id; if( hevc_get_xps_id(p_nalb->p_buffer, p_nalb->i_buffer, &i_id) && InsertXPS(p_dec, i_nal_type, i_id, p_nalb) ) { const hevc_sequence_parameter_set_t *p_sps; if( i_nal_type == HEVC_NAL_SPS && (p_sps = p_dec->p_sys->rgi_p_decsps[i_id]) ) { if(!p_dec->fmt_out.video.i_frame_rate) { (void) hevc_get_frame_rate( p_sps, p_dec->p_sys->rgi_p_decvps, &p_dec->fmt_out.video.i_frame_rate, &p_dec->fmt_out.video.i_frame_rate_base ); } if(p_dec->fmt_out.video.primaries == COLOR_PRIMARIES_UNDEF) { (void) hevc_get_colorimetry( p_sps, &p_dec->fmt_out.video.primaries, &p_dec->fmt_out.video.transfer, &p_dec->fmt_out.video.space, &p_dec->fmt_out.video.b_color_range_full); } unsigned sizes[4]; if( hevc_get_picture_size( p_sps, &sizes[0], &sizes[1], &sizes[2], &sizes[3] ) ) { if( p_dec->fmt_out.video.i_width != sizes[0] || p_dec->fmt_out.video.i_height != sizes[1] ) { p_dec->fmt_out.video.i_width = sizes[0]; p_dec->fmt_out.video.i_height = sizes[1]; } } if(p_dec->fmt_out.i_profile == -1) { uint8_t i_profile, i_level; if( hevc_get_sps_profile_tier_level( p_sps, &i_profile, &i_level ) ) { p_dec->fmt_out.i_profile = i_profile; p_dec->fmt_out.i_level = i_level; } } } } break; } case HEVC_NAL_PREF_SEI: HxxxParse_AnnexB_SEI( p_nalb->p_buffer, p_nalb->i_buffer, 2 /* nal header */, ParseSEICallback, p_dec ); break; default: break; } block_ChainLastAppend(&p_sys->pre.pp_chain_last, p_nalb); return p_ret; }
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; }