/*****************************************************************************
- * mux.c: muxer using ffmpeg (libavformat).
+ * mux.c: muxer using libavformat
*****************************************************************************
* Copyright (C) 2006 the VideoLAN team
* $Id$
#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 <libavformat/avformat.h>
#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;
- URLContext url;
- URLProtocol prot;
bool b_write_header;
bool b_error;
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 );
+ vlc_init_avformat();
- 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 =
- guess_format(NULL, p_mux->p_access->psz_path, NULL);
+#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)
{
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 = av_alloc_format_context();
+ 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 = 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 =
- (int64_t (*) (URLContext *, int64_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 );
+#if (LIBAVFORMAT_VERSION_INT >= ((52<<16)+(105<<8)+0))
+ 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 );
+
+
+#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 )
{
free( p_sys );
return VLC_EGENERIC;
}
+#endif
-#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(0<<8)+0)
- p_sys->oc->pb = &p_sys->io;
-#else
+#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;
{
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 )
+ if( !p_sys->b_write_header && !p_sys->b_error && 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( 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++ )
{
- 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->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, i_aspect_num, i_aspect_den;
+ int i_codec_id;
msg_Dbg( p_mux, "adding input" );
p_input->p_sys = malloc( sizeof( int ) );
*((int *)p_input->p_sys) = p_sys->oc->nb_streams;
+ if( p_input->p_fmt->i_cat != VIDEO_ES && p_input->p_fmt->i_cat != AUDIO_ES)
+ {
+ msg_Warn( p_mux, "Unhandled ES category" );
+ 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 = (void*)p_mux;
+ codec->opaque = p_mux;
switch( p_input->p_fmt->i_cat )
{
case AUDIO_ES:
- codec->codec_type = CODEC_TYPE_AUDIO;
+ codec->codec_type = AVMEDIA_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};
+ codec->frame_size = p_input->p_fmt->audio.i_frame_length;
break;
case VIDEO_ES:
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->codec_type = AVMEDIA_TYPE_VIDEO;
codec->width = p_input->p_fmt->video.i_width;
codec->height = p_input->p_fmt->video.i_height;
av_reduce( &codec->sample_aspect_ratio.num,
codec->time_base.num = p_input->p_fmt->video.i_frame_rate_base;
break;
- default:
- msg_Warn( p_mux, "Unhandled ES category" );
}
codec->bit_rate = p_input->p_fmt->i_bitrate;
pkt.size = p_data->i_buffer;
pkt.stream_index = i_stream;
- if( p_data->i_flags & BLOCK_FLAG_TYPE_I ) pkt.flags |= PKT_FLAG_KEY;
+ if( p_data->i_flags & BLOCK_FLAG_TYPE_I ) pkt.flags |= AV_PKT_FLAG_KEY;
/* avformat expects pts/dts which start from 0 */
p_data->i_dts -= p_mux->p_sys->i_initial_dts;
if( p_sys->b_write_header )
{
+ int error;
msg_Dbg( p_mux, "writing header" );
- if( av_write_header( p_sys->oc ) < 0 )
+#if (LIBAVFORMAT_VERSION_INT >= ((53<<16)+(2<<8)+0))
+ 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);
+#else
+ error = av_write_header( p_sys->oc );
+#endif
+ if( error < 0 )
{
- msg_Err( p_mux, "could not write header" );
+ errno = AVUNERROR(error);
+ msg_Err( p_mux, "could not write header: %m" );
p_sys->b_write_header = false;
p_sys->b_error = true;
return VLC_EGENERIC;
}
#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(0<<8)+0)
- put_flush_packet( p_sys->oc->pb );
+ avio_flush( p_sys->oc->pb );
#else
- put_flush_packet( &p_sys->oc->pb );
+ avio_flush( &p_sys->oc->pb );
#endif
p_sys->b_write_header = false;
}
*****************************************************************************/
static int IOWrite( void *opaque, uint8_t *buf, int buf_size )
{
- URLContext *p_url = opaque;
- sout_mux_t *p_mux = p_url->priv_data;
+ sout_mux_t *p_mux = opaque;
int i_ret;
#ifdef AVFORMAT_DEBUG
static int64_t IOSeek( void *opaque, int64_t offset, int whence )
{
- URLContext *p_url = opaque;
- sout_mux_t *p_mux = p_url->priv_data;
+ sout_mux_t *p_mux = opaque;
#ifdef AVFORMAT_DEBUG
msg_Dbg( p_mux, "IOSeek offset: %"PRId64", whence: %i", offset, whence );