📄 ts.c
字号:
if ( ( i_spu_delay >= INT64_C(100000000) ) || ( i_spu_delay < INT64_C(10000) ) ) { BufferChainClean( &p_stream->chain_pes ); p_stream->i_pes_dts = 0; p_stream->i_pes_used = 0; p_stream->i_pes_length = 0; continue; } } } b_ok = false; if( p_stream == p_pcr_stream || p_sys->b_data_alignment || p_input->p_fmt->i_codec != VLC_FOURCC('m', 'p', 'g', 'a') ) { p_data = block_FifoGet( p_input->p_fifo ); if( p_input->p_fmt->i_codec == VLC_FOURCC('m', 'p', '4', 'a' ) ) p_data = Add_ADTS( p_data, p_input->p_fmt ); } else p_data = FixPES( p_mux, p_input->p_fifo ); if( block_FifoCount( p_input->p_fifo ) > 0 && p_input->p_fmt->i_cat != SPU_ES ) { block_t *p_next = block_FifoShow( p_input->p_fifo ); p_data->i_length = p_next->i_dts - p_data->i_dts; } else if( p_input->p_fmt->i_codec != VLC_FOURCC('s', 'u', 'b', 't' ) ) p_data->i_length = 1000; if( ( p_pcr_stream->i_pes_dts > 0 && p_data->i_dts - 10000000 > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length ) || p_data->i_dts < p_stream->i_pes_dts || ( p_stream->i_pes_dts > 0 && p_input->p_fmt->i_cat != SPU_ES && p_data->i_dts - 10000000 > p_stream->i_pes_dts + p_stream->i_pes_length ) ) { msg_Warn( p_mux, "packet with too strange dts " "(dts=%"PRId64",old=%"PRId64",pcr=%"PRId64")", p_data->i_dts, p_stream->i_pes_dts, p_pcr_stream->i_pes_dts ); block_Release( p_data ); BufferChainClean( &p_stream->chain_pes ); p_stream->i_pes_dts = 0; p_stream->i_pes_used = 0; p_stream->i_pes_length = 0; if( p_input->p_fmt->i_cat != SPU_ES ) { BufferChainClean( &p_pcr_stream->chain_pes ); p_pcr_stream->i_pes_dts = 0; p_pcr_stream->i_pes_used = 0; p_pcr_stream->i_pes_length = 0; } } else { int i_header_size = 0; int b_data_alignment = 0; if( p_input->p_fmt->i_cat == SPU_ES ) { if( p_input->p_fmt->i_codec == VLC_FOURCC('s','u','b','t') ) { /* Prepend header */ p_data = block_Realloc( p_data, 2, p_data->i_buffer ); p_data->p_buffer[0] = ( (p_data->i_buffer - 2) >> 8) & 0xff; p_data->p_buffer[1] = ( (p_data->i_buffer - 2) ) & 0xff; /* remove trailling \0 if any */ if( p_data->i_buffer > 2 && p_data->p_buffer[p_data->i_buffer -1] == '\0' ) p_data->i_buffer--; /* Append a empty sub (sub text only) */ if( p_data->i_length > 0 && !( p_data->i_buffer == 1 && *p_data->p_buffer == ' ' ) ) { block_t *p_spu = block_New( p_mux, 3 ); p_spu->i_dts = p_spu->i_pts = p_data->i_dts + p_data->i_length; p_spu->i_length = 1000; p_spu->p_buffer[0] = 0; p_spu->p_buffer[1] = 1; p_spu->p_buffer[2] = ' '; EStoPES( p_mux->p_sout, &p_spu, p_spu, p_input->p_fmt, p_stream->i_stream_id, 1, 0, 0, 0 ); p_data->p_next = p_spu; } } else if( p_input->p_fmt->i_codec == VLC_FOURCC('t','e','l','x') ) { /* EN 300 472 */ i_header_size = 0x24; b_data_alignment = 1; } else if( p_input->p_fmt->i_codec == VLC_FOURCC('d','v','b','s') ) { /* EN 300 743 */ b_data_alignment = 1; } } else if( p_data->i_length < 0 || p_data->i_length > 2000000 ) { /* FIXME choose a better value, but anyway we * should never have to do that */ p_data->i_length = 1000; } p_stream->i_pes_length += p_data->i_length; if( p_stream->i_pes_dts == 0 ) { p_stream->i_pes_dts = p_data->i_dts; } /* Convert to pes */ if( p_stream->i_stream_id == 0xa0 && p_data->i_pts <= 0 ) { /* XXX yes I know, it's awful, but it's needed, * so don't remove it ... */ p_data->i_pts = p_data->i_dts; } EStoPES ( p_mux->p_sout, &p_data, p_data, p_input->p_fmt, p_stream->i_stream_id, 1, b_data_alignment, i_header_size, 0 ); BufferChainAppend( &p_stream->chain_pes, p_data ); if( p_sys->b_use_key_frames && p_stream == p_pcr_stream && (p_data->i_flags & BLOCK_FLAG_TYPE_I) && !(p_data->i_flags & BLOCK_FLAG_NO_KEYFRAME) && (p_stream->i_pes_length > 400000) ) { i_shaping_delay = p_stream->i_pes_length; p_stream->b_key_frame = 1; } } } } if( b_ok ) { break; } } /* save */ i_pcr_dts = p_pcr_stream->i_pes_dts; i_pcr_length = p_pcr_stream->i_pes_length; p_pcr_stream->b_key_frame = 0; /* msg_Dbg( p_mux, "starting muxing %lldms", i_pcr_length / 1000 ); */ /* 2: calculate non accurate total size of muxed ts */ i_packet_count = 0; for( i = 0; i < p_mux->i_nb_inputs; i++ ) { ts_stream_t *p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys; block_t *p_pes; /* False for pcr stream but it will be enough to do PCR algo */ for( p_pes = p_stream->chain_pes.p_first; p_pes != NULL; p_pes = p_pes->p_next ) { int i_size = p_pes->i_buffer; if( p_pes->i_dts + p_pes->i_length > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length ) { mtime_t i_frag = p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length - p_pes->i_dts; if( i_frag < 0 ) { /* Next stream */ break; } i_size = p_pes->i_buffer * i_frag / p_pes->i_length; } i_packet_count += ( i_size + 183 ) / 184; } } /* add overhead for PCR (not really exact) */ i_packet_count += (8 * i_pcr_length / p_sys->i_pcr_delay + 175) / 176; /* 3: mux PES into TS */ BufferChainInit( &chain_ts ); /* append PAT/PMT -> FIXME with big pcr delay it won't have enough pat/pmt */ GetPAT( p_mux, &chain_ts ); GetPMT( p_mux, &chain_ts ); i_packet_pos = 0; i_packet_count += chain_ts.i_depth; /* msg_Dbg( p_mux, "estimated pck=%d", i_packet_count ); */ for( ;; ) { int i_stream; mtime_t i_dts; ts_stream_t *p_stream; sout_input_t *p_input; block_t *p_ts; bool b_pcr; /* Select stream (lowest dts) */ for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ ) { p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys; if( p_stream->i_pes_dts == 0 ) { continue; } if( i_stream == -1 || p_stream->i_pes_dts < i_dts ) { i_stream = i; i_dts = p_stream->i_pes_dts; } } if( i_stream == -1 || i_dts > i_pcr_dts + i_pcr_length ) { break; } p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys; p_input = p_mux->pp_inputs[i_stream]; /* do we need to issue pcr */ b_pcr = false; if( p_stream == p_pcr_stream && i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count >= p_sys->i_pcr + p_sys->i_pcr_delay ) { b_pcr = true; p_sys->i_pcr = i_pcr_dts + i_packet_pos * i_pcr_length / i_packet_count; } /* Build the TS packet */ p_ts = TSNew( p_mux, p_stream, b_pcr ); if( p_sys->csa != NULL && (p_input->p_fmt->i_cat != AUDIO_ES || p_sys->b_crypt_audio) && (p_input->p_fmt->i_cat != VIDEO_ES || p_sys->b_crypt_video) ) { p_ts->i_flags |= BLOCK_FLAG_SCRAMBLED; } i_packet_pos++; /* */ BufferChainAppend( &chain_ts, p_ts ); } /* 4: date and send */ TSSchedule( p_mux, &chain_ts, i_pcr_length, i_pcr_dts ); }}#define STD_PES_PAYLOAD 170static block_t *FixPES( sout_mux_t *p_mux, block_fifo_t *p_fifo ){ block_t *p_data; size_t i_size; p_data = block_FifoShow( p_fifo ); i_size = p_data->i_buffer; if( i_size == STD_PES_PAYLOAD ) { return block_FifoGet( p_fifo ); } else if( i_size > STD_PES_PAYLOAD ) { block_t *p_new = block_New( p_mux, STD_PES_PAYLOAD ); vlc_memcpy( p_new->p_buffer, p_data->p_buffer, STD_PES_PAYLOAD ); p_new->i_pts = p_data->i_pts; p_new->i_dts = p_data->i_dts; p_new->i_length = p_data->i_length * STD_PES_PAYLOAD / p_data->i_buffer; p_data->i_buffer -= STD_PES_PAYLOAD; p_data->p_buffer += STD_PES_PAYLOAD; p_data->i_pts += p_new->i_length; p_data->i_dts += p_new->i_length; p_data->i_length -= p_new->i_length; p_data->i_flags |= BLOCK_FLAG_NO_KEYFRAME; return p_new; } else { block_t *p_next; int i_copy; p_data = block_FifoGet( p_fifo ); p_data = block_Realloc( p_data, 0, STD_PES_PAYLOAD ); p_next = block_FifoShow( p_fifo ); if ( p_data->i_flags & BLOCK_FLAG_NO_KEYFRAME ) { p_data->i_flags &= ~BLOCK_FLAG_NO_KEYFRAME; p_data->i_pts = p_next->i_pts; p_data->i_dts = p_next->i_dts; } i_copy = __MIN( STD_PES_PAYLOAD - i_size, p_next->i_buffer ); vlc_memcpy( &p_data->p_buffer[i_size], p_next->p_buffer, i_copy ); p_next->i_pts += p_next->i_length * i_copy / p_next->i_buffer; p_next->i_dts += p_next->i_length * i_copy / p_next->i_buffer; p_next->i_length -= p_next->i_length * i_copy / p_next->i_buffer; p_next->i_buffer -= i_copy; p_next->p_buffer += i_copy; p_next->i_flags |= BLOCK_FLAG_NO_KEYFRAME; if( !p_next->i_buffer ) { p_next = block_FifoGet( p_fifo ); block_Release( p_next ); } return p_data; }}static block_t *Add_ADTS( block_t *p_data, es_format_t *p_fmt ){ uint8_t *p_extra = p_fmt->p_extra; if( !p_data || p_fmt->i_extra < 2 || !p_extra ) return p_data; /* no data to construct the headers */ int i_index = ( (p_extra[0] << 1) | (p_extra[1] >> 7) ) & 0x0f; int i_profile = (p_extra[0] >> 3) - 1; /* i_profile < 4 */ if( i_index == 0x0f && p_fmt->i_extra < 5 ) return p_data; /* not enough data */ int i_channels = (p_extra[i_index == 0x0f ? 4 : 1] >> 3) & 0x0f;#define ADTS_HEADER_SIZE 7 /* CRC needs 2 more bytes */ /* keep a copy in case block_Realloc() fails */ block_t *p_bak_block = block_Duplicate( p_data ); if( !p_bak_block ) /* OOM, block_Realloc() is likely to lose our block */ return p_data; /* the frame isn't correct but that's the best we have */ block_t *p_new_block = block_Realloc( p_data, ADTS_HEADER_SIZE, p_data->i_buffer ); if( !p_new_block ) return p_bak_bl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -