system.c
来自「VLC媒体播放程序」· C语言 代码 · 共 1,499 行 · 第 1/4 页
C
1,499 行
byte_t * p_peek; size_t i_packet_size; ssize_t i_error, i_read; /* Read what we believe to be a packet header. */ PEEK( 4 ); if( p_peek[0] || p_peek[1] || p_peek[2] != 1 || p_peek[3] < 0xB9 ) { if( p_peek[0] || p_peek[1] || p_peek[2] ) { /* It is common for MPEG-1 streams to pad with zeros * (although it is forbidden by the recommendation), so * don't bother everybody in this case. */ msg_Warn( p_input, "garbage (0x%.2x%.2x%.2x%.2x)", p_peek[0], p_peek[1], p_peek[2], p_peek[3] ); } /* This is not the startcode of a packet. Read the stream * until we find one. */ while( p_peek[0] || p_peek[1] || p_peek[2] != 1 || p_peek[3] < 0xB9 ) { p_input->p_current_data++; PEEK( 4 ); if( p_input->b_die ) return( -1 ); } /* Packet found. */ } /* 0x1B9 == SYSTEM_END_CODE, it is only 4 bytes long. */ if( p_peek[3] != 0xB9 ) { /* The packet is at least 6 bytes long. */ PEEK( 6 ); if( p_peek[3] != 0xBA ) { /* That's the case for all packets, except pack header. */ i_packet_size = (p_peek[4] << 8) | p_peek[5]; } else { /* Pack header. */ if( (p_peek[4] & 0xC0) == 0x40 ) { /* MPEG-2 */ i_packet_size = 8; } else if( (p_peek[4] & 0xF0) == 0x20 ) { /* MPEG-1 */ i_packet_size = 6; } else { msg_Err( p_input, "unable to determine stream type" ); p_input->p_current_data++; return( -1 ); } } } else { /* System End Code */ i_packet_size = -2; } /* Fetch a packet of the appropriate size. */ i_read = input_SplitBuffer( p_input, pp_data, i_packet_size + 6 ); if( i_read <= 0 ) { return( i_read ); } /* In MPEG-2 pack headers we still have to read stuffing bytes. */ if( ((*pp_data)->p_demux_start[3] == 0xBA) && (i_packet_size == 8) ) { size_t i_stuffing = ((*pp_data)->p_demux_start[13] & 0x7); /* Force refill of the input buffer - though we don't care * about p_peek. Please note that this is unoptimized. */ PEEK( i_stuffing ); p_input->p_current_data += i_stuffing; } return( 1 );}#undef PEEK/***************************************************************************** * ParsePS: read the PS header *****************************************************************************/static es_descriptor_t * ParsePS( input_thread_t * p_input, data_packet_t * p_data ){ uint32_t i_code; es_descriptor_t * p_es = NULL; i_code = p_data->p_demux_start[3]; if( i_code > 0xBC ) /* ES start code */ { uint16_t i_id; unsigned int i_dummy; /* This is a PES packet. Find out if we want it or not. */ i_id = GetID( p_input, p_data ); vlc_mutex_lock( &p_input->stream.stream_lock ); if( p_input->stream.pp_programs[0]->b_is_ok ) { /* Look only at the selected ES. */ for( i_dummy = 0; i_dummy < p_input->stream.i_selected_es_number; i_dummy++ ) { if( p_input->stream.pp_selected_es[i_dummy] != NULL && p_input->stream.pp_selected_es[i_dummy]->i_id == i_id ) { p_es = p_input->stream.pp_selected_es[i_dummy]; break; } } } else { vlc_bool_t b_auto_spawn = VLC_FALSE; stream_ps_data_t * p_demux = (stream_ps_data_t *)p_input->stream.pp_programs[0]->p_demux_data; /* Search all ES ; if not found -> AddES */ p_es = input_FindES( p_input, i_id ); if( p_es == NULL && !p_demux->b_has_PSM ) { int i_fourcc, i_cat; /* Set stream type and auto-spawn. */ if( (i_id & 0xF0) == 0xE0 ) { /* MPEG video */ i_fourcc = VLC_FOURCC('m','p','g','v'); i_cat = VIDEO_ES;#ifdef AUTO_SPAWN if( !p_input->stream.b_seekable ) b_auto_spawn = VLC_TRUE;#endif } else if( (i_id & 0xE0) == 0xC0 ) { /* MPEG audio */ i_fourcc = VLC_FOURCC('m','p','g','a'); i_cat = AUDIO_ES;#ifdef AUTO_SPAWN if( !p_input->stream.b_seekable ) if( config_GetInt( p_input, "audio-channel" ) == (i_id & 0x1F) || ( config_GetInt( p_input, "audio-channel" ) < 0 && !(i_id & 0x1F) ) ) switch( config_GetInt( p_input, "audio-type" ) ) { case -1: case REQUESTED_MPEG: b_auto_spawn = VLC_TRUE; }#endif } else if( (i_id & 0xF8FF) == 0x88BD ) { i_fourcc = VLC_FOURCC('d','t','s','b'); i_cat = AUDIO_ES;#ifdef AUTO_SPAWN if( !p_input->stream.b_seekable ) if( config_GetInt( p_input, "audio-channel" ) == ((i_id & 0x700) >> 8) || ( config_GetInt( p_input, "audio-channel" ) < 0 && !((i_id & 0x700) >> 8)) ) switch( config_GetInt( p_input, "audio-type" ) ) { case -1: case REQUESTED_DTS: b_auto_spawn = VLC_TRUE; }#endif } else if( (i_id & 0xF0FF) == 0x80BD ) { /* A52 audio (0x80->0x8F) */ i_fourcc = VLC_FOURCC('a','5','2','b'); i_cat = AUDIO_ES;#ifdef AUTO_SPAWN if( !p_input->stream.b_seekable ) if( config_GetInt( p_input, "audio-channel" ) == ((i_id & 0xF00) >> 8) || ( config_GetInt( p_input, "audio-channel" ) < 0 && !((i_id & 0xF00) >> 8)) ) switch( config_GetInt( p_input, "audio-type" ) ) { case -1: case REQUESTED_A52: b_auto_spawn = VLC_TRUE; }#endif } else if( (i_id & 0xE0FF) == 0x20BD ) { /* Subtitles video (0x20->0x3F) */ i_fourcc = VLC_FOURCC('s','p','u','b'); i_cat = SPU_ES;#ifdef AUTO_SPAWN if( !p_input->stream.b_seekable ) if( config_GetInt( p_input, "spu-channel" ) == ((i_id & 0x1F00) >> 8) ) { b_auto_spawn = VLC_TRUE; }#endif } else if( (i_id & 0xF0FF) == 0xA0BD ) { /* LPCM audio (0xA0->0xAF) */ i_fourcc = VLC_FOURCC('l','p','c','b'); i_cat = AUDIO_ES; } else if( (i_id & 0xFFFF) == 0x70BD ) { /* SVCD OGT subtitles in stream 0x070 */ i_fourcc = VLC_FOURCC('o','g','t', ' '); i_cat = SPU_ES; b_auto_spawn = VLC_TRUE; } else if( ((i_id >> 8) & 0xFF) <= 0x03 && (i_id & 0x00FF) == 0x00BD ) { /* CVD subtitles (0x00->0x03) */ i_fourcc = VLC_FOURCC('c','v','d', ' '); i_cat = SPU_ES; b_auto_spawn = VLC_TRUE; } else { i_cat = UNKNOWN_ES; i_fourcc = 0; } p_es = input_AddES( p_input, p_input->stream.pp_programs[0], i_id, i_cat, NULL, 0 ); p_es->i_stream_id = p_data->p_demux_start[3]; p_es->i_fourcc = i_fourcc; if( b_auto_spawn ) input_SelectES( p_input, p_es ); /* Tell the interface the stream has changed */ p_input->stream.b_changed = 1; } } /* stream.b_is_ok */ vlc_mutex_unlock( &p_input->stream.stream_lock ); } /* i_code > 0xBC */ return( p_es );}/***************************************************************************** * DemuxPS: first step of demultiplexing: the PS header *****************************************************************************/static void DemuxPS( input_thread_t * p_input, data_packet_t * p_data ){ uint32_t i_code; vlc_bool_t b_trash = 0; es_descriptor_t * p_es = NULL; mpeg_demux_t *p_mpeg_demux = (mpeg_demux_t *)p_input->p_private; i_code = ((uint32_t)p_data->p_demux_start[0] << 24) | ((uint32_t)p_data->p_demux_start[1] << 16) | ((uint32_t)p_data->p_demux_start[2] << 8) | p_data->p_demux_start[3]; if( i_code <= 0x1BC ) { switch( i_code ) { case 0x1BA: /* PACK_START_CODE */ { /* Read the SCR. */ mtime_t scr_time; uint32_t i_mux_rate; if( (p_data->p_demux_start[4] & 0xC0) == 0x40 ) { /* MPEG-2 */ byte_t p_header[14]; byte_t * p_byte; p_byte = p_data->p_demux_start; if( MoveChunk( p_header, &p_data, &p_byte, 14 ) != 14 ) { msg_Warn( p_input, "packet too short to have a header" ); b_trash = 1; break; } scr_time = ((mtime_t)(p_header[4] & 0x38) << 27) | ((mtime_t)(U32_AT(p_header + 4) & 0x03FFF800) << 4) | ((( ((mtime_t)U16_AT(p_header + 6) << 16) | (mtime_t)U16_AT(p_header + 8) ) & 0x03FFF800) >> 11); /* mux_rate */ i_mux_rate = ((uint32_t)U16_AT(p_header + 10) << 6) | (p_header[12] >> 2); /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME * This is the biggest kludge ever ! * I don't know what's wrong with mux_rate calculation * but this heuristic works well : */ i_mux_rate <<= 1; i_mux_rate /= 3; } else { /* MPEG-1 SCR is like PTS. */ byte_t p_header[12]; byte_t * p_byte; p_byte = p_data->p_demux_start; if( MoveChunk( p_header, &p_data, &p_byte, 12 ) != 12 ) { msg_Warn( p_input, "packet too short to have a header" ); b_trash = 1; break; } scr_time = ((mtime_t)(p_header[4] & 0x0E) << 29) | (((mtime_t)U32_AT(p_header + 4) & 0xFFFE00) << 6) | ((mtime_t)p_header[7] << 7) | ((mtime_t)p_header[8] >> 1); /* mux_rate */ i_mux_rate = (U32_AT(p_header + 8) & 0x7FFFFE) >> 1; } p_mpeg_demux->cur_scr_time = scr_time; p_mpeg_demux->i_cur_mux_rate = i_mux_rate; b_trash = 1; } break; case 0x1BB: /* SYSTEM_START_CODE */ b_trash = 1; /* Nothing interesting */ break; case 0x1BC: /* PROGRAM_STREAM_MAP_CODE */ DecodePSM( p_input, p_data ); b_trash = 1; break; case 0x1B9: /* PROGRAM_END_CODE */ b_trash = 1; break; default: /* This should not happen */ b_trash = 1; msg_Warn( p_input, "unwanted packet received " "with startcode 0x%.8x", i_code ); } } else { p_es = ParsePS( p_input, p_data ); /* Call the pace control. * FIXME: see hack note about cur_scr_time in system.h. */ if( p_mpeg_demux->cur_scr_time != -1 )
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?