⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ts.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 5 页
字号:
 *****************************************************************************/static int Open( vlc_object_t *p_this ){    demux_t     *p_demux = (demux_t*)p_this;    demux_sys_t *p_sys;    const uint8_t *p_peek;    int          i_sync, i_peek, i;    int          i_packet_size;    ts_pid_t    *pat;    const char  *psz_mode;    bool         b_append;    bool         b_topfield = false;    vlc_value_t  val;    if( stream_Peek( p_demux->s, &p_peek, TS_PACKET_SIZE_MAX ) <        TS_PACKET_SIZE_MAX ) return VLC_EGENERIC;    if( memcmp( p_peek, "TFrc", 4 ) == 0 )    {        b_topfield = true;        msg_Dbg( p_demux, "this is a topfield file" );    }    /* Search first sync byte */    for( i_sync = 0; i_sync < TS_PACKET_SIZE_MAX; i_sync++ )    {        if( p_peek[i_sync] == 0x47 ) break;    }    if( i_sync >= TS_PACKET_SIZE_MAX && !b_topfield )    {        if( !p_demux->b_force )            return VLC_EGENERIC;        msg_Warn( p_demux, "this does not look like a TS stream, continuing" );    }    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( p_demux->b_force )    {        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 ) );    if( !p_sys )        return VLC_ENOMEM;    memset( p_sys, 0, sizeof( demux_sys_t ) );    p_sys->i_packet_size = i_packet_size;    vlc_mutex_init( &p_sys->csa_lock );    /* Fill dump mode fields */    p_sys->i_write = 0;    p_sys->p_file = NULL;    p_sys->b_file_out = false;    p_sys->psz_file = var_CreateGetString( p_demux, "ts-dump-file" );    if( *p_sys->psz_file != '\0' )    {        p_sys->b_file_out = 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 = 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 = true;    p_sys->b_dvb_control = true;    p_sys->i_dvb_program = 0;    p_sys->i_dvb_start = 0;    p_sys->i_dvb_length = 0;    for( i = 0; i < 8192; i++ )    {        ts_pid_t *pid = &p_sys->pid[i];        pid->i_pid      = i;        pid->b_seen     = false;        pid->b_valid    = false;    }    /* PID 8191 is padding */    p_sys->pid[8191].b_seen = true;    p_sys->i_packet_size = i_packet_size;    p_sys->b_udp_out = false;    p_sys->i_ts_read = 50;    p_sys->csa = NULL;    /* Init PAT handler */    pat = &p_sys->pid[0];    PIDInit( pat, 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, true, NULL );        sdt->psi->handle =            dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t)PSINewTableCallBack,                                p_demux );        PIDInit( eit, true, NULL );        eit->psi->handle =            dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t)PSINewTableCallBack,                                p_demux );        if( p_sys->b_dvb_control )        {            if( stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,                                ACCESS_SET_PRIVATE_ID_STATE, 0x11, true ) ||                stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,                                ACCESS_SET_PRIVATE_ID_STATE, 0x12, true ) )                p_sys->b_dvb_control = false;        }    }#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 = 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( VLC_OBJECT(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 = 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 );        }    }    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 );    p_sys->b_user_pmt = false;    if( val.psz_string && *val.psz_string )        UserPmt( p_demux, val.psz_string );    free( val.psz_string );    var_Create( p_demux, "ts-csa-ck", VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );    var_Get( p_demux, "ts-csa-ck", &val );    if( val.psz_string && *val.psz_string )    {        int i_res;        vlc_value_t csa2;        p_sys->csa = csa_New();        var_Create( p_demux, "ts-csa2-ck", VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND);        var_Get( p_demux, "ts-csa2-ck", &csa2 );        i_res = csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, val.psz_string, true );        if( i_res == VLC_SUCCESS && csa2.psz_string && *csa2.psz_string )        {            if( csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, csa2.psz_string, false ) != VLC_SUCCESS )            {                csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, val.psz_string, false );            }        }        else if ( i_res == VLC_SUCCESS )        {            csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, val.psz_string, false );        }        else        {            csa_Delete( p_sys->csa );            p_sys->csa = NULL;        }        if( p_sys->csa )        {            vlc_value_t pkt_val;            var_AddCallback( p_demux, "ts-csa-ck", ChangeKeyCallback, (void *)1 );            var_AddCallback( p_demux, "ts-csa2-ck", ChangeKeyCallback, NULL );            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 );        }        free( csa2.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;            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -