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 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; }