system.c
来自「VLC媒体播放程序」· C语言 代码 · 共 1,499 行 · 第 1/4 页
C
1,499 行
{ /* stream_private_id */ i_pes_header_size += 1; } /* Now we've parsed the header, we just have to indicate in some * specific data packets where the PES payload begins (renumber * p_payload_start), so that the decoders can find the beginning * of their data right out of the box. */ p_data = p_pes->p_first; i_payload_size = p_data->p_payload_end - p_data->p_payload_start; while( i_pes_header_size > i_payload_size ) { /* These packets are entirely filled by the PES header. */ i_pes_header_size -= i_payload_size; p_data->p_payload_start = p_data->p_payload_end; /* Go to the next data packet. */ if( (p_data = p_data->p_next) == NULL ) { msg_Warn( p_input, "PES header bigger than payload" ); input_DeletePES( p_input->p_method_data, p_pes ); p_pes = NULL; return; } i_payload_size = p_data->p_payload_end - p_data->p_payload_start; } /* This last packet is partly header, partly payload. */ if( i_payload_size < i_pes_header_size ) { msg_Warn( p_input, "PES header bigger than payload" ); input_DeletePES( p_input->p_method_data, p_pes ); p_pes = NULL; return; } p_data->p_payload_start += i_pes_header_size; /* Now we can eventually put the PES packet in the decoder's * PES fifo */ if( p_es->p_dec != NULL ) { input_DecodePES( p_es->p_dec, p_pes ); } else if ( p_es->p_dec == NULL && ((es_ts_data_t*)p_es->p_demux_data)->b_dvbsub) { es_descriptor_t* p_dvbsub; uint8_t i_count; uint8_t i; i_count = ((es_ts_data_t*)p_es->p_demux_data)->i_dvbsub_es_count; // If a language is selected, we send the packet to the decoder for(i = 0; i < i_count; i++) { p_dvbsub = ((es_ts_data_t*)p_es->p_demux_data)->p_dvbsub_es[i]; if(p_dvbsub->p_dec !=NULL) { input_DecodePES ( p_dvbsub->p_dec, p_pes ); break; } } if(i == i_count) { input_DeletePES( p_input->p_method_data, p_pes ); } } else { msg_Err( p_input, "no fifo to receive PES %p " "(who wrote this damn code ?)", p_pes ); input_DeletePES( p_input->p_method_data, p_pes ); } p_pes = NULL; }#undef p_pes}/***************************************************************************** * GatherPES: ***************************************************************************** * Gather a PES packet. *****************************************************************************/static void GatherPES( input_thread_t * p_input, data_packet_t * p_data, es_descriptor_t * p_es, vlc_bool_t b_unit_start, vlc_bool_t b_packet_lost ){#define p_pes (p_es->p_pes) if( b_packet_lost && p_pes != NULL ) { p_pes->b_discontinuity = 1; } if( b_unit_start && p_pes != NULL ) { /* If the data packet contains the begining of a new PES packet, and * if we were reassembling a PES packet, then the PES should be * complete now, so parse its header and give it to the decoders. */ ParsePES( p_input, p_es ); } if( !b_unit_start && p_pes == NULL ) { /* Random access... */ input_DeletePacket( p_input->p_method_data, p_data ); } else { if( b_unit_start ) { /* If we are at the beginning of a new PES packet, we must fetch * a new PES buffer to begin with the reassembly of this PES * packet. This is also here that we can synchronize with the * stream if we lost packets or if the decoder has just * started. */ if( (p_pes = input_NewPES( p_input->p_method_data ) ) == NULL ) { msg_Err( p_input, "out of memory" ); p_input->b_error = 1; return; } p_pes->i_rate = p_input->stream.control.i_rate; p_pes->p_first = p_data; /* If the PES header fits in the first data packet, we can * already set p_gather->i_pes_real_size. */ if( p_data->p_payload_end - p_data->p_payload_start >= PES_HEADER_SIZE ) { p_es->i_pes_real_size = ((uint16_t)p_data->p_payload_start[4] << 8) + p_data->p_payload_start[5]; if ( p_es->i_pes_real_size ) { p_es->i_pes_real_size += 6; } } else { p_es->i_pes_real_size = 0; } } else { /* Update the relations between the data packets */ p_pes->p_last->p_next = p_data; } p_pes->p_last = p_data; p_pes->i_nb_data++; /* Size of the payload carried in the data packet */ p_pes->i_pes_size += (p_data->p_payload_end - p_data->p_payload_start); /* We can check if the packet is finished */ if( p_es->i_pes_real_size && p_pes->i_pes_size >= p_es->i_pes_real_size ) { if( p_pes->i_pes_size > p_es->i_pes_real_size ) { msg_Warn( p_input, "Oversized PES packet for PID %d: expected %d, actual %d", p_es->i_id, p_es->i_pes_real_size, p_pes->i_pes_size ); } /* The packet is finished, parse it */ ParsePES( p_input, p_es ); } }#undef p_pes}/* * PS Demultiplexing *//***************************************************************************** * GetID: Get the ID of a stream *****************************************************************************/static uint16_t GetID( input_thread_t *p_input, data_packet_t * p_data ){ uint16_t i_id; i_id = p_data->p_demux_start[3]; /* stream_id */ if( i_id == 0xBD ) { mpeg_demux_t *p_mpeg_demux = (mpeg_demux_t *)p_input->p_private; /* FIXME : this is not valid if the header is split in multiple * packets */ /* stream_private_id */ i_id |= p_data->p_demux_start[ 9 + p_data->p_demux_start[8] ] << 8; /* FIXME: See note about cur_scr_time above. */ p_mpeg_demux->cur_scr_time = -1; } return( i_id );}/***************************************************************************** * DecodePSM: Decode the Program Stream Map information ***************************************************************************** * FIXME : loads are not aligned in this function *****************************************************************************/static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data ){ stream_ps_data_t * p_demux = (stream_ps_data_t *)p_input->stream.p_demux_data; byte_t * p_byte; byte_t * p_end; unsigned int i; unsigned int i_new_es_number = 0; if( p_data->p_demux_start + 10 > p_data->p_payload_end ) { msg_Err( p_input, "PSM too short, packet corrupt" ); return; } if( p_demux->b_has_PSM && p_demux->i_PSM_version == (p_data->p_demux_start[6] & 0x1F) ) { /* Already got that one. */ return; } p_demux->b_has_PSM = 1; p_demux->i_PSM_version = p_data->p_demux_start[6] & 0x1F; /* Go to elementary_stream_map_length, jumping over * program_stream_info. */ p_byte = p_data->p_demux_start + 10 + U16_AT(&p_data->p_demux_start[8]); if( p_byte > p_data->p_payload_end ) { msg_Err( p_input, "PSM too short, packet corrupt" ); return; } /* This is the full size of the elementary_stream_map. * 2 == elementary_stream_map_length * Please note that CRC_32 is not included in the length. */ p_end = p_byte + 2 + U16_AT(p_byte); p_byte += 2; if( p_end > p_data->p_payload_end ) { msg_Err( p_input, "PSM too short, packet corrupt" ); return; } vlc_mutex_lock( &p_input->stream.stream_lock ); /* 4 == minimum useful size of a section */ while( p_byte + 4 <= p_end ) { es_descriptor_t * p_es = NULL; uint8_t i_stream_id = p_byte[1]; /* FIXME: there will be a problem with private streams... (same * stream_id) */ /* Look for the ES in the ES table */ for( i = i_new_es_number; i < p_input->stream.pp_programs[0]->i_es_number; i++ ) { if( p_input->stream.pp_programs[0]->pp_es[i]->i_stream_id == i_stream_id ) { p_es = p_input->stream.pp_programs[0]->pp_es[i]; /* FIXME: do something below */#if 0 if( p_es->i_type != p_byte[0] ) { input_DelES( p_input, p_es ); p_es = NULL; } else#endif { /* Move the ES to the beginning. */ p_input->stream.pp_programs[0]->pp_es[i] = p_input->stream.pp_programs[0]->pp_es[ i_new_es_number ]; p_input->stream.pp_programs[0]->pp_es[ i_new_es_number ] = p_es; i_new_es_number++; } break; } } /* The goal is to have all the ES we have just read in the * beginning of the pp_es table, and all the others at the end, * so that we can close them more easily at the end. */ if( p_es == NULL ) { int i_fourcc, i_cat; switch( p_byte[0] ) { case MPEG1_VIDEO_ES: case MPEG2_VIDEO_ES: case MPEG2_MOTO_VIDEO_ES: i_fourcc = VLC_FOURCC('m','p','g','v'); i_cat = VIDEO_ES; break; case DVD_SPU_ES: i_fourcc = VLC_FOURCC('s','p','u','b'); i_cat = SPU_ES; break; case MPEG1_AUDIO_ES: case MPEG2_AUDIO_ES: i_fourcc = VLC_FOURCC('m','p','g','a'); i_cat = AUDIO_ES; break; case A52_AUDIO_ES: i_fourcc = VLC_FOURCC('a','5','2','b'); i_cat = AUDIO_ES; break; case LPCM_AUDIO_ES: i_fourcc = VLC_FOURCC('l','p','c','b'); i_cat = AUDIO_ES; break; default: i_cat = UNKNOWN_ES; i_fourcc = 0; break; } p_es = input_AddES( p_input, p_input->stream.pp_programs[0], i_stream_id, i_cat, NULL, 0 ); p_es->i_fourcc = i_fourcc; /* input_AddES has inserted the new element at the end. */ p_input->stream.pp_programs[0]->pp_es[ p_input->stream.pp_programs[0]->i_es_number ] = p_input->stream.pp_programs[0]->pp_es[ i_new_es_number ]; p_input->stream.pp_programs[0]->pp_es[ i_new_es_number ] = p_es; i_new_es_number++; } p_byte += 4 + U16_AT(&p_byte[2]); } /* Un-select the streams that are no longer parts of the program. */ while( i_new_es_number < p_input->stream.pp_programs[0]->i_es_number ) { /* We remove pp_es[i_new_es_member] and not pp_es[i] because the * list will be emptied starting from the end */ input_DelES( p_input, p_input->stream.pp_programs[0]->pp_es[i_new_es_number] ); } msg_Dbg( p_input, "the stream map after the PSM is now:" ); input_DumpStream( p_input ); vlc_mutex_unlock( &p_input->stream.stream_lock );}/***************************************************************************** * ReadPS: store a PS 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( (size_t)i_error < SIZE ) \ { \ /* EOF */ \ return( 0 ); \ }static ssize_t ReadPS( input_thread_t * p_input, data_packet_t ** pp_data ){
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?