📄 ts.c
字号:
if( b_topfield ) { /* Read the entire Topfield header */ i_peek = TS_TOPFIELD_HEADER; } else { /* Check next 3 sync bytes */ i_peek = TS_PACKET_SIZE_MAX * 3 + i_sync + 1; } if( ( stream_Peek( p_demux->s, &p_peek, i_peek ) ) < i_peek ) { msg_Err( p_demux, "cannot peek" ); return VLC_EGENERIC; } if( p_peek[i_sync + TS_PACKET_SIZE_188] == 0x47 && p_peek[i_sync + 2 * TS_PACKET_SIZE_188] == 0x47 && p_peek[i_sync + 3 * TS_PACKET_SIZE_188] == 0x47 ) { i_packet_size = TS_PACKET_SIZE_188; } else if( p_peek[i_sync + TS_PACKET_SIZE_192] == 0x47 && p_peek[i_sync + 2 * TS_PACKET_SIZE_192] == 0x47 && p_peek[i_sync + 3 * TS_PACKET_SIZE_192] == 0x47 ) { i_packet_size = TS_PACKET_SIZE_192; } else if( p_peek[i_sync + TS_PACKET_SIZE_204] == 0x47 && p_peek[i_sync + 2 * TS_PACKET_SIZE_204] == 0x47 && p_peek[i_sync + 3 * TS_PACKET_SIZE_204] == 0x47 ) { i_packet_size = TS_PACKET_SIZE_204; } else if( !strcmp( p_demux->psz_demux, "ts" ) ) { i_packet_size = TS_PACKET_SIZE_188; } else if( b_topfield ) { i_packet_size = TS_PACKET_SIZE_188;#if 0 /* I used the TF5000PVR 2004 Firmware .doc header documentation, * http://www.i-topfield.com/data/product/firmware/Structure%20of%20Recorded%20File%20in%20TF5000PVR%20(Feb%2021%202004).doc * but after the filename the offsets seem to be incorrect. - DJ */ int i_duration, i_name; char *psz_name = malloc(25); char *psz_event_name; char *psz_event_text = malloc(130); char *psz_ext_text = malloc(1025); // 2 bytes version Uimsbf (4,5) // 2 bytes reserved (6,7) // 2 bytes duration in minutes Uimsbf (8,9( i_duration = (int) (p_peek[8] << 8) | p_peek[9]; msg_Dbg( p_demux, "Topfield recording length: +/- %d minutes", i_duration); // 2 bytes service number in channel list (10, 11) // 2 bytes service type Bslbf 0=TV 1=Radio Bslb (12, 13) // 4 bytes of reserved + tuner info (14,15,16,17) // 2 bytes of Service ID Bslbf (18,19) // 2 bytes of PMT PID Uimsbf (20,21) // 2 bytes of PCR PID Uimsbf (22,23) // 2 bytes of Video PID Uimsbf (24,25) // 2 bytes of Audio PID Uimsbf (26,27) // 24 bytes filename Bslbf memcpy( psz_name, &p_peek[28], 24 ); psz_name[24] = '\0'; msg_Dbg( p_demux, "recordingname=%s", psz_name ); // 1 byte of sat index Uimsbf (52) // 3 bytes (1 bit of polarity Bslbf +23 bits reserved) // 4 bytes of freq. Uimsbf (56,57,58,59) // 2 bytes of symbol rate Uimsbf (60,61) // 2 bytes of TS stream ID Uimsbf (62,63) // 4 bytes reserved // 2 bytes reserved // 2 bytes duration Uimsbf (70,71) //i_duration = (int) (p_peek[70] << 8) | p_peek[71]; //msg_Dbg( p_demux, "Topfield 2nd duration field: +/- %d minutes", i_duration); // 4 bytes EventID Uimsbf (72-75) // 8 bytes of Start and End time info (76-83) // 1 byte reserved (84) // 1 byte event name length Uimsbf (89) i_name = (int)(p_peek[89]&~0x81); msg_Dbg( p_demux, "event name length = %d", i_name); psz_event_name = malloc( i_name+1 ); // 1 byte parental rating (90) // 129 bytes of event text memcpy( psz_event_name, &p_peek[91], i_name ); psz_event_name[i_name] = '\0'; memcpy( psz_event_text, &p_peek[91+i_name], 129-i_name ); psz_event_text[129-i_name] = '\0'; msg_Dbg( p_demux, "event name=%s", psz_event_name ); msg_Dbg( p_demux, "event text=%s", psz_event_text ); // 12 bytes reserved (220) // 6 bytes reserved // 2 bytes Event Text Length Uimsbf // 4 bytes EventID Uimsbf // FIXME We just have 613 bytes. not enough for this entire text // 1024 bytes Extended Event Text Bslbf memcpy( psz_ext_text, p_peek+372, 1024 ); psz_ext_text[1024] = '\0'; msg_Dbg( p_demux, "extended event text=%s", psz_ext_text ); // 52 bytes reserved Bslbf#endif } else { msg_Warn( p_demux, "TS module discarded (lost sync)" ); return VLC_EGENERIC; } p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); memset( p_sys, 0, sizeof( demux_sys_t ) ); p_sys->i_packet_size = i_packet_size; /* Fill dump mode fields */ p_sys->i_write = 0; p_sys->p_file = NULL; p_sys->b_file_out = VLC_FALSE; p_sys->psz_file = var_CreateGetString( p_demux, "ts-dump-file" ); if( *p_sys->psz_file != '\0' ) { p_sys->b_file_out = VLC_TRUE; var_Create( p_demux, "ts-dump-append", VLC_VAR_BOOL|VLC_VAR_DOINHERIT ); var_Get( p_demux, "ts-dump-append", &val ); b_append = val.b_bool; if ( b_append ) psz_mode = "ab"; else psz_mode = "wb"; if( !strcmp( p_sys->psz_file, "-" ) ) { msg_Info( p_demux, "dumping raw stream to standard output" ); p_sys->p_file = stdout; } else if( ( p_sys->p_file = utf8_fopen( p_sys->psz_file, psz_mode ) ) == NULL ) { msg_Err( p_demux, "cannot create `%s' for writing", p_sys->psz_file ); p_sys->b_file_out = VLC_FALSE; } if( p_sys->b_file_out ) { vlc_value_t bufsize; /* Determine how many packets to read. */ var_Create( p_demux, "ts-dump-size", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_demux, "ts-dump-size", &bufsize ); p_sys->i_ts_read = (int) (bufsize.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 ); msg_Info( p_demux, "%s raw stream to file `%s' reading packets %d", b_append ? "appending" : "dumping", p_sys->psz_file, p_sys->i_ts_read ); } } /* Fill p_demux field */ if( p_sys->b_file_out ) p_demux->pf_demux = DemuxFile; else p_demux->pf_demux = Demux; p_demux->pf_control = Control; /* 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; } /* PID 8191 is padding */ p_sys->pid[8191].b_seen = VLC_TRUE; 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 && !p_sys->b_file_out ) { 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_ConnectUDP( p_demux, val.psz_string, i_port, 0 ); 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; }#ifndef TS_NO_CSA_CK_MSG 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] );#endif p_sys->csa = csa_New(); if( p_sys->csa ) { vlc_value_t pkt_val; csa_SetCW( p_sys->csa, ck, ck ); var_Create( p_demux, "ts-csa-pkt", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_demux, "ts-csa-pkt", &pkt_val ); if( pkt_val.i_int < 4 || pkt_val.i_int > 188 ) { msg_Err( p_demux, "wrong packet size %d specified.", pkt_val.i_int ); msg_Warn( p_demux, "using default packet size of 188 bytes" ); p_sys->i_csa_pkt_size = 188; } else p_sys->i_csa_pkt_size = pkt_val.i_int; msg_Dbg( p_demux, "decrypting %d bytes of packet", p_sys->i_csa_pkt_size ); } } } 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -