📄 ogg.c
字号:
sout_input_t *p_input = p_mux->pp_inputs[i]; ogg_stream_t *p_stream = (ogg_stream_t*)p_input->p_sys; if( p_stream->i_fourcc == VLC_FOURCC( 'v', 'o', 'r', 'b' ) || p_stream->i_fourcc == VLC_FOURCC( 's', 'p', 'x', ' ' ) || p_stream->i_fourcc == VLC_FOURCC( 't', 'h', 'e', 'o' ) ) { /* Special case, headers are already there in the incoming stream. * We need to gather them an mark them as headers. */ int j = 2; if( p_stream->i_fourcc == VLC_FOURCC( 's', 'p', 'x', ' ' ) ) j = 1; p_extra = p_input->p_fmt->p_extra; i_extra = p_input->p_fmt->i_extra; /* Skip 1 header */ op.bytes = *(p_extra++) << 8; op.bytes |= (*(p_extra++) & 0xFF); op.packet = p_extra; p_extra += op.bytes; i_extra -= (op.bytes + 2); while( j-- ) { op.bytes = *(p_extra++) << 8; op.bytes |= (*(p_extra++) & 0xFF); op.packet = p_extra; p_extra += op.bytes; i_extra -= (op.bytes + 2); if( i_extra < 0 ) { msg_Err( p_mux, "header data corrupted"); op.bytes += i_extra; } op.b_o_s = 0; op.e_o_s = 0; op.granulepos = 0; op.packetno = p_stream->i_packet_no++; ogg_stream_packetin( &p_stream->os, &op ); p_og = OggStreamFlush( p_mux, &p_stream->os, 0 ); block_ChainAppend( &p_hdr, p_og ); } } else if( p_stream->i_fourcc != VLC_FOURCC( 'f', 'l', 'a', 'c' ) ) { uint8_t com[128]; int i_com; /* comment */ com[0] = PACKET_TYPE_COMMENT; i_com = snprintf( &com[1], 128, PACKAGE_VERSION" stream output" ) + 1; op.packet = com; op.bytes = i_com; op.b_o_s = 0; op.e_o_s = 0; op.granulepos = 0; op.packetno = p_stream->i_packet_no++; ogg_stream_packetin( &p_stream->os, &op ); p_og = OggStreamFlush( p_mux, &p_stream->os, 0 ); block_ChainAppend( &p_hdr, p_og ); } /* Special case for mp4v and flac */ if( ( p_stream->i_fourcc == VLC_FOURCC( 'm', 'p', '4', 'v' ) || p_stream->i_fourcc == VLC_FOURCC( 'f', 'l', 'a', 'c' ) ) && p_input->p_fmt->i_extra ) { /* Send a packet with the VOL data for mp4v * or STREAMINFO for flac */ msg_Dbg( p_mux, "writing extra data" ); op.bytes = p_input->p_fmt->i_extra; op.packet = p_input->p_fmt->p_extra; if( p_stream->i_fourcc == VLC_FOURCC( 'f', 'l', 'a', 'c' ) ) { /* Skip the flac stream marker */ op.bytes -= 4; op.packet+= 4; } op.b_o_s = 0; op.e_o_s = 0; op.granulepos = 0; op.packetno = p_stream->i_packet_no++; ogg_stream_packetin( &p_stream->os, &op ); p_og = OggStreamFlush( p_mux, &p_stream->os, 0 ); block_ChainAppend( &p_hdr, p_og ); } } /* set HEADER flag */ for( p_og = p_hdr; p_og != NULL; p_og = p_og->p_next ) { p_og->i_flags |= BLOCK_FLAG_HEADER; } return p_hdr;}static block_t *OggCreateFooter( sout_mux_t *p_mux, mtime_t i_dts ){ sout_mux_sys_t *p_sys = p_mux->p_sys; block_t *p_hdr = NULL; block_t *p_og; ogg_packet op; int i; /* flush all remaining data */ for( i = 0; i < p_mux->i_nb_inputs; i++ ) { ogg_stream_t *p_stream = p_mux->pp_inputs[i]->p_sys; /* skip newly added streams */ if( p_stream->b_new ) continue; if( ( p_og = OggStreamFlush( p_mux, &p_stream->os, 0 ) ) ) { OggSetDate( p_og, p_stream->i_dts, p_stream->i_length ); sout_AccessOutWrite( p_mux->p_access, p_og ); } } /* Write eos packets for each stream. */ for( i = 0; i < p_mux->i_nb_inputs; i++ ) { ogg_stream_t *p_stream = p_mux->pp_inputs[i]->p_sys; /* skip newly added streams */ if( p_stream->b_new ) continue; op.packet = NULL; op.bytes = 0; op.b_o_s = 0; op.e_o_s = 1; op.granulepos = -1; op.packetno = p_stream->i_packet_no++; ogg_stream_packetin( &p_stream->os, &op ); p_og = OggStreamFlush( p_mux, &p_stream->os, 0 ); block_ChainAppend( &p_hdr, p_og ); ogg_stream_clear( &p_stream->os ); } for( i = 0; i < p_sys->i_del_streams; i++ ) { op.packet = NULL; op.bytes = 0; op.b_o_s = 0; op.e_o_s = 1; op.granulepos = -1; op.packetno = p_sys->pp_del_streams[i]->i_packet_no++; ogg_stream_packetin( &p_sys->pp_del_streams[i]->os, &op ); p_og = OggStreamFlush( p_mux, &p_sys->pp_del_streams[i]->os, 0 ); block_ChainAppend( &p_hdr, p_og ); ogg_stream_clear( &p_sys->pp_del_streams[i]->os ); } return p_hdr;}static void OggSetDate( block_t *p_og, mtime_t i_dts, mtime_t i_length ){ int i_count; block_t *p_tmp; mtime_t i_delta; for( p_tmp = p_og, i_count = 0; p_tmp != NULL; p_tmp = p_tmp->p_next ) { i_count++; } i_delta = i_length / i_count; for( p_tmp = p_og; p_tmp != NULL; p_tmp = p_tmp->p_next ) { p_tmp->i_dts = i_dts; p_tmp->i_length = i_delta; i_dts += i_delta; }}/***************************************************************************** * Mux: multiplex available data in input fifos into the Ogg bitstream *****************************************************************************/static int Mux( sout_mux_t *p_mux ){ sout_mux_sys_t *p_sys = p_mux->p_sys; block_t *p_og = NULL; int i_stream; mtime_t i_dts; if( p_sys->i_add_streams || p_sys->i_del_streams ) { /* Open new ogg stream */ if( MuxGetStream( p_mux, &i_stream, &i_dts) < 0 ) { msg_Dbg( p_mux, "waiting for data..." ); return VLC_SUCCESS; } if( p_sys->i_streams ) { /* Close current ogg stream */ int i; msg_Dbg( p_mux, "writing footer" ); block_ChainAppend( &p_og, OggCreateFooter( p_mux, 0 ) ); /* Remove deleted logical streams */ for( i = 0; i < p_sys->i_del_streams; i++ ) { FREE( p_sys->pp_del_streams[i]->p_oggds_header ); FREE( p_sys->pp_del_streams[i] ); } FREE( p_sys->pp_del_streams ); p_sys->i_streams = 0; } msg_Dbg( p_mux, "writing header" ); p_sys->i_start_dts = i_dts; p_sys->i_streams = p_mux->i_nb_inputs; p_sys->i_del_streams = 0; p_sys->i_add_streams = 0; block_ChainAppend( &p_og, OggCreateHeader( p_mux, i_dts ) ); /* Write header and/or footer */ OggSetDate( p_og, i_dts, 0 ); sout_AccessOutWrite( p_mux->p_access, p_og ); p_og = NULL; } for( ;; ) { if( MuxGetStream( p_mux, &i_stream, 0 ) < 0 ) return VLC_SUCCESS; MuxBlock( p_mux, p_mux->pp_inputs[i_stream] ); } return VLC_SUCCESS;}static int MuxBlock( sout_mux_t *p_mux, sout_input_t *p_input ){ sout_mux_sys_t *p_sys = p_mux->p_sys; ogg_stream_t *p_stream = (ogg_stream_t*)p_input->p_sys; block_t *p_data = block_FifoGet( p_input->p_fifo ); block_t *p_og = NULL; ogg_packet op; if( p_stream->i_fourcc != VLC_FOURCC( 'v', 'o', 'r', 'b' ) && p_stream->i_fourcc != VLC_FOURCC( 'f', 'l', 'a', 'c' ) && p_stream->i_fourcc != VLC_FOURCC( 's', 'p', 'x', ' ' ) && p_stream->i_fourcc != VLC_FOURCC( 't', 'h', 'e', 'o' ) ) { p_data = block_Realloc( p_data, 1, p_data->i_buffer ); p_data->p_buffer[0] = PACKET_IS_SYNCPOINT; // FIXME } op.packet = p_data->p_buffer; op.bytes = p_data->i_buffer; op.b_o_s = 0; op.e_o_s = 0; op.packetno = p_stream->i_packet_no++; if( p_stream->i_cat == AUDIO_ES ) { if( p_stream->i_fourcc == VLC_FOURCC( 'v', 'o', 'r', 'b' ) || p_stream->i_fourcc == VLC_FOURCC( 'f', 'l', 'a', 'c' ) || p_stream->i_fourcc == VLC_FOURCC( 's', 'p', 'x', ' ' ) ) { /* number of sample from begining + current packet */ op.granulepos = ( p_data->i_dts - p_sys->i_start_dts + p_data->i_length ) * (mtime_t)p_input->p_fmt->audio.i_rate / I64C(1000000); } else if( p_stream->p_oggds_header ) { /* number of sample from begining */ op.granulepos = ( p_data->i_dts - p_sys->i_start_dts ) * p_stream->p_oggds_header->i_samples_per_unit / I64C(1000000); } } else if( p_stream->i_cat == VIDEO_ES ) { if( p_stream->i_fourcc == VLC_FOURCC( 't', 'h', 'e', 'o' ) ) { /* FIXME, we assume only keyframes */ op.granulepos = ( ( p_data->i_dts - p_sys->i_start_dts ) * p_input->p_fmt->video.i_frame_rate / p_input->p_fmt->video.i_frame_rate_base / I64C(1000000) ) << p_stream->i_keyframe_granule_shift; } else if( p_stream->p_oggds_header ) op.granulepos = ( p_data->i_dts - p_sys->i_start_dts ) * I64C(10) / p_stream->p_oggds_header->i_time_unit; } else if( p_stream->i_cat == SPU_ES ) { /* granulepos is in milisec */ op.granulepos = ( p_data->i_dts - p_sys->i_start_dts ) / 1000; } ogg_stream_packetin( &p_stream->os, &op ); if( p_stream->i_cat == SPU_ES || p_stream->i_fourcc == VLC_FOURCC( 's', 'p', 'x', ' ' ) ) { /* Subtitles or Speex packets are quite small so they * need to be flushed to be sent on time */ p_og = OggStreamFlush( p_mux, &p_stream->os, p_data->i_dts ); } else { p_og = OggStreamPageOut( p_mux, &p_stream->os, p_data->i_dts ); } if( p_og ) { OggSetDate( p_og, p_stream->i_dts, p_stream->i_length ); p_stream->i_dts = -1; p_stream->i_length = 0; sout_AccessOutWrite( p_mux->p_access, p_og ); } else { if( p_stream->i_dts < 0 ) { p_stream->i_dts = p_data->i_dts; } p_stream->i_length += p_data->i_length; } block_Release( p_data ); return VLC_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -