vlc | branch: master | Francois Cartegnie <[email protected]> | Tue Feb 26 15:44:26 2019 +0100| [2cd5e84b4086690ee7f372736ead445b95dffddb] | committer: Francois Cartegnie
packetizer: hevc: use recovery points > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=2cd5e84b4086690ee7f372736ead445b95dffddb --- modules/packetizer/hevc.c | 87 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 76 insertions(+), 11 deletions(-) diff --git a/modules/packetizer/hevc.c b/modules/packetizer/hevc.c index 05c3a1b126..a5049f275d 100644 --- a/modules/packetizer/hevc.c +++ b/modules/packetizer/hevc.c @@ -88,8 +88,16 @@ typedef struct const hevc_video_parameter_set_t *p_active_vps; const hevc_sequence_parameter_set_t *p_active_sps; const hevc_picture_parameter_set_t *p_active_pps; + enum + { + MISSING = 0, + COMPLETE, + SENT, + } sets; + /* Recovery starts from IFRAME or SEI recovery point */ + bool b_recovery_point; + hevc_sei_pic_timing_t *p_timing; - bool b_init_sequence_complete; date_t dts; vlc_tick_t pts; @@ -108,6 +116,7 @@ static block_t *ParseNALBlock(decoder_t *, bool *pb_ts_used, block_t *); static int PacketizeValidate(void *p_private, block_t *); static bool ParseSEICallback( const hxxx_sei_data_t *, void * ); static block_t *GetCc( decoder_t *, decoder_cc_desc_t * ); +static block_t *GetXPSCopy(decoder_sys_t *); #define BLOCK_FLAG_DROP (1 << BLOCK_FLAG_PRIVATE_SHIFT) @@ -131,6 +140,18 @@ static block_t * OutputQueues(decoder_sys_t *p_sys, bool b_valid) if(p_sys->pre.p_chain) { i_flags |= p_sys->pre.p_chain->i_flags; + if(p_sys->b_recovery_point && p_sys->sets != SENT) + { + if(p_sys->pre.p_chain->i_buffer >= 5 && + hevc_getNALType(&p_sys->pre.p_chain->p_buffer[4]) == HEVC_NAL_AUD) + { + block_t *p_au = p_sys->pre.p_chain; + p_sys->pre.p_chain = p_sys->pre.p_chain->p_next; + p_au->p_next = NULL; + block_ChainLastAppend(&pp_output_last, p_au); + } + block_ChainLastAppend(&pp_output_last, GetXPSCopy(p_sys)); + } block_ChainLastAppend(&pp_output_last, p_sys->pre.p_chain); INITQ(pre); } @@ -207,6 +228,7 @@ static int Open(vlc_object_t *p_this) date_Init( &p_sys->dts, 2 * 30000, 1001 ); p_sys->pts = VLC_TICK_INVALID; p_sys->b_need_ts = true; + p_sys->sets = MISSING; /* Set callbacks */ const uint8_t *p_extra = p_dec->fmt_in.p_extra; @@ -336,7 +358,8 @@ static void PacketizeReset(void *p_private, bool b_broken) if(p_out) block_ChainRelease(p_out); - p_sys->b_init_sequence_complete = false; + p_sys->sets = MISSING; + p_sys->b_recovery_point = false; p_sys->b_need_ts = true; date_Set(&p_sys->dts, VLC_TICK_INVALID); } @@ -459,6 +482,23 @@ static bool InsertXPS(decoder_t *p_dec, uint8_t i_nal_type, uint8_t i_id, return false; } +static block_t *GetXPSCopy(decoder_sys_t *p_sys) +{ + block_t *p_chain = NULL; + block_t **pp_append = &p_chain; + struct hevc_tuple_s *xpstype[3] = {p_sys->rg_vps, p_sys->rg_sps, p_sys->rg_pps}; + size_t xpsmax[3] = {HEVC_VPS_ID_MAX, HEVC_SPS_ID_MAX, HEVC_PPS_ID_MAX}; + for(size_t i=0; i<3; i++) + for(size_t j=0; j<xpsmax[i]; j++) + { + block_t *p_dup; + if(xpstype[i]->p_nal && + (p_dup = block_Duplicate(xpstype[i]->p_nal))) + block_ChainLastAppend(&pp_append, p_dup); + }; + return p_chain; +} + static bool XPSReady(decoder_sys_t *p_sys) { for(unsigned i=0;i<=HEVC_PPS_ID_MAX; i++) @@ -645,7 +685,8 @@ static block_t *ParseVCL(decoder_t *p_dec, uint8_t i_nal_type, block_t *p_frag) 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); + p_outputchain = OutputQueues(p_sys, p_sys->sets != MISSING && + p_sys->b_recovery_point); } hevc_slice_segment_header_t *p_sli = hevc_decode_slice_header(p_buffer, i_buffer, true, @@ -702,14 +743,16 @@ static block_t *ParseVCL(decoder_t *p_dec, uint8_t i_nal_type, block_t *p_frag) hevc_rbsp_release_slice_header(p_sli); } - if(!p_sys->b_init_sequence_complete && i_layer == 0 && - (p_frag->i_flags & BLOCK_FLAG_TYPE_I) && XPSReady(p_sys)) + if(p_sys->sets == MISSING && i_layer == 0 && XPSReady(p_sys)) + p_sys->sets = COMPLETE; + + if(p_sys->sets != MISSING && (p_frag->i_flags & BLOCK_FLAG_TYPE_I)) { - p_sys->b_init_sequence_complete = true; + p_sys->b_recovery_point = true; /* won't care about SEI recovery */ } - if( !p_sys->b_init_sequence_complete ) - cc_storage_reset( p_sys->p_ccs ); + if(!p_sys->b_recovery_point) /* content will be dropped */ + cc_storage_reset(p_sys->p_ccs); block_ChainLastAppend(&p_sys->frame.pp_chain_last, p_frag); @@ -722,13 +765,15 @@ static block_t * ParseAUHead(decoder_t *p_dec, uint8_t i_nal_type, block_t *p_na block_t *p_ret = NULL; if(p_sys->post.p_chain || p_sys->frame.p_chain) - p_ret = OutputQueues(p_sys, p_sys->b_init_sequence_complete); + p_ret = OutputQueues(p_sys, p_sys->sets != MISSING && + p_sys->b_recovery_point); switch(i_nal_type) { case HEVC_NAL_AUD: if(!p_ret && p_sys->pre.p_chain) - p_ret = OutputQueues(p_sys, p_sys->b_init_sequence_complete); + p_ret = OutputQueues(p_sys, p_sys->sets != MISSING && + p_sys->b_recovery_point); break; case HEVC_NAL_VPS: @@ -741,6 +786,11 @@ static block_t * ParseAUHead(decoder_t *p_dec, uint8_t i_nal_type, block_t *p_na if(hxxx_strip_AnnexB_startcode(&p_xps, &i_xps) && hevc_get_xps_id(p_nalb->p_buffer, p_nalb->i_buffer, &i_id)) InsertXPS(p_dec, i_nal_type, i_id, p_nalb); + if(p_sys->sets != SENT) /* will store/inject on first recovery point */ + { + block_Release(p_nalb); + return p_ret; + } break; } @@ -766,7 +816,8 @@ static block_t * ParseAUTail(decoder_t *p_dec, uint8_t i_nal_type, block_t *p_na { case HEVC_NAL_EOS: case HEVC_NAL_EOB: - p_ret = OutputQueues(p_sys, p_sys->b_init_sequence_complete); + p_ret = OutputQueues(p_sys, p_sys->sets != MISSING && + p_sys->b_recovery_point); if( p_ret ) p_ret->i_flags |= BLOCK_FLAG_END_OF_SEQUENCE; break; @@ -896,6 +947,12 @@ static block_t *ParseNALBlock(decoder_t *p_dec, bool *pb_ts_used, block_t *p_fra p_output = GatherAndValidateChain(p_output); if(p_output) { + if(p_sys->sets != SENT) + { + assert(p_sys->sets == COMPLETE); + p_sys->sets = SENT; + } + SetOutputBlockProperties( p_dec, p_output ); if (dts != VLC_TICK_INVALID) date_Set(&p_sys->dts, dts); @@ -953,6 +1010,14 @@ static bool ParseSEICallback( const hxxx_sei_data_t *p_sei_data, void *cbdata ) p_sei_data->itu_t35.u.cc.i_data ); } } break; + case HXXX_SEI_RECOVERY_POINT: + { + if( !p_sys->b_recovery_point ) + { + msg_Dbg( p_dec, "Seen SEI recovery point, %d recovery frames", p_sei_data->recovery.i_frames ); + p_sys->b_recovery_point = true; + } + } break; case HXXX_SEI_FRAME_PACKING_ARRANGEMENT: { if( p_dec->fmt_in.video.multiview_mode == MULTIVIEW_2D ) _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
