📄 ogg.c
字号:
switch( p_stream->i_fourcc ) { case VLC_FOURCC( 'm', 'p', 'g', 'v' ): case VLC_FOURCC( 'm', 'p', '4', 'v' ): case VLC_FOURCC( 'D', 'I', 'V', '3' ): case VLC_FOURCC( 'M', 'J', 'P', 'G' ): case VLC_FOURCC( 'W', 'M', 'V', '1' ): case VLC_FOURCC( 'W', 'M', 'V', '2' ): case VLC_FOURCC( 'W', 'M', 'V', '3' ): case VLC_FOURCC( 'S', 'N', 'O', 'W' ): case VLC_FOURCC( 'd', 'r', 'a', 'c' ): p_stream->p_oggds_header = malloc( sizeof(oggds_header_t) ); memset( p_stream->p_oggds_header, 0, sizeof(oggds_header_t) ); p_stream->p_oggds_header->i_packet_type = PACKET_TYPE_HEADER; memcpy( p_stream->p_oggds_header->stream_type, "video", 5 ); if( p_stream->i_fourcc == VLC_FOURCC( 'm', 'p', '4', 'v' ) ) { memcpy( p_stream->p_oggds_header->sub_type, "XVID", 4 ); } else if( p_stream->i_fourcc == VLC_FOURCC( 'D', 'I', 'V', '3' ) ) { memcpy( p_stream->p_oggds_header->sub_type, "DIV3", 4 ); } else { memcpy( p_stream->p_oggds_header->sub_type, &p_stream->i_fourcc, 4 ); } SetDWLE( &p_stream->p_oggds_header->i_size, sizeof( oggds_header_t ) - 1 ); SetQWLE( &p_stream->p_oggds_header->i_time_unit, I64C(10000000) * p_input->p_fmt->video.i_frame_rate_base / (int64_t)p_input->p_fmt->video.i_frame_rate ); SetQWLE( &p_stream->p_oggds_header->i_samples_per_unit, 1 ); SetDWLE( &p_stream->p_oggds_header->i_default_len, 1 ); /* ??? */ SetDWLE( &p_stream->p_oggds_header->i_buffer_size, 1024*1024 ); SetWLE( &p_stream->p_oggds_header->i_bits_per_sample, 0 ); SetDWLE( &p_stream->p_oggds_header->header.video.i_width, p_input->p_fmt->video.i_width ); SetDWLE( &p_stream->p_oggds_header->header.video.i_height, p_input->p_fmt->video.i_height ); msg_Dbg( p_mux, "%4.4s stream", (char *)&p_stream->i_fourcc ); break; case VLC_FOURCC( 't', 'h', 'e', 'o' ): msg_Dbg( p_mux, "theora stream" ); break; default: FREE( p_input->p_sys ); return VLC_EGENERIC; } break; case AUDIO_ES: switch( p_stream->i_fourcc ) { case VLC_FOURCC( 'v', 'o', 'r', 'b' ): msg_Dbg( p_mux, "vorbis stream" ); break; case VLC_FOURCC( 's', 'p', 'x', ' ' ): msg_Dbg( p_mux, "speex stream" ); break; case VLC_FOURCC( 'f', 'l', 'a', 'c' ): msg_Dbg( p_mux, "flac stream" ); break; default: fourcc_to_wf_tag( p_stream->i_fourcc, &i_tag ); if( i_tag == WAVE_FORMAT_UNKNOWN ) { FREE( p_input->p_sys ); return VLC_EGENERIC; } p_stream->p_oggds_header = malloc( sizeof(oggds_header_t) + p_input->p_fmt->i_extra ); memset( p_stream->p_oggds_header, 0, sizeof(oggds_header_t) ); p_stream->p_oggds_header->i_packet_type = PACKET_TYPE_HEADER; SetDWLE( &p_stream->p_oggds_header->i_size, sizeof( oggds_header_t ) - 1 + p_input->p_fmt->i_extra ); if( p_input->p_fmt->i_extra ) { memcpy( &p_stream->p_oggds_header[1], p_input->p_fmt->p_extra, p_input->p_fmt->i_extra ); } memcpy( p_stream->p_oggds_header->stream_type, "audio", 5 ); memset( p_stream->p_oggds_header->sub_type, 0, 4 ); sprintf( p_stream->p_oggds_header->sub_type, "%-x", i_tag ); SetQWLE( &p_stream->p_oggds_header->i_time_unit, I64C(10000000) ); SetDWLE( &p_stream->p_oggds_header->i_default_len, 1 ); SetDWLE( &p_stream->p_oggds_header->i_buffer_size, 30*1024 ); SetQWLE( &p_stream->p_oggds_header->i_samples_per_unit, p_input->p_fmt->audio.i_rate ); SetWLE( &p_stream->p_oggds_header->i_bits_per_sample, p_input->p_fmt->audio.i_bitspersample ); SetDWLE( &p_stream->p_oggds_header->header.audio.i_channels, p_input->p_fmt->audio.i_channels ); SetDWLE( &p_stream->p_oggds_header->header.audio.i_block_align, p_input->p_fmt->audio.i_blockalign ); SetDWLE( &p_stream->p_oggds_header->header.audio.i_avgbytespersec, p_input->p_fmt->i_bitrate / 8); msg_Dbg( p_mux, "%4.4s stream", (char *)&p_stream->i_fourcc ); break; } break; case SPU_ES: switch( p_stream->i_fourcc ) { case VLC_FOURCC( 's', 'u','b', 't' ): p_stream->p_oggds_header = malloc( sizeof(oggds_header_t) ); memset( p_stream->p_oggds_header, 0, sizeof(oggds_header_t) ); p_stream->p_oggds_header->i_packet_type = PACKET_TYPE_HEADER; memcpy( p_stream->p_oggds_header->stream_type, "text", 4 ); msg_Dbg( p_mux, "subtitles stream" ); break; default: FREE( p_input->p_sys ); return VLC_EGENERIC; } break; default: FREE( p_input->p_sys ); return VLC_EGENERIC; } p_stream->b_new = VLC_TRUE; p_sys->i_add_streams++; return VLC_SUCCESS;}/***************************************************************************** * DelStream: Delete an elementary stream from the muxed stream *****************************************************************************/static int DelStream( 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_og; msg_Dbg( p_mux, "removing input" ); /* flush all remaining data */ if( p_input->p_sys ) { if( !p_stream->b_new ) { while( p_input->p_fifo->i_depth ) MuxBlock( p_mux, p_input ); } if( !p_stream->b_new && ( 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 ); } /* move input in delete queue */ if( !p_stream->b_new ) { p_sys->pp_del_streams = realloc( p_sys->pp_del_streams, (p_sys->i_del_streams + 1) * sizeof(ogg_stream_t *) ); p_sys->pp_del_streams[p_sys->i_del_streams++] = p_stream; } else { /* wasn't already added so get rid of it */ FREE( p_stream->p_oggds_header ); FREE( p_stream ); p_sys->i_add_streams--; } } p_input->p_sys = NULL; return 0;}/***************************************************************************** * Ogg bitstream manipulation routines *****************************************************************************/static block_t *OggStreamFlush( sout_mux_t *p_mux, ogg_stream_state *p_os, mtime_t i_pts ){ block_t *p_og, *p_og_first = NULL; ogg_page og; while( ogg_stream_flush( p_os, &og ) ) { /* Flush all data */ p_og = block_New( p_mux, og.header_len + og.body_len ); memcpy( p_og->p_buffer, og.header, og.header_len ); memcpy( p_og->p_buffer + og.header_len, og.body, og.body_len ); p_og->i_dts = 0; p_og->i_pts = i_pts; p_og->i_length = 0; i_pts = 0; // write it only once block_ChainAppend( &p_og_first, p_og ); } return p_og_first;}static block_t *OggStreamPageOut( sout_mux_t *p_mux, ogg_stream_state *p_os, mtime_t i_pts ){ block_t *p_og, *p_og_first = NULL; ogg_page og; while( ogg_stream_pageout( p_os, &og ) ) { /* Flush all data */ p_og = block_New( p_mux, og.header_len + og.body_len ); memcpy( p_og->p_buffer, og.header, og.header_len ); memcpy( p_og->p_buffer + og.header_len, og.body, og.body_len ); p_og->i_dts = 0; p_og->i_pts = i_pts; p_og->i_length = 0; i_pts = 0; // write them only once block_ChainAppend( &p_og_first, p_og ); } return p_og_first;}static block_t *OggCreateHeader( sout_mux_t *p_mux, mtime_t i_dts ){ block_t *p_hdr = NULL; block_t *p_og = NULL; ogg_packet op; uint8_t *p_extra; int i, i_extra; /* Write header for each stream. All b_o_s (beginning of stream) packets * must appear first in the ogg stream so we take care of them first. */ for( i = 0; i < p_mux->i_nb_inputs; i++ ) { sout_input_t *p_input = p_mux->pp_inputs[i]; ogg_stream_t *p_stream = (ogg_stream_t*)p_input->p_sys; p_stream->b_new = VLC_FALSE; msg_Dbg( p_mux, "creating header for %4.4s", (char *)&p_stream->i_fourcc ); ogg_stream_init( &p_stream->os, p_stream->i_serial_no ); p_stream->i_packet_no = 0; 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' ) ) { /* First packet in order: vorbis/speex/theora info */ p_extra = p_input->p_fmt->p_extra; i_extra = p_input->p_fmt->i_extra; op.bytes = *(p_extra++) << 8; op.bytes |= (*(p_extra++) & 0xFF); op.packet = p_extra; i_extra -= (op.bytes + 2); if( i_extra < 0 ) { msg_Err( p_mux, "header data corrupted"); op.bytes += i_extra; } op.b_o_s = 1; 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 ); /* Get keyframe_granule_shift for theora granulepos calculation */ if( p_stream->i_fourcc == VLC_FOURCC( 't', 'h', 'e', 'o' ) ) { int i_keyframe_frequency_force = 1 << ((op.packet[40] << 6 >> 3) | (op.packet[41] >> 5)); /* granule_shift = i_log( frequency_force -1 ) */ p_stream->i_keyframe_granule_shift = 0; i_keyframe_frequency_force--; while( i_keyframe_frequency_force ) { p_stream->i_keyframe_granule_shift++; i_keyframe_frequency_force >>= 1; } } } else if( p_stream->i_fourcc == VLC_FOURCC( 'f', 'l', 'a', 'c' ) ) { /* flac stream marker (yeah, only that in the 1st packet) */ op.packet = (unsigned char *)"fLaC"; op.bytes = 4; op.b_o_s = 1; 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 ); } else if( p_stream->p_oggds_header ) { /* ds header */ op.packet = (uint8_t*)p_stream->p_oggds_header; op.bytes = p_stream->p_oggds_header->i_size + 1; op.b_o_s = 1; 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 ); } /* Take care of the non b_o_s headers */ for( i = 0; i < p_mux->i_nb_inputs; i++ ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -