📄 ty.c
字号:
if( offset > 0 ) { /* PES Header was found, but not complete, so trim the end of this record */ p_block->i_buffer -= rec_len - offset; return 1; } return -1; /* partial PES, no audio data */ } /* full PES header present, extract PTS */ p_sys->lastAudioPTS = get_pts( &p_block->p_buffer[ offset + pts_offset ] ); if (p_sys->firstAudioPTS < 0) p_sys->firstAudioPTS = p_sys->lastAudioPTS; p_block->i_pts = p_sys->lastAudioPTS; /*msg_Dbg(p_demux, "Audio PTS %lld", p_sys->lastAudioPTS );*/ /* adjust audio record to remove PES header */ memmove(p_block->p_buffer + offset, p_block->p_buffer + offset + pes_length, rec_len - pes_length); p_block->i_buffer -= pes_length; return 0;}/* =========================================================================== *//* TyDemux: Read & Demux one record from the chunk * * Returns -1 in case of error, 0 in case of EOF, 1 otherwise * * NOTE: I think we can return the number of packets sent instead of just 1. * that means we can demux an entire chunk and shoot it back (may be more efficient) * -- should try that some day :) -- */int TyDemux(demux_t *p_demux){ int invalidType = 0; int recordsDecoded = 0; int rec_type; long l_rec_size; int i_cur_rec; int subrec_type; ty_rec_hdr_t *rec_hdr; block_t *p_block_in = NULL; int esOffset1; unsigned char lastCC[ 16 ]; unsigned char lastXDS[ 16 ]; demux_sys_t *p_sys = p_demux->p_sys; /*msg_Dbg(p_demux, "ty demux processing" );*/ /* did we hit EOF earlier? */ if (p_sys->eof) return 0; /* * what we do (1 record now.. maybe more later): * - use stream_Read() to read the chunk header & record headers * - discard entire chunk if it is a PART header chunk * - parse all the headers into record header array * - keep a pointer of which record we're on * - use stream_Block() to fetch each record * - parse out PTS from PES headers * - set PTS for data packets * - pass the data on to the proper codec via es_out_Send() * if this is the first time or * if we're at the end of this chunk, start a new one */ /* parse the next chunk's record headers */ if (p_sys->b_first_chunk || p_sys->i_cur_rec >= p_sys->i_num_recs) if (get_chunk_header(p_demux) == 0) return 0; /*====================================================================== * parse & send one record of the chunk *====================================================================== */ i_cur_rec = p_sys->i_cur_rec; recordsDecoded++; rec_hdr = &p_sys->rec_hdrs[ i_cur_rec ]; subrec_type = rec_hdr->subrec_type; rec_type = rec_hdr->rec_type; l_rec_size = rec_hdr->l_rec_size; if (!rec_hdr->b_ext) { /*msg_Dbg(p_demux, "Record Type 0x%x/%02x %ld bytes", subrec_type, rec_type, l_rec_size );*/ /* some normal records are 0 length, so check for that... */ if (l_rec_size > 0) { /* read in this record's payload */ if( !( p_block_in = stream_Block( p_demux->s, l_rec_size ) ) ) { /* EOF */ p_sys->eof = 1; return 0; } /* set these as 'unknown' for now */ p_block_in->i_pts = p_block_in->i_dts = 0; } else { /* no data in payload; we're done */ p_sys->i_cur_rec++; return 1; } } /*else { -- don't read any data from the stream, data was in the record header -- msg_Dbg(p_demux, "Record Type 0x%02x/%02x, ext data = %02x, %02x", subrec_type, rec_type, rec_hdr->ex1, rec_hdr->ex2); }*/ /*================================================================* * Video Parsing *================================================================*/ if ( rec_type == 0xe0 ) { if( subrec_type == 0x06 ) { /* get the PTS from this packet. * Do NOT Pass this packet (a PES Header) on to the MPEG2 codec */ find_es_header( ty_VideoPacket, p_block_in->p_buffer, l_rec_size, &esOffset1 ); if ( esOffset1 != -1 ) { /* msg_Dbg(p_demux, "Video PES hdr at offset %d", esOffset1); */ p_sys->lastVideoPTS = get_pts( &p_block_in->p_buffer[ esOffset1 + 9 ] ); /*msg_Dbg(p_demux, "Video rec %d PTS "I64Fd, p_sys->i_cur_rec, p_sys->lastVideoPTS );*/ } block_Release(p_block_in); } else {#if 0 msg_Dbg(p_demux, "packet buffer has " "%02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %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], p_block_in->p_buffer[4], p_block_in->p_buffer[5], p_block_in->p_buffer[6], p_block_in->p_buffer[7], p_block_in->p_buffer[8], p_block_in->p_buffer[9], p_block_in->p_buffer[10], p_block_in->p_buffer[11], p_block_in->p_buffer[12], p_block_in->p_buffer[13], p_block_in->p_buffer[14], p_block_in->p_buffer[15]);#endif /* if it's not a continue blk, then set PTS */ if (subrec_type != 0x02) { /*msg_Dbg(p_demux, "Video rec %d type 0x%02X", p_sys->i_cur_rec, subrec_type);*/ /* if it's a GOP header, make sure it's legal * (if we have enough data) */ /* Some ty files don't have this bit set * and it causes problems */ if (subrec_type == 0x0c && l_rec_size >= 6) p_block_in->p_buffer[5] |= 0x08; /* set PTS for this block before we send */ if (p_sys->lastVideoPTS > 0) { p_block_in->i_pts = p_sys->lastVideoPTS; /* PTS gets used ONCE. * Any subsequent frames we get BEFORE next PES * header will have their PTS computed in the codec */ p_sys->lastVideoPTS = 0; } } es_out_Send(p_demux->out, p_sys->p_video, p_block_in); } } /* end if video rec type */ /* ================================================================ * Audio Parsing * ================================================================ * parse PES headers and send the rest to the codec */ else if ( rec_type == 0xc0 ) {#if 0 int i; printf( "Audio Packet Header " ); for( i = 0 ; i < 24 ; i++ ) printf( "%2.2x ", p_block_in->p_buffer[i] ); printf( "\n" );#endif /* load a codec if we haven't yet */ if ( p_sys->p_audio == NULL ) { if ( subrec_type == 0x09 ) { /* set up for AC-3 audio */ msg_Dbg(p_demux, "detected AC-3 Audio" ); setup_audio_streams('A', p_demux); } else { /* set up for MPEG audio */ msg_Dbg(p_demux, "detected MPEG Audio" ); setup_audio_streams('M', p_demux); } } /* SA or DTiVo Audio Data, no PES (continued block) * ================================================ */ if ( subrec_type == 2 ) { /* continue PES if previous was incomplete */ /* TODO: Make this work for all series & types of tivos */ if (p_sys->i_pes_buf_cnt > 0) { int i_need = SERIES1_PES_LENGTH - p_sys->i_pes_buf_cnt; msg_Dbg(p_demux, "continuing PES header"); /* do we have enough data to complete? */ if (i_need < l_rec_size) { /* we have enough; reconstruct this p_frame with the new hdr */ memcpy(&p_sys->pes_buffer[p_sys->i_pes_buf_cnt], p_block_in->p_buffer, i_need); /* advance the block past the PES header (don't want to send it) */ p_block_in->p_buffer += i_need; p_block_in->i_buffer -= i_need; /* get the PTS out of this PES header (MPEG or AC3) */ if (p_sys->b_mpeg_audio) find_es_header(ty_MPEGAudioPacket, p_sys->pes_buffer, 10, &esOffset1); else find_es_header(ty_AC3AudioPacket, p_sys->pes_buffer, 10, &esOffset1); if (esOffset1 < 0) { /* god help us; something's really wrong */ msg_Err(p_demux, "can't find audio PES header in packet"); } else { p_sys->lastAudioPTS = get_pts( &p_sys->pes_buffer[ esOffset1 + DTIVO_PTS_OFFSET ] ); p_block_in->i_pts = p_sys->lastAudioPTS; } p_sys->i_pes_buf_cnt = 0; } else { /* don't have complete PES hdr; save what we have and return */ memcpy(&p_sys->pes_buffer[p_sys->i_pes_buf_cnt], p_block_in->p_buffer, l_rec_size); p_sys->i_pes_buf_cnt += l_rec_size; p_sys->i_cur_rec++; block_Release(p_block_in); return 1; } } /* set PCR before we send */ /*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 ); } /* subrec == 2 */ /* MPEG Audio with PES Header, either SA or DTiVo */ /* ================================================ */ if ( subrec_type == 0x03 ) { find_es_header( ty_MPEGAudioPacket, 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 hdr at offset %d", esOffset1);*/ /* SA PES Header, No Audio Data */ /* ================================================ */ if ( ( esOffset1 == 0 ) && ( l_rec_size == 16 ) ) { p_sys->tivoType = 1; p_sys->lastAudioPTS = get_pts( &p_block_in->p_buffer[ SA_PTS_OFFSET ] ); if (p_sys->firstAudioPTS < 0) p_sys->firstAudioPTS = p_sys->lastAudioPTS; block_Release(p_block_in); /*msg_Dbg(p_demux, "SA Audio PTS %lld", p_sys->lastAudioPTS );*/ } else /* DTiVo Audio with PES Header */ /* ================================================ */ { p_sys->tivoType = 2; /* Check for complete PES * (TODO: handle proper size for tivo version) */ 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++; block_Release(p_block_in); return 1; }#if 0 msg_Dbg(p_demux, "packet buffer has " "%02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %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], p_block_in->p_buffer[4], p_block_in->p_buffer[5], p_block_in->p_buffer[6], p_block_in->p_buffer[7], p_block_in->p_buffer[8], p_block_in->p_buffer[9], p_block_in->p_buffer[10], p_block_in->p_buffer[11], p_block_in->p_buffer[12], p_block_in->p_buffer[13], p_block_in->p_buffer[14], p_block_in->p_buffer[15]);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -