📄 ty.c
字号:
return VLC_EGENERIC; } /* load the chunk */ p_sys->i_stuff_cnt = 0; get_chunk_header(p_demux); /* seek within the chunk to get roughly to where we want */ p_sys->i_cur_rec = (int) ((double) ((seek_pos % CHUNK_SIZE) / (double) (CHUNK_SIZE)) * p_sys->i_num_recs); msg_Dbg(p_demux, "Seeked to file pos %"PRId64, seek_pos); msg_Dbg(p_demux, " (chunk %d, record %d)", p_sys->i_cur_chunk - 1, p_sys->i_cur_rec); /* seek to the start of this record's data. * to do that, we have to skip past all prior records */ l_skip_amt = 0; for (i=0; i<p_sys->i_cur_rec; i++) l_skip_amt += p_sys->rec_hdrs[i].l_rec_size; stream_Seek(p_demux->s, ((p_sys->i_cur_chunk-1) * CHUNK_SIZE) + (p_sys->i_num_recs * 16) + l_skip_amt + 4); /* to hell with syncing any audio or video, just start reading records... :) */ /*p_sys->lastAudioPTS = p_sys->lastVideoPTS = 0;*/ es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); return VLC_SUCCESS;}/* XDS decoder *///#define TY_XDS_DEBUGstatic void XdsInit( xds_t *h ){ int i, j; h->b_xds = false; h->i_class = XDS_MAX_CLASS_COUNT; h->i_type = 0; h->b_future = false; for( i = 0; i < XDS_MAX_CLASS_COUNT; i++ ) { for( j = 0; j < 128; j++ ) h->pkt[i][j].b_started = false; } h->b_meta_changed = false; memset( &h->meta, 0, sizeof(h->meta) );}static void XdsExit( xds_t *h ){ /* */ free( h->meta.psz_channel_name ); free( h->meta.psz_channel_call_letter ); free( h->meta.psz_channel_number ); /* */ free( h->meta.current.psz_name ); free( h->meta.current.psz_rating ); /* */ free( h->meta.future.psz_name ); free( h->meta.future.psz_rating );}static void XdsStringUtf8( char dst[2*32+1], const uint8_t *p_src, int i_src ){ int i; int i_dst; for( i = 0, i_dst = 0; i < i_src; i++ ) { switch( p_src[i] ) {#define E2( c, u1, u2 ) case c: dst[i_dst++] = u1; dst[i_dst++] = u2; break E2( 0x2a, 0xc3,0xa1); // lowercase a, acute accent E2( 0x5c, 0xc3,0xa9); // lowercase e, acute accent E2( 0x5e, 0xc3,0xad); // lowercase i, acute accent E2( 0x5f, 0xc3,0xb3); // lowercase o, acute accent E2( 0x60, 0xc3,0xba); // lowercase u, acute accent E2( 0x7b, 0xc3,0xa7); // lowercase c with cedilla E2( 0x7c, 0xc3,0xb7); // division symbol E2( 0x7d, 0xc3,0x91); // uppercase N tilde E2( 0x7e, 0xc3,0xb1); // lowercase n tilde#undef E2 default: dst[i_dst++] = p_src[i]; break; } } dst[i_dst++] = '\0';}static bool XdsChangeString( xds_t *h, char **ppsz_dst, const char *psz_new ){ if( *ppsz_dst && psz_new && !strcmp( *ppsz_dst, psz_new ) ) return false; if( *ppsz_dst == NULL && psz_new == NULL ) return false; free( *ppsz_dst ); if( psz_new ) *ppsz_dst = strdup( psz_new ); else *ppsz_dst = NULL; h->b_meta_changed = true; return true;}static void XdsDecodeCurrentFuture( xds_t *h, xds_packet_t *pk ){ xds_meta_program_t *p_prg = h->b_future ? &h->meta.future : &h->meta.current; char name[2*32+1]; int i_rating; switch( h->i_type ) { case 0x03: XdsStringUtf8( name, pk->p_data, pk->i_data ); if( XdsChangeString( h, &p_prg->psz_name, name ) ) { //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Current/Future (Program Name) %d'\n", pk->i_data ); //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> program name %s\n", name ); } break; case 0x05: i_rating = (pk->p_data[0] & 0x18); if( i_rating == 0x08 ) { /* TPG */ static const char *pppsz_ratings[8][2] = { { "None", "No rating (no content advisory)" }, { "TV-Y", "All Children (no content advisory)" }, { "TV-Y7", "Directed to Older Children (V = Fantasy Violence)" }, { "TV-G", "General Audience (no content advisory)" }, { "TV-PG", "Parental Guidance Suggested" }, { "TV-14", "Parents Strongly Cautioned" }, { "TV-MA", "Mature Audience Only" }, { "None", "No rating (no content advisory)" } }; p_prg->rating = XDS_META_PROGRAM_RATING_TPG; if( XdsChangeString( h, &p_prg->psz_rating, pppsz_ratings[pk->p_data[1]&0x07][0] ) ) { //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Current/Future (Rating) %d'\n", pk->i_data ); //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> TPG Rating %s (%s)\n", // pppsz_ratings[pk->p_data[1]&0x07][0], pppsz_ratings[pk->p_data[1]&0x07][1] ); } } else if( i_rating == 0x00 || i_rating == 0x10 ) { /* MPAA */ static const char *pppsz_ratings[8][2] = { { "N/A", "N/A" }, { "G", "General Audiences" }, { "PG", "Parental Guidance Suggested" }, { "PG-13", "Parents Strongly Cautioned" }, { "R", "Restricted" }, { "NC-17", "No one 17 and under admitted" }, { "X", "No one under 17 admitted" }, { "NR", "Not Rated" }, }; p_prg->rating = XDS_META_PROGRAM_RATING_MPAA; if( XdsChangeString( h, &p_prg->psz_rating, pppsz_ratings[pk->p_data[0]&0x07][0] ) ) { //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Current/Future (Rating) %d'\n", pk->i_data ); //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> TPG Rating %s (%s)\n", // pppsz_ratings[pk->p_data[0]&0x07][0], pppsz_ratings[pk->p_data[0]&0x07][1] ); } } else { /* Non US Rating TODO */ assert( i_rating == 0x18 ); // only left value possible */ p_prg->rating = XDS_META_PROGRAM_RATING_NONE; if( XdsChangeString( h, &p_prg->psz_rating, NULL ) ) { //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Current/Future (Rating) %d'\n", pk->i_data ); //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> 0x%2.2x 0x%2.2x\n", pk->p_data[0], pk->p_data[1] ); } } break; default:#ifdef TY_XDS_DEBUG fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Current/Future (Unknown 0x%x)'\n", h->i_type );#endif break; }}static void XdsDecodeChannel( xds_t *h, xds_packet_t *pk ){ char name[2*32+1]; char chan[2*32+1]; switch( h->i_type ) { case 0x01: if( pk->i_data < 2 ) return; XdsStringUtf8( name, pk->p_data, pk->i_data ); if( XdsChangeString( h, &h->meta.psz_channel_name, name ) ) { //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Network Name) %d'\n", pk->i_data ); //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> %s\n", name ); } break; case 0x02: if( pk->i_data < 4 ) return; XdsStringUtf8( name, pk->p_data, 4 ); if( XdsChangeString( h, &h->meta.psz_channel_call_letter, name ) ) { //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Network Call Letter)' %d\n", pk->i_data ); //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> call letter %s\n", name ); } if( pk->i_data >= 6 ) { XdsStringUtf8( chan, &pk->p_data[4], 2 ); if( XdsChangeString( h, &h->meta.psz_channel_number, chan ) ) { //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Network Call Letter)' %d\n", pk->i_data ); //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> channel number %s\n", chan ); } } else { if( XdsChangeString( h, &h->meta.psz_channel_number, NULL ) ) { //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Network Call Letter)' %d\n", pk->i_data ); //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: ====> no channel number letter anymore\n" ); } } break; case 0x03: //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Channel Tape Delay)'\n" ); break; case 0x04: //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Transmission Signal Identifier)'\n" ); break; default:#ifdef TY_XDS_DEBUG fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Channel (Unknown 0x%x)'\n", h->i_type );#endif break; }}static void XdsDecode( xds_t *h, xds_packet_t *pk ){ switch( h->i_class ) { case XDS_CLASS_CURRENT: case XDS_CLASS_FUTURE: XdsDecodeCurrentFuture( h, pk ); break; case XDS_CLASS_CHANNEL: XdsDecodeChannel( h, pk ); break; case XDS_CLASS_MISCELLANEOUS:#ifdef TY_XDS_DEBUG fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Miscellaneous'\n" );#endif break; case XDS_CLASS_PUBLIC_SERVICE:#ifdef TY_XDS_DEBUG fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: class 'Public Service'\n" );#endif break; default: //fprintf( stderr, "xxxxxxxxxxxxxxxXDS XdsDecode: unknown class\n" ); break; }}static void XdsParse( xds_t *h, uint8_t d1, uint8_t d2 ){ /* TODO check parity */ d1 &= 0x7f; d2 &= 0x7f; /* */ if( d1 >= 0x01 && d1 <= 0x0e ) { const xds_class_t i_class = ( d1 - 1 ) >> 1; const int i_type = d2; const bool b_start = d1 & 0x01; xds_packet_t *pk = &h->pkt[i_class][i_type]; if( !b_start && !pk->b_started ) { //fprintf( stderr, "xxxxxxxxxxxxxxxXDS Continuying a non started packet, ignoring\n" ); h->b_xds = false; return; } h->b_xds = true; h->i_class = i_class; h->i_type = i_type; h->b_future = !b_start; pk->b_started = true; if( b_start ) { pk->i_data = 0; pk->i_sum = d1 + d2; } } else if( d1 == 0x0f && h->b_xds ) { xds_packet_t *pk = &h->pkt[h->i_class][h->i_type]; /* TODO checksum and decode */ pk->i_sum += d1 + d2; if( pk->i_sum & 0x7f ) { //fprintf( stderr, "xxxxxxxxxxxxxxxXDS invalid checksum, ignoring ---------------------------------\n" ); pk->b_started = false; return; } if( pk->i_data <= 0 ) { //fprintf( stderr, "xxxxxxxxxxxxxxxXDS empty packet, ignoring ---------------------------------\n" ); pk->b_started = false; return; } //if( pk->p_data[pk->i_data-1] == 0x40 ) /* Padding byte */ // pk->i_data--; XdsDecode( h, pk ); /* Reset it */ pk->b_started = false; } else if( d1 >= 0x20 && h->b_xds ) { xds_packet_t *pk = &h->pkt[h->i_class][h->i_type]; if( pk->i_data+2 > XDS_MAX_DATA_SIZE ) { /* Broken -> reinit */ //fprintf( stderr, "xxxxxxxxxxxxxxxXDS broken, reset\n" ); h->b_xds = false; pk->b_started = false; return; } /* TODO check parity bit */ pk->p_data[pk->i_data++] = d1 & 0x7f; pk->p_data[pk->i_data++] = d2 & 0x7f; pk->i_sum += d1+d2; } else { h->b_xds = false; }}static void DemuxDecodeXds( demux_t *p_demux, uint8_t d1, uint8_t d2 ){ demux_sys_t *p_sys = p_demux->p_sys; XdsParse( &p_demux->p_sys->xds, d1, d2 ); if( p_demux->p_sys->xds.b_meta_changed ) { xds_meta_t *m = &p_sys->xds.meta; vlc_meta_t *p_meta;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -