📄 ts.c
字号:
/* Init p_sys field */ p_sys->b_meta = VLC_TRUE; p_sys->b_dvb_control = VLC_TRUE; p_sys->i_dvb_program = 0; for( i = 0; i < 8192; i++ ) { ts_pid_t *pid = &p_sys->pid[i]; pid->i_pid = i; pid->b_seen = VLC_FALSE; pid->b_valid = VLC_FALSE; } p_sys->i_packet_size = i_packet_size; p_sys->b_udp_out = VLC_FALSE; p_sys->i_ts_read = 50; p_sys->csa = NULL; /* Init PAT handler */ pat = &p_sys->pid[0]; PIDInit( pat, VLC_TRUE, NULL ); pat->psi->handle = dvbpsi_AttachPAT( (dvbpsi_pat_callback)PATCallBack, p_demux );#ifdef TS_USE_DVB_SI if( p_sys->b_meta ) { ts_pid_t *sdt = &p_sys->pid[0x11]; ts_pid_t *eit = &p_sys->pid[0x12]; PIDInit( sdt, VLC_TRUE, NULL ); sdt->psi->handle = dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t)PSINewTableCallBack, p_demux ); PIDInit( eit, VLC_TRUE, NULL ); eit->psi->handle = dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t)PSINewTableCallBack, p_demux ); if( p_sys->b_dvb_control ) { stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, ACCESS_SET_PRIVATE_ID_STATE, 0x11, VLC_TRUE ); stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, ACCESS_SET_PRIVATE_ID_STATE, 0x12, VLC_TRUE ); } }#endif /* Init PMT array */ p_sys->i_pmt = 0; p_sys->pmt = NULL; /* Read config */ var_Create( p_demux, "ts-es-id-pid", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Get( p_demux, "ts-es-id-pid", &val ); p_sys->b_es_id_pid = val.b_bool; var_Create( p_demux, "ts-out", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Get( p_demux, "ts-out", &val ); if( val.psz_string && *val.psz_string ) { vlc_value_t mtu; char *psz = strchr( val.psz_string, ':' ); int i_port = 0; p_sys->b_udp_out = VLC_TRUE; if( psz ) { *psz++ = '\0'; i_port = atoi( psz ); } if( i_port <= 0 ) i_port = 1234; msg_Dbg( p_demux, "resend ts to '%s:%d'", val.psz_string, i_port ); p_sys->fd = net_OpenUDP( p_demux, "", 0, val.psz_string, i_port ); if( p_sys->fd < 0 ) { msg_Err( p_demux, "failed to open udp socket, send disabled" ); p_sys->b_udp_out = VLC_FALSE; } else { var_Create( p_demux, "ts-out-mtu", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_demux, "ts-out-mtu", &mtu ); p_sys->i_ts_read = mtu.i_int / p_sys->i_packet_size; if( p_sys->i_ts_read <= 0 ) { p_sys->i_ts_read = 1500 / p_sys->i_packet_size; } p_sys->buffer = malloc( p_sys->i_packet_size * p_sys->i_ts_read ); } } if( val.psz_string ) { free( val.psz_string ); } /* We handle description of an extra PMT */ var_Create( p_demux, "ts-extra-pmt", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Get( p_demux, "ts-extra-pmt", &val ); if( val.psz_string && strchr( val.psz_string, '=' ) != NULL ) { char *psz = val.psz_string; int i_pid = strtol( psz, &psz, 0 ); if( i_pid >= 2 && i_pid < 8192 ) { ts_pid_t *pmt = &p_sys->pid[i_pid]; msg_Dbg( p_demux, "extra pmt specified (pid=%d)", i_pid ); PIDInit( pmt, VLC_TRUE, NULL ); pmt->psi->i_prg = 1; pmt->psi->prg = malloc( sizeof(ts_prg_psi_t) ); /* FIXME we should also ask for a number */ pmt->psi->prg[0]->handle = dvbpsi_AttachPMT( 1, (dvbpsi_pmt_callback)PMTCallBack, p_demux ); pmt->psi->prg[0]->i_number = 0; /* special one */ psz = strchr( psz, '=' ) + 1; /* can't failed */ while( psz && *psz ) { char *psz_next = strchr( psz, ',' ); int i_pid, i_stream_type; if( psz_next ) { *psz_next++ = '\0'; } i_pid = strtol( psz, &psz, 0 ); if( *psz == ':' ) { i_stream_type = strtol( psz + 1, &psz, 0 ); if( i_pid >= 2 && i_pid < 8192 && !p_sys->pid[i_pid].b_valid ) { ts_pid_t *pid = &p_sys->pid[i_pid]; PIDInit( pid, VLC_FALSE, pmt->psi); if( pmt->psi->prg[0]->i_pid_pcr <= 0 ) { pmt->psi->prg[0]->i_pid_pcr = i_pid; } PIDFillFormat( pid, i_stream_type); if( pid->es->fmt.i_cat != UNKNOWN_ES ) { if( p_sys->b_es_id_pid ) { pid->es->fmt.i_id = i_pid; } msg_Dbg( p_demux, " * es pid=%d type=%d " "fcc=%4.4s", i_pid, i_stream_type, (char*)&pid->es->fmt.i_codec ); pid->es->id = es_out_Add( p_demux->out, &pid->es->fmt ); } } } psz = psz_next; } } } if( val.psz_string ) { free( val.psz_string ); } var_Create( p_demux, "ts-csa-ck", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Get( p_demux, "ts-csa-ck", &val ); if( val.psz_string && *val.psz_string ) { char *psz = val.psz_string; if( psz[0] == '0' && ( psz[1] == 'x' || psz[1] == 'X' ) ) { psz += 2; } if( strlen( psz ) != 16 ) { msg_Warn( p_demux, "invalid csa ck (it must be 16 chars long)" ); } else {#ifndef UNDER_CE uint64_t i_ck = strtoull( psz, NULL, 16 );#else uint64_t i_ck = strtoll( psz, NULL, 16 );#endif uint8_t ck[8]; int i; for( i = 0; i < 8; i++ ) { ck[i] = ( i_ck >> ( 56 - 8*i) )&0xff; } msg_Dbg( p_demux, "using CSA scrambling with " "ck=%x:%x:%x:%x:%x:%x:%x:%x", ck[0], ck[1], ck[2], ck[3], ck[4], ck[5], ck[6], ck[7] ); p_sys->csa = csa_New(); csa_SetCW( p_sys->csa, ck, ck ); } } if( val.psz_string ) { free( val.psz_string ); } var_Create( p_demux, "ts-silent", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Get( p_demux, "ts-silent", &val ); p_sys->b_silent = val.b_bool; return VLC_SUCCESS;}/***************************************************************************** * Close *****************************************************************************/static void Close( vlc_object_t *p_this ){ demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys = p_demux->p_sys; 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 ); } free( p_sys );}/***************************************************************************** * 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -