📄 ogg.c
字号:
/***************************************************************************** * ogg.c: ogg muxer module for vlc ***************************************************************************** * Copyright (C) 2001, 2002, 2006 the VideoLAN team * $Id: ogg.c 14918 2006-03-25 12:54:27Z fkuehne $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * Gildas Bazin <gbazin@videolan.org> * * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdlib.h>#include <string.h>#ifdef HAVE_TIME_H# include <time.h>#endif#include <vlc/vlc.h>#include <vlc/input.h>#include <vlc/sout.h>#include "codecs.h"#include <ogg/ogg.h>/***************************************************************************** * Module descriptor *****************************************************************************/static int Open ( vlc_object_t * );static void Close ( vlc_object_t * );vlc_module_begin(); set_description( _("Ogg/OGM muxer") ); set_capability( "sout mux", 10 ); set_category( CAT_SOUT ); set_subcategory( SUBCAT_SOUT_MUX ); add_shortcut( "ogg" ); add_shortcut( "ogm" ); set_callbacks( Open, Close );vlc_module_end();/***************************************************************************** * Exported prototypes *****************************************************************************/static int Control ( sout_mux_t *, int, va_list );static int AddStream( sout_mux_t *, sout_input_t * );static int DelStream( sout_mux_t *, sout_input_t * );static int Mux ( sout_mux_t * );static int MuxBlock ( sout_mux_t *, sout_input_t * );static block_t *OggCreateHeader( sout_mux_t *, mtime_t );static block_t *OggCreateFooter( sout_mux_t *, mtime_t );/***************************************************************************** * Misc declarations *****************************************************************************/#define FREE( p ) if( p ) { free( p ); (p) = NULL; }/* Structures used for OggDS headers used in ogm files */#define PACKET_TYPE_HEADER 0x01#define PACKET_TYPE_COMMENT 0x03#define PACKET_IS_SYNCPOINT 0x08typedef struct#ifdef HAVE_ATTRIBUTE_PACKED __attribute__((__packed__))#endif{ int32_t i_width; int32_t i_height;} oggds_header_video_t;typedef struct#ifdef HAVE_ATTRIBUTE_PACKED __attribute__((__packed__))#endif{ int16_t i_channels; int16_t i_block_align; int32_t i_avgbytespersec;} oggds_header_audio_t;typedef struct#ifdef HAVE_ATTRIBUTE_PACKED __attribute__((__packed__))#endif{ uint8_t i_packet_type; char stream_type[8]; char sub_type[4]; int32_t i_size; int64_t i_time_unit; int64_t i_samples_per_unit; int32_t i_default_len; int32_t i_buffer_size; int16_t i_bits_per_sample; int16_t i_padding_0; /* Because the original is using MSVC packing style */ union { oggds_header_video_t video; oggds_header_audio_t audio; } header; int32_t i_padding_1; /* Because the original is using MSVC packing style */} oggds_header_t;/* * TODO move this function to src/stream_output.c (used by nearly all muxers) */static int MuxGetStream( sout_mux_t *p_mux, int *pi_stream, mtime_t *pi_dts ){ mtime_t i_dts; int i_stream; int i; for( i = 0, i_dts = 0, i_stream = -1; i < p_mux->i_nb_inputs; i++ ) { block_fifo_t *p_fifo; p_fifo = p_mux->pp_inputs[i]->p_fifo; /* We don't really need to have anything in the SPU fifo */ if( p_mux->pp_inputs[i]->p_fmt->i_cat == SPU_ES && p_fifo->i_depth == 0 ) continue; if( p_fifo->i_depth ) { block_t *p_buf; p_buf = block_FifoShow( p_fifo ); if( i_stream < 0 || p_buf->i_dts < i_dts ) { i_dts = p_buf->i_dts; i_stream = i; } } else return -1; } if( pi_stream ) *pi_stream = i_stream; if( pi_dts ) *pi_dts = i_dts; return i_stream;}/***************************************************************************** * Definitions of structures and functions used by this plugins *****************************************************************************/typedef struct{ int i_cat; int i_fourcc; int b_new; mtime_t i_dts; mtime_t i_length; int i_packet_no; int i_serial_no; int i_keyframe_granule_shift; /* Theora only */ ogg_stream_state os; oggds_header_t *p_oggds_header;} ogg_stream_t;struct sout_mux_sys_t{ int i_streams; mtime_t i_start_dts; int i_next_serial_no; /* number of logical streams pending to be added */ int i_add_streams; /* logical streams pending to be deleted */ int i_del_streams; ogg_stream_t **pp_del_streams;};static void OggSetDate( block_t *, mtime_t , mtime_t );static block_t *OggStreamFlush( sout_mux_t *, ogg_stream_state *, mtime_t );/***************************************************************************** * Open: Open muxer *****************************************************************************/static int Open( vlc_object_t *p_this ){ sout_mux_t *p_mux = (sout_mux_t*)p_this; sout_mux_sys_t *p_sys; msg_Info( p_mux, "Open" ); p_sys = malloc( sizeof( sout_mux_sys_t ) ); p_sys->i_streams = 0; p_sys->i_add_streams = 0; p_sys->i_del_streams = 0; p_sys->pp_del_streams = 0; p_mux->p_sys = p_sys; p_mux->pf_control = Control; p_mux->pf_addstream = AddStream; p_mux->pf_delstream = DelStream; p_mux->pf_mux = Mux; /* First serial number is random. * (Done like this because on win32 you need to seed the random number * generator once per thread). */ srand( (unsigned int)time( NULL ) ); p_sys->i_next_serial_no = rand(); return VLC_SUCCESS;}/***************************************************************************** * Close: Finalize ogg bitstream and close muxer *****************************************************************************/static void Close( vlc_object_t * p_this ){ sout_mux_t *p_mux = (sout_mux_t*)p_this; sout_mux_sys_t *p_sys = p_mux->p_sys; msg_Info( p_mux, "Close" ); if( p_sys->i_del_streams ) { block_t *p_og = NULL; mtime_t i_dts = -1; int i; /* Close the current ogg stream */ 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++ ) { i_dts = p_sys->pp_del_streams[i]->i_dts; ogg_stream_clear( &p_sys->pp_del_streams[i]->os ); 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 -= p_sys->i_del_streams; /* Write footer */ OggSetDate( p_og, i_dts, 0 ); sout_AccessOutWrite( p_mux->p_access, p_og ); } free( p_sys );}/***************************************************************************** * Control: *****************************************************************************/static int Control( sout_mux_t *p_mux, int i_query, va_list args ){ vlc_bool_t *pb_bool; char **ppsz; switch( i_query ) { case MUX_CAN_ADD_STREAM_WHILE_MUXING: pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * ); *pb_bool = VLC_TRUE; return VLC_SUCCESS; case MUX_GET_ADD_STREAM_WAIT: pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * ); *pb_bool = VLC_TRUE; return VLC_SUCCESS; case MUX_GET_MIME: ppsz = (char**)va_arg( args, char ** ); *ppsz = strdup( "application/ogg" ); return VLC_SUCCESS; default: return VLC_EGENERIC; }}/***************************************************************************** * AddStream: Add an elementary stream to the muxed stream *****************************************************************************/static int AddStream( 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; uint16_t i_tag; msg_Dbg( p_mux, "adding input" ); p_input->p_sys = p_stream = malloc( sizeof( ogg_stream_t ) ); p_stream->i_cat = p_input->p_fmt->i_cat; p_stream->i_fourcc = p_input->p_fmt->i_codec; p_stream->i_serial_no = p_sys->i_next_serial_no++; p_stream->i_packet_no = 0; p_stream->p_oggds_header = 0; switch( p_input->p_fmt->i_cat ) { case VIDEO_ES: if( !p_input->p_fmt->video.i_frame_rate || !p_input->p_fmt->video.i_frame_rate_base ) { msg_Warn( p_mux, "Missing frame rate, assuming 25fps" ); p_input->p_fmt->video.i_frame_rate = 25; p_input->p_fmt->video.i_frame_rate_base = 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -