📄 input_file.c
字号:
if( p_ps->ps_data[0] || p_ps->ps_data[1] || (p_ps->ps_data[2] != 0x01) ) { intf_ErrMsg ( "input error: not a startcode (0x%.2x%.2x%.2x instead of 0x000001)\n", p_ps->ps_data[0], p_ps->ps_data[1], p_ps->ps_data[2] ); return -1; } p_ps->pes_type = NO_PES; p_ps->offset = 0; p_ps->pes_size = (p_ps->ps_data[4] << 8) + p_ps->ps_data[5] + 6; p_ps->has_pts = p_ps->ps_data[7] & 0xc0; } /* if the actual data we have in pes_data is not a PES, then * we read the next one. */ if( (p_ps->pes_type == NO_PES) && !p_ps->to_skip ) { p_ps->pes_id = p_ps->ps_data[3]; if (p_ps->pes_id == 0xbd) { p_ps->private_id = p_ps->ps_data[ 9 + p_ps->ps_data[8] ]; if ((p_ps->private_id & 0xf0) == 0x80) { /* flux audio ac3 */ p_ps->pes_type = AC3_PES; } else if ((p_ps->private_id & 0xf0) == 0x20) { /* subtitles */ p_ps->pes_type = SUBTITLE_PES; } else { /* unknown private data */ p_ps->pes_type = PRIVATE_PES; } } else if ((p_ps->pes_id & 0xe0) == 0xc0) { /* flux audio */ p_ps->pes_type = AUDIO_PES; //write (1, p_ps->ps_data + 9 + p_ps->ps_data[8], 2048 - (9 + p_ps->ps_data[8])); } else if ((p_ps->pes_id & 0xf0) == 0xe0) { /* flux video */ p_ps->pes_type = VIDEO_PES; } else if (p_ps->pes_id == 0xba) { p_ps->pes_type = NO_PES; p_ps->pes_size = 14; /* 8 extra characters after 0x000001ba**** */ p_ps->to_skip = 14; } else { p_ps->pes_type = UNKNOWN_PES; p_ps->to_skip = p_ps->pes_size; } } if( p_ps->to_skip ) { if( p_ps->to_skip < TS_PACKET_SIZE ) { p_ps->ps_data += p_ps->to_skip; p_ps->offset += p_ps->to_skip; p_ps->to_skip = 0; } else { p_ps->ps_data += TS_PACKET_SIZE; p_ps->offset += TS_PACKET_SIZE; p_ps->to_skip -= TS_PACKET_SIZE; } } /* now that we know what we have, we can either * write this packet's data in the buffer, skip it, * or write a PMT or PAT table and wait for the next * turn before writing the packet. */ switch (p_ps->sent_ts & 0xff) { case 0x80: write_pmt(p_ps,ts); p_ps->pmt_counter++; p_ps->ts_to_write--; p_ps->ts_written++; ts+=188; break; case 0x00: write_pat(p_ps,ts); p_ps->pat_counter++; p_ps->ts_to_write--; p_ps->ts_written++; ts+=188; break; } /* if there's still no found PCR_PID, and no PTS in this PES, we trash it */ if (!p_ps->found_pts) { if (p_ps->has_pts) { intf_Msg( "input: found a PTS, at last ...\n" ); p_ps->found_pts = 1; } else p_ps->pes_type = NO_PES; } if (p_ps->ts_to_write) { switch(p_ps->pes_type) { case VIDEO_PES: case AUDIO_PES:case SUBTITLE_PES: case AC3_PES: pid = get_pid (p_ps); write_media_ts(p_ps, ts, pid); p_ps->ts_to_write--; p_ps->ts_written++; ts+=188; p_ps->media_counter[pid]++; break; case UNKNOWN_PES: default: p_ps->pes_type = NO_PES; break; } } } //p_ps->ps_data += TS_PACKET_SIZE; return p_ps->ts_written;}/****************************************************************************** * ps_fill : Fill the data buffer with TS created from a PS file ******************************************************************************/void ps_fill( input_file_t * p_if, boolean_t wait ){ in_data_t * p_in_data = &p_if->in_data; ps_t * p_ps = &p_if->ps; int i, how_many; int pcr_flag; file_ts_packet *ts; /* How many TS packet for the next UDP packet */ how_many = TS_IN_UDP; pcr_flag = 0; /* for every single TS packet */ while( !p_if->b_die ) { /* wait until we have one free item to store the UDP packet read */ vlc_mutex_lock(&p_in_data->lock); while((p_in_data->end+BUF_SIZE+1-p_in_data->start)%(BUF_SIZE+1) == BUF_SIZE ) { /* The buffer is full */ if(wait) { vlc_cond_wait(&p_in_data->notfull, &p_in_data->lock); if( p_if->b_die ) return; } else { vlc_mutex_unlock(&p_in_data->lock); if (!pcr_flag) { intf_ErrMsg( "input error: bad PCR PID\n" ); } return; } } vlc_mutex_unlock(&p_in_data->lock); /* read a whole UDP packet from the file */ p_ps->ts_to_write = how_many; if(ps_read(&p_if->options, p_ps, ts = (file_ts_packet *)(p_in_data->buf + p_in_data->end)) != how_many) { msleep( 50000 ); /* XXX we need an INPUT_IDLE */ intf_ErrMsg( "input error: read() error\n" ); } /* Scan to mark TS packets containing a PCR */ for(i=0; i<how_many; i++, ts++) { pcr_flag |= keep_pcr(p_ps->pcr_pid, ts); } vlc_mutex_lock(&p_in_data->lock); p_in_data->end++; p_in_data->end %= BUF_SIZE+1; vlc_cond_signal(&p_in_data->notempty); vlc_mutex_unlock(&p_in_data->lock); }}int init_synchro( input_file_t * p_if ){ int i, pcr_count; int howmany = TS_IN_UDP; file_ts_packet * ts; synchro_t * p_synchro = &p_if->synchro; in_data_t * p_in_data = &p_if->in_data; own_pcr_t * p_own_pcr = &p_if->own_pcr; p_synchro->slope = 0; pcr_count = 0; /* * Initialisation of the synchro mecanism : wait for 1 PCR * to evaluate delta_clock */ while( 1 ) { vlc_mutex_lock( &p_in_data->lock ); while( p_in_data->end == p_in_data->start ) { vlc_cond_wait(&p_in_data->notempty, &p_in_data->lock); } /* if( p_in_data->end == p_in_data->start ) { intf_ErrMsg( "input error: init_synchro error, not enough PCR found\n" ); return( -1 ); } */ vlc_mutex_unlock( &p_in_data->lock ); ts = (file_ts_packet*)(p_in_data->buf + p_in_data->start); for( i=0 ; i < howmany ; i++, ts++ ) { if( ts == p_own_pcr->buf[p_own_pcr->start] && !(((u8*)ts)[5] & 0x80) ) { p_synchro->last_pcr = ts; p_synchro->last_pcr_time = ConvertPCRTime( ts ); p_synchro->delta_clock = mdate() - ConvertPCRTime(ts); adjust( p_if, ts ); pcr_count++; } } vlc_mutex_lock( &p_in_data->lock ); p_in_data->start++; p_in_data->start %= BUF_SIZE + 1; vlc_cond_signal( &p_in_data->notfull ); vlc_mutex_unlock( &p_in_data->lock ); if(pcr_count) break; } return( 0 );}/***************************************************************************** * input_DiskThread : main thread *****************************************************************************/void input_DiskThread( input_file_t * p_if ){ ps_fill( p_if, 1 ); vlc_thread_exit();}/***************************************************************************** * input_FileOpen : open a file descriptor *****************************************************************************/int input_FileOpen( input_thread_t *p_input ){ options_t * p_options = &input_file.options; p_options->in = -1; p_options->playlist = (char **)p_input->p_source; p_options->i_list_index = p_input->i_port; if( file_next( p_options ) < 0 ) { intf_ErrMsg( "input error: cannot open the file %s", p_input->p_source ); } input_file.b_die = 0; safe_read( p_options, &p_options->i_file_type, 1 ); switch( p_options->i_file_type ) { case 0x00: p_options->pcr_pid = PCR_PID; ps_thread( &input_file ); break; case 0x47: intf_ErrMsg( "input error: ts files are not currently supported\n" ); return( 1 ); default: intf_ErrMsg( "input error: cannot determine stream type\n" ); return( 1 ); } return( 0 );}/***************************************************************************** * input_FileRead : read from a file *****************************************************************************/int input_FileRead( input_thread_t *p_input, const struct iovec *p_vector, size_t i_count ){ in_data_t * p_in_data = &input_file.in_data; synchro_t * p_synchro = &input_file.synchro; own_pcr_t * p_own_pcr = &input_file.own_pcr; int i, howmany; file_ts_packet * ts; /* XXX XXX XXX * End condition not verified, should put a flag in ps_fill */ howmany = TS_IN_UDP; vlc_mutex_lock( &p_in_data->lock ); while( p_in_data->end == p_in_data->start ) { if( !input_file.b_die ) vlc_cond_wait( &p_in_data->notempty, &p_in_data->lock ); } vlc_mutex_unlock( &p_in_data->lock ); ts = (file_ts_packet*)(p_in_data->buf + p_in_data->start); for( i=0 ; i < howmany ; i++, ts++ ) { if( p_synchro->slope && (i == howmany-1) ) { wait_a_moment( &input_file, ts ); } if( ts == p_own_pcr->buf[p_own_pcr->start] ) { /* the TS packet contains a PCR, so we try to adjust the clock */ adjust( &input_file, ts ); } } for( i=0 ; i<howmany ; i++ ) { memcpy( p_vector[i].iov_base, (char*)(ts - howmany + i), p_vector[i].iov_len ); } vlc_mutex_lock(&p_in_data->lock); p_in_data->start++; p_in_data->start %= BUF_SIZE + 1; vlc_cond_signal(&p_in_data->notfull); vlc_mutex_unlock(&p_in_data->lock); return( 188*howmany );}/***************************************************************************** * input_FileClose : close a file descriptor *****************************************************************************/void input_FileClose( input_thread_t *p_input ){ input_file.b_die = 1; vlc_cond_signal( &input_file.in_data.notfull ); vlc_thread_join( input_file.disk_thread ); close( input_file.options.in );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -