📄 ty.c
字号:
/* set PCR before we send */ if( p_block_in->i_pts > 0 ) es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block_in->i_pts ); es_out_Send( p_demux->out, p_sys->p_audio, p_block_in ); } /* if DTiVo */ } /* if subrec == 0x03 */ /* SA Audio with no PES Header */ /* ================================================ */ if ( subrec_type == 0x04 ) { /*msg_Dbg(p_demux, "Adding SA Audio Packet Size %ld", l_rec_size ); */ /* set PCR before we send */ if (p_sys->lastAudioPTS > 0) { p_block_in->i_pts = p_sys->lastAudioPTS; es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block_in->i_pts ); } es_out_Send( p_demux->out, p_sys->p_audio, p_block_in ); } /* DTiVo AC3 Audio Data with PES Header */ /* ================================================ */ if ( subrec_type == 0x09 ) { find_es_header( ty_AC3AudioPacket, p_block_in->p_buffer, l_rec_size, &esOffset1 ); /*msg_Dbg(p_demux, "buffer has %#02x %#02x %#02x %#02x", p_block_in->p_buffer[0], p_block_in->p_buffer[1], p_block_in->p_buffer[2], p_block_in->p_buffer[3]); msg_Dbg(p_demux, "audio ES AC3 hdr at offset %d", esOffset1);*/ /* Check for complete PES */ if (check_sync_pes(p_demux, p_block_in, esOffset1, l_rec_size) == -1) { /* partial PES header found, nothing else. we're done. */ p_sys->i_cur_rec++; return 1; } /* set PCR before we send (if PTS found) */ if( p_block_in->i_pts > 0 ) { es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block_in->i_pts ); } es_out_Send( p_demux->out, p_sys->p_audio, p_block_in ); } } /* end "if audio" */ /* ================================================================ */ /* Closed Caption */ /* ================================================================ */ else if ( rec_type == 0x01 ) { /*msg_Dbg(p_demux, "CC1 %02x %02x [%c%c]", rec_hdr->ex1, rec_hdr->ex2, rec_hdr->ex1, rec_hdr->ex2 );*/ /* construct a 'user-data' MPEG packet */ lastCC[ 0x00 ] = 0x00; lastCC[ 0x01 ] = 0x00; lastCC[ 0x02 ] = 0x01; lastCC[ 0x03 ] = 0xb2; lastCC[ 0x04 ] = 'T'; /* vcdimager code says this byte should be 0x11 */ lastCC[ 0x05 ] = 'Y'; /* (no other notes there) */ lastCC[ 0x06 ] = 0x01; lastCC[ 0x07 ] = rec_hdr->ex1; lastCC[ 0x08 ] = rec_hdr->ex2; /* not sure what to send, because VLC doesn't yet support * teletext type of subtitles (only supports the full-sentence type) */ /*p_block_in = block_NewEmpty(); ???? es_out_Send( p_demux->out, p_sys->p_subt_es, p_block_in );*/ } else if ( rec_type == 0x02 ) { /*msg_Dbg(p_demux, "CC2 %02x %02x", rec_hdr->ex1, rec_hdr->ex2 );*/ /* construct a 'user-data' MPEG packet */ lastXDS[ 0x00 ] = 0x00; lastXDS[ 0x01 ] = 0x00; lastXDS[ 0x02 ] = 0x01; lastXDS[ 0x03 ] = 0xb2; lastXDS[ 0x04 ] = 'T'; /* vcdimager code says this byte should be 0x11 */ lastXDS[ 0x05 ] = 'Y'; /* (no other notes there) */ lastXDS[ 0x06 ] = 0x02; lastXDS[ 0x07 ] = rec_hdr->ex1; lastXDS[ 0x08 ] = rec_hdr->ex2; /* not sure what to send, because VLC doesn't support this?? */ /*p_block_in = block_NewEmpty(); ???? es_out_Send( p_demux->out, p_sys->p_audio, p_block_in );*/ } /* ================================================================ */ /* Tivo data services (e.g. "thumbs-up to record!") useless for us */ /* ================================================================ */ else if ( rec_type == 0x03 ) { } /* ================================================================ */ /* Unknown, but seen regularly */ /* ================================================================ */ else if ( rec_type == 0x05 ) { } else { msg_Dbg(p_demux, "Invalid record type 0x%02x", rec_type ); if (p_block_in) block_Release(p_block_in); invalidType++; } p_sys->i_cur_rec++; return 1;}/* seek to a position within the stream, if possible */static int ty_stream_seek(demux_t *p_demux, double seek_pct){ demux_sys_t *p_sys = p_demux->p_sys; int64_t seek_pos = p_sys->i_stream_size * seek_pct; int i; long l_skip_amt; /* if we're not seekable, there's nothing to do */ if (!p_sys->b_seekable) return VLC_EGENERIC; /* figure out which chunk we want & go there */ p_sys->i_chunk_count = seek_pos / CHUNK_SIZE; if ( stream_Seek( p_demux->s, p_sys->i_chunk_count * CHUNK_SIZE)) { /* can't seek stream */ return VLC_EGENERIC; } /* load the chunk */ 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 " I64Fd, seek_pos); msg_Dbg(p_demux, " (chunk %d, record %d)", p_sys->i_chunk_count - 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_chunk_count-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;}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, *p_i64; /*msg_Info(p_demux, "control cmd %d", i_query);*/ switch( i_query ) { case DEMUX_GET_POSITION: /* arg is 0.0 - 1.0 percent of overall file position */ if( ( i64 = p_sys->i_stream_size ) > 0 ) { pf = (double*) va_arg( args, double* ); *pf = (double)stream_Tell( p_demux->s ) / (double) i64; return VLC_SUCCESS; } return VLC_EGENERIC; case DEMUX_SET_POSITION: /* arg is 0.0 - 1.0 percent of overall file position */ f = (double) va_arg( args, double ); //msg_Dbg(p_demux, "Control - set position to %2.3f", f); if ((i64 = p_sys->i_stream_size) > 0) return ty_stream_seek(p_demux, f); return VLC_EGENERIC; case DEMUX_GET_TIME: /* return latest PTS - start PTS */ p_i64 = (int64_t *) va_arg(args, int64_t *); *p_i64 = p_sys->lastAudioPTS - p_sys->firstAudioPTS; return VLC_SUCCESS; case DEMUX_SET_TIME: /* arg is time in microsecs */ case DEMUX_GET_LENGTH: /* length of program in microseconds, 0 if unk */ case DEMUX_GET_FPS: default: return VLC_EGENERIC; }}/* =========================================================================== */static void TyClose( vlc_object_t *p_this ){ demux_sys_t *p_sys = ((demux_t *) p_this)->p_sys; free(p_sys->rec_hdrs); free(p_sys);}/* =========================================================================== */static int get_chunk_header(demux_t *p_demux){ int i_readSize, i_num_recs, i; uint8_t packet_header[4]; uint8_t record_header[16]; ty_rec_hdr_t *p_rec_hdr; demux_sys_t *p_sys = p_demux->p_sys; int i_payload_size = 0; /* sum of all records */ msg_Dbg(p_demux, "parsing ty chunk #%d", p_sys->i_chunk_count ); /* if we have left-over filler space from the last chunk, get that */ if (p_sys->i_stuff_cnt > 0) stream_Read( p_demux->s, NULL, p_sys->i_stuff_cnt); /* read the TY packet header */ i_readSize = stream_Read( p_demux->s, packet_header, 4 ); p_sys->i_chunk_count++; if ( i_readSize < 4 ) { /* EOF */ p_sys->eof = 1; return 0; } /* if it's a PART Header, then try again. */ if( U32_AT( &packet_header[ 0 ] ) == TIVO_PES_FILEID ) { msg_Dbg( p_demux, "skipping TY PART Header" ); /* TODO: if stream is seekable, should we seek() instead of read() ?? */ stream_Read( p_demux->s, NULL, CHUNK_SIZE - 4 ); return get_chunk_header(p_demux); } /* number of records in chunk (8- or 16-bit number) */ if (packet_header[3] & 0x80) { /* 16 bit rec cnt */ p_sys->i_num_recs = i_num_recs = (packet_header[1] << 8) + packet_header[0]; p_sys->i_seq_rec = (packet_header[3] << 8) + packet_header[2]; if (p_sys->i_seq_rec != 0xffff) { p_sys->i_seq_rec &= ~0x8000; } } else { /* 8 bit reclen - tivo 1.3 format */ p_sys->i_num_recs = i_num_recs = packet_header[0]; p_sys->i_seq_rec = packet_header[1]; } p_sys->i_cur_rec = 0; p_sys->b_first_chunk = VLC_FALSE; /*msg_Dbg( p_demux, "chunk has %d records", i_num_recs );*/ /* parse headers into array */ if (p_sys->rec_hdrs) free(p_sys->rec_hdrs); p_sys->rec_hdrs = malloc(i_num_recs * sizeof(ty_rec_hdr_t)); for (i = 0; i < i_num_recs; i++) { i_readSize = stream_Read( p_demux->s, record_header, 16 ); if (i_readSize < 16) { /* EOF */ p_sys->eof = VLC_TRUE; return 0; } p_rec_hdr = &p_sys->rec_hdrs[i]; /* for brevity */ p_rec_hdr->rec_type = record_header[3]; p_rec_hdr->subrec_type = record_header[2] & 0x0f; if ((record_header[ 0 ] & 0x80) == 0x80) { unsigned char b1, b2; /* marker bit 2 set, so read extended data */ b1 = ( ( ( record_header[ 0 ] & 0x0f ) << 4 ) | ( ( record_header[ 1 ] & 0xf0 ) >> 4 ) ); b1 &= 0x7f; b2 = ( ( ( record_header[ 1 ] & 0x0f ) << 4 ) | ( ( record_header[ 2 ] & 0xf0 ) >> 4 ) ); b2 &= 0x7f; p_rec_hdr->ex1 = b1; p_rec_hdr->ex2 = b2; p_rec_hdr->l_rec_size = 0; p_rec_hdr->b_ext = VLC_TRUE; } else { p_rec_hdr->l_rec_size = ( record_header[ 0 ] << 8 | record_header[ 1 ] ) << 4 | ( record_header[ 2 ] >> 4 ); i_payload_size += p_rec_hdr->l_rec_size; p_rec_hdr->b_ext = VLC_FALSE; } } /* end of record-header loop */ p_sys->i_stuff_cnt = CHUNK_SIZE - 4 - (p_sys->i_num_recs * 16) - i_payload_size; if (p_sys->i_stuff_cnt > 0) msg_Dbg( p_demux, "chunk has %d stuff bytes at end", p_sys->i_stuff_cnt ); return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -