@ -193,6 +193,10 @@ static char *subtitle_codec_name = NULL;
static char * subtitle_language = NULL ;
static unsigned int subtitle_codec_tag = 0 ;
static int data_disable = 0 ;
static char * data_codec_name = NULL ;
static unsigned int data_codec_tag = 0 ;
static float mux_preload = 0.5 ;
static float mux_max_delay = 0.7 ;
@ -211,6 +215,7 @@ static const char *pass_logfilename_prefix;
static int audio_stream_copy = 0 ;
static int video_stream_copy = 0 ;
static int subtitle_stream_copy = 0 ;
static int data_stream_copy = 0 ;
static int video_sync_method = - 1 ;
static int audio_sync_method = 0 ;
static float audio_drift_threshold = 0.1 ;
@ -555,6 +560,7 @@ static int ffmpeg_exit(int ret)
av_free ( video_codec_name ) ;
av_free ( audio_codec_name ) ;
av_free ( subtitle_codec_name ) ;
av_free ( data_codec_name ) ;
av_free ( video_standard ) ;
@ -2254,6 +2260,8 @@ static int transcode(AVFormatContext **output_files,
codec - > width = icodec - > width ;
codec - > height = icodec - > height ;
break ;
case AVMEDIA_TYPE_DATA :
break ;
default :
abort ( ) ;
}
@ -3016,6 +3024,11 @@ static void opt_subtitle_codec(const char *arg)
opt_codec ( & subtitle_stream_copy , & subtitle_codec_name , AVMEDIA_TYPE_SUBTITLE , arg ) ;
}
static void opt_data_codec ( const char * arg )
{
opt_codec ( & data_stream_copy , & data_codec_name , AVMEDIA_TYPE_DATA , arg ) ;
}
static int opt_codec_tag ( const char * opt , const char * arg )
{
char * tail ;
@ -3409,15 +3422,19 @@ static void opt_input_file(const char *filename)
av_freep ( & subtitle_codec_name ) ;
}
static void check_audio_video_sub_inputs ( int * has_video_ptr , int * has_audio_ptr ,
int * has_subtitle_ptr )
static void check_inputs ( int * has_video_ptr ,
int * has_audio_ptr ,
int * has_subtitle_ptr ,
int * has_data_ptr )
{
int has_video , has_audio , has_subtitle , i , j ;
int has_video , has_audio , has_subtitle , has_data , i , j ;
AVFormatContext * ic ;
has_video = 0 ;
has_audio = 0 ;
has_subtitle = 0 ;
has_data = 0 ;
for ( j = 0 ; j < nb_input_files ; j + + ) {
ic = input_files [ j ] ;
for ( i = 0 ; i < ic - > nb_streams ; i + + ) {
@ -3435,6 +3452,7 @@ static void check_audio_video_sub_inputs(int *has_video_ptr, int *has_audio_ptr,
case AVMEDIA_TYPE_DATA :
case AVMEDIA_TYPE_ATTACHMENT :
case AVMEDIA_TYPE_UNKNOWN :
has_data = 1 ;
break ;
default :
abort ( ) ;
@ -3444,6 +3462,7 @@ static void check_audio_video_sub_inputs(int *has_video_ptr, int *has_audio_ptr,
* has_video_ptr = has_video ;
* has_audio_ptr = has_audio ;
* has_subtitle_ptr = has_subtitle ;
* has_data_ptr = has_data ;
}
static void new_video_stream ( AVFormatContext * oc , int file_idx )
@ -3676,6 +3695,45 @@ static void new_audio_stream(AVFormatContext *oc, int file_idx)
audio_stream_copy = 0 ;
}
static void new_data_stream ( AVFormatContext * oc , int file_idx )
{
AVStream * st ;
AVOutputStream * ost ;
AVCodec * codec = NULL ;
AVCodecContext * data_enc ;
st = av_new_stream ( oc , oc - > nb_streams < nb_streamid_map ? streamid_map [ oc - > nb_streams ] : 0 ) ;
if ( ! st ) {
fprintf ( stderr , " Could not alloc stream \n " ) ;
ffmpeg_exit ( 1 ) ;
}
ost = new_output_stream ( oc , file_idx ) ;
data_enc = st - > codec ;
output_codecs = grow_array ( output_codecs , sizeof ( * output_codecs ) , & nb_output_codecs , nb_output_codecs + 1 ) ;
if ( ! data_stream_copy ) {
fprintf ( stderr , " Data stream encoding not supported yet (only streamcopy) \n " ) ;
ffmpeg_exit ( 1 ) ;
}
avcodec_get_context_defaults3 ( st - > codec , codec ) ;
data_enc - > codec_type = AVMEDIA_TYPE_DATA ;
if ( data_codec_tag )
data_enc - > codec_tag = data_codec_tag ;
if ( oc - > oformat - > flags & AVFMT_GLOBALHEADER ) {
data_enc - > flags | = CODEC_FLAG_GLOBAL_HEADER ;
avcodec_opts [ AVMEDIA_TYPE_DATA ] - > flags | = CODEC_FLAG_GLOBAL_HEADER ;
}
if ( data_stream_copy ) {
st - > stream_copy = 1 ;
}
data_disable = 0 ;
av_freep ( & data_codec_name ) ;
data_stream_copy = 0 ;
}
static void new_subtitle_stream ( AVFormatContext * oc , int file_idx )
{
AVStream * st ;
@ -3746,6 +3804,7 @@ static int opt_new_stream(const char *opt, const char *arg)
if ( ! strcmp ( opt , " newvideo " ) ) new_video_stream ( oc , file_idx ) ;
else if ( ! strcmp ( opt , " newaudio " ) ) new_audio_stream ( oc , file_idx ) ;
else if ( ! strcmp ( opt , " newsubtitle " ) ) new_subtitle_stream ( oc , file_idx ) ;
else if ( ! strcmp ( opt , " newdata " ) ) new_data_stream ( oc , file_idx ) ;
else av_assert0 ( 0 ) ;
return 0 ;
}
@ -3776,8 +3835,8 @@ static int opt_streamid(const char *opt, const char *arg)
static void opt_output_file ( const char * filename )
{
AVFormatContext * oc ;
int err , use_video , use_audio , use_subtitle ;
int input_has_video , input_has_audio , input_has_subtitle ;
int err , use_video , use_audio , use_subtitle , use_data ;
int input_has_video , input_has_audio , input_has_subtitle , input_has_data ;
AVFormatParameters params , * ap = & params ;
AVOutputFormat * file_oformat ;
@ -3805,28 +3864,36 @@ static void opt_output_file(const char *filename)
use_video = file_oformat - > video_codec ! = CODEC_ID_NONE | | video_stream_copy | | video_codec_name ;
use_audio = file_oformat - > audio_codec ! = CODEC_ID_NONE | | audio_stream_copy | | audio_codec_name ;
use_subtitle = file_oformat - > subtitle_codec ! = CODEC_ID_NONE | | subtitle_stream_copy | | subtitle_codec_name ;
use_data = data_stream_copy | | data_codec_name ; /* XXX once generic data codec will be available add a ->data_codec reference and use it here */
/* disable if no corresponding type found and at least one
input file */
if ( nb_input_files > 0 ) {
check_audio_video_sub_inputs ( & input_has_video , & input_has_audio ,
& input_has_subtitle ) ;
check_inputs ( & input_has_video ,
& input_has_audio ,
& input_has_subtitle ,
& input_has_data ) ;
if ( ! input_has_video )
use_video = 0 ;
if ( ! input_has_audio )
use_audio = 0 ;
if ( ! input_has_subtitle )
use_subtitle = 0 ;
if ( ! input_has_data )
use_data = 0 ;
}
/* manual disable */
if ( audio_disable ) use_audio = 0 ;
if ( video_disable ) use_video = 0 ;
if ( subtitle_disable ) use_subtitle = 0 ;
if ( data_disable ) use_data = 0 ;
if ( use_video ) new_video_stream ( oc , nb_output_files ) ;
if ( use_audio ) new_audio_stream ( oc , nb_output_files ) ;
if ( use_subtitle ) new_subtitle_stream ( oc , nb_output_files ) ;
if ( use_data ) new_data_stream ( oc , nb_output_files ) ;
oc - > timestamp = recording_timestamp ;
@ -4236,6 +4303,8 @@ static int opt_preset(const char *opt, const char *arg)
opt_video_codec ( tmp2 ) ;
} else if ( ! strcmp ( tmp , " scodec " ) ) {
opt_subtitle_codec ( tmp2 ) ;
} else if ( ! strcmp ( tmp , " dcodec " ) ) {
opt_data_codec ( tmp2 ) ;
} else if ( opt_default ( tmp , tmp2 ) < 0 ) {
fprintf ( stderr , " %s: Invalid option or argument: '%s', parsed as '%s' = '%s' \n " , filename , line , tmp , tmp2 ) ;
ffmpeg_exit ( 1 ) ;
@ -4389,6 +4458,8 @@ static const OptionDef options[] = {
{ " vpre " , OPT_FUNC2 | HAS_ARG | OPT_VIDEO | OPT_EXPERT , { ( void * ) opt_preset } , " set the video options to the indicated preset " , " preset " } ,
{ " spre " , OPT_FUNC2 | HAS_ARG | OPT_SUBTITLE | OPT_EXPERT , { ( void * ) opt_preset } , " set the subtitle options to the indicated preset " , " preset " } ,
{ " fpre " , OPT_FUNC2 | HAS_ARG | OPT_EXPERT , { ( void * ) opt_preset } , " set options from indicated preset file " , " filename " } ,
/* data codec support */
{ " dcodec " , HAS_ARG | OPT_DATA , { ( void * ) opt_data_codec } , " force data codec ('copy' to copy stream) " , " codec " } ,
{ " default " , OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT , { ( void * ) opt_default } , " generic catch all option " , " " } ,
{ NULL , } ,