system.c
来自「VLC媒体播放程序」· C语言 代码 · 共 1,499 行 · 第 1/4 页
C
1,499 行
{ input_ClockManageRef( p_input, p_input->stream.p_selected_program, p_mpeg_demux->cur_scr_time ); if( p_mpeg_demux->i_cur_mux_rate != p_input->stream.i_mux_rate && p_input->stream.i_mux_rate ) { msg_Warn( p_input, "mux_rate changed prev: %ud, cur: %ud;" " expect cosmetic errors" , (unsigned int) p_input->stream.i_mux_rate, (unsigned int) p_mpeg_demux->i_cur_mux_rate ); } p_input->stream.i_mux_rate = p_mpeg_demux->i_cur_mux_rate; } vlc_mutex_lock( &p_input->stream.control.control_lock ); if( p_es != NULL && p_es->p_dec != NULL && (p_es->i_cat != AUDIO_ES || !p_input->stream.control.b_mute) ) { vlc_mutex_unlock( &p_input->stream.control.control_lock ); p_es->c_packets++; GatherPES( p_input, p_data, p_es, 1, 0 ); } else { vlc_mutex_unlock( &p_input->stream.control.control_lock ); b_trash = 1; } } /* Trash the packet if it has no payload or if it isn't selected */ if( b_trash ) { input_DeletePacket( p_input->p_method_data, p_data ); p_input->stream.c_packets_trashed++; }}/* * TS Demultiplexing *//***************************************************************************** * ReadTS: store a TS packet into a data_buffer_t *****************************************************************************/#define PEEK( SIZE ) \ i_error = input_Peek( p_input, &p_peek, SIZE ); \ if( i_error == -1 ) \ { \ return( -1 ); \ } \ else if( i_error < SIZE ) \ { \ /* EOF */ \ return( 0 ); \ }static ssize_t ReadTS( input_thread_t * p_input, data_packet_t ** pp_data ){ byte_t * p_peek; ssize_t i_error, i_read; PEEK( 1 ); if( *p_peek != TS_SYNC_CODE ) { msg_Warn( p_input, "garbage at input (%x)", *p_peek ); if( p_input->i_mtu ) { while( *p_peek != TS_SYNC_CODE ) { /* Try to resync on next packet. */ PEEK( TS_PACKET_SIZE ); p_input->p_current_data += TS_PACKET_SIZE; PEEK( 1 ); } } else { /* Move forward until we find 0x47 (and hope it's the good * one... FIXME) */ while( *p_peek != TS_SYNC_CODE ) { p_input->p_current_data++; PEEK( 1 ); } } } i_read = input_SplitBuffer( p_input, pp_data, TS_PACKET_SIZE ); if( i_read <= 0 ) { return( i_read ); } return( 1 );}/***************************************************************************** * DemuxTS: first step of demultiplexing: the TS header *****************************************************************************/static void DemuxTS( input_thread_t * p_input, data_packet_t * p_data, psi_callback_t pf_psi_callback ){ uint16_t i_pid; unsigned int i_dummy; vlc_bool_t b_adaptation; /* Adaptation field is present */ vlc_bool_t b_payload; /* Packet carries payload */ vlc_bool_t b_unit_start; /* A PSI or a PES start in the packet */ vlc_bool_t b_trash = 0; /* Is the packet unuseful ? */ vlc_bool_t b_lost = 0; /* Was there a packet loss ? */ vlc_bool_t b_psi = 0; /* Is this a PSI ? */ vlc_bool_t b_dvbsub = 0; /* Is this a dvb subtitle ? */ vlc_bool_t b_pcr = 0; /* Does it have a PCR ? */ vlc_bool_t b_scrambled; es_descriptor_t * p_es = NULL; es_ts_data_t * p_es_demux = NULL; pgrm_ts_data_t * p_pgrm_demux = NULL; stream_ts_data_t * p_stream_demux = (stream_ts_data_t *)p_input->stream.p_demux_data;#define p (p_data->p_demux_start) /* Extract flags values from TS common header. */ i_pid = ((p[1] & 0x1F) << 8) | p[2]; b_unit_start = (p[1] & 0x40); b_scrambled = (p[3] & 0xc0); b_adaptation = (p[3] & 0x20); b_payload = (p[3] & 0x10); /* Was there a transport error ? */ if ( p[1] & 0x80 ) { msg_Warn( p_input, "transport_error_indicator set for PID %d counter %x", i_pid, p[3] & 0x0f ); } /* Find out the elementary stream. */ vlc_mutex_lock( &p_input->stream.stream_lock ); for( i_dummy = 0; i_dummy < p_input->stream.i_pgrm_number; i_dummy ++ ) { if( (( pgrm_ts_data_t * ) p_input->stream.pp_programs[i_dummy]-> p_demux_data)->i_pcr_pid == i_pid ) { b_pcr = 1; break; } } p_es = input_FindES( p_input, i_pid ); if( (p_es != NULL) && (p_es->p_demux_data != NULL) ) { p_es_demux = (es_ts_data_t *)p_es->p_demux_data; if( p_es_demux->b_psi ) { b_psi = 1; } else if ( p_es_demux->b_dvbsub ) { b_dvbsub = 1; } else { p_pgrm_demux = (pgrm_ts_data_t *)p_es->p_pgrm->p_demux_data; } } vlc_mutex_lock( &p_input->stream.control.control_lock ); if( ( p_es == NULL ) || (p_es->i_cat == AUDIO_ES && p_input->stream.control.b_mute) ) { /* Not selected. Just read the adaptation field for a PCR. */ b_trash = 1; } else if( p_es->p_dec == NULL && !b_psi && !b_dvbsub ) { b_trash = 1; } else if( b_scrambled ) { msg_Warn( p_input, "scrambled packet for PID %d counter %x", i_pid, p[3] & 0x0f ); b_trash = 1; } vlc_mutex_unlock( &p_input->stream.control.control_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock ); /* Don't change the order of the tests : if b_psi then p_pgrm_demux * may still be null. Who said it was ugly ? * I have written worse. --Meuuh */ if( ( p_es ) && ((p_es->p_dec != NULL) || b_psi || b_pcr || b_dvbsub) ) { p_es->c_packets++; /* Extract adaptation field information if any */ if( !b_adaptation ) { /* We don't have any adaptation_field, so payload starts * immediately after the 4 byte TS header */ p_data->p_payload_start += 4; } else { /* p[4] is adaptation_field_length minus one */ p_data->p_payload_start += 5 + p[4]; /* The adaptation field can be limited to the * adaptation_field_length byte, so that there is nothing to do: * skip this possibility */ if( p[4] ) { /* If the packet has both adaptation_field and payload, * adaptation_field cannot be more than 182 bytes long; if * there is only an adaptation_field, it must fill the next * 183 bytes. */ if( b_payload ? (p[4] > 182) : (p[4] != 183) ) { msg_Warn( p_input, "invalid TS adaptation field for PID %d (%2x)", i_pid, p[4] ); p_data->b_discard_payload = 1; p_es->c_invalid_packets++; /* The length was invalid so we shouldn't have added it to * p_payload_start above. Ensure p_payload_start has a * valid value by setting it equal to p_payload_end. This * also stops any data being processed from the packet. */ p_data->p_payload_start = p_data->p_payload_end; } /* Now we are sure that the byte containing flags is present: * read it */ else { /* discontinuity_indicator */ if( p[5] & 0x80 ) { msg_Warn( p_input, "discontinuity_indicator encountered by TS demux " "(PID %d: current %d, packet %d)", i_pid, ( p_es_demux->i_continuity_counter ) & 0x0f, p[3] & 0x0f ); /* If the PID carries the PCR, there will be a system * time-based discontinuity. We let the PCR decoder * handle that. */ p_es->p_pgrm->i_synchro_state = SYNCHRO_REINIT; /* Don't resynchronise the counter here - it will * be checked later and b_lost will then be set if * necessary. */ } } /* valid TS adaptation field ? */ } /* length > 0 */ } /* has adaptation field */ /* Check the continuity of the stream. */ i_dummy = ((p[3] & 0x0f) - p_es_demux->i_continuity_counter) & 0x0f; if( b_payload && ( i_dummy == 1 || (b_psi && p_stream_demux->b_buggy_psi ) ) ) { /* Everything is ok, just increase our counter */ (p_es_demux->i_continuity_counter)++; } else { if( !b_payload && i_dummy == 0 ) { /* This is a packet without payload, this is allowed by the * draft. As there is nothing interesting in this packet * (except PCR that have already been handled), we can trash * the packet. */ b_trash = 1; } else if( !b_payload ) { /* If there is no payload, the counter should be unchanged */ msg_Warn( p_input, "packet rxd for PID %d with no payload but " "wrong counter: current %d, packet %d", i_pid, p_es_demux->i_continuity_counter & 0x0f, p[3] & 0x0f ); } else if( i_dummy <= 0 ) { /* Duplicate packet: mark it as being to be trashed. */ msg_Warn( p_input, "duplicate packet received for PID %d (counter %d)", p_es->i_id, p[3] & 0x0f ); b_trash = 1; } else if( p_es_demux->i_continuity_counter == 0xFF ) { /* This means that the packet is the first one we receive for * this ES since the continuity counter ranges between 0 and * 0x0F excepts when it has been initialized by the input: * init the counter to the correct value. */ msg_Warn( p_input, "first packet for PID %d received " "by TS demux", p_es->i_id ); p_es_demux->i_continuity_counter = (p[3] & 0x0f); } else { /* This can indicate that we missed a packet or that the * continuity_counter wrapped and we received a dup packet: * as we don't know, do as if we missed a packet to be sure * to recover from this situation */ msg_Warn( p_input, "packet lost by TS demux for PID %d: current %d, packet %d", i_pid, p_es_demux->i_continuity_counter & 0x0f, p[3] & 0x0f ); b_lost = 1; p_es_demux->i_continuity_counter = p[3] & 0x0f; } /* not continuous */ } /* continuity */ } /* if selected or PCR */ /* Handle PCR */ if( b_pcr && b_adaptation && (p[5] & 0x10) && p[4]>=7 ) { /* Read the PCR. */ mtime_t pcr_time; pcr_time = ( (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 ); /* Call the pace control. */ for( i_dummy = 0; i_dummy < p_input->stream.i_pgrm_number; i_dummy ++ ) { if( ( ( pgrm_ts_data_t * ) p_input->stream.pp_programs[i_dummy]-> p_demux_data )->i_pcr_pid == i_pid ) { input_ClockManageRef( p_input, p_input->stream.pp_programs[i_dummy], pcr_time ); } } } /* Trash the packet if it has no payload or if it isn't selected */ if( b_trash ) { input_DeletePacket( p_input->p_method_data, p_data ); p_input->stream.c_packets_trashed++; } else { if( b_psi ) { /* The payload contains PSI tables */ (* pf_psi_callback) ( p_input, p_data, p_es, b_unit_start ); } else { /* The payload carries a PES stream */ GatherPES( p_input, p_data, p_es, b_unit_start, b_lost ); } }#undef p}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?