📄 ts.c
字号:
int i; msg_Dbg( p_demux, "pid list:" ); for( i = 0; i < 8192; i++ ) { ts_pid_t *pid = &p_sys->pid[i]; if( pid->b_valid && pid->psi ) { switch( pid->i_pid ) { case 0: /* PAT */ dvbpsi_DetachPAT( pid->psi->handle ); free( pid->psi ); break; case 1: /* CAT */ free( pid->psi ); break; case 0x11: /* SDT */ case 0x12: /* EIT */ dvbpsi_DetachDemux( pid->psi->handle ); free( pid->psi ); break; default: PIDClean( p_demux->out, pid ); break; } } else if( pid->b_valid && pid->es ) { PIDClean( p_demux->out, pid ); } if( pid->b_seen ) { msg_Dbg( p_demux, " - pid[%d] seen", pid->i_pid ); } if( p_sys->b_dvb_control && pid->i_pid > 0 ) { /* too much */ stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, ACCESS_SET_PRIVATE_ID_STATE, pid->i_pid, VLC_FALSE ); } } if( p_sys->b_udp_out ) { net_Close( p_sys->fd ); free( p_sys->buffer ); } if( p_sys->csa ) { csa_Delete( p_sys->csa ); } if( p_sys->i_pmt ) free( p_sys->pmt ); if ( p_sys->p_programs_list ) { vlc_value_t val; val.p_list = p_sys->p_programs_list; var_Change( p_demux, "programs", VLC_VAR_FREELIST, &val, NULL ); } /* If in dump mode, then close the file */ if( p_sys->b_file_out ) { msg_Info( p_demux ,"closing %s ("I64Fd" Kbytes dumped)", p_sys->psz_file, p_sys->i_write / 1024 ); if( p_sys->p_file != stdout ) { fclose( p_sys->p_file ); p_sys->p_file = NULL; } free( p_sys->buffer ); } free( p_sys->psz_file ); p_sys->psz_file = NULL; free( p_sys );}/***************************************************************************** * DemuxFile: *****************************************************************************/static int DemuxFile( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; uint8_t *p_buffer = p_sys->buffer; /* Put first on sync byte */ int i_diff= 0; int i_data= 0; int i_pos = 0; int i_bufsize = p_sys->i_packet_size * p_sys->i_ts_read; i_data = stream_Read( p_demux->s, p_sys->buffer, i_bufsize ); if( (i_data <= 0) && (i_data < p_sys->i_packet_size) ) { msg_Dbg( p_demux, "error reading malformed packets" ); return i_data; } /* Test continuity counter */ while( i_pos < i_data ) { ts_pid_t *p_pid; /* point to a PID structure */ vlc_bool_t b_payload; /* indicates a packet with payload */ vlc_bool_t b_adaptation; /* adaptation field */ int i_cc = 0; /* continuity counter */ if( p_sys->buffer[i_pos] != 0x47 ) { msg_Warn( p_demux, "lost sync" ); while( !p_demux->b_die && (i_pos < i_data) ) { i_pos++; if( p_sys->buffer[i_pos] == 0x47 ) break; } if( !p_demux->b_die ) msg_Warn( p_demux, "sync found" ); } /* continuous when (one of this): * diff == 1 * diff == 0 and payload == 0 * diff == 0 and duplicate packet (playload != 0) <- should we * test the content ? */ i_cc = p_buffer[i_pos+3]&0x0f; b_payload = p_buffer[i_pos+3]&0x10; b_adaptation = p_buffer[i_pos+3]&0x20; /* Get the PID */ p_pid = &p_sys->pid[ ((p_buffer[i_pos+1]&0x1f)<<8)|p_buffer[i_pos+2] ]; /* Detect discontinuity indicator in adaptation field */ if( b_adaptation && p_buffer[i_pos + 4] > 0 ) { if( p_buffer[i_pos+5]&0x80 ) msg_Warn( p_demux, "discontinuity indicator (pid=%d) ", p_pid->i_pid ); if( p_buffer[i_pos+5]&0x40 ) msg_Warn( p_demux, "random access indicator (pid=%d) ", p_pid->i_pid ); } i_diff = ( i_cc - p_pid->i_cc )&0x0f; if( b_payload && i_diff == 1 ) { p_pid->i_cc = ( p_pid->i_cc + 1 ) & 0xf; } else { if( p_pid->i_cc == 0xff ) { msg_Warn( p_demux, "first packet for pid=%d cc=0x%x", p_pid->i_pid, i_cc ); p_pid->i_cc = i_cc; } else if( i_diff != 0 ) { /* FIXME what to do when discontinuity_indicator is set ? */ msg_Warn( p_demux, "transport error detected 0x%x instead of 0x%x", i_cc, ( p_pid->i_cc + 1 )&0x0f ); p_pid->i_cc = i_cc; /* Mark transport error in the TS packet. */ p_buffer[i_pos+1] |= 0x80; } } /* Test if user wants to decrypt it first */ if( p_sys->csa ) csa_Decrypt( p_demux->p_sys->csa, &p_buffer[i_pos], p_demux->p_sys->i_csa_pkt_size ); i_pos += p_sys->i_packet_size; } /* Then write */ i_data = fwrite( p_sys->buffer, 1, i_data, p_sys->p_file ); if( i_data < 0 ) { msg_Err( p_demux, "failed to write data" ); return -1; }#if 0 msg_Dbg( p_demux, "dumped %d bytes", i_data );#endif p_sys->i_write += i_data; return 1;}/***************************************************************************** * Demux: *****************************************************************************/static int Demux( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; int i_pkt; /* We read at most 100 TS packet or until a frame is completed */ for( i_pkt = 0; i_pkt < p_sys->i_ts_read; i_pkt++ ) { vlc_bool_t b_frame = VLC_FALSE; block_t *p_pkt; ts_pid_t *p_pid; /* Get a new TS packet */ if( !( p_pkt = stream_Block( p_demux->s, p_sys->i_packet_size ) ) ) { msg_Dbg( p_demux, "eof ?" ); return 0; } /* Check sync byte and re-sync if needed */ if( p_pkt->p_buffer[0] != 0x47 ) { msg_Warn( p_demux, "lost synchro" ); block_Release( p_pkt ); while( !p_demux->b_die ) { uint8_t *p_peek; int i_peek, i_skip = 0; i_peek = stream_Peek( p_demux->s, &p_peek, p_sys->i_packet_size * 10 ); if( i_peek < p_sys->i_packet_size + 1 ) { msg_Dbg( p_demux, "eof ?" ); return 0; } while( i_skip < i_peek - p_sys->i_packet_size ) { if( p_peek[i_skip] == 0x47 && p_peek[i_skip + p_sys->i_packet_size] == 0x47 ) { break; } i_skip++; } msg_Dbg( p_demux, "skipping %d bytes of garbage", i_skip ); stream_Read( p_demux->s, NULL, i_skip ); if( i_skip < i_peek - p_sys->i_packet_size ) { break; } } if( !( p_pkt = stream_Block( p_demux->s, p_sys->i_packet_size ) ) ) { msg_Dbg( p_demux, "eof ?" ); return 0; } } if( p_sys->b_udp_out ) { memcpy( &p_sys->buffer[i_pkt * p_sys->i_packet_size], p_pkt->p_buffer, p_sys->i_packet_size ); } /* Parse the TS packet */ p_pid = &p_sys->pid[PIDGet( p_pkt )]; if( p_pid->b_valid ) { if( p_pid->psi ) { if( p_pid->i_pid == 0 || p_pid->i_pid == 0x11 || p_pid->i_pid == 0x12 ) { dvbpsi_PushPacket( p_pid->psi->handle, p_pkt->p_buffer ); } else { int i_prg; for( i_prg = 0; i_prg < p_pid->psi->i_prg; i_prg++ ) { dvbpsi_PushPacket( p_pid->psi->prg[i_prg]->handle, p_pkt->p_buffer ); } } block_Release( p_pkt ); } else if( !p_sys->b_udp_out ) { b_frame = GatherPES( p_demux, p_pid, p_pkt ); } else { PCRHandle( p_demux, p_pid, p_pkt ); block_Release( p_pkt ); } } else { if( !p_pid->b_seen ) { msg_Dbg( p_demux, "pid[%d] unknown", p_pid->i_pid ); } /* We have to handle PCR if present */ PCRHandle( p_demux, p_pid, p_pkt ); block_Release( p_pkt ); } p_pid->b_seen = VLC_TRUE; if( b_frame ) { break; } } if( p_sys->b_udp_out ) { /* Send the complete block */ net_Write( p_demux, p_sys->fd, NULL, p_sys->buffer, p_sys->i_ts_read * p_sys->i_packet_size ); } 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; int64_t *pi64; int i_int; if( p_sys->b_file_out ) return demux2_vaControlHelper( p_demux->s, 0, -1, 0, 1, i_query, args ); 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 ); es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); if( stream_Seek( p_demux->s, (int64_t)(i64 * f) ) ) { return VLC_EGENERIC; } return VLC_SUCCESS;#if 0 case DEMUX_GET_TIME: pi64 = (int64_t*)va_arg( args, int64_t * ); if( p_sys->i_time < 0 ) { *pi64 = 0; return VLC_EGENERIC; } *pi64 = p_sys->i_time; return VLC_SUCCESS; case DEMUX_GET_LENGTH: pi64 = (int64_t*)va_arg( args, int64_t * ); if( p_sys->i_mux_rate > 0 ) { *pi64 = I64C(1000000) * ( stream_Size( p_demux->s ) / 50 ) / p_sys->i_mux_rate; return VLC_SUCCESS; } *pi64 = 0; return VLC_EGENERIC;#else case DEMUX_GET_TIME: case DEMUX_GET_LENGTH: pi64 = (int64_t*)va_arg( args, int64_t * ); *pi64 = 0; return VLC_SUCCESS;#endif case DEMUX_SET_GROUP: { uint16_t i_vpid = 0, i_apid1 = 0, i_apid2 = 0, i_apid3 = 0; ts_prg_psi_t *p_prg = NULL; vlc_list_t *p_list; i_int = (int)va_arg( args, int ); p_list = (vlc_list_t *)va_arg( args, vlc_list_t * ); msg_Dbg( p_demux, "DEMUX_SET_GROUP %d %p", i_int, p_list ); if( p_sys->b_dvb_control && i_int > 0 && i_int != p_sys->i_dvb_program ) { int i_pmt_pid = -1; int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -