📄 input_file.c
字号:
/***************************************************************************** * input_file.c: functions to read from a file ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN * * Authors: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include "defs.h"#include <stdio.h>#include <unistd.h> /* close() */#include <sys/types.h> /* on BSD, uio.h needs types.h */#include <sys/uio.h> /* "input.h" */#include <sys/stat.h> /* fstat, off_t ... */#include <netinet/in.h> /* ntohl() */#include <fcntl.h> /* open() */#include <malloc.h> /* malloc, read ... */#include <string.h>#include "config.h"#include "common.h"#include "threads.h"#include "mtime.h"#include "intf_msg.h"#include "main.h"#include "input.h"#include "input_ps.h"#include "input_file.h"#define BUF_SIZE (797*3)#define PS_METHOD 1#define TS_METHOD 2#define TS_PACKET_SIZE 188#define TS_IN_UDP 7#define MAX_AUDIO_CHANNEL 15#define MAX_SUBTITLES_CHANNEL 31#define NO_SUBTITLES 255#define PS_BUFFER_SIZE 16384#define NO_PES 0#define AUDIO_PES 1#define VIDEO_PES 2#define AC3_PES 3#define SUBTITLE_PES 4#define LPCM_PES 5#define PRIVATE_PES 6#define UNKNOWN_PES 12#define PCR_PID 0x20 /* 0x20 == first video stream * 0x40 == first audio stream */typedef u8 file_ts_packet[TS_PACKET_SIZE];typedef file_ts_packet udp_packet[TS_IN_UDP];typedef struct synchro_struct{ mtime_t delta_clock; mtime_t slope; mtime_t last_pcr_time; file_ts_packet *last_pcr;} synchro_t;typedef struct in_data_s{ int start, end; vlc_mutex_t lock; vlc_cond_t notfull; vlc_cond_t notempty; udp_packet buf[BUF_SIZE+1];} in_data_t;typedef struct own_pcr_s{ int start, end; vlc_mutex_t lock; file_ts_packet *buf[(BUF_SIZE+1)*TS_IN_UDP+1];} own_pcr_t;typedef struct options_s{ unsigned int pcr_pid; u8 i_file_type; int in; char **playlist; int i_list_index;} options_t;typedef struct s_ps{ unsigned int pat_counter; unsigned int pmt_counter; /* * These 3 parameters are passed * as command line arguments */ unsigned int audio_channel; unsigned int subtitles_channel; unsigned int audio_type; /* * 16 audio mpeg streams * 16 audio AV3 streams * 16 video mpeg streams * 32 subtitle streams */ unsigned int media_counter[0x100]; unsigned int association_table[0x100]; unsigned int found_streams; unsigned int found_pts; unsigned int ts_to_write; unsigned int ts_written; unsigned int sent_ts; unsigned char *ps_data; unsigned char *ps_end; unsigned char *ps_buffer; unsigned int pes_id; unsigned int private_id; unsigned int has_pts; unsigned int pcr_pid; unsigned int pes_type; unsigned int pes_size; unsigned int to_skip; unsigned int offset;} ps_t;typedef struct input_file_s{ boolean_t b_die; /* b_die flag for the disk thread */ vlc_thread_t disk_thread; synchro_t synchro; ps_t ps; in_data_t in_data; options_t options; own_pcr_t own_pcr;} input_file_t;/* local prototypes */void ps_fill( input_file_t * p_if, boolean_t wait );ssize_t safe_read(options_t *p_options, unsigned char *buf, int count);void input_DiskThread( input_file_t * p_if );int init_synchro( input_file_t * p_if );input_file_t input_file;/****************************************************************************** * ConvertPCRTime : extracts and converts the PCR time in microseconds ******************************************************************************/s64 ConvertPCRTime(file_ts_packet *pcr_buff){ return( (((((s64)U32_AT(((u8*)pcr_buff)+6)) << 1) | (((u8*)pcr_buff)[10] >> 7)) * 300) / 27 );}/****************************************************************************** * wait_a_moment : Compute how long we must wait before sending a TS packet ******************************************************************************/static void wait_a_moment( input_file_t * p_if, file_ts_packet *ts){ synchro_t * p_synchro = &input_file.synchro; static int retard_count = 0; static s64 wait_max = 0; s64 sendtime; /* the date at which the TS packet should be sent */ s64 wait; sendtime = p_synchro->last_pcr_time + p_synchro->delta_clock + p_synchro->slope * ((ts - p_synchro->last_pcr + (BUF_SIZE+1)*TS_IN_UDP) % ((BUF_SIZE+1)*TS_IN_UDP)); wait = sendtime - mdate(); if( wait > 0 ) { retard_count = 0; if(wait > 100000) { intf_DbgMsg( "input warning: wait time may be too long : %Ld\n", wait ); return; } msleep( wait ); } else { if( wait < wait_max ) { wait_max = wait; } retard_count++; if( retard_count == 16 ) { retard_count = 0; } }}/****************************************************************************** * adjust : Adjust the encoder clock & remove the PCR from own_pcr ******************************************************************************/static void adjust( input_file_t * p_if, file_ts_packet *ts ){ synchro_t * p_synchro = &p_if->synchro; own_pcr_t * p_own_pcr = &p_if->own_pcr; file_ts_packet *next_pcr; int no_discontinuity = 1; if( ((u8*)ts)[5] & 0x80 ) { /* There is a discontinuity - I recalculate the delta */ p_synchro->delta_clock = mdate() - ConvertPCRTime(ts); intf_DbgMsg( "input warning: clock discontinuity\n" ); no_discontinuity = 0; } else { p_synchro->last_pcr = ts; p_synchro->last_pcr_time = ConvertPCRTime( ts ); } vlc_mutex_lock(&p_own_pcr->lock); p_own_pcr->start++; p_own_pcr->start %= (BUF_SIZE+1)*TS_IN_UDP+1; /* If we have 2 consecutiv PCR, we can reevaluate slope */ if( (p_own_pcr->start != p_own_pcr->end) && no_discontinuity && !((((u8*) next_pcr = p_own_pcr->buf[p_own_pcr->start]))[5] & 0x80)) { s64 current_pcr_time = ConvertPCRTime(ts); s64 next_pcr_time = ConvertPCRTime(next_pcr); if( (next_pcr_time - current_pcr_time < 0) || (next_pcr_time - current_pcr_time > 700000)) { intf_DbgMsg( "input warning: possible discontinuity\n" ); p_synchro->delta_clock = mdate() - next_pcr_time; } else { p_synchro->slope = (next_pcr_time - current_pcr_time) / ((next_pcr - ts + (BUF_SIZE+1)*TS_IN_UDP) % ((BUF_SIZE+1)*TS_IN_UDP)); } } vlc_mutex_unlock(&p_own_pcr->lock);}/***************************************************************************** * file_next : Opens the next available file *****************************************************************************/int file_next( options_t *options ){ /* the check for index == 0 should be done _before_ */ options->i_list_index--; if( options->in != -1 ) { close( options->in ); } if( !strcmp( options->playlist[options->i_list_index], "-" ) ) { /* read stdin */ return ( options->in = 0 ); } else { /* read the actual file */ fprintf( stderr, "Playing file %s\n", options->playlist[options->i_list_index] ); return ( options->in = open( options->playlist[options->i_list_index], O_RDONLY | O_NDELAY ) ); }}/***************************************************************************** * safe_read : Buffered reading method *****************************************************************************/ssize_t safe_read( options_t *options, unsigned char *buf, int count ){ int ret, cnt=0; while( cnt < count ) { ret = read( options->in, buf + cnt, count - cnt ); if( ret < 0 ) return ret; if( ret == 0 ) { /* zero means end of file */ if( options->i_list_index ) { file_next( options ); } else { break; } } cnt += ret; } return cnt;}/****************************************************************************** * keep_pcr : Put a TS packet in the fifo if it owns a PCR ******************************************************************************/int keep_pcr(int pcr_pid, file_ts_packet *ts){ own_pcr_t * p_own_pcr = &input_file.own_pcr;#define p ((u8 *)ts) if ((p[3] & 0x20) && p[4] && (p[5] & 0x10) && ((((p[1]<<8)+p[2]) & 0x1FFF) == pcr_pid)) { /* adaptation_field_control is set, adaptation_field_lenght is not 0, * PCR_flag is set, pid == pcr_pid */ vlc_mutex_lock(&p_own_pcr->lock); p_own_pcr->buf[p_own_pcr->end++] = ts; p_own_pcr->end %= (BUF_SIZE+1)*TS_IN_UDP+1; vlc_mutex_unlock(&p_own_pcr->lock); return 1; } else return 0;#undef p}/****************************************************************************** * get_pid : gets a pid from a PES type ******************************************************************************/int get_pid (ps_t *p_ps){ int i, tofind, delta; char* type;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -