📄 ps.c
字号:
p_sys->b_lost_sync = false; if( p_sys->i_length < 0 && p_sys->b_seekable ) FindLength( p_demux ); if( ( p_pkt = ps_pkt_read( p_demux->s, i_code ) ) == NULL ) { return 0; } switch( i_code ) { case 0x1b9: block_Release( p_pkt ); break; case 0x1ba: if( !ps_pkt_parse_pack( p_pkt, &p_sys->i_scr, &i_mux_rate ) ) { if( !p_sys->b_have_pack ) p_sys->b_have_pack = true; /* done later on to work around bad vcd/svcd streams */ /* es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_scr ); */ if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate; } block_Release( p_pkt ); break; case 0x1bb: if( !ps_pkt_parse_system( p_pkt, &p_sys->psm, p_sys->tk ) ) { int i; for( i = 0; i < PS_TK_COUNT; i++ ) { ps_track_t *tk = &p_sys->tk[i]; if( tk->b_seen && !tk->es && tk->fmt.i_cat != UNKNOWN_ES ) { tk->es = es_out_Add( p_demux->out, &tk->fmt ); } } } block_Release( p_pkt ); break; case 0x1bc: if( p_sys->psm.i_version == 0xFFFF ) msg_Dbg( p_demux, "contains a PSM"); ps_psm_fill( &p_sys->psm, p_pkt, p_sys->tk, p_demux->out ); block_Release( p_pkt ); break; default: if( (i_id = ps_pkt_id( p_pkt )) >= 0xc0 ) { bool b_new = false; ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(i_id)]; if( !tk->b_seen ) { if( !ps_track_fill( tk, &p_sys->psm, i_id ) ) { tk->es = es_out_Add( p_demux->out, &tk->fmt ); b_new = true; } else { msg_Dbg( p_demux, "es id=0x%x format unknown", i_id ); } tk->b_seen = true; } /* The popular VCD/SVCD subtitling WinSubMux does not * renumber the SCRs when merging subtitles into the PES */ if( tk->b_seen && ( tk->fmt.i_codec == VLC_FOURCC('o','g','t',' ') || tk->fmt.i_codec == VLC_FOURCC('c','v','d',' ') ) ) { p_sys->i_scr = -1; } if( p_sys->i_scr > 0 ) es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_scr ); p_sys->i_scr = -1; if( tk->b_seen && tk->es && (#ifdef ZVBI_COMPILED /* FIXME!! */ tk->fmt.i_codec == VLC_FOURCC('t','e','l','x') ||#endif !ps_pkt_parse_pes( p_pkt, tk->i_skip ) ) ) { if( !b_new && !p_sys->b_have_pack && (tk->fmt.i_cat == AUDIO_ES) && (p_pkt->i_pts > 0) ) { /* A hack to sync the A/V on PES files. */ msg_Dbg( p_demux, "force SCR: %"PRId64, p_pkt->i_pts ); es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_pkt->i_pts ); } if( (int64_t)p_pkt->i_pts > p_sys->i_current_pts ) { p_sys->i_current_pts = (int64_t)p_pkt->i_pts; } es_out_Send( p_demux->out, tk->es, p_pkt ); } else { block_Release( p_pkt ); } } else { block_Release( p_pkt ); } break; } return 1;}/***************************************************************************** * Control: *****************************************************************************/static int Control( demux_t *p_demux, int i_query, va_list args ){ demux_sys_t *p_sys = p_demux->p_sys; double f, *pf; int64_t i64, *pi64; switch( i_query ) { case DEMUX_GET_POSITION: pf = (double*) va_arg( args, double* ); i64 = stream_Size( p_demux->s ); if( i64 > 0 ) { *pf = (double)stream_Tell( p_demux->s ) / (double)i64; } else { *pf = 0.0; } return VLC_SUCCESS; case DEMUX_SET_POSITION: f = (double) va_arg( args, double ); i64 = stream_Size( p_demux->s ); p_sys->i_current_pts = 0; es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); return stream_Seek( p_demux->s, (int64_t)(i64 * f) ); case DEMUX_GET_TIME: pi64 = (int64_t*)va_arg( args, int64_t * ); if( p_sys->i_time_track >= 0 && p_sys->i_current_pts > 0 ) { *pi64 = p_sys->i_current_pts - p_sys->tk[p_sys->i_time_track].i_first_pts; return VLC_SUCCESS; } if( p_sys->i_mux_rate > 0 ) { *pi64 = (int64_t)1000000 * ( stream_Tell( p_demux->s ) / 50 ) / p_sys->i_mux_rate; return VLC_SUCCESS; } *pi64 = 0; return VLC_EGENERIC; case DEMUX_GET_LENGTH: pi64 = (int64_t*)va_arg( args, int64_t * ); if( p_sys->i_length > 0 ) { *pi64 = p_sys->i_length; return VLC_SUCCESS; } else if( p_sys->i_mux_rate > 0 ) { *pi64 = (int64_t)1000000 * ( stream_Size( p_demux->s ) / 50 ) / p_sys->i_mux_rate; return VLC_SUCCESS; } *pi64 = 0; return VLC_EGENERIC; case DEMUX_SET_TIME: i64 = (int64_t)va_arg( args, int64_t ); if( p_sys->i_time_track >= 0 && p_sys->i_current_pts > 0 ) { int64_t i_now = p_sys->i_current_pts - p_sys->tk[p_sys->i_time_track].i_first_pts; int64_t i_pos = stream_Tell( p_demux->s ); int64_t i_offset = i_pos / (i_now / 1000000) * ((i64 - i_now) / 1000000); stream_Seek( p_demux->s, i_pos + i_offset); es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); return VLC_SUCCESS; } return VLC_EGENERIC; case DEMUX_GET_FPS: default: return VLC_EGENERIC; }}/***************************************************************************** * Divers: *****************************************************************************//* PSResynch: resynch on a system startcode * It doesn't skip more than 512 bytes * -1 -> error, 0 -> not synch, 1 -> ok */static int ps_pkt_resynch( stream_t *s, uint32_t *pi_code ){ const uint8_t *p_peek; int i_peek; int i_skip; if( stream_Peek( s, &p_peek, 4 ) < 4 ) { return -1; } if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 && p_peek[3] >= 0xb9 ) { *pi_code = 0x100 | p_peek[3]; return 1; } if( ( i_peek = stream_Peek( s, &p_peek, 512 ) ) < 4 ) { return -1; } i_skip = 0; for( ;; ) { if( i_peek < 4 ) { break; } if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 && p_peek[3] >= 0xb9 ) { *pi_code = 0x100 | p_peek[3]; return stream_Read( s, NULL, i_skip ) == i_skip ? 1 : -1; } p_peek++; i_peek--; i_skip++; } return stream_Read( s, NULL, i_skip ) == i_skip ? 0 : -1;}static block_t *ps_pkt_read( stream_t *s, uint32_t i_code ){ const uint8_t *p_peek; int i_peek = stream_Peek( s, &p_peek, 14 ); int i_size = ps_pkt_size( p_peek, i_peek ); VLC_UNUSED(i_code); if( i_size <= 6 && p_peek[3] > 0xba ) { /* Special case, search the next start code */ i_size = 6; for( ;; ) { i_peek = stream_Peek( s, &p_peek, i_size + 1024 ); if( i_peek <= i_size + 4 ) { return NULL; } while( i_size <= i_peek - 4 ) { if( p_peek[i_size] == 0x00 && p_peek[i_size+1] == 0x00 && p_peek[i_size+2] == 0x01 && p_peek[i_size+3] >= 0xb9 ) { return stream_Block( s, i_size ); } i_size++; } } } else { /* Normal case */ return stream_Block( s, i_size ); } return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -