📄 ty.c
字号:
/* 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; /* store the TY PTS if there is one */ if (subrec_type == 0x07) { p_sys->l_last_ty_pts = rec_hdr->l_ty_pts; /* should we use audio or video PTS? */ //p_sys->l_last_ty_pts_sync = p_sys->lastAudioPTS; } else { /* yes I know this is a cheap hack. It's the timestamp used for display and skipping fwd/back, so it doesn't have to be accurate to the millisecond. I adjust it here by roughly one 1/30 sec. Yes it will be slightly off for UK streams, but it's OK. */ p_sys->l_last_ty_pts += 35000000; //p_sys->l_last_ty_pts += 33366667; } /* 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; } } /* Register the CC decoders when needed */ for( i = 0; i < 4; i++ ) { static const vlc_fourcc_t fcc[4] = { VLC_FOURCC('c', 'c', '1', ' '), VLC_FOURCC('c', 'c', '2', ' '), VLC_FOURCC('c', 'c', '3', ' '), VLC_FOURCC('c', 'c', '4', ' ') }; static const char *ppsz_description[4] = { N_("Closed captions 1"), N_("Closed captions 2"), N_("Closed captions 3"), N_("Closed captions 4"), }; es_format_t fmt; if( !p_sys->cc.pb_present[i] || p_sys->p_cc[i] ) continue; es_format_Init( &fmt, SPU_ES, fcc[i] ); fmt.psz_description = strdup( _(ppsz_description[i]) ); fmt.i_group = TY_ES_GROUP; p_sys->p_cc[i] = es_out_Add( p_demux->out, &fmt ); es_format_Clean( &fmt ); } /* Send the CC data */ if( p_block_in->i_pts > 0 && p_sys->cc.i_data > 0 ) { int i_cc_count; block_t *p_cc = block_New( p_demux, p_sys->cc.i_data ); p_cc->i_flags |= BLOCK_FLAG_TYPE_I; p_cc->i_pts = p_block_in->i_pts; memcpy( p_cc->p_buffer, p_sys->cc.p_data, p_sys->cc.i_data ); for( i = 0, i_cc_count = 0; i < 4; i++ ) i_cc_count += p_sys->p_cc[i] ? 1 : 0; for( i = 0; i < 4; i++ ) { if( !p_sys->p_cc[i] ) continue; if( i_cc_count > 1 ) es_out_Send( p_demux->out, p_sys->p_cc[i], block_Duplicate( p_cc ) ); else es_out_Send( p_demux->out, p_sys->p_cc[i], p_cc ); } cc_Flush( &p_sys->cc ); } //msg_Dbg(p_demux, "sending rec %d as video type 0x%02x", //p_sys->i_cur_rec, subrec_type); es_out_Send(p_demux->out, p_sys->p_video, p_block_in); return 0;}static int DemuxRecAudio( demux_t *p_demux, ty_rec_hdr_t *rec_hdr, block_t *p_block_in ){ demux_sys_t *p_sys = p_demux->p_sys; const int subrec_type = rec_hdr->subrec_type; const long l_rec_size = rec_hdr->l_rec_size; int esOffset1; assert( rec_hdr->rec_type == 0xc0 ); if( !p_block_in ) return -1;#if 0 int i; fprintf( stderr, "Audio Packet Header " ); for( i = 0 ; i < 24 ; i++ ) fprintf( stderr, "%2.2x ", p_block_in->p_buffer[i] ); fprintf( stderr, "\n" );#endif if( subrec_type == 2 ) { /* SA or DTiVo Audio Data, no PES (continued block) * ================================================ */ /* continue PES if previous was incomplete */ if (p_sys->i_pes_buf_cnt > 0) { const int i_need = p_sys->i_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) { /* 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; /* */ block_Release(p_block_in); return 0; } /* 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->audio_type == TIVO_AUDIO_MPEG) esOffset1 = find_es_header(ty_MPEGAudioPacket, p_sys->pes_buffer, 5); else esOffset1 = find_es_header(ty_AC3AudioPacket, p_sys->pes_buffer, 5); 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 + p_sys->i_Pts_Offset ] ); p_block_in->i_pts = p_sys->lastAudioPTS; } p_sys->i_pes_buf_cnt = 0; } /* S2 DTivo has AC3 packets with 2 padding bytes at end. This is * not allowed in the AC3 spec and will cause problems. So here * we try to trim things. */ /* Also, S1 DTivo has alternating short / long AC3 packets. That * is, one packet is short (incomplete) and the next packet has * the first one's missing data, plus all of its own. Strange. */ if (p_sys->audio_type == TIVO_AUDIO_AC3 && p_sys->tivo_series == TIVO_SERIES2) { if (p_sys->l_ac3_pkt_size + p_block_in->i_buffer > AC3_PKT_LENGTH) { p_block_in->i_buffer -= 2; p_sys->l_ac3_pkt_size = 0; } else { p_sys->l_ac3_pkt_size += p_block_in->i_buffer; } } } else if( subrec_type == 0x03 ) { /* MPEG Audio with PES Header, either SA or DTiVo */ /* ================================================ */ esOffset1 = find_es_header( ty_MPEGAudioPacket, p_block_in->p_buffer, 5 ); /*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->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); return 0; /*msg_Dbg(p_demux, "SA Audio PTS %lld", p_sys->lastAudioPTS );*/ } /* DTiVo Audio with PES Header */ /* ================================================ */ /* 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. */ block_Release(p_block_in); return 0; }#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 } else if( subrec_type == 0x04 ) { /* SA Audio with no PES Header */ /* ================================================ */ /*msg_Dbg(p_demux, "Adding SA Audio Packet Size %ld", l_rec_size ); */ if (p_sys->lastAudioPTS > 0) p_block_in->i_pts = p_sys->lastAudioPTS; } else if( subrec_type == 0x09 ) { /* DTiVo AC3 Audio Data with PES Header */ /* ================================================ */ esOffset1 = find_es_header( ty_AC3AudioPacket, p_block_in->p_buffer, 5 );#if 0 msg_Dbg(p_demux, "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]); msg_Dbg(p_demux, "audio ES AC3 hdr at offset %d", esOffset1);#endif /* 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. */ block_Release(p_block_in); return 0; } /* S2 DTivo has invalid long AC3 packets */ if (p_sys->tivo_series == TIVO_SERIES2) { if (p_block_in->i_buffer > AC3_PKT_LENGTH) { p_block_in->i_buffer -= 2; p_sys->l_ac3_pkt_size = 0; } else { p_sys->l_ac3_pkt_size = p_block_in->i_buffer; } } } else { /* Unsupported/Unknown */ block_Release(p_block_in); return 0; } /* 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 ); /* Send data */ es_out_Send( p_demux->out, p_sys->p_audio, p_block_in ); return 0;}static int DemuxRecCc( demux_t *p_demux, ty_rec_hdr_t *rec_hdr, block_t *p_block_in ){ demux_sys_t *p_sys = p_demux->p_sys; int i_field; int i_channel; if( p_block_in ) block_Release(p_block_in); if( rec_hdr->rec_type == 0x01 ) i_field = 0; else if( rec_hdr->rec_type == 0x02 ) i_field = 1; else return 0; /* XDS data (extract programs infos) transmitted on field 2 only */ if( i_field == 1 ) DemuxDecodeXds( p_demux, rec_hdr->ex1, rec_hdr->ex2 ); if( p_sys->cc.i_data + 3 > CC_MAX_DATA_SIZE ) return 0; p_sys->cc.p_data[p_sys->cc.i_data+0] = i_field; p_sys->cc.p_data[p_sys->cc.i_data+1] = rec_hdr->ex1; p_sys->cc.p_data[p_sys->cc.i_data+2] = rec_hdr->ex2; p_sys->cc.i_data += 3; i_channel = cc_Channel( i_field, &p_sys->cc.p_data[p_sys->cc.i_data-3 + 1] ); if( i_channel >= 0 && i_channel < 4 ) p_sys->cc.pb_present[i_channel] = true; return 0;}/* seek to a position within the stream, if possible */static int ty_stream_seek_pct(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, i_cur_part; 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 part & chunk we want & go there */ i_cur_part = seek_pos / TIVO_PART_LENGTH; p_sys->i_cur_chunk = seek_pos / CHUNK_SIZE; /* try to read the part header (master chunk) if it's there */ if ( stream_Seek( p_demux->s, i_cur_part * TIVO_PART_LENGTH )) { /* can't seek stream */ return VLC_EGENERIC; } parse_master(p_demux); /* now for the actual chunk */ if ( stream_Seek( p_demux->s, p_sys->i_cur_chunk * CHUNK_SIZE)) { /* can't seek stream */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -