/*****************************************************************************
* mux.c: muxer using libavformat
*****************************************************************************
- * Copyright (C) 2006 the VideoLAN team
+ * Copyright (C) 2006 VLC authors and VideoLAN
* $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
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser 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.
+ * You should have received a copy of the GNU Lesser 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.
*****************************************************************************/
/*****************************************************************************
#include "avformat.h"
#include "../../codec/avcodec/avcodec.h"
-#include "../../codec/avcodec/avutil.h"
+#include "../../codec/avcodec/avcommon.h"
-/* Support for deprecated APIs */
-#if LIBAVFORMAT_VERSION_INT < ((52<<16)+(105<<8)+0)
-# define avio_flush put_flush_packet
-#endif
//#define AVFORMAT_DEBUG 1
static const char *const ppsz_mux_options[] = {
- "mux", NULL
+ "mux", "options", NULL
};
/*****************************************************************************
*****************************************************************************/
struct sout_mux_sys_t
{
-#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(105<<8)+0)
AVIOContext *io;
-#else
- ByteIOContext io;
-#endif
int io_buffer_size;
uint8_t *io_buffer;
AVFormatContext *oc;
bool b_write_header;
+ bool b_write_keyframe;
bool b_error;
-
- int64_t i_initial_dts;
};
/*****************************************************************************
sout_mux_sys_t *p_sys;
char *psz_mux;
- /* Should we call it only once ? */
- av_register_all();
- av_log_set_callback( LibavutilCallback );
+ vlc_init_avformat(p_this);
- config_ChainParse( p_mux, "ffmpeg-", ppsz_mux_options, p_mux->p_cfg );
+ config_ChainParse( p_mux, "sout-avformat-", ppsz_mux_options, p_mux->p_cfg );
/* Find the requested muxer */
- psz_mux = var_GetNonEmptyString( p_mux, "ffmpeg-mux" );
+ psz_mux = var_GetNonEmptyString( p_mux, "sout-avformat-mux" );
if( psz_mux )
{
-#if( LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT( 52, 45, 0 ) )
file_oformat = av_guess_format( psz_mux, NULL, NULL );
-#else
- file_oformat = guess_format( psz_mux, NULL, NULL );
-#endif
free( psz_mux );
}
else
{
file_oformat =
-#if( LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT( 52, 45, 0 ) )
av_guess_format( NULL, p_mux->p_access->psz_path, NULL);
-#else
- guess_format( NULL, p_mux->p_access->psz_path, NULL);
-#endif
}
if (!file_oformat)
{
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 ) );
+ if( !p_sys )
+ return VLC_ENOMEM;
p_sys->oc = avformat_alloc_context();
p_sys->oc->oformat = file_oformat;
+ /* If we use dummy access, let avformat write output */
+ if( !strcmp( p_mux->p_access->psz_access, "dummy") )
+ strcpy( p_sys->oc->filename, p_mux->p_access->psz_path );
/* Create I/O wrapper */
- p_sys->io_buffer_size = 32768; /* FIXME */
+ p_sys->io_buffer_size = 10 * 1024 * 1024; /* FIXME */
p_sys->io_buffer = malloc( p_sys->io_buffer_size );
-#if (LIBAVFORMAT_VERSION_INT >= ((52<<16)+(105<<8)+0))
+ bool b_can_seek;
+ if( sout_AccessOutControl( p_mux->p_access, ACCESS_OUT_CAN_SEEK, &b_can_seek ) )
+ b_can_seek = false;
p_sys->io = avio_alloc_context(
-#else
- init_put_byte( &p_sys->io,
-#endif
p_sys->io_buffer, p_sys->io_buffer_size,
- 1, p_mux, NULL, IOWrite, IOSeek );
+ 1, p_mux, NULL, IOWrite, b_can_seek ? IOSeek : NULL );
-
-#if (LIBAVFORMAT_VERSION_INT < ((52<<16)+(105<<8)+0))
- AVFormatParameters params, *ap = ¶ms;
- 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;
- }
-#endif
-
-#if (LIBAVFORMAT_VERSION_INT >= ((52<<16)+(105<<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_write_keyframe = false;
p_sys->b_error = false;
- p_sys->i_initial_dts = 0;
+
+ /* Fill p_mux fields */
+ p_mux->pf_control = Control;
+ p_mux->pf_addstream = AddStream;
+ p_mux->pf_delstream = DelStream;
+ p_mux->pf_mux = Mux;
return VLC_SUCCESS;
}
msg_Err( p_mux, "could not write trailer" );
}
-#if( LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT( 52, 96, 0 ) )
avformat_free_context(p_sys->oc);
-#else
- for( unsigned i = 0 ; i < p_sys->oc->nb_streams; i++ )
- {
- av_free( p_sys->oc->streams[i]->codec->extradata );
- av_free( p_sys->oc->streams[i]->codec );
-#if( LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT( 52, 81, 0 ) )
- av_free( p_sys->oc->streams[i]->info );
-#endif
- av_free( p_sys->oc->streams[i] );
- }
- av_free( p_sys->oc->streams );
- av_free( p_sys->oc );
-#endif
free( p_sys->io_buffer );
free( p_sys );
sout_mux_sys_t *p_sys = p_mux->p_sys;
AVCodecContext *codec;
AVStream *stream;
- int i_codec_id;
+ unsigned i_codec_id;
msg_Dbg( p_mux, "adding input" );
return VLC_EGENERIC;
}
-#if (LIBAVFORMAT_VERSION_INT >= ((53<<16)+(10<<8)+0))
stream = avformat_new_stream( p_sys->oc, NULL);
-#else
- stream = av_new_stream( p_sys->oc, p_sys->oc->nb_streams);
-#endif
if( !stream )
{
free( p_input->p_sys );
}
codec = stream->codec;
- /* This is used by LibavutilCallback (avutil.h) to print messages */
codec->opaque = p_mux;
switch( p_input->p_fmt->i_cat )
&codec->sample_aspect_ratio.den,
p_input->p_fmt->video.i_sar_num,
p_input->p_fmt->video.i_sar_den, 1 << 30 /* something big */ );
-#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(21<<8)+0)
- stream->sample_aspect_ratio.num = codec->sample_aspect_ratio.num;
stream->sample_aspect_ratio.den = codec->sample_aspect_ratio.den;
-#endif
+ stream->sample_aspect_ratio.num = codec->sample_aspect_ratio.num;
codec->time_base.den = p_input->p_fmt->video.i_frame_rate;
codec->time_base.num = p_input->p_fmt->video.i_frame_rate_base;
break;
}
codec->bit_rate = p_input->p_fmt->i_bitrate;
-#if LIBAVFORMAT_VERSION_INT >= ((51<<16)+(8<<8)+0)
codec->codec_tag = av_codec_get_tag( p_sys->oc->oformat->codec_tag, i_codec_id );
- if( !codec->codec_tag && i_codec_id == CODEC_ID_MP2 )
+ if( !codec->codec_tag && i_codec_id == AV_CODEC_ID_MP2 )
{
- i_codec_id = CODEC_ID_MP3;
+ i_codec_id = AV_CODEC_ID_MP3;
codec->codec_tag = av_codec_get_tag( p_sys->oc->oformat->codec_tag, i_codec_id );
}
-#else
-# warning "WARNING!!!!!!!"
-# warning "Using libavformat muxing with versions older than 51.8.0 (r7593) might produce broken files."
- /* This is a hack */
- if( i_codec_id == CODEC_ID_MP2 )
- i_codec_id = CODEC_ID_MP3;
- codec->codec_tag = p_input->p_fmt->i_original_fourcc ?: p_input->p_fmt->i_codec;
-#endif
codec->codec_id = i_codec_id;
if( p_input->p_fmt->i_extra )
pkt.size = p_data->i_buffer;
pkt.stream_index = i_stream;
- if( p_data->i_flags & BLOCK_FLAG_TYPE_I ) pkt.flags |= AV_PKT_FLAG_KEY;
+ if( p_data->i_flags & BLOCK_FLAG_TYPE_I )
+ {
+#ifdef AVFMT_ALLOW_FLUSH
+ /* Make sure we don't inadvertedly mark buffered data as keyframes. */
+ if( p_sys->oc->oformat->flags & AVFMT_ALLOW_FLUSH )
+ av_write_frame( p_sys->oc, NULL );
+#endif
- /* avformat expects pts/dts which start from 0 */
- p_data->i_dts -= p_mux->p_sys->i_initial_dts;
- p_data->i_pts -= p_mux->p_sys->i_initial_dts;
+ p_sys->b_write_keyframe = true;
+ pkt.flags |= AV_PKT_FLAG_KEY;
+ }
if( p_data->i_pts > 0 )
pkt.pts = p_data->i_pts * p_stream->time_base.den /
int error;
msg_Dbg( p_mux, "writing header" );
-#if (LIBAVFORMAT_VERSION_INT >= ((53<<16)+(2<<8)+0))
- error = avformat_write_header( p_sys->oc, NULL /* options */ );
-#else
- error = av_write_header( p_sys->oc );
-#endif
+ char *psz_opts = var_GetNonEmptyString( p_mux, "sout-avformat-options" );
+ AVDictionary *options = NULL;
+ if (psz_opts && *psz_opts)
+ options = vlc_av_get_options(psz_opts);
+ free(psz_opts);
+ error = avformat_write_header( p_sys->oc, options ? &options : NULL);
+ AVDictionaryEntry *t = NULL;
+ while ((t = av_dict_get(options, "", t, AV_DICT_IGNORE_SUFFIX))) {
+ msg_Err( p_mux, "Unknown option \"%s\"", t->key );
+ }
+ av_dict_free(&options);
if( error < 0 )
{
errno = AVUNERROR(error);
return VLC_EGENERIC;
}
-#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(0<<8)+0)
avio_flush( p_sys->oc->pb );
-#else
- avio_flush( &p_sys->oc->pb );
-#endif
p_sys->b_write_header = false;
}
if( i_stream < 0 )
return VLC_SUCCESS;
- if( !p_mux->p_sys->i_initial_dts )
- p_mux->p_sys->i_initial_dts = i_dts;
-
MuxBlock( p_mux, p_mux->pp_inputs[i_stream] );
}
msg_Dbg( p_mux, "IOWrite %i bytes", buf_size );
#endif
- block_t *p_buf = block_New( p_mux->p_sout, buf_size );
+ block_t *p_buf = block_Alloc( buf_size );
if( buf_size > 0 ) memcpy( p_buf->p_buffer, buf, buf_size );
if( p_mux->p_sys->b_write_header )
p_buf->i_flags |= BLOCK_FLAG_HEADER;
+ if( p_mux->p_sys->b_write_keyframe )
+ {
+ p_buf->i_flags |= BLOCK_FLAG_TYPE_I;
+ p_mux->p_sys->b_write_keyframe = false;
+ }
+
i_ret = sout_AccessOutWrite( p_mux->p_access, p_buf );
return i_ret ? i_ret : -1;
}