📄 mux.c
字号:
/***************************************************************************** * mux.c: muxer using ffmpeg (libavformat). ***************************************************************************** * Copyright (C) 2006 the VideoLAN team * $Id$ * * Authors: 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_block.h>#include <vlc_sout.h>/* ffmpeg header */#ifdef HAVE_LIBAVFORMAT_AVFORMAT_H# include <libavformat/avformat.h>#elif defined(HAVE_FFMPEG_AVFORMAT_H)# include <ffmpeg/avformat.h>#endif#include "avformat.h"#include "../../codec/avcodec/fourcc.h"#include "../../codec/avcodec/avutil.h"//#define AVFORMAT_DEBUG 1static const char *const ppsz_mux_options[] = { "mux", NULL};/***************************************************************************** * mux_sys_t: mux descriptor *****************************************************************************/struct sout_mux_sys_t{ ByteIOContext io; int io_buffer_size; uint8_t *io_buffer; AVFormatContext *oc; URLContext url; URLProtocol prot; bool b_write_header; bool b_error; int64_t i_initial_dts;};/***************************************************************************** * Local 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 IOWrite( void *opaque, uint8_t *buf, int buf_size );static offset_t IOSeek( void *opaque, offset_t offset, int whence );/***************************************************************************** * Open *****************************************************************************/int OpenMux( vlc_object_t *p_this ){ AVOutputFormat *file_oformat; sout_mux_t *p_mux = (sout_mux_t*)p_this; sout_mux_sys_t *p_sys; AVFormatParameters params, *ap = ¶ms; char *psz_mux; /* Should we call it only once ? */ av_register_all(); av_log_set_callback( LibavutilCallback ); config_ChainParse( p_mux, "ffmpeg-", ppsz_mux_options, p_mux->p_cfg ); /* Find the requested muxer */ psz_mux = var_GetNonEmptyString( p_mux, "ffmpeg-mux" ); if( psz_mux ) { file_oformat = guess_format( psz_mux, NULL, NULL ); } else { file_oformat = guess_format(NULL, p_mux->p_access->psz_path, NULL); } if (!file_oformat) { msg_Err( p_mux, "unable for find a suitable output format" ); return VLC_EGENERIC; } /* Fill p_mux fields */ p_mux->pf_control = Control; p_mux->pf_addstream = AddStream; p_mux->pf_delstream = DelStream; p_mux->pf_mux = Mux; p_mux->p_sys = p_sys = malloc( sizeof( sout_mux_sys_t ) ); p_sys->oc = av_alloc_format_context(); p_sys->oc->oformat = file_oformat; /* Create I/O wrapper */ p_sys->io_buffer_size = 32768; /* FIXME */ p_sys->io_buffer = malloc( p_sys->io_buffer_size ); p_sys->url.priv_data = p_mux; p_sys->url.prot = &p_sys->prot; p_sys->url.prot->name = "VLC I/O wrapper"; p_sys->url.prot->url_open = 0; p_sys->url.prot->url_read = 0; p_sys->url.prot->url_write = (int (*) (URLContext *, unsigned char *, int))IOWrite; p_sys->url.prot->url_seek = (offset_t (*) (URLContext *, offset_t, int))IOSeek; p_sys->url.prot->url_close = 0; p_sys->url.prot->next = 0; init_put_byte( &p_sys->io, p_sys->io_buffer, p_sys->io_buffer_size, 1, &p_sys->url, NULL, IOWrite, IOSeek ); memset( ap, 0, sizeof(*ap) ); if( av_set_parameters( p_sys->oc, ap ) < 0 ) { msg_Err( p_mux, "invalid encoding parameters" ); av_free( p_sys->oc ); free( p_sys->io_buffer ); free( p_sys ); return VLC_EGENERIC; }#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(0<<8)+0) p_sys->oc->pb = &p_sys->io;#else p_sys->oc->pb = p_sys->io;#endif p_sys->oc->nb_streams = 0; p_sys->b_write_header = true; p_sys->b_error = false; p_sys->i_initial_dts = 0; return VLC_SUCCESS;}/***************************************************************************** * Close *****************************************************************************/void CloseMux( 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; unsigned int i; if( av_write_trailer( p_sys->oc ) < 0 ) { msg_Err( p_mux, "could not write trailer" ); } for( i = 0 ; i < p_sys->oc->nb_streams; i++ ) { if( p_sys->oc->streams[i]->codec->extradata ) av_free( p_sys->oc->streams[i]->codec->extradata ); av_free( p_sys->oc->streams[i]->codec ); av_free( p_sys->oc->streams[i] ); } av_free( p_sys->oc ); free( p_sys->io_buffer ); free( p_sys );}/***************************************************************************** * AddStream *****************************************************************************/static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input ){ sout_mux_sys_t *p_sys = p_mux->p_sys; AVCodecContext *codec; AVStream *stream; int i_codec_id, i_aspect_num, i_aspect_den; msg_Dbg( p_mux, "adding input" ); if( !GetFfmpegCodec( p_input->p_fmt->i_codec, 0, &i_codec_id, 0 ) ) { msg_Dbg( p_mux, "couldn't find codec for fourcc '%4.4s'", (char *)&p_input->p_fmt->i_codec ); return VLC_EGENERIC; } p_input->p_sys = malloc( sizeof( int ) ); *((int *)p_input->p_sys) = p_sys->oc->nb_streams; stream = av_new_stream( p_sys->oc, p_sys->oc->nb_streams); if( !stream ) { free( p_input->p_sys ); return VLC_EGENERIC; } codec = stream->codec; /* This is used by LibavutilCallback (avutil.h) to print messages */ codec->opaque = (void*)p_mux; switch( p_input->p_fmt->i_cat ) { case AUDIO_ES: codec->codec_type = CODEC_TYPE_AUDIO; codec->channels = p_input->p_fmt->audio.i_channels; codec->sample_rate = p_input->p_fmt->audio.i_rate; codec->time_base = (AVRational){1, codec->sample_rate}; break; 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; } codec->codec_type = CODEC_TYPE_VIDEO; codec->width = p_input->p_fmt->video.i_width; codec->height = p_input->p_fmt->video.i_height; av_reduce( &i_aspect_num, &i_aspect_den, p_input->p_fmt->video.i_aspect, VOUT_ASPECT_FACTOR, 1 << 30 /* something big */ ); av_reduce( &codec->sample_aspect_ratio.num, &codec->sample_aspect_ratio.den, i_aspect_num * (int64_t)codec->height,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -