📄 ts.c
字号:
p_pes->i_pts = i_pts * 100 / 9; } p_pes->i_length = i_length * 100 / 9; p_block = block_ChainGather( p_pes ); if( pid->es->fmt.i_codec == VLC_FOURCC( 's', 'u', 'b', 't' ) ) { if( i_pes_size > 0 && p_block->i_buffer > i_pes_size ) { p_block->i_buffer = i_pes_size; } /* Append a \0 */ p_block = block_Realloc( p_block, 0, p_block->i_buffer + 1 ); p_block->p_buffer[p_block->i_buffer -1] = '\0'; } for( i = 0; i < pid->i_extra_es; i++ ) { es_out_Send( p_demux->out, pid->extra_es[i]->id, block_Duplicate( p_block ) ); } es_out_Send( p_demux->out, pid->es->id, p_block ); } else { msg_Warn( p_demux, "empty pes" ); }}static void PCRHandle( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ){ demux_sys_t *p_sys = p_demux->p_sys; const uint8_t *p = p_bk->p_buffer; if( ( p[3]&0x20 ) && /* adaptation */ ( p[5]&0x10 ) && ( p[4] >= 7 ) ) { int i; mtime_t i_pcr; /* 33 bits */ i_pcr = ( (mtime_t)p[6] << 25 ) | ( (mtime_t)p[7] << 17 ) | ( (mtime_t)p[8] << 9 ) | ( (mtime_t)p[9] << 1 ) | ( (mtime_t)p[10] >> 7 ); /* Search program and set the PCR */ for( i = 0; i < p_sys->i_pmt; i++ ) { int i_prg; for( i_prg = 0; i_prg < p_sys->pmt[i]->psi->i_prg; i_prg++ ) { if( pid->i_pid == p_sys->pmt[i]->psi->prg[i_prg]->i_pid_pcr ) { es_out_Control( p_demux->out, ES_OUT_SET_GROUP_PCR, (int)p_sys->pmt[i]->psi->prg[i_prg]->i_number, (int64_t)(i_pcr * 100 / 9) ); } } } }}static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk ){ const uint8_t *p = p_bk->p_buffer; const vlc_bool_t b_unit_start = p[1]&0x40; const vlc_bool_t b_adaptation = p[3]&0x20; const vlc_bool_t b_payload = p[3]&0x10; const int i_cc = p[3]&0x0f; /* continuity counter */ vlc_bool_t b_discontinuity = VLC_FALSE;/* discontinuity */ /* transport_scrambling_control is ignored */ int i_skip = 0; vlc_bool_t i_ret = VLC_FALSE; int i_diff;#if 0 msg_Dbg( p_demux, "pid=%d unit_start=%d adaptation=%d payload=%d " "cc=0x%x", pid->i_pid, b_unit_start, b_adaptation, b_payload, i_cc );#endif /* For now, ignore additional error correction * TODO: handle Reed-Solomon 204,188 error correction */ p_bk->i_buffer = TS_PACKET_SIZE_188; if( p[1]&0x80 ) { msg_Dbg( p_demux, "transport_error_indicator set (pid=%d)", pid->i_pid ); if( pid->es->p_pes ) //&& pid->es->fmt.i_cat == VIDEO_ES ) pid->es->p_pes->i_flags |= BLOCK_FLAG_CORRUPTED; } if( p_demux->p_sys->csa ) { csa_Decrypt( p_demux->p_sys->csa, p_bk->p_buffer, p_demux->p_sys->i_csa_pkt_size ); } if( !b_adaptation ) { /* We don't have any adaptation_field, so payload starts * immediately after the 4 byte TS header */ i_skip = 4; } else { /* p[4] is adaptation_field_length minus one */ i_skip = 5 + p[4]; if( p[4] > 0 ) { /* discontinuity indicator found in stream */ b_discontinuity = (p[5]&0x80) ? VLC_TRUE : VLC_FALSE; if( b_discontinuity && pid->es->p_pes ) { msg_Warn( p_demux, "discontinuity indicator (pid=%d) ", pid->i_pid ); /* pid->es->p_pes->i_flags |= BLOCK_FLAG_DISCONTINUITY; */ }#if 0 if( p[5]&0x40 ) msg_Dbg( p_demux, "random access indicator (pid=%d) ", pid->i_pid );#endif } } /* Test continuity counter */ /* continuous when (one of this): * diff == 1 * diff == 0 and payload == 0 * diff == 0 and duplicate packet (playload != 0) <- should we * test the content ? */ i_diff = ( i_cc - pid->i_cc )&0x0f; if( b_payload && i_diff == 1 ) { pid->i_cc = ( pid->i_cc + 1 ) & 0xf; } else { if( pid->i_cc == 0xff ) { msg_Warn( p_demux, "first packet for pid=%d cc=0x%x", pid->i_pid, i_cc ); pid->i_cc = i_cc; } else if( i_diff != 0 && !b_discontinuity ) { msg_Warn( p_demux, "discontinuity received 0x%x instead of 0x%x (pid=%d)", i_cc, ( pid->i_cc + 1 )&0x0f, pid->i_pid ); pid->i_cc = i_cc; if( pid->es->p_pes && pid->es->fmt.i_cat != VIDEO_ES ) { /* Small video artifacts are usually better then * dropping full frames */ pid->es->p_pes->i_flags |= BLOCK_FLAG_CORRUPTED; } } } PCRHandle( p_demux, pid, p_bk ); if( i_skip >= 188 || pid->es->id == NULL || p_demux->p_sys->b_udp_out ) { block_Release( p_bk ); return i_ret; } /* We have to gather it */ p_bk->p_buffer += i_skip; p_bk->i_buffer -= i_skip; if( b_unit_start ) { if( pid->es->p_pes ) { ParsePES( p_demux, pid ); i_ret = VLC_TRUE; } block_ChainLastAppend( &pid->es->pp_last, p_bk ); if( p_bk->i_buffer > 6 ) { pid->es->i_pes_size = GetWBE( &p_bk->p_buffer[4] ); if( pid->es->i_pes_size > 0 ) { pid->es->i_pes_size += 6; } } pid->es->i_pes_gathered += p_bk->i_buffer; if( pid->es->i_pes_size > 0 && pid->es->i_pes_gathered >= pid->es->i_pes_size ) { ParsePES( p_demux, pid ); i_ret = VLC_TRUE; } } else { if( pid->es->p_pes == NULL ) { /* msg_Dbg( p_demux, "broken packet" ); */ block_Release( p_bk ); } else { block_ChainLastAppend( &pid->es->pp_last, p_bk ); pid->es->i_pes_gathered += p_bk->i_buffer; if( pid->es->i_pes_size > 0 && pid->es->i_pes_gathered >= pid->es->i_pes_size ) { ParsePES( p_demux, pid ); i_ret = VLC_TRUE; } } } return i_ret;}static int PIDFillFormat( ts_pid_t *pid, int i_stream_type ){ es_format_t *fmt = &pid->es->fmt; switch( i_stream_type ) { case 0x01: /* MPEG-1 video */ case 0x02: /* MPEG-2 video */ case 0x80: /* MPEG-2 MOTO video */ es_format_Init( fmt, VIDEO_ES, VLC_FOURCC( 'm', 'p', 'g', 'v' ) ); break; case 0x03: /* MPEG-1 audio */ case 0x04: /* MPEG-2 audio */ es_format_Init( fmt, AUDIO_ES, VLC_FOURCC( 'm', 'p', 'g', 'a' ) ); break; case 0x11: /* MPEG4 (audio) */ case 0x0f: /* ISO/IEC 13818-7 Audio with ADTS transport syntax */ es_format_Init( fmt, AUDIO_ES, VLC_FOURCC( 'm', 'p', '4', 'a' ) ); break; case 0x10: /* MPEG4 (video) */ es_format_Init( fmt, VIDEO_ES, VLC_FOURCC( 'm', 'p', '4', 'v' ) ); pid->es->b_gather = VLC_TRUE; break; case 0x1B: /* H264 <- check transport syntax/needed descriptor */ es_format_Init( fmt, VIDEO_ES, VLC_FOURCC( 'h', '2', '6', '4' ) ); break; case 0x81: /* A52 (audio) */ es_format_Init( fmt, AUDIO_ES, VLC_FOURCC( 'a', '5', '2', ' ' ) ); break; case 0x82: /* DVD_SPU (sub) */ es_format_Init( fmt, SPU_ES, VLC_FOURCC( 's', 'p', 'u', ' ' ) ); break; case 0x83: /* LPCM (audio) */ es_format_Init( fmt, AUDIO_ES, VLC_FOURCC( 'l', 'p', 'c', 'm' ) ); break; case 0x84: /* SDDS (audio) */ es_format_Init( fmt, AUDIO_ES, VLC_FOURCC( 's', 'd', 'd', 's' ) ); break; case 0x85: /* DTS (audio) */ es_format_Init( fmt, AUDIO_ES, VLC_FOURCC( 'd', 't', 's', ' ' ) ); break; case 0x91: /* A52 vls (audio) */ es_format_Init( fmt, AUDIO_ES, VLC_FOURCC( 'a', '5', '2', 'b' ) ); break; case 0x92: /* DVD_SPU vls (sub) */ es_format_Init( fmt, SPU_ES, VLC_FOURCC( 's', 'p', 'u', 'b' ) ); break; case 0x94: /* SDDS (audio) */ es_format_Init( fmt, AUDIO_ES, VLC_FOURCC( 's', 'd', 'd', 'b' ) ); break; case 0xa0: /* MSCODEC vlc (video) (fixed later) */ es_format_Init( fmt, UNKNOWN_ES, 0 ); pid->es->b_gather = VLC_TRUE; break; case 0x06: /* PES_PRIVATE (fixed later) */ case 0x12: /* MPEG-4 generic (sub/scene/...) (fixed later) */ default: es_format_Init( fmt, UNKNOWN_ES, 0 ); break; } /* PES packets usually contain truncated frames */ fmt->b_packetized = VLC_FALSE; return fmt->i_cat == UNKNOWN_ES ? VLC_EGENERIC : VLC_SUCCESS ;}/***************************************************************************** * MP4 specific functions (IOD parser) *****************************************************************************/static int IODDescriptorLength( int *pi_data, uint8_t **pp_data ){ unsigned int i_b; unsigned int i_len = 0; do { i_b = **pp_data; (*pp_data)++; (*pi_data)--; i_len = ( i_len << 7 ) + ( i_b&0x7f ); } while( i_b&0x80 ); return( i_len );}static int IODGetByte( int *pi_data, uint8_t **pp_data ){ if( *pi_data > 0 ) { const int i_b = **pp_data; (*pp_data)++; (*pi_data)--; return( i_b ); } return( 0 );}static int IODGetWord( int *pi_data, uint8_t **pp_data ){ const int i1 = IODGetByte( pi_data, pp_data ); const int i2 = IODGetByte( pi_data, pp_data ); return( ( i1 << 8 ) | i2 );}static int IODGet3Bytes( int *pi_data, uint8_t **pp_data ){ const int i1 = IODGetByte( pi_data, pp_data ); const int i2 = IODGetByte( pi_data, pp_data ); const int i3 = IODGetByte( pi_data, pp_data ); return( ( i1 << 16 ) | ( i2 << 8) | i3 );}static uint32_t IODGetDWord( int *pi_data, uint8_t **pp_data ){ const uint32_t i1 = IODGetWord( pi_data, pp_data ); const uint32_t i2 = IODGetWord( pi_data, pp_data ); return( ( i1 << 16 ) | i2 );}static char* IODGetURL( int *pi_data, uint8_t **pp_data ){ char *url; int i_url_len, i; i_url_len = IODGetByte( pi_data, pp_data ); url = malloc( i_url_len + 1 ); for( i = 0; i < i_url_len; i++ ) { url[i] = IODGetByte( pi_data, pp_data ); } url[i_url_len] = '\0'; return( url );}static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data ){ iod_descriptor_t *p_iod; int i; int i_es_index; uint8_t i_flags, i_iod_tag, byte1, byte2, byte3; vlc_bool_t b_url; int i_iod_length; p_iod = malloc( sizeof( iod_descriptor_t ) ); memset( p_iod, 0, sizeof( iod_descriptor_t ) );#ifdef TS_DEBUG fprintf( stderr, "\n************ IOD ************" );#endif for( i = 0; i < 255; i++ ) { p_iod->es_descr[i].b_ok = 0; } i_es_index = 0; if( i_data < 3 ) { return p_iod; } byte1 = IODGetByte( &i_data, &p_data ); byte2 = IODGetByte( &i_data, &p_data ); byte3 = IODGetByte( &i_data, &p_data ); if( byte2 == 0x02 ) //old vlc's buggy implementation of the IOD_descriptor { p_iod->i_iod_label_scope = 0x11; p_iod->i_iod_label = byte1; i_iod_tag = byte2; } else //correct implementation of the IOD_descriptor { p_iod->i_iod_label_scope = byte1; p_iod->i_iod_label = byte2; i_iod_tag = byte3; }#ifdef TS_DEBUG fprintf( stderr, "\n* iod_label:%d", p_iod->i_iod_label ); fprintf( stderr, "\n* ===========" ); fprintf( stderr, "\n* t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -